11<?php
2-
32/**
43 * Joomla! Content Management System
54 *
6- * @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
5+ * @copyright (C) 2017 Open Source Matters, Inc.
76 * @license GNU General Public License version 2 or later; see LICENSE.txt
87 */
98
109namespace Joomla \CMS \Form ;
1110
1211use Joomla \Database \DatabaseAwareTrait ;
12+ use RuntimeException ;
1313
1414// phpcs:disable PSR1.Files.SideEffects
1515\defined ('_JEXEC ' ) or die;
1616// phpcs:enable PSR1.Files.SideEffects
1717
1818/**
19- * Default factory for creating Form objects
19+ * Default factory for creating Form objects.
20+ *
21+ * This version restores caching and XML data loading behavior
22+ * that was originally part of Form::getInstance(), addressing
23+ * performance and duplication issues noted in #46369.
2024 *
2125 * @since 4.0.0
2226 */
@@ -25,21 +29,80 @@ class FormFactory implements FormFactoryInterface
2529 use DatabaseAwareTrait;
2630
2731 /**
28- * Method to get an instance of a form.
32+ * Cache of created form instances.
33+ *
34+ * @var Form[]
35+ */
36+ private static array $ forms = [];
37+
38+ /**
39+ * Creates or returns a cached instance of a form.
2940 *
30- * @param string $name The name of the form.
31- * @param array $options An array of form options.
41+ * Behaves similarly to the old Form::getInstance():
42+ * - Returns a cached instance if already loaded.
43+ * - Loads XML or string data into the form.
44+ *
45+ * @param string $name The name of the form.
46+ * @param string|null $data The XML file path or XML string to load.
47+ * @param array $options Optional form options.
48+ * @param bool $replace Whether to replace existing fields.
49+ * @param string|null $xpath XPath to search for fields.
3250 *
3351 * @return Form
3452 *
53+ * @throws RuntimeException When the form cannot be loaded.
54+ *
3555 * @since 4.0.0
3656 */
37- public function createForm (string $ name , array $ options = []): Form
38- {
39- $ form = new Form ($ name , $ options );
57+ public function createForm (
58+ string $ name ,
59+ ?string $ data = null ,
60+ array $ options = [],
61+ bool $ replace = true ,
62+ ?string $ xpath = null
63+ ): Form {
64+ // If a form with this name already exists, return the cached instance
65+ if (isset (self ::$ forms [$ name ])) {
66+ return self ::$ forms [$ name ];
67+ }
4068
69+ // Create a new Form instance
70+ $ form = new Form ($ name , $ options );
4171 $ form ->setDatabase ($ this ->getDatabase ());
4272
73+ // Load XML or string data if provided
74+ if ($ data ) {
75+ // Check if data is an XML string or a file path
76+ if (str_starts_with ($ data , '< ' )) {
77+ // Data is XML string
78+ if (!$ form ->load ($ data , $ replace , $ xpath )) {
79+ throw new RuntimeException (sprintf ('%s() could not load XML form data ' , __METHOD__ ));
80+ }
81+ } else {
82+ // Data is file path
83+ if (!$ form ->loadFile ($ data , $ replace , $ xpath )) {
84+ throw new RuntimeException (sprintf ('%s() could not load form file: %s ' , __METHOD__ , $ data ));
85+ }
86+ }
87+ }
88+
89+ // Cache this form instance
90+ self ::$ forms [$ name ] = $ form ;
91+
4392 return $ form ;
4493 }
94+
95+ /**
96+ * Clears cached form instances.
97+ *
98+ * Useful for testing or if forms need to be reloaded at runtime.
99+ *
100+ * @return void
101+ *
102+ * @since 4.0.0
103+ */
104+ public static function clearCache (): void
105+ {
106+ self ::$ forms = [];
107+ }
45108}
0 commit comments