@@ -29,14 +29,9 @@ class LiveCodeTest extends TestCase
2929 private static $ changeCheckDir = '' ;
3030
3131 /**
32- * @var array
32+ * @var mixed
3333 */
34- private static $ uiDataComponentInterface = [
35- 'Magento\Framework\App\ActionInterface ' ,
36- 'Magento\Framework\View\Element\BlockInterface ' ,
37- 'Magento\Framework\View\Element\UiComponentInterface ' ,
38- 'Magento\Framework\View\Element\UiComponent\DataProvider\DataProviderInterface ' ,
39- ];
34+ private static mixed $ frontendUIComponent ;
4035
4136 /**
4237 * Setup basics for all tests
@@ -116,7 +111,7 @@ private static function getModulesRequiringGraphQLChange(): array
116111 continue ;
117112 }
118113
119- if (!in_array ($ moduleName , $ requireGraphQLChanges ) && self ::isViewLayerClass ($ whitelistFile )) {
114+ if (!in_array ($ moduleName , $ requireGraphQLChanges ) && self ::isViewLayerClass ($ whitelistFile, $ moduleName )) {
120115 $ requireGraphQLChanges [] = $ moduleName . "GraphQl " ;
121116 }
122117 }
@@ -138,20 +133,20 @@ private static function getModuleName(string $filePath): string
138133 }
139134
140135 /**
141- * Return true if the class implements any of the defined interfaces
136+ * Return true if the class is a data provider for the frontend
142137 *
143138 * @param string $filePath
139+ * @param string $moduleName
144140 * @return bool
145141 */
146- private static function isViewLayerClass (string $ filePath ): bool
142+ private static function isViewLayerClass (string $ filePath, string $ moduleName ): bool
147143 {
148144 $ className = self ::getClassNameWithNamespace ($ filePath );
149- if (!$ className || str_contains (strtolower ($ className ), 'adminhtml ' )) {
150- return false ;
145+ $ adminChange = str_contains (strtolower ($ className ), 'adminhtml ' );
146+ if ($ className && !$ adminChange && self ::isFrontendUIComponent ($ moduleName , $ className )) {
147+ return true ;
151148 }
152-
153- $ implementingInterfaces = array_values (class_implements ($ className ));
154- return !empty (array_intersect ($ implementingInterfaces , self ::$ uiDataComponentInterface ));
149+ return false ;
155150 }
156151
157152 /**
@@ -168,4 +163,50 @@ private static function getClassNameWithNamespace(string $filePath): string
168163 }
169164 return '' ;
170165 }
166+
167+ /**
168+ * Check if the class is a frontend data provider
169+ *
170+ * @param string $moduleName
171+ * @param string $className
172+ * @return bool
173+ */
174+ private static function isFrontendUIComponent (string $ moduleName , string $ className ): bool
175+ {
176+ if (!isset (self ::$ frontendUIComponent [$ moduleName ])) {
177+ $ files = glob (BP . '/app/code/Magento/ ' .$ moduleName .'/view/frontend/*/*.xml ' );
178+
179+ if (is_array ($ files )) {
180+ $ uIComponentClasses = [];
181+
182+ foreach ($ files as $ filename ) {
183+ $ uIComponentClasses [] = simplexml_load_file ($ filename )->xpath ('//@class ' );
184+ }
185+ self ::$ frontendUIComponent [$ moduleName ] = self ::filterUiComponents (
186+ array_unique (array_merge ([], ...$ uIComponentClasses )),
187+ $ moduleName
188+ );
189+ }
190+ }
191+ return in_array ($ className , self ::$ frontendUIComponent [$ moduleName ]);
192+ }
193+
194+ /**
195+ * Filter the array of classes to return only the classes in this module
196+ *
197+ * @param array $uIComponentClasses
198+ * @param string $moduleName
199+ * @return array
200+ */
201+ private static function filterUiComponents (array $ uIComponentClasses , string $ moduleName ): array
202+ {
203+ $ frontendUIComponent = [];
204+ foreach ($ uIComponentClasses as $ dataProvider ) {
205+ $ dataProviderClass = ltrim ((string )$ dataProvider ->class , '\\' );
206+ if (str_starts_with ($ dataProviderClass , 'Magento \\' . $ moduleName )) {
207+ $ frontendUIComponent [] = $ dataProviderClass ;
208+ }
209+ }
210+ return $ frontendUIComponent ;
211+ }
171212}
0 commit comments