@@ -18,7 +18,7 @@ class HTMLServerComponentsCompiler
1818 /**
1919 * Library version
2020 */
21- const VERSION = '0.4.3 ' ;
21+ const VERSION = '0.5.0 ' ;
2222
2323 /**
2424 * Stores the added aliases
@@ -49,136 +49,110 @@ public function addAlias($alias, $original)
4949 /**
5050 * Converts components code (if any) into HTML code
5151 *
52- * @param string $content The content to be processed
52+ * @param string|\IvoPetkov\HTMLServerComponent $content The content to be processed
5353 * @param array $options Compiler options
5454 * @throws \InvalidArgumentException
5555 * @return string The result HTML code
5656 */
5757 public function process ($ content , $ options = [])
5858 {
59- if (!is_string ($ content )) {
59+ if (!is_string ($ content ) && !( $ content instanceof \ IvoPetkov \HTMLServerComponent) ) {
6060 throw new \InvalidArgumentException ('' );
6161 }
6262 if (!is_array ($ options )) {
6363 throw new \InvalidArgumentException ('' );
6464 }
65+ if (is_string ($ content ) && strpos ($ content , '<component ' ) === false ) {
66+ return $ content ;
67+ }
6568 if (isset ($ options ['_internal_process_components ' ]) && $ options ['_internal_process_components ' ] === false ) {
6669 return $ content ;
6770 }
68- $ domDocument = new \IvoPetkov \HTML5DOMDocument ();
69- $ domDocument ->loadHTML ($ content );
70- $ componentElements = $ domDocument ->getElementsByTagName ('component ' );
71- $ componentElementsCount = $ componentElements ->length ;
72- if ($ componentElementsCount > 0 ) {
73- for ($ i = 0 ; $ i < $ componentElementsCount ; $ i ++) {
74- $ component = $ componentElements ->item (0 );
75- $ attributes = $ component ->getAttributes ();
76- if (isset ($ attributes ['src ' ])) {
77- $ srcAttributeValue = $ attributes ['src ' ];
78- if (isset ($ this ->aliases [$ srcAttributeValue ])) {
79- $ sourceParts = explode (': ' , $ this ->aliases [$ srcAttributeValue ], 2 );
80- } else {
81- $ sourceParts = explode (': ' , $ srcAttributeValue , 2 );
71+
72+ $ getComponentFileContent = function ($ file , $ component , $ variables ) {
73+ if (is_file ($ file )) {
74+ $ __componentFile = $ file ;
75+ unset($ file );
76+ if (!empty ($ variables )) {
77+ extract ($ variables , EXTR_SKIP );
78+ }
79+ unset($ variables );
80+ ob_start ();
81+ include $ __componentFile ;
82+ $ content = ob_get_clean ();
83+ return $ content ;
84+ } else {
85+ throw new \Exception ('Component file cannot be found ( ' . $ file . ') ' );
86+ }
87+ };
88+
89+ $ getComponentResultHTML = function ($ component ) use (&$ getComponentFileContent , $ options ) {
90+ if (isset ($ component ->attributes ['src ' ])) {
91+ // todo check alias of alias
92+ $ srcAttributeValue = $ component ->attributes ['src ' ];
93+ if (isset ($ this ->aliases [$ srcAttributeValue ])) {
94+ $ sourceParts = explode (': ' , $ this ->aliases [$ srcAttributeValue ], 2 );
95+ } else {
96+ $ sourceParts = explode (': ' , $ srcAttributeValue , 2 );
97+ }
98+ if (sizeof ($ sourceParts ) === 2 ) {
99+ $ scheme = $ sourceParts [0 ];
100+ if (isset ($ options ['recursive ' ]) && $ options ['recursive ' ] === false ) {
101+ $ componentOptions = array_merge ($ options , ['_internal_process_components ' => false ]);
82102 }
83- if (sizeof ($ sourceParts ) === 2 ) {
84- $ scheme = $ sourceParts [0 ];
85- if (isset ($ options ['recursive ' ]) && $ options ['recursive ' ] === false && ($ scheme === 'data ' || $ scheme === 'file ' )) {
86- $ componentOptions = array_values ($ options );
87- $ componentOptions ['_internal_process_components ' ] = false ;
103+ if ($ scheme === 'data ' ) {
104+ if (substr ($ sourceParts [1 ], 0 , 7 ) === 'base64, ' ) {
105+ return $ this ->process (base64_decode (substr ($ sourceParts [1 ], 7 )), isset ($ componentOptions ) ? $ componentOptions : $ options );
88106 }
89- if ($ scheme === 'data ' ) {
90- $ componentHTML = $ this ->processData ($ sourceParts [1 ], isset ($ componentOptions ) ? $ componentOptions : $ options );
91- } elseif ($ scheme === 'file ' ) {
92- $ componentHTML = $ this ->processFile (urldecode ($ sourceParts [1 ]), $ attributes , $ component ->innerHTML , [], isset ($ componentOptions ) ? $ componentOptions : $ options );
93- } else {
94- throw new \Exception ('URI scheme not valid! ' . $ domDocument ->saveHTML ($ component ));
95- }
96- } else {
97- throw new \Exception ('URI scheme not found! ' . $ domDocument ->saveHTML ($ component ));
107+ throw new \Exception ('Data URI scheme only supports base64! ' . (string ) $ component );
108+ } elseif ($ scheme === 'file ' ) {
109+ return $ this ->process ($ getComponentFileContent (urldecode ($ sourceParts [1 ]), $ component , isset ($ options ['variables ' ]) && is_array ($ options ['variables ' ]) ? $ options ['variables ' ] : []), isset ($ componentOptions ) ? $ componentOptions : $ options );
98110 }
99- } else {
100- throw new \Exception ('Component src attribute missing! ' . $ domDocument ->saveHTML ($ component ));
111+ throw new \Exception ('URI scheme not valid! ' . (string ) $ component );
101112 }
113+ throw new \Exception ('URI scheme not found! ' . (string ) $ component );
114+ }
115+ throw new \Exception ('Component src attribute missing! ' . (string ) $ component );
116+ };
102117
103- $ isInBodyTag = false ;
104- $ parentNode = $ component ->parentNode ;
105- while ($ parentNode !== null && isset ($ parentNode ->tagName )) {
106- if ($ parentNode ->tagName === 'body ' ) {
107- $ isInBodyTag = true ;
108- break ;
118+ $ domDocument = new \IvoPetkov \HTML5DOMDocument ();
119+ if ($ content instanceof \IvoPetkov \HTMLServerComponent) {
120+ $ domDocument ->loadHTML ($ getComponentResultHTML ($ content ));
121+ } else {
122+ $ domDocument ->loadHTML ($ content );
123+ $ componentElements = $ domDocument ->getElementsByTagName ('component ' );
124+ $ componentElementsCount = $ componentElements ->length ;
125+ if ($ componentElementsCount > 0 ) {
126+ for ($ i = 0 ; $ i < $ componentElementsCount ; $ i ++) {
127+ $ componentElement = $ componentElements ->item (0 );
128+ $ component = $ this ->constructComponent ($ componentElement ->getAttributes (), $ componentElement ->innerHTML );
129+ $ componentResultHTML = $ getComponentResultHTML ($ component );
130+
131+ $ isInBodyTag = false ;
132+ $ parentNode = $ componentElement ->parentNode ;
133+ while ($ parentNode !== null && isset ($ parentNode ->tagName )) {
134+ if ($ parentNode ->tagName === 'body ' ) {
135+ $ isInBodyTag = true ;
136+ break ;
137+ }
138+ $ parentNode = $ parentNode ->parentNode ;
139+ }
140+ if ($ isInBodyTag ) {
141+ $ insertTargetName = 'html-server-components-compiler-target- ' . uniqid ();
142+ $ componentElement ->parentNode ->insertBefore ($ domDocument ->createInsertTarget ($ insertTargetName ), $ componentElement );
143+ $ domDocument ->insertHTML ($ componentResultHTML , $ insertTargetName );
144+ } else {
145+ $ domDocument ->insertHTML ($ componentResultHTML );
109146 }
110- $ parentNode = $ parentNode ->parentNode ;
111- }
112- if ($ isInBodyTag ) {
113- $ insertTargetName = 'html-server-components-compiler-target- ' . uniqid ();
114- $ component ->parentNode ->insertBefore ($ domDocument ->createInsertTarget ($ insertTargetName ), $ component );
115- $ domDocument ->insertHTML ($ componentHTML , $ insertTargetName );
116- } else {
117- $ domDocument ->insertHTML ($ componentHTML );
118- }
119147
120- $ component ->parentNode ->removeChild ($ component );
148+ $ componentElement ->parentNode ->removeChild ($ componentElement );
149+ }
121150 }
122151 }
123152
124153 return $ domDocument ->saveHTML ();
125154 }
126155
127- /**
128- * Creates a component from the data specified and processes the content
129- *
130- * @param string $data The data to be used as component content. Currently only base64 encoded data is allowed.
131- * @param array $options Compiler options
132- * @return string The result HTML code
133- * @throws \InvalidArgumentException
134- */
135- public function processData ($ data , $ options = [])
136- {
137- if (!is_string ($ data )) {
138- throw new \InvalidArgumentException ('' );
139- }
140- if (!is_array ($ options )) {
141- throw new \InvalidArgumentException ('' );
142- }
143- $ content = $ data ;
144- if (substr ($ data , 0 , 7 ) === 'base64, ' ) {
145- $ content = base64_decode (substr ($ data , 7 ));
146- }
147- return $ this ->process ($ content , $ options );
148- }
149-
150- /**
151- * Creates a component from the file specified and processes the content
152- *
153- * @param string $file The file to be run as component
154- * @param array $attributes Component object attributes
155- * @param string $innerHTML Component object innerHTML
156- * @param array $variables List of variables that will be passes to the file. They will be available in the file scope.
157- * @param array $options Compiler options
158- * @return string The result HTML code
159- * @throws \InvalidArgumentException
160- */
161- public function processFile ($ file , $ attributes = [], $ innerHTML = '' , $ variables = [], $ options = [])
162- {
163- if (!is_string ($ file )) {
164- throw new \InvalidArgumentException ('' );
165- }
166- if (!is_array ($ attributes )) {
167- throw new \InvalidArgumentException ('' );
168- }
169- if (!is_string ($ innerHTML )) {
170- throw new \InvalidArgumentException ('' );
171- }
172- if (!is_array ($ variables )) {
173- throw new \InvalidArgumentException ('' );
174- }
175- if (!is_array ($ options )) {
176- throw new \InvalidArgumentException ('' );
177- }
178- $ component = $ this ->constructComponent ($ attributes , $ innerHTML );
179- return $ this ->process ($ this ->getComponentFileContent ($ file , array_merge ($ variables , ['component ' => $ component ])), $ options );
180- }
181-
182156 /**
183157 * Constructs a component object
184158 *
@@ -187,7 +161,7 @@ public function processFile($file, $attributes = [], $innerHTML = '', $variables
187161 * @return \IvoPetkov\HTMLServerComponent A component object
188162 * @throws \InvalidArgumentException
189163 */
190- protected function constructComponent ($ attributes = [], $ innerHTML = '' )
164+ public function constructComponent ($ attributes = [], $ innerHTML = '' )
191165 {
192166 if (!is_array ($ attributes )) {
193167 throw new \InvalidArgumentException ('' );
@@ -201,36 +175,4 @@ protected function constructComponent($attributes = [], $innerHTML = '')
201175 return $ component ;
202176 }
203177
204- /**
205- * Includes a component file and returns its content
206- *
207- * @param string $file The filename
208- * @param array $variables List of variables that will be passes to the file. They will be available in the file scope.
209- * @return string The content of the file
210- * @throws \InvalidArgumentException
211- * @throws \Exception
212- */
213- protected function getComponentFileContent ($ file , $ variables )
214- {
215- if (!is_string ($ file )) {
216- throw new \InvalidArgumentException ('' );
217- }
218- if (!is_array ($ variables )) {
219- throw new \InvalidArgumentException ('' );
220- }
221- if (is_file ($ file )) {
222- $ __componentFile = $ file ;
223- unset($ file );
224- if (!empty ($ variables )) {
225- extract ($ variables , EXTR_SKIP );
226- }
227- ob_start ();
228- include $ __componentFile ;
229- $ content = ob_get_clean ();
230- return $ content ;
231- } else {
232- throw new \Exception ('Component file cannot be found ( ' . $ file . ') ' );
233- }
234- }
235-
236178}
0 commit comments