/
www
/
wwwroot
/
alo88.autos
/
wp-content
/
plugins
/
wp-content-crawler
/
app
/
Objects
/
Filtering
/
Upload File
HOME
<?php /** * Created by PhpStorm. * User: turgutsaricam * Date: 24/03/2020 * Time: 21:49 * * @since 1.11.0 */ namespace WPCCrawler\Objects\Filtering; use Illuminate\Support\Arr; use WPCCrawler\Environment; use WPCCrawler\Objects\Crawling\Data\CategoryData; use WPCCrawler\Objects\Crawling\Data\PostData; use WPCCrawler\Objects\Events\Base\AbstractCrawlingEvent; use WPCCrawler\Objects\Events\EventService; use WPCCrawler\Objects\Filtering\Commands\CommandService; use WPCCrawler\Objects\Filtering\Commands\Views\ViewDefinition; use WPCCrawler\Objects\Filtering\Commands\Views\ViewDefinitionList; use WPCCrawler\Objects\Filtering\Enums\CommandType; use WPCCrawler\Objects\Filtering\Interfaces\HasTestViewDefinitions; use WPCCrawler\Objects\Filtering\Interfaces\HasViewDefinitions; use WPCCrawler\Objects\Filtering\Objects\FieldConfig; use WPCCrawler\Objects\Filtering\Property\PropertyService; use WPCCrawler\Objects\Settings\SettingsImpl; use WPCCrawler\Objects\Transformation\Interfaces\Transformable; use WPCCrawler\Objects\Transformation\Objects\TransformableField; use WPCCrawler\Objects\Transformation\Objects\TransformableFieldList; use WPCCrawler\Objects\Views\TestResultContainer; use WPCCrawler\Objects\Views\ViewService; use WPCCrawler\PostDetail\PostDetailsService; class FilteringService { const AJAX_CMD_VIEW_DEFINITIONS = 'viewDefinitions'; /** @var SettingsImpl */ private $settings; /** * @var null|array Key-value pairs where keys are view keys and the values are JS templates of the views. This is * used to collect the view definitions from all items that {@link HasViewDefinitions} */ private $viewTemplates = null; /** * @var null|array Array of arrays. Each inner array has these: * string 'identifier' Identifier of the subject group, such as 'post' or 'woocommerce' * string 'name' Human-readable name of the subject group, such as 'Post' or 'WooCommerce' * array 'subjects' Array of arrays. Each inner array has these: * string 'title' Title of the subject, such as 'Post URL' or 'Product Attribute Values' * string 'key' Dot key of this subject, i.e. transformable field * array 'dataTypes' An array of integers each corresponding to a data type * array 'fieldConfigs' Array representations of the field configs * array 'filterViews' Array representation of view definition list */ private $subjectGroupsArray = null; /** * @var null|array Key-value pairs where keys are dot keys of the subjects (with identifiers) and the values are the * titles of the subjects. */ private $subjectTitleMap = null; /** * @param SettingsImpl $settings Site settings for which the filtering service is needed. * @since 1.11.0 */ public function __construct(SettingsImpl $settings) { $this->settings = $settings; } /** * Handle an AJAX request * * @param array $data Request data * @return array The result * @since 1.11.0 */ public function handleAjax($data): array { if (!is_array($data)) return []; $cmd = Arr::get($data, 'filteringCmd'); if ($cmd === static::AJAX_CMD_VIEW_DEFINITIONS) { return $this->getDefinitionsAsArray(); } return []; } /** * Get all of the values required to implement the filtering in the front-end * * @return array Definitions of subjects, properties, commands, and views as array. The main contains 'subjects', * 'properties', 'commands', and 'viewTemplates' keys * @since 1.11.0 */ public function getDefinitionsAsArray(): array { $this->viewTemplates = []; // Add the views of commands and properties $this->addViewTemplatesFromItems(array_values($this->propertyService()->getRegistry())); $this->addViewTemplatesFromItems(array_values($this->commandService()->getRegistry())); $this->addViewDefinitionList($this->createCustomViews()); $result = [ 'properties' => $this->propertyService()->getPropertiesAsArray(), 'subjectGroups' => $this->getSubjectGroupsAsArray(), 'events' => $this->getEventsAsArray(), 'commands' => $this->commandService()->getCommandsAsArray(), 'viewTemplates' => $this->viewTemplates, ]; $this->viewTemplates = null; return $result; } /** * @return array See {@link subjectGroupsArray} * @since 1.11.0 */ public function getSubjectGroupsAsArray(): array { if ($this->subjectGroupsArray === null) { $this->subjectGroupsArray = $this->createSubjectGroupsArray(); } return $this->subjectGroupsArray; } /** * @return array See {@link subjectTitleMap} * @since 1.11.0 */ public function getSubjectTitleMap(): array { if ($this->subjectTitleMap === null) { $this->subjectTitleMap = $this->createSubjectTitleMap(); } return $this->subjectTitleMap; } /** * @return SettingsImpl * @since 1.11.0 */ public function getSettings(): SettingsImpl { return $this->settings; } /** * Get the command service * * @return CommandService * @since 1.11.0 */ public function commandService(): CommandService { return CommandService::getInstance(); } /** * Get the property service * * @return PropertyService * @since 1.11.0 */ public function propertyService(): PropertyService { return PropertyService::getInstance(); } /* * */ /** * Calls {@link addViewDefinitionList()} for each view definition list in the given array * * @param HasViewDefinitions[]|HasTestViewDefinitions[] $itemsWithViews * @since 1.11.0 */ private function addViewTemplatesFromItems(?array $itemsWithViews): void { if (!$itemsWithViews) return; foreach($itemsWithViews as $itemWithView) { if (is_a($itemWithView, HasViewDefinitions::class)) { $this->addViewDefinitionList($itemWithView->getViewDefinitions()); } if (is_a($itemWithView, HasTestViewDefinitions::class)) { $this->addViewDefinitionList($itemWithView->getTestViewDefinitions()); } } } /** * Add the templates of the view definitions into {@link viewTemplates} * * @param ViewDefinitionList|null $viewList * @since 1.11.0 */ private function addViewDefinitionList(?ViewDefinitionList $viewList): void { if (!$viewList) return; $viewService = ViewService::getInstance(); foreach($viewList->getItems() as $item) { $viewInstance = $viewService->getViewInstance($item->getViewClass()); if ($viewInstance === null) continue; $viewKey = $viewInstance->getKey(); // If the template already exists, continue with the next one. if (isset($this->viewTemplates[$viewKey])) continue; $this->viewTemplates[$viewKey] = $viewInstance->renderAsJsTemplate($this->getSettings()); } } /** * @return array Creates an array structured the same as {@link subjectGroupsArray} * @since 1.11.0 */ private function createSubjectGroupsArray(): array { // Add the view templates of the special fields $specialFields = SpecialFieldService::getInstance()->getSpecialFields(); $this->addViewTemplatesFromItems($specialFields->getItems()); $result = [ // Create the transformable fields for category data $this->createTransformableFieldGroup( Environment::defaultCategoryIdentifier(), _wpcc('Category'), $this->getCommandFields(new CategoryData()) ), // Create special transformable fields $this->createTransformableFieldGroup( SpecialFieldService::SPECIAL_FIELD_IDENTIFIER, _wpcc('Special'), $specialFields->toArray() ), // Create the transformable fields for a default WordPress post $this->createTransformableFieldGroup( Environment::defaultPostIdentifier(), _wpcc('Post'), $this->getCommandFields(new PostData()) ), ]; // Create registered post details' transformable fields $factories = PostDetailsService::getInstance()->getTransformableFactories($this->getSettings()); foreach($factories as $factory) { /** @var Transformable $data */ $data = $factory->getDetailData(); $result[] = $this->createTransformableFieldGroup( $factory->getIdentifier(), $factory->getName(), $this->getCommandFields($data) ); } return $result; } /** * @param string $identifier Identifier of the group * @param string $name Human-readable name of the group * @param array $subjects An array of the array versions of a {@link Transformable}'s fields. See * {@link getCommandFields()}. * @return array An array that can be sent to the front-end * @since 1.11.0 */ private function createTransformableFieldGroup(string $identifier, string $name, array $subjects): array { return [ 'identifier' => $identifier, 'name' => $name, 'subjects' => $subjects ]; } /** * Get the array versions of {@link TransformableField}s that can be used by the commands * * @param Transformable $data * @return array * @since 1.11.0 */ private function getCommandFields(Transformable $data): array { $transformableFields = $data->getInteractableFields(); $actionCommandFields = $data->getActionCommandFields(); $conditionCommandFields = $data->getConditionCommandFields(); $fields = $transformableFields->toArray(); $this->addCommandFields($fields, $actionCommandFields, CommandType::ACTION); $this->addCommandFields($fields, $conditionCommandFields, CommandType::CONDITION); // Add the view templates of the fields $this->addViewTemplatesFromItems($transformableFields->getItems()); if($actionCommandFields) $this->addViewTemplatesFromItems($actionCommandFields->getItems()); if($conditionCommandFields) $this->addViewTemplatesFromItems($conditionCommandFields->getItems()); return $fields; } /** * Prepare command fields and add them into an array * * @param array $fields An array in which the array versions of * {@link TransformableField}s will be added * @param TransformableFieldList|null $fieldList A list of fields that will be prepared and added to the given * fields array * @param string|string[] $commandTypes The command types for the fields in the given list. These types * will assigned to the fields in the given list * @since 1.11.0 */ private function addCommandFields(array &$fields, ?TransformableFieldList $fieldList, $commandTypes): void { if ($fieldList === null) return; if (!is_array($commandTypes)) $commandTypes = [$commandTypes]; $items = $fieldList->getItems(); array_walk($items, function($item) use (&$commandTypes) { /** @var TransformableField $item */ // If there is no field config, assign a new field config with the given command types and null event group $fieldConfigs = $item->getFieldConfigs(); if ($fieldConfigs === null) { $item->addFieldConfig(new FieldConfig(null, $commandTypes)); } else { // Otherwise, modify each field config so that they only have the given command types foreach($fieldConfigs as $fieldConfig) $fieldConfig->setCommandTypes($commandTypes); } }); $fields = array_merge($fields, $fieldList->toArray()); } /** * @return array Array representations of the events supported by the filters * @since 1.11.0 */ private function getEventsAsArray(): array { $events = EventService::getInstance()->getAllEvents(AbstractCrawlingEvent::class); return array_map(function($event) { /** @var AbstractCrawlingEvent $event */ return $event->toArray(); }, $events); } /** * Get custom views that are needed in the UI. These views are the views whose definitions exist in the backend and * that are needed in the frontend. By sending these views from backend, we keep the code DRY. * * @return ViewDefinitionList A list that contains custom views that are needed for special purposes * @since 1.11.0 */ private function createCustomViews(): ViewDefinitionList { return (new ViewDefinitionList()) ->add(new ViewDefinition(TestResultContainer::class)); } /** * @return array Creates an array structured as {@link subjectTitleMap} * @since 1.11.0 */ private function createSubjectTitleMap(): array { $result = []; foreach($this->getSubjectGroupsAsArray() as $subjectGroup) { $identifier = $subjectGroup['identifier']; foreach($subjectGroup['subjects'] as $subject) { $result["$identifier.{$subject['key']}"] = $subject['title']; } } return $result; } }