← All changes
|
modules/global-classes/usage/applied-global-classes-usage.php
+57
-88
4.1.0-dev2
→
3.30.1
View file →
| @@ -1,9 +1,14 @@ | ||
| 1 | 1 | <?php |
| 2 | 2 | |
| 3 | -namespace Elementor\Modules\GlobalClasses\Usage; | |
| 3 | +namespace Elementor\Modules\Global_Classes\Usage; | |
| 4 | 4 | |
| 5 | +use Elementor\Core\Base\Document; | |
| 6 | +use Elementor\Core\Utils\Collection; | |
| 7 | +use Elementor\Modules\AtomicWidgets\Elements\Atomic_Element_Base; | |
| 8 | +use Elementor\Modules\AtomicWidgets\Elements\Atomic_Widget_Base; | |
| 5 | 9 | use Elementor\Modules\GlobalClasses\Global_Classes_Repository; |
| 10 | +use Elementor\Modules\GlobalClasses\Utils\Atomic_Elements_Utils; | |
| 6 | 11 | use Elementor\Plugin; |
| 7 | 12 | |
| 8 | 13 | if ( ! defined( 'ABSPATH' ) ) { |
| 9 | 14 | exit; // Exit if accessed directly. |
| @@ -8,116 +13,80 @@ | ||
| 8 | 13 | if ( ! defined( 'ABSPATH' ) ) { |
| 9 | 14 | exit; // Exit if accessed directly. |
| 10 | 15 | } |
| 11 | 16 | |
| 12 | -/** | |
| 13 | - * Collects and exposes usage data for all global CSS classes across Elementor documents. | |
| 14 | - */ | |
| 15 | 17 | class Applied_Global_Classes_Usage { |
| 16 | - | |
| 17 | 18 | /** |
| 18 | - * Document types that should be excluded from usage reporting. | |
| 19 | + * Get data about how global classes are applied across Elementor elements. | |
| 19 | 20 | * |
| 20 | - * @var string[] | |
| 21 | + * @return array<string, int> Statistics about applied global classes per global class | |
| 21 | 22 | */ |
| 22 | - private array $excluded_types = [ 'e-flexbox', 'template' ]; | |
| 23 | + public function get() { | |
| 24 | + $total_count_per_class_id = []; | |
| 25 | + $global_class_ids = Global_Classes_Repository::make()->all()->get_items()->keys()->all(); | |
| 23 | 26 | |
| 24 | - /** | |
| 25 | - * Tracks usage for each global class. | |
| 26 | - * | |
| 27 | - * @var array<string, Css_Class_Usage> | |
| 28 | - */ | |
| 29 | - private array $class_usages = []; | |
| 27 | + if ( empty( $global_class_ids ) ) { | |
| 28 | + return []; | |
| 29 | + } | |
| 30 | 30 | |
| 31 | - /** | |
| 32 | - * Returns the total usage count per class ID (excluding template-only classes). | |
| 33 | - * | |
| 34 | - * @return array<string, int> | |
| 35 | - */ | |
| 36 | - public function get(): array { | |
| 37 | - $this->build_class_usages(); | |
| 31 | + Plugin::$instance->db->iterate_elementor_documents( function( $document, $elements_data ) use ( &$total_count_per_class_id, $global_class_ids ) { | |
| 32 | + $count_per_global_class = $this->get_classes_count_per_class( $elements_data, $global_class_ids ); | |
| 38 | 33 | |
| 39 | - $result = []; | |
| 40 | - foreach ( $this->class_usages as $class_id => $usage ) { | |
| 41 | - if ( $usage->get_total_usage() > 0 ) { | |
| 42 | - $result[ $class_id ] = $usage->get_total_usage(); | |
| 43 | - } | |
| 34 | + $total_count_per_class_id = Collection::make( $count_per_global_class )->reduce( function( $carry, $count, $class_id ) { | |
| 35 | + $carry[ $class_id ] ??= 0; | |
| 36 | + $carry[ $class_id ] += $count; | |
| 37 | + | |
| 38 | + return $carry; | |
| 39 | + }, $total_count_per_class_id ); | |
| 40 | + }); | |
| 41 | + | |
| 42 | + foreach ( $global_class_ids as $global_class_id ) { | |
| 43 | + $total_count_per_class_id[ $global_class_id ] ??= 0; | |
| 44 | 44 | } |
| 45 | 45 | |
| 46 | - return $result; | |
| 46 | + return $total_count_per_class_id; | |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | - /** | |
| 50 | - * Returns detailed usage information per class ID. | |
| 51 | - * Each class ID maps to a list of document usages (excluding excluded types). | |
| 52 | - * | |
| 53 | - * @return array<string, array{ | |
| 54 | - * pageId: int, | |
| 55 | - * title: string, | |
| 56 | - * type: string, | |
| 57 | - * total: int, | |
| 58 | - * elements: string[] | |
| 59 | - * }> | |
| 60 | - */ | |
| 61 | - public function get_detailed_usage(): array { | |
| 62 | - $this->build_class_usages(); | |
| 49 | + private function get_classes_count_per_class( $elements_data, $global_class_ids ) { | |
| 50 | + $count_per_class = []; | |
| 63 | 51 | |
| 64 | - $result = []; | |
| 52 | + Plugin::$instance->db->iterate_data( $elements_data, function( $element_data ) use ( $global_class_ids, &$count_per_class ) { | |
| 53 | + $element_type = Atomic_Elements_Utils::get_element_type( $element_data ); | |
| 54 | + $element_instance = Atomic_Elements_Utils::get_element_instance( $element_type ); | |
| 65 | 55 | |
| 66 | - foreach ( $this->class_usages as $class_id => $usage ) { | |
| 67 | - $pages = $usage->get_pages(); | |
| 56 | + if ( ! Atomic_Elements_Utils::is_atomic_element( $element_instance ) ) { | |
| 57 | + return; | |
| 58 | + } | |
| 68 | 59 | |
| 69 | - $filtered_pages = array_filter( | |
| 70 | - $pages, | |
| 71 | - fn( $page_data ) => ! in_array( $page_data['type'], $this->excluded_types, true ) | |
| 72 | - ); | |
| 60 | + /** @var Atomic_Element_Base | Atomic_Widget_Base $element_instance */ | |
| 61 | + $applied_classes_per_element = $this->get_applied_global_classes_per_element( $element_instance->get_props_schema(), $element_data, $global_class_ids ); | |
| 73 | 62 | |
| 74 | - if ( empty( $filtered_pages ) ) { | |
| 75 | - continue; | |
| 63 | + foreach ( $applied_classes_per_element as $global_class_id => $count ) { | |
| 64 | + $count_per_class[ $global_class_id ] ??= 0; | |
| 65 | + $count_per_class[ $global_class_id ] += $count; | |
| 76 | 66 | } |
| 67 | + }); | |
| 77 | 68 | |
| 78 | - foreach ( $filtered_pages as $page_id => $page_data ) { | |
| 79 | - $result[ $class_id ][] = [ | |
| 80 | - 'pageId' => $page_id, | |
| 81 | - 'title' => $page_data['title'], | |
| 82 | - 'type' => $page_data['type'], | |
| 83 | - 'total' => $page_data['total'], | |
| 84 | - 'elements' => $page_data['elements'], | |
| 85 | - ]; | |
| 86 | - } | |
| 87 | - } | |
| 88 | - | |
| 89 | - return $result; | |
| 69 | + return $count_per_class; | |
| 90 | 70 | } |
| 91 | 71 | |
| 92 | - /** | |
| 93 | - * Builds the internal usage map from all Elementor documents. | |
| 94 | - * | |
| 95 | - * This method initializes and aggregates class usage from all relevant documents, | |
| 96 | - * merging duplicate class IDs found in multiple pages. | |
| 97 | - */ | |
| 98 | - private function build_class_usages(): void { | |
| 99 | - $this->class_usages = []; | |
| 72 | + private function get_applied_global_classes_per_element( $atomic_props_schema, $atomic_element_data, $global_class_ids ) { | |
| 73 | + return Collection::make( $atomic_props_schema )->reduce( function( $carry, $prop_value, $prop_name ) use ( $atomic_element_data, $global_class_ids ) { | |
| 74 | + if ( ! Atomic_Elements_Utils::is_classes_prop( $prop_value ) ) { | |
| 75 | + return $carry; | |
| 76 | + } | |
| 100 | 77 | |
| 101 | - $class_ids = array_keys( Global_Classes_Repository::make()->all_labels() ); | |
| 102 | - $class_id_set = array_fill_keys( $class_ids, true ); | |
| 78 | + $prop_applied_global_class_ids = $this->get_applied_global_classes( $atomic_element_data['settings'][ $prop_name ]['value'] ?? [], $global_class_ids ); | |
| 103 | 79 | |
| 104 | - Plugin::$instance->db->iterate_elementor_documents( | |
| 105 | - function ( $document ) use ( $class_id_set ) { | |
| 106 | - $usage = new Document_Usage( $document, $class_id_set ); | |
| 107 | - $usage->analyze(); | |
| 80 | + foreach ( $prop_applied_global_class_ids as $global_class_id ) { | |
| 81 | + $carry[ $global_class_id ] ??= 0; | |
| 82 | + $carry[ $global_class_id ] += 1; | |
| 83 | + } | |
| 108 | 84 | |
| 109 | - foreach ( $usage->get_usages() as $class_id => $class_usage ) { | |
| 110 | - if ( ! isset( $class_id_set[ $class_id ] ) ) { | |
| 111 | - continue; | |
| 112 | - } | |
| 85 | + return $carry; | |
| 86 | + }, [] ); | |
| 87 | + } | |
| 113 | 88 | |
| 114 | - if ( ! isset( $this->class_usages[ $class_id ] ) ) { | |
| 115 | - $this->class_usages[ $class_id ] = $class_usage; | |
| 116 | - } else { | |
| 117 | - $this->class_usages[ $class_id ]->merge( $class_usage ); | |
| 118 | - } | |
| 119 | - } | |
| 120 | - } | |
| 121 | - ); | |
| 89 | + private function get_applied_global_classes( $prop, $global_class_ids ) { | |
| 90 | + return array_intersect( $prop, $global_class_ids ); | |
| 122 | 91 | } |
| 123 | 92 | } |