diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b470dd..2c514d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,24 @@ # (MODX)EvolutionCMS.libraries.ddTools changelog +## Version 0.64 (2024-09-06) + +* \+ `\DDTools\Tools\Objects::extend` → Parameters → `$params->extendableProperties`: The new optional parameter. Allows to use for extending not all properties from additional objects or arrays (see README → Examples). +* \+ `\DDTools\Storage\Storage` → `items_update`, `items_updateOne`, `items_delete`, `items_deleteOne`, `items_get`, `items_getOne` → Parameters: + * \+ `$params->where` → Valid values → `null`: The new supported value. It is equal to ''. + * \+ `$params->where->{$propName}`: + * \+ You can also specify multiple value variants through an array. + * \+ You don't have to worry about passing empty arrays, they will just be ignored. +* \+ `\DDTools\Tools\Cache`: + * \+ There are now 2 levels of caching: stable (file-based) and quick (`$_SESSION`-based). All methods now utilize both levels automatically. + * \+ `getSeveral`: The new public static method. Retrieves data of several items from cache storage (see README). + * \+ `saveSeveral`: The new public static method. Saves data of several items to cache storage (see README). + * \+ `save`, `saveSeveral`, `get`, `getSeveral`, `delete` → Parameters → `$params->resourceId` → Valid values → `string`: The new supported value. You can use a custom string as the resource ID, not only an integer ID. + * \+ `getSeveral`, `delete` → Parameters → `$params->resourceId` → Valid values → `array`: The new supported value. You can specify multiple IDs. + * \+ `delete` → Parameters → `$params->resourceId` → Valid values → `'*'`: The new supported value. + * \+ `save` → Parameters → `$params->isExtendEnabled`: The new optional parameter. Allows to extend existing data (see README). + + ## Version 0.63 (2024-08-02) * \+ `\DDTools\Tools\Cache`: The new class. Allows you to cache some data (e. g. a snippet result) to a file in the `assets/cache/ddCache` folder (see README). diff --git a/CHANGELOG_ru.md b/CHANGELOG_ru.md index 3c9e449..389e435 100644 --- a/CHANGELOG_ru.md +++ b/CHANGELOG_ru.md @@ -1,6 +1,24 @@ # (MODX)EvolutionCMS.libraries.ddTools changelog +## Version 0.64 (2024-09-06) + +* \+ `\DDTools\Tools\Objects::extend` → Параметры → `$params->extendableProperties`: Новый необязательный параметр. Позволяет использовать для расширения не все свойства из дополнительных объектов или массивов (см. README → Примеры). +* \+ `\DDTools\Storage\Storage` → `items_update`, `items_updateOne`, `items_delete`, `items_deleteOne`, `items_get`, `items_getOne` → Параметры: + * \+ `$params->where` → Допустимые значения → `null`: Новое значение. Эквивалентно `''`. + * \+ `$params->where->{$propName}`: + * \+ Вы также можете указать несколько вариантов значений с помощью массива. + * \+ Вам не нужно беспокоиться о передаче пустых массивов, они будут просто проигнорированы. +* \+ `\DDTools\Tools\Cache`: + * \+ Теперь существует 2 уровня кэширования: постоянное (на основе файлов) и быстрое (на основе `$_SESSION`). Все методы используют оба уровня автоматически. + * \+ `getSeveral`: Новый публичный статичный метод. Получает из кеша данные о нескольких элементах (см. README). + * \+ `saveSeveral`: Новый публичный статичный метод. Сохраняет в кэш данные нескольких элементов (см. README). + * \+ `save`, `saveSeveral`, `get`, `getSeveral`, `delete` → Параметры → `$params->resourceId` → Допустимые значения → `string`: Новое значение. В качестве идентификатора ресурса можно использовать не только числовой идентификатор, но и произвольную строку. + * \+ `getSeveral`, `delete` → Параметры → `$params->resourceId` → Допустимые значения → `array`: Новое значение. Можно указать несколько ID. + * \+ `delete` → Параметры → `$params->resourceId` → Допустимые значения → `'*'`: Новое значение. + * \+ `save` → Параметры → `$params->isExtendEnabled`: Новый необязательный параметр. Позволяет дополнить уже существующие данные (см. README). + + ## Версия 0.63 (2024-08-02) * \+ `\DDTools\Tools\Cache`: Новый класс. Позволяет кэшировать какие-то данные (например, результаты сниппетов) в файл в папке `assets/cache/ddCache` (см. README). @@ -10,7 +28,7 @@ ## Версия 0.62.1 (2024-06-17) -* \* `\ddTools::parseText` → Parameters → `$params->isCompletelyParsingEnabled`: Неработающая поддержка устаревшего названия `$params->mergeAll` исправлена. +* \* `\ddTools::parseText` → Параметры → `$params->isCompletelyParsingEnabled`: Неработающая поддержка устаревшего названия `$params->mergeAll` исправлена. ## Версия 0.62 (2024-06-14) diff --git a/README.md b/README.md index 6975a6b..161c45f 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ The method tends to change URL as little as possible and just prepends required All kinds of query parameters, hash, ports, etc. are not modified. * `$params` - * Description: Parameters, the pass-by-name style is used. + * Description: The parameters object. * Valid values: * `stdClass` * `arrayAssociative` @@ -135,7 +135,7 @@ The same as `$modx->getTpl` with some differences: Replaces placeholders in a text with required values. * `$params` - * Description: Parameters, the pass-by-name style is used. + * Description: The parameters object. * Valid values: * `stdClass` * `arrayAssociative` @@ -205,7 +205,7 @@ It returns an associative array, in which the correct parameter names are the ke You can use the `exctract` function to turn the array into variables of the current symbol table. * `$params` - * Description: Parameters, the pass-by-name style is used. + * Description: The parameters object. * Valid values: * `stdClass` * `arrayAssociative` @@ -271,7 +271,7 @@ You can use the `exctract` function to turn the array into variables of the curr Modify your images: create thumbnails, crop, resize, fill background color or add watermark. * `$params` - * Description: Parameters, the pass-by-name style is used. + * Description: The parameters object. * Valid values: * `stdClass` * `arrayAssociative` @@ -350,7 +350,7 @@ The first reason for creating this method is convenience to not thinking about t Second, the different order of parameters in the native PHP functions makes us crazy. * `$params` - * Description: Parameters, the pass-by-name style is used. + * Description: The parameters object. * Valid values: * `stdClass` * `arrayAssociative` @@ -376,7 +376,7 @@ Second, the different order of parameters in the native PHP functions makes us c Get the value of an object property or an array element in any nesting level in one way regardless of the “object” type. * `$params` - * Description: Parameters, the pass-by-name style is used. + * Description: The parameters object. * Valid values: * `stdClass` * `arrayAssociative` @@ -422,7 +422,7 @@ Converts an object type. Arrays, [JSON](https://en.wikipedia.org/wiki/JSON) and [Query string](https://en.wikipedia.org/wiki/Query_string) objects are also supported. * `$params` - * Description: Parameters, the pass-by-name style is used. + * Description: The parameters object. * Valid values: * `stdClass` * `arrayAssociative` @@ -471,7 +471,7 @@ Arrays, [JSON](https://en.wikipedia.org/wiki/JSON) and [Query string](https://en Merge the contents of two or more objects or arrays together into the first one. * `$params` - * Description: Parameters, the pass-by-name style is used. + * Description: The parameters object. * Valid values: * `stdClass` * `arrayAssociative` @@ -511,6 +511,18 @@ Merge the contents of two or more objects or arrays together into the first one. * `NULL` * Valid values: `boolean` * Default value: `true` + +* `$params->extendableProperties` + * Description: An array of property names that can be extended from additional objects or arrays. Properties in the initial object or array are not restricted by this parameter. + * Valid values: + * `array` + * `null` or any empty value — all properties will be extended + * Default value: `null` + +* `$params->extendableProperties[$i]` + * Description: The name of a property that is allowed to be extended from additional objects or arrays. + * Valid values: `string` + * **Required** #### `\DDTools\Tools\Objects::unfold($params)` @@ -519,7 +531,7 @@ Converts a multidimensional array/object into an one-dimensional one joining the For example, it can be helpful while using placeholders like `[+size.width+]`. * `$params` - * Description: Parameters, the pass-by-name style is used. + * Description: The parameters object. * Valid values: * `stdClass` * `arrayAssociative` @@ -559,25 +571,38 @@ For example, it can be helpful while using placeholders like `[+size.width+]`. ### `\DDTools\Tools\Cache` -You can cache some data (e. g. a snippet result) to a file. +You can cache some data (e. g. a snippet result). +* There are 2 levels of caching: stable (file-based) and quick (`$_SESSION`-based). All methods utilize both levels automatically. +* The name of each cache item is `[+prefix+]-[+resourceId+]-[+suffix+]`. +* Each cache item can contain a `string`, `array` or `stdClass`. * All cache files are stored in the `assets/cache/ddCache` folder. -* The name of each cache file is `[+prefix+]-[+resourceId+]-[+suffix+].php`. -* Each cache file can contain a string, array or stdClass. +* The name of each cache file is `[+cacheName+].php`. +* Quick cache items are stored in `$_SESSION['ddCache']`. -#### `\DDTools\Tools\Cache::save($params)`, `\DDTools\Tools\Cache::get($params)` +#### `\DDTools\Tools\Cache::save($params)` + +Saves custom data to cache storage. * `$params` - * Description: The object of parameters. + * Description: The parameters object. * Valid values: * `stdClass` * `arrayAssociative` * **Required** +* `$params->data` + * Description: Data to save. + * Valid values: + * `string` + * `array` + * `stdClass` + * **Required** + * `$params->resourceId` * Description: Resource ID related to cache (e. g. document ID). - * Valid values: `integer` + * Valid values: `string` * **Required** * `$params->suffix` @@ -586,27 +611,83 @@ You can cache some data (e. g. a snippet result) to a file. * **Required** * `$params->prefix` - * Description: Cache file prefix. Useful if you want to cache some custom data that is not related to any documents. + * Description: Cache prefix. Useful if you want to cache some custom data that is not related to any documents. * Valid values: `string` * Default value: `'doc'` + +* `$params->isExtendEnabled` + * Description: Should existing data be extended by `$params->data` or overwritten? + * Valid values: `boolean` + * Default value: `false` -#### `\DDTools\Tools\Cache::save($params)` +#### `\DDTools\Tools\Cache::saveSeveral($params)` -Saves custom data to a cache file. +Saves data of several items to cache storage. -* `$params->data` - * Description: Data to save. +* `$params` + * Description: The parameters object. + * Valid values: + * `stdClass` + * `arrayAssociative` + * **Required** + +* `$params->items` + * Description: Items to save. + * Valid values: + * `stdClass` + * `arrayAssociative` + * **Required** + +* `$params->items->{$resourceId}` + * Description: Item data to save. Key is resource ID related to cache (e. g. document ID). * Valid values: * `string` * `array` * `stdClass` * **Required** + +* `$params->suffix` + * Description: Cache suffix. + * Valid values: `string` + * **Required** + +* `$params->prefix` + * Description: Cache prefix. + * Valid values: `string` + * Default value: `'doc'` + +* `$params->isExtendEnabled` + * Description: Should existing items data be extended by `$params->items` or overwritten? + * Valid values: `boolean` + * Default value: `false` #### `\DDTools\Tools\Cache::get($params)` -Retrieves data from a cache file. +Retrieves item data from cache storage. + +* `$params` + * Description: The parameters object. + * Valid values: + * `stdClass` + * `arrayAssociative` + * **Required** + +* `$params->resourceId` + * Description: Resource ID related to cache (e. g. document ID). + * Valid values: `string` + * **Required** + +* `$params->suffix` + * Description: Cache suffix. + * Valid values: `string` + * **Required** + +* `$params->prefix` + * Description: Cache prefix. + * Valid values: `string` + * Default value: `'doc'` ##### Returns @@ -618,29 +699,90 @@ Retrieves data from a cache file. * `string` * `array` * `stdClass` - * `null` — means that the cache file does not exist + * `null` — means that the cache item does not exist + + +#### `\DDTools\Tools\Cache::getSeveral($params)` + +Retrieves data of several items from cache storage. + + +* `$params` + * Description: The parameters object. + * Valid values: + * `stdClass` + * `arrayAssociative` + * **Required** + +* `$params->resourceId` + * Description: Resource ID(s) related to cache (e. g. document ID). + * Valid values: + * `string` + * `'*'` — means any ID + * `array` — you can specify multiple IDs + * **Required** + +* `$params->resourceId[$i]` + * Description: A resource ID. + * Valid values: `string` + * **Required** + +* `$params->suffix` + * Description: Cache suffix. + * Valid values: `string` + * **Required** + +* `$params->prefix` + * Description: Cache prefix. + * Valid values: `string` + * Default value: `'doc'` + + +##### Returns + +* `$result` + * Description: Cached items data. + * Valid values: + * `stdClass` + * `null` — means that the cache of specified items does not exist + +* `$result->{$resourceName}` + * Description: Cached item data. + * A key is an item's cache name (`[+prefix+]-[+resourceId+]-[+suffix+]`), a value is a data. + * Type of returned data depends on type of saved data. + * Valid values: + * `string` + * `array` + * `stdClass` #### `\DDTools\Tools\Cache::delete($params)` -Deletes one or more cache files. +Deletes one or more cache items. * `$params` - * Description: The object of parameters. + * Description: The parameters object. * Valid values: * `stdClass` * `arrayAssociative` * Default value: — * `$params->resourceId` - * Description: Resource ID related to cache (e. g. document ID). + * Description: Resource ID(s) related to cache (e. g. document ID). * Valid values: - * `integer` + * `string` + * `'*'` — means any ID + * `array` — you can specify multiple IDs * `null` — cache of all resources will be cleared independent of `$params->prefix` * Default value: `null` +* `$params->resourceId[$i]` + * Description: A resource ID. + * Valid values: `string` + * Default value: — + * `$params->prefix` - * Description: Cache file prefix. Useful if you want to cache some custom data that is not related to any documents. + * Description: Cache prefix. Useful if you want to cache some custom data that is not related to any documents. * Valid values: * `string` * `'*'` — means any prefix @@ -662,7 +804,7 @@ Class representing a collection of some objects or arrays. #### `\DDTools\ObjectCollection::__construct($params)` * `$params` - * Description: Parameters, the pass-by-name style is used. + * Description: The parameters object. * Valid values: * `stdClass` * `arrayAssociative` @@ -717,7 +859,7 @@ Has the same parameters as `\DDTools\ObjectCollection::__construct($params)`. Gets an array of required collection items. * `$params` - * Description: Parameters, the pass-by-name style is used. + * Description: The parameters object. * Valid values: * `stdClass` * `arrayAssociative` @@ -803,7 +945,7 @@ Gets an array of required collection items. Gets required item. * `$params` - * Description: Parameters, the pass-by-name style is used. + * Description: The parameters object. * Valid values: * `stdClass` * `arrayAssociative` @@ -830,7 +972,7 @@ Counts all items. Converts type of needed items in collection. * `$params` - * Description: Parameters, the pass-by-name style is used. + * Description: The parameters object. * Valid values: * `stdClass` * `arrayAssociative` @@ -855,7 +997,7 @@ Converts type of needed items in collection. Undates properties of existing items with new values. * `$params` - * Description: Parameters, the pass-by-name style is used. + * Description: The parameters object. * Valid values: * `stdClass` * `arrayAssociative` @@ -890,7 +1032,7 @@ Undates properties of existing items with new values. Deletes required items from collection. * `$params` - * Description: Parameters, the pass-by-name style is used. + * Description: The parameters object. * Valid values: * `stdClass` * `arrayAssociative` @@ -927,7 +1069,7 @@ Sets data of an item object. All setting of an item data inside the class must b It's convenient to override this method in child classes if items are not plain objects. * `$params` - * Description: Parameters, the pass-by-name style is used. + * Description: The parameters object. * Valid values: * `stdClass` * `arrayAssociative` @@ -952,7 +1094,7 @@ Returns data of an item object. All getting of an item data inside the class mus It's convenient to override this method in child classes if items are not plain objects. * `$params` - * Description: Parameters, the pass-by-name style is used. + * Description: The parameters object. * Valid values: * `stdClass` * `arrayAssociative` @@ -1089,7 +1231,7 @@ You can see an example of how it works in the [(MODX)EvolutionCMS.snippets.ddGet #### `\DDTools\Base\AncestorTrait::createChildInstance($params)` * `$params` - * Description: Parameters, the pass-by-name style is used. + * Description: The parameters object. * Valid values: * `stdClass` * `arrayAssociative` @@ -1128,7 +1270,7 @@ You can see an example of how it works in the [(MODX)EvolutionCMS.snippets.ddGet #### `\DDTools\Base\AncestorTrait::getChildClassName($params)` * `$params` - * Description: The object of parameters. + * Description: The parameters object. * Valid values: * `stdClass` * `arrayAssociative` @@ -1293,22 +1435,22 @@ Static method for easy running needed snippet using only it's name and parameter `$params->url` can be set in various ways for more convenience: ```php -//Relative +// Relative $url = 'some/page?q=42#hash'; -//Relative starting with slash +// Relative starting with slash $url = '/some/page?q=42#hash'; -//Absolute starting with domain +// Absolute starting with domain $url = 'example.com/some/page?q=42#hash'; -//Absolute starting with double slash +// Absolute starting with double slash $url = '//example.com/some/page?q=42#hash'; -//Absolute starting with scheme +// Absolute starting with scheme $url = 'https://example.com/some/page?q=42#hash'; ``` ```php \ddTools::convertUrlToAbsolute([ 'url' => $url, - //The parameter is optional and is used here just for clarity. By default it will be equal to domain of your site. + // The parameter is optional and is used here just for clarity. By default it will be equal to domain of your site. 'host' => 'example.com', ]); ``` @@ -1327,18 +1469,18 @@ Over time, we decided to rename the parameters as `docField` and `docId` respect And we want to save backward compatibility, the snippet must work with the old names and send message to the MODX event log. ```php -//Include (MODX)EvolutionCMS.libraries.ddTools +// Include (MODX)EvolutionCMS.libraries.ddTools require_once( $modx->getConfig('base_path') . 'assets/libs/ddTools/modx.ddtools.class.php' ); -//Backward compatibility +// Backward compatibility extract(\ddTools::verifyRenamedParams([ - //We called the method inside of a snippet, so its parameters are contained in the `$params` variable (MODX feature) + // We called the method inside of a snippet, so its parameters are contained in the `$params` variable (MODX feature) 'params' => $params, 'compliance' => [ - //The new name => The old name + // The new name => The old name 'docField' => 'getEmail', 'docId' => 'getId', ], @@ -1351,10 +1493,10 @@ After some time we decided to rename the parameters again as `email_docField` и ```php extract(\ddTools::verifyRenamedParams([ - //We called the method inside of a snippet, so its parameters are contained in the `$params` variable (MODX feature) + // We called the method inside of a snippet, so its parameters are contained in the `$params` variable (MODX feature) 'params' => $params, 'compliance' => [ - //The new name => The old names + // The new name => The old names 'email_docField' => [ 'docField', 'getEmail', @@ -1364,7 +1506,7 @@ extract(\ddTools::verifyRenamedParams([ 'getId', ], ], - //Also you can prevent writing to the CMS event log if you want + // Also you can prevent writing to the CMS event log if you want 'writeToLog' => false, ])); ``` @@ -1409,14 +1551,14 @@ Returns: ```php \ddTools::parseText([ - //Data can have a complex nested structure + // Data can have a complex nested structure 'data' => [ 'title' => 'Bethink Yourselves!', 'text' => '

Question your actions and consider the morality behind them.

', - //Note that this is not a string, but that's okay + // Note that this is not a string, but that's okay 'meta' => [ - //Moreover, any depth is supported - //And objects are also supported as well as arrays regardless of nesting level + // Moreover, any depth is supported + // And objects are also supported as well as arrays regardless of nesting level 'author' => (object) [ 'firstName' => 'Leo', 'lastName' => 'Tolstoy', @@ -1424,8 +1566,8 @@ Returns: 'date' => '1904', ], ], - //For nested data you can use placeholders like '[+meta.date+]' for getting a property - //Or like '[+meta+]' to get whole object as JSON + // For nested data you can use placeholders like '[+meta.date+]' for getting a property + // Or like '[+meta+]' to get whole object as JSON 'text' => '

[+title+]

@@ -1460,7 +1602,7 @@ Users use the format that is convenient to them and we support both. Just call this method and don't care about it. ```php -//We can pass string in JSON format +// We can pass string in JSON format \DDTools\Tools\Objects::convertType([ 'object' => '{ "pagetitle": "Test title", @@ -1469,7 +1611,7 @@ Just call this method and don't care about it. 'type' => 'objectArray', ]); -//Or Query string +// Or Query string \DDTools\Tools\Objects::convertType([ 'object' => 'pagetitle=Test title&published=0', 'type' => 'objectArray', @@ -1532,7 +1674,7 @@ Returns: ```php \DDTools\Tools\Objects::convertType([ 'object' => "{ - //This is HJSON, not JSON, so we can use comments insides + // This is HJSON, not JSON, so we can use comments insides keys: and values can be specified without quotes, multilineValues: ''' @@ -1564,9 +1706,9 @@ stdClass::__set_state(array( \DDTools\Tools\Objects::convertType([ 'object' => [ 'data-name' => 'KINO', - //Will be converted to 1 + // Will be converted to 1 'data-is-active' => true, - //Will be converted to JSON array + // Will be converted to JSON array 'data-members' => [ 'Viktor Tsoi', 'Yuri Kasparyan', @@ -1697,10 +1839,10 @@ var_export( Returns: ```php -//The object expanded the source array +// The object expanded the source array array( 'name' => 'jokes', - //The array expanded the source object + // The array expanded the source object 'countries' => stdClass::__set_state( 'usa' => 'democracy', 'china' => 'democracy too', @@ -1775,6 +1917,57 @@ stdClass::__set_state(array( ``` +##### Extending only specific properties from subsequent objects (`$params->extendableProperties`) + +Sometimes you want to keep only the key ingredients, like avoiding the pineapple on your pizza. + +```php +var_export( + \DDTools\Tools\Objects::extend([ + 'objects' => [ + (object) [ + 'name' => 'Classic Italian Pizza', + 'toppings' => (object) [ + 'cheese' => 'mozzarella', + 'tomatoSauce' => true, + 'olive' => true, + ], + 'size' => 'medium', + ], + [ + // Not interested in extra toppings + 'toppings' => [ + 'pineapple' => true, + ], + 'size' => 'large', + 'price' => 15.99, + ], + ], + // Only keeping the price and size + 'extendableProperties' => [ + 'price', + 'size', + ], + ]) +); +``` + +Returns: + +```php +stdClass::__set_state(array( + 'name' => 'Classic Italian Pizza', + 'toppings' => stdClass::__set_state(array( + 'cheese' => 'mozzarella', + 'tomatoSauce' => true, + 'olive' => true, + )), + 'size' => 'large', + 'price' => 15.99, +)) +``` + + #### `\DDTools\Tools\Objects::unfold($params)` @@ -1873,15 +2066,15 @@ stdClass::__set_state(array ( ##### Cross-type unfolding (`$params->isCrossTypeEnabled` == `true`) ```php -//Array +// Array $data = [ - //Array + // Array 'bin1' => [ 'plastic' => 'plastic bottles', 'paper' => 'newspapers', 'glass' => 'glass bottles', ], - //Object + // Object 'bin2' => (object) [ 'organic' => 'food waste', 'paper' => 'cardboard boxes', @@ -2016,11 +2209,11 @@ Both calls return `'Floyd'`. Source object can be nested, and elements of all levels can be mix of objects and arrays. ```php -//For example let the first level be stdClass +// For example let the first level be stdClass $sourceObject = (object) [ - //Let the second level be an indexed array + // Let the second level be an indexed array 'PinkFloyd' => [ - //Let the third level be an associative array + // Let the third level be an associative array [ 'name' => 'Syd Barrett', 'role' => 'lead and rhythm guitars, vocals', @@ -2029,7 +2222,7 @@ $sourceObject = (object) [ 'name' => 'David Gilmour', 'role' => 'lead and rhythm guitars, vocals, bass, keyboards, synthesisers', ], - //Let Roger be a little bit special ;) + // Let Roger be a little bit special ;) (object) [ 'name' => 'Roger Waters', 'role' => 'bass, vocals, rhythm guitar, synthesisers', @@ -2297,7 +2490,7 @@ array( ```php $collection->getItems([ - //Spaces, tabs and line breaks are also allowed and do not matter + // Spaces, tabs and line breaks are also allowed and do not matter 'filter' => ' gender == female || nobelPeacePrize == 1 && isHuman == 0 @@ -2309,7 +2502,7 @@ Returns: ```php array( - //gender == female + // gender == female 0 => array( 'name' => 'Mary Teresa', 'isHuman' => 1, @@ -2317,7 +2510,7 @@ array( 'nobelPeacePrize' => 1, 'religion' => 'Catholicism', ), - //nobelPeacePrize == 1 && isHuman == 0 + // nobelPeacePrize == 1 && isHuman == 0 1 => array( 'name' => 'ICAN', 'isHuman' => 0, @@ -2497,13 +2690,13 @@ Returns: ```php array( 0 => stdClass::__set_state(array( - //Existing properties that absent in `$params->data` have remained as is + // Existing properties that absent in `$params->data` have remained as is 'name' => 'Mahatma Gandhi', 'isHuman' => 1, 'gender' => 'male', - //Given property values have overwritten the existing ones + // Given property values have overwritten the existing ones 'nobelPeacePrize' => 1, - //Non-existing properties have been created + // Non-existing properties have been created 'birthday' => '2 October 1869', )) ) @@ -2525,7 +2718,7 @@ Returns: ```php array( - //2 humans have been deleted, 1 have remained + // 2 humans have been deleted, 1 have remained 0 => stdClass::__set_state(array( 'name' => 'Tenzin Gyatso', 'isHuman' => 1, diff --git a/composer.json b/composer.json index b47e654..0396a73 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "dd/evolutioncms-libraries-ddtools", "type": "modxevo-library-ddtools", - "version": "0.63.0", + "version": "0.64.0", "description": "A library with various tools facilitating your work.", "keywords": [ "modx", diff --git a/modx.ddtools.class.php b/modx.ddtools.class.php index f4043ef..6159111 100644 --- a/modx.ddtools.class.php +++ b/modx.ddtools.class.php @@ -1,7 +1,7 @@ '', 'event_log' => '', 'manager_log' => '', 'manager_users' => '', 'system_eventnames' => '', 'system_settings' => '', - //Documents + // Documents 'site_content' => '', 'documentgroup_names' => '', 'document_groups' => '', - //Templates + // Templates 'site_templates' => '', - //Chunks + // Chunks 'site_htmlsnippets' => '', - //TVs + // TVs 'site_tmplvars' => '', 'site_tmplvar_access' => '', 'site_tmplvar_contentvalues' => '', 'site_tmplvar_templates' => '', - //Snippets + // Snippets 'site_snippets' => '', - //Plugins + // Plugins 'site_plugins' => '', 'site_plugin_events' => '', - //Modules + // Modules 'site_modules' => '', 'site_module_access' => '', 'site_module_depobj' => '', - //Users + // Users 'membergroup_access' => '', 'membergroup_names' => '', 'member_groups' => '', @@ -112,14 +112,14 @@ class ddTools { /** * __construct - * @version 1.0.5 (2024-08-02) + * @version 1.0.6 (2024-08-04) */ private function __construct(){ global $modx; self::$modx = $modx; - //Init full table names + // Init full table names foreach ( self::$tables as $tableAlias => @@ -128,7 +128,7 @@ private function __construct(){ self::$tables[$tableAlias] = self::$modx->getFullTableName($tableAlias); } - //We need to include required files if Composer is not used + // We need to include required files if Composer is not used if(!class_exists('\DDTools\Tools\Files')){ require_once( __DIR__ . @@ -175,11 +175,11 @@ public static function isEmpty($value = null): bool { /** * orderedParamsToNamed - * @version 1.1.6 (2019-06-22) + * @version 1.1.7 (2024-08-04) * * @desc Convert list of ordered parameters to named. Method is public, but be advised that this is beta-version! * - * @param $params {stdClass|arrayAssociative} — Parameters, the pass-by-name style is used. @required + * @param $params {stdClass|arrayAssociative} — The parameters object. @required * @param $params->paramsList {array} — Parameters in ordered list (func_get_args). @required * @param $params->paramsList[i] {mixed} — Parameter value. @required * @param $params->compliance {array} — The order of parameters. @required @@ -197,15 +197,15 @@ public static function orderedParamsToNamed($params){ 'backtraceArray' => [] ]; - //Перебираем массив соответствия + // Перебираем массив соответствия foreach ( $params->compliance as $index => $name ){ - //Если параметр задан + // Если параметр задан if (isset($params->paramsList[$index])){ - //Сохраним его + // Сохраним его $result[$name] = $params->paramsList[$index]; } @@ -213,7 +213,7 @@ public static function orderedParamsToNamed($params){ } $logData->backtraceArray = debug_backtrace(); - //Remove this method + // Remove this method array_shift($logData->backtraceArray); $caller = $logData->backtraceArray[0]; $caller = @@ -225,7 +225,7 @@ public static function orderedParamsToNamed($params){ $caller['function'] ; - //General info with code example + // General info with code example $logData->message = '

Deprecated ordered parameters.

Ordered list of parameters is no longer allowed, use the “pass-by-name” style.

' . '
//Old style' .
@@ -254,7 +254,7 @@ public static function orderedParamsToNamed($params){
 	
 	/**
 	 * explodeAssoc
-	 * @version 1.1.6 (2020-06-07)
+	 * @version 1.1.7 (2024-08-04)
 	 * 
 	 * @desc Splits string on two separators in the associative array.
 	 * 
@@ -271,12 +271,12 @@ public static function explodeAssoc(
 	){
 		$result = [];
 		
-		//Если строка пустая, выкидываем сразу
+		// Если строка пустая, выкидываем сразу
 		if ($inputString == ''){
 			return $result;
 		}
 		
-		//Разбиваем по парам
+		// Разбиваем по парам
 		$inputString = explode(
 			$itemDelimiter,
 			$inputString
@@ -286,7 +286,7 @@ public static function explodeAssoc(
 			$inputString as
 			$item
 		){
-			//Разбиваем на ключ-значение
+			// Разбиваем на ключ-значение
 			$item = explode(
 				$keyValDelimiter,
 				$item
@@ -304,7 +304,7 @@ public static function explodeAssoc(
 	
 	/**
 	 * sort2dArray
-	 * @version 1.3.1 (2024-08-02)
+	 * @version 1.3.2 (2024-08-04)
 	 * 
 	 * @desc Sorts 2-dimensional array by multiple columns (like in SQL) using Hoare's method, also referred to as quicksort. The sorting is stable.
 	 * 
@@ -322,7 +322,7 @@ public static function sort2dArray(
 		$sortDir = 1,
 		$i = 0
 	){
-		//В качестве эталона получаем сортируемое значение (по первому условию сортировки) первого элемента
+		// В качестве эталона получаем сортируемое значение (по первому условию сортировки) первого элемента
 		$currentItem_comparisonValue = \DDTools\Tools\Objects::getPropValue([
 			'object' => array_values($array)[0],
 			'propName' => $sortBy[$i]
@@ -341,7 +341,7 @@ public static function sort2dArray(
 		$resultArrayRight = [];
 		$resultArrayCenter = [];
 		
-		//Перебираем массив
+		// Перебираем массив
 		foreach (
 			$array as
 			$arrayItemKey =>
@@ -352,12 +352,12 @@ public static function sort2dArray(
 				'propName' => $sortBy[$i]
 			]);
 			
-			//Если эталон и текущее значение — числа
+			// Если эталон и текущее значение — числа
 			if (
 				$isCurrentItemComparisonValueNumeric &&
 				is_numeric($arrayItem_comparisonValue)
 			){
-				//Получаем нужную циферку
+				// Получаем нужную циферку
 				$cmpRes =
 					$arrayItem_comparisonValue == $currentItem_comparisonValue ?
 					0 :
@@ -367,22 +367,22 @@ public static function sort2dArray(
 						-1
 					)
 				;
-			//Если они строки
+			// Если они строки
 			}else{
-				//Сравниваем текущее значение со значением эталонного
+				// Сравниваем текущее значение со значением эталонного
 				$cmpRes = strcmp(
 					$arrayItem_comparisonValue,
 					$currentItem_comparisonValue
 				);
 			}
 			
-			//Если меньше эталона, отбрасываем в массив меньших
+			// Если меньше эталона, отбрасываем в массив меньших
 			if ($cmpRes * $sortDir < 0){
 				$resultArray = &$resultArrayLeft;
-			//Если больше — в массив больших
+			// Если больше — в массив больших
 			}elseif ($cmpRes * $sortDir > 0){
 				$resultArray = &$resultArrayRight;
-			//Если равно — в центральный
+			// Если равно — в центральный
 			}else{
 				$resultArray = &$resultArrayCenter;
 			}
@@ -394,7 +394,7 @@ public static function sort2dArray(
 			}
 		}
 		
-		//Массивы меньших и массивы больших прогоняем по тому же алгоритму (если в них что-то есть)
+		// Массивы меньших и массивы больших прогоняем по тому же алгоритму (если в них что-то есть)
 		$resultArrayLeft =
 			count($resultArrayLeft) > 1 ?
 			self::sort2dArray(
@@ -415,7 +415,7 @@ public static function sort2dArray(
 			) :
 			$resultArrayRight
 		;
-		//Массив одинаковых прогоняем по следующему условию сортировки (если есть условие и есть что сортировать)
+		// Массив одинаковых прогоняем по следующему условию сортировки (если есть условие и есть что сортировать)
 		$resultArrayCenter =
 			(
 				count($resultArrayCenter) > 1 &&
@@ -430,7 +430,7 @@ public static function sort2dArray(
 			$resultArrayCenter
 		;
 		
-		//Склеиваем отсортированные меньшие, средние и большие
+		// Склеиваем отсортированные меньшие, средние и большие
 		return array_merge(
 			$resultArrayLeft,
 			$resultArrayCenter,
@@ -440,7 +440,7 @@ public static function sort2dArray(
 	
 	/**
 	 * parseFileNameVersion
-	 * @version 1.1.4 (2020-02-11)
+	 * @version 1.1.5 (2024-08-04)
 	 * 
 	 * @desc Parses a file path and gets its name, version & extension.
 	 * 
@@ -452,23 +452,23 @@ public static function sort2dArray(
 	 * @return $result['extension'] {string} — File extension.
 	 */
 	public static function parseFileNameVersion($file){
-		//Если сразу передали массив
+		// Если сразу передали массив
 		if (is_array($file)){
-			//Просто запоминаем его
+			// Просто запоминаем его
 			$fileinfo = $file;
-			//А также запоминаем строку
+			// А также запоминаем строку
 			$file =
 				$fileinfo['dirname'] .
 				'/' .
 				$fileinfo['basename']
 			;
-			//Если передали строку
+			// Если передали строку
 		}else{
-			//Получаем необходимые данные
+			// Получаем необходимые данные
 			$fileinfo = pathinfo($file);
 		}
 		
-		//Fail by default
+		// Fail by default
 		$result = [
 			'name' => strtolower($file),
 			'version' => '0',
@@ -478,14 +478,14 @@ public static function parseFileNameVersion($file){
 				$fileinfo['extension']
 		];
 		
-		//Try to get file version [0 — full name, 1 — script name, 2 — version, 3 — all chars after version]
+		// Try to get file version [0 — full name, 1 — script name, 2 — version, 3 — all chars after version]
 		preg_match(
 			'/(\D*?)-?(\d(?:\.\d+)*(?:-?[A-Za-z])*)(.*)/',
 			$fileinfo['basename'],
 			$match
 		);
 		
-		//If not fail
+		// If not fail
 		if (count($match) >= 4){
 			$result['name'] = strtolower($match[1]);
 			$result['version'] = strtolower($match[2]);
@@ -496,11 +496,11 @@ public static function parseFileNameVersion($file){
 	
 	/**
 	 * convertUrlToAbsolute
-	 * @version 1.0.1 (2024-08-02)
+	 * @version 1.0.2 (2024-08-04)
 	 * 
 	 * @desc Converts relative URLs to absolute.
 	 * 
-	 * @param $params {stdClass|arrayAssociative} — Parameters, the pass-by-name style is used. @required
+	 * @param $params {stdClass|arrayAssociative} — The parameters object. @required
 	 * @param $params->url {string} — Source URL. Can be set as relative with(out) host or absolute with(out) protocol: example.com/some/url, some/url, /some/url, //example.com/some/url, https://example.com/some/url. @required
 	 * @param $params->host {string} — Host for the result URL. Default: $_SERVER['HTTP_HOST'].
 	 * @param $params->scheme {string} — Scheme for the result URL. Default: 'https' || 'http' depending on $_SERVER['HTTPS'].
@@ -508,10 +508,10 @@ public static function parseFileNameVersion($file){
 	 * @return {string}
 	 */
 	public static function convertUrlToAbsolute($params){
-		//# Prepare params
+		// # Prepare params
 		$params = \DDTools\Tools\Objects::extend([
 			'objects' => [
-				//Defaults
+				// Defaults
 				(object) [
 					'url' => '',
 					'host' => $_SERVER['HTTP_HOST'],
@@ -536,10 +536,10 @@ public static function convertUrlToAbsolute($params){
 		}
 		
 		
-		//# Run
+		// # Run
 		$result = '';
 		
-		//E. g. '//example.com/some/url'
+		// E. g. '//example.com/some/url'
 		if (
 			substr(
 				$params->url,
@@ -553,7 +553,7 @@ public static function convertUrlToAbsolute($params){
 				':' .
 				$params->url
 			;
-		//E. g. 'https://example.com/some/url'
+		// E. g. 'https://example.com/some/url'
 		}elseif (
 			!empty(parse_url(
 				$params->url,
@@ -561,7 +561,7 @@ public static function convertUrlToAbsolute($params){
 			))
 		){
 			$result = $params->url;
-		//E. g. 'example.com/some/url'
+		// E. g. 'example.com/some/url'
 		}elseif (
 			strpos(
 				$params->url,
@@ -574,7 +574,7 @@ public static function convertUrlToAbsolute($params){
 				'://' .
 				$params->url
 			;
-		//E. g. 'some/url', '/some/url'
+		// E. g. 'some/url', '/some/url'
 		}else{
 			$result =
 				$params->scheme .
@@ -629,7 +629,7 @@ public static function generateRandomString(
 	
 	/**
 	 * escapingForJS
-	 * @version 1.1.2 (2019-06-22)
+	 * @version 1.1.3 (2024-08-04)
 	 * 
 	 * @desc Escaping chars in string for JS.
 	 * 
@@ -638,13 +638,13 @@ public static function generateRandomString(
 	 * @return {string}
 	 */
 	public static function escapeForJS($str){
-		//Backslach escaping (see issue #1)
+		// Backslach escaping (see issue #1)
 		$str = str_replace(
 			'\\',
 			'\\\\',
 			$str
 		);
-		//Line breaks
+		// Line breaks
 		$str = str_replace(
 			"\r\n",
 			' ',
@@ -660,7 +660,7 @@ public static function escapeForJS($str){
 			' ',
 			$str
 		);
-		//Tabs
+		// Tabs
 		$str = str_replace(
 			chr(9),
 			' ',
@@ -671,7 +671,7 @@ public static function escapeForJS($str){
 			' ',
 			$str
 		);
-		//MODX placeholders
+		// MODX placeholders
 		$str = str_replace(
 			'[+',
 			'\[\+',
@@ -682,7 +682,7 @@ public static function escapeForJS($str){
 			'\+\]',
 			$str
 		);
-		//Quotes
+		// Quotes
 		$str = str_replace(
 			"'",
 			"\'",
@@ -699,11 +699,11 @@ public static function escapeForJS($str){
 
 	/**
 	 * getPlaceholdersFromText
-	 * @version 1.0.2 (2020-02-11)
+	 * @version 1.0.3 (2024-08-04)
 	 * 
 	 * @desc Finds all placeholders' names and returns them as an array.
 	 * 
-	 * @param $params {stdClass|arrayAssociative} — Parameters, the pass-by-name style is used. @required
+	 * @param $params {stdClass|arrayAssociative} — The parameters object. @required
 	 * @param $params->text {string} — Source string. @required
 	 * @param $params->placeholderPrefix {string} — Placeholders prefix. Default: '[+'.
 	 * @param $params->placeholderSuffix {string} — Placeholders suffix. Default: '+]'.
@@ -711,7 +711,7 @@ public static function escapeForJS($str){
 	 * @return {array}
 	 */
 	public static function getPlaceholdersFromText($params = []){
-		//Defaults
+		// Defaults
 		$params = (object) array_merge(
 			[
 				'text' => '',
@@ -745,11 +745,11 @@ public static function getPlaceholdersFromText($params = []){
 	
 	/**
 	 * logEvent
-	 * @version 1.0.3 (2020-02-11)
+	 * @version 1.0.4 (2024-08-04)
 	 * 
 	 * @desc Add an alert message to the system event log with debug info (backtrace, snippet name, document id, etc).
 	 * 
-	 * @param $params {stdClass|arrayAssociative} — Parameters, the pass-by-name style is used. @required
+	 * @param $params {stdClass|arrayAssociative} — The parameters object. @required
 	 * @param $params->message {string} — Message to be logged. Default: ''.
 	 * @param $params->source {string} — Source of the event (module, snippet name, etc). Default: $modx->currentSnippet || caller.
 	 * @param $params->eventId {integer} — Event ID. Default: 1.
@@ -759,12 +759,12 @@ public static function getPlaceholdersFromText($params = []){
 	 * @return {void}
 	 */
 	public static function logEvent($params){
-		//Defaults
+		// Defaults
 		$params = (object) array_merge(
 			[
 				'message' => '',
 				'source' => '',
-				//TODO: Why “1”, what does it mean?
+				// TODO: Why “1”, what does it mean?
 				'eventId' => 1,
 				'eventType' => 'warning',
 // 				'backtraceArray' => debug_backtrace(),
@@ -773,10 +773,10 @@ public static function logEvent($params){
 		);
 		
 		
-		//Prepare backtrace and caller
+		// Prepare backtrace and caller
 		if (!isset($params->backtraceArray)){
 			$params->backtraceArray = debug_backtrace();
-			//Remove this method
+			// Remove this method
 			array_shift($params->backtraceArray);
 		}
 		$caller = $params->backtraceArray[0];
@@ -792,7 +792,7 @@ public static function logEvent($params){
 		
 		$debugInfo = [];
 		
-		//Add current document Id to debug info
+		// Add current document Id to debug info
 		if (!empty(self::$modx->documentIdentifier)){
 			$debugInfo[] =
 				'
  • Document id: “' . @@ -801,14 +801,14 @@ public static function logEvent($params){ ; } - //Is the code being run in the snippet? + // Is the code being run in the snippet? if (!empty(self::$modx->currentSnippet)){ - //Empty source + // Empty source if ($params->source == ''){ - //Set as source + // Set as source $params->source = self::$modx->currentSnippet; }else{ - //Add to debug info + // Add to debug info $debugInfo[] = '
  • Snippet: “' . self::$modx->currentSnippet . @@ -822,7 +822,7 @@ public static function logEvent($params){ } - //Add debug info to the message + // Add debug info to the message $params->message .= '

    Debug info

    '; if (!empty($debugInfo)){ @@ -836,27 +836,27 @@ public static function logEvent($params){ ; } - //Add backtrace to message + // Add backtrace to message $params->message .= self::$modx->get_backtrace($params->backtraceArray); - //Prepare event type + // Prepare event type switch (substr( $params->eventType, 0, 1 )){ - //Information + // Information case 'i': $params->eventType = 1; break; - //Warning + // Warning case 'w': $params->eventType = 2; break; - //Error + // Error case 'e': $params->eventType = 3; break; @@ -873,18 +873,18 @@ public static function logEvent($params){ /** * getTpl - * @version 1.0 (2023-05-14) + * @version 1.0.1 (2024-08-04) * * @see README.md */ public static function getTpl($tpl = ''){ - //Cast the parameter to a string + // Cast the parameter to a string $tpl = $tpl . ''; $result = $tpl; if (!empty($tpl)){ - //$modx->getTpl('@CODE:') returns '@CODE:' O_o + // $modx->getTpl('@CODE:') returns '@CODE:' O_o if ( substr( $tpl, @@ -907,7 +907,7 @@ public static function getTpl($tpl = ''){ /** * parseText - * @version 1.9.1 (2024-06-06) + * @version 1.9.2 (2024-08-04) * * @see README.md */ @@ -942,7 +942,7 @@ public static function parseText($params = []){ $result = static::parseSource($result); } - //It is needed only after static::parseSource because some snippets can create the new empty placeholders + // It is needed only after static::parseSource because some snippets can create the new empty placeholders if ($params->removeEmptyPlaceholders){ $result = preg_replace( '/(\[\+\S+?\+\])/m', @@ -956,16 +956,16 @@ public static function parseText($params = []){ /** * parseText_parepareParams - * @version 1.0.2 (2024-08-02) + * @version 1.0.3 (2024-08-04) * - * @param $params {stdClass|arrayAssociative} — The object of parameters. See $this->parseText. + * @param $params {stdClass|arrayAssociative} — The parameters object. See $this->parseText. * * @return {string} */ private static function parseText_parepareParams($params = []): \stdClass { - //For backward compatibility + // For backward compatibility if (func_num_args() > 1){ - //Convert ordered list of params to named + // Convert ordered list of params to named $params = self::orderedParamsToNamed([ 'paramsList' => func_get_args(), 'compliance' => [ @@ -988,7 +988,7 @@ private static function parseText_parepareParams($params = []): \stdClass { $params = \DDTools\Tools\Objects::extend([ 'objects' => [ - //Defaults + // Defaults (object) [ 'text' => '', 'data' => null, @@ -1006,9 +1006,9 @@ private static function parseText_parepareParams($params = []): \stdClass { /** * parseText_prepareData - * @version 1.0.1 (2024-08-02) + * @version 1.0.2 (2024-08-04) * - * @param $params {stdClass|arrayAssociative} — The object of parameters. See $this->parseText. + * @param $params {stdClass|arrayAssociative} — The parameters object. See $this->parseText. * @param $params->data {stdClass|array|string} * * @return {stdClass} @@ -1018,7 +1018,7 @@ private static function parseText_prepareData($params = []): \stdClass { $result = new \stdClass(); - //Arrays and objects are already ready to use + // Arrays and objects are already ready to use if ( !is_object($params->data) && !is_array($params->data) @@ -1038,7 +1038,7 @@ private static function parseText_prepareData($params = []): \stdClass { is_object($value) || is_array($value) ){ - //Unfold for nested objects and arrays support (e. g. ['some' => ['a' => 'one', 'b' => 'two'] ] → '[+some.a+]', '[+some.b+]'; ['some' => ['one', 'two'] ] → '[+some.0+]', '[some.1]') + // Unfold for nested objects and arrays support (e. g. ['some' => ['a' => 'one', 'b' => 'two'] ] → '[+some.a+]', '[+some.b+]'; ['some' => ['one', 'two'] ] → '[+some.0+]', '[some.1]') $unfoldedValue = \DDTools\Tools\Objects::unfold([ 'object' => [ $key => $value @@ -1054,7 +1054,7 @@ private static function parseText_prepareData($params = []): \stdClass { $result->{$unfoldedValue_itemKey} = $unfoldedValue_itemValue; } - //Also add object value as JSON + // Also add object value as JSON $value = \DDTools\Tools\Objects::convertType([ 'object' => $value, 'type' => 'stringJsonAuto' @@ -1069,9 +1069,9 @@ private static function parseText_prepareData($params = []): \stdClass { /** * parseText_parseItem - * @version 1.1 (2024-06-06) + * @version 1.1.1 (2024-08-04) * - * @param $params {stdClass|arrayAssociative} — The object of parameters. + * @param $params {stdClass|arrayAssociative} — The parameters object. * @param $params->text {string} — Source text. * @param $params->placeholder {string} — Placeholder string, e. g. [+fullName+]. * @param $params->value {string} — Placeholder value. @@ -1094,7 +1094,7 @@ private static function parseText_parseItem($params = []) :string { /** * parseSource - * @version 1.1 (2018-12-24) + * @version 1.1.1 (2024-08-04) * * @desc Parse the source (run $modx->parseDocumentSource and $modx->rewriteUrls); * @@ -1103,7 +1103,7 @@ private static function parseText_parseItem($params = []) :string { * @return {string} */ public static function parseSource($source){ - //Uncashed snippets must be evaled too + // Uncashed snippets must be evaled too $source = strtr( $source, [ @@ -1117,11 +1117,11 @@ public static function parseSource($source){ /** * clearCache - * @version 1.1 (2020-02-11) + * @version 1.1.1 (2024-08-04) * * @desc Clears cache of required document(s) and their parents. * - * @param $params {stdClass|arrayAssociative} — Parameters, the pass-by-name style is used. @required + * @param $params {stdClass|arrayAssociative} — The parameters object. @required * @param $params->docIds {arrayAssociative|stringCommaSeparated} — Document ID(s). @required * @param $params->docIds[i] {integer} — Document ID. @required * @param $params->clearParentsCache {boolean} — Is need to clear parents cache? Default: true. @@ -1129,7 +1129,7 @@ public static function parseSource($source){ * @return {void} */ public static function clearCache($params){ - //Defaults + // Defaults $params = (object) array_merge( [ 'clearParentsCache' => true, @@ -1137,7 +1137,7 @@ public static function clearCache($params){ (array) $params ); - //Comma separated strings support + // Comma separated strings support if (!is_array($params->docIds)){ $params->docIds = explode( ',', @@ -1157,14 +1157,14 @@ public static function clearCache($params){ $params->docIds as $docId ){ - //$_GET cache + // $_GET cache $cacheFiles = glob( $cacheFilePrefix . $docId . '_*' . $cacheFileSuffix ); - //Without $_GET + // Without $_GET $cacheFiles[] = $cacheFilePrefix . $docId . @@ -1182,10 +1182,10 @@ public static function clearCache($params){ unlink($cacheFiles_item); } - //IF need to clear parents cache too + // IF need to clear parents cache too if ($params->clearParentsCache){ self::clearCache([ - //Get all parents + // Get all parents 'docIds' => self::getDocumentParentIds([ 'docId' => $docId ]), @@ -1197,11 +1197,11 @@ public static function clearCache($params){ /** * prepareDocData - * @version 2.0.4 (2020-02-11) + * @version 2.0.5 (2024-08-04) * * @desc Prepare document data from single array of fields and TVs: separate them and get TV IDs if needed. * - * @param $params {stdClass|arrayAssociative} — Parameters, the pass-by-name style is used. @required + * @param $params {stdClass|arrayAssociative} — The parameters object. @required * @param $params->data {stdClass|arrayAssociative} — Array of document fields (from table `site_content`) or TVs with values. @required * @param $params->data->{$key} {mixed} — Field value (optional), when key is field name. The method use only keys, values just will be returned without changes. @required * @param $params->tvAdditionalFieldsToGet {array} — Fields of TVs to get if needed (e. g. 'id', 'type'). Default: []. @@ -1217,7 +1217,7 @@ public static function clearCache($params){ * @return $result->tvsAdditionalData[key][item] {string} — TV data. */ public static function prepareDocData($params){ - //Defaults + // Defaults $params = (object) array_merge( [ 'tvAdditionalFieldsToGet' => [] @@ -1231,28 +1231,28 @@ public static function prepareDocData($params){ 'tvsAdditionalData' => [] ]; - //Перебираем поля, раскидываем на поля документа и TV + // Перебираем поля, раскидываем на поля документа и TV foreach ( $params->data as $data_itemFieldName => $data_itemFieldValue ){ - //Если это не поле документа + // Если это не поле документа if (!in_array( $data_itemFieldName, self::$documentFields )){ - //Запоминаем как TV`шку + // Запоминаем как TV`шку $result->tvsData[$data_itemFieldName] = $data_itemFieldValue; }else{ - //Save as document field + // Save as document field $result->fieldsData[$data_itemFieldName] = $data_itemFieldValue; } } if ( !empty($params->tvAdditionalFieldsToGet) && - //Если есть хоть одна TV + // Если есть хоть одна TV count($result->tvsData) > 0 ){ if (!in_array( @@ -1262,9 +1262,9 @@ public static function prepareDocData($params){ $params->tvAdditionalFieldsToGet[] = 'name'; } - //Получаем id всех необходимых TV + // Получаем id всех необходимых TV $dbRes = self::$modx->db->select( - //Fields + // Fields ( '`' . implode( @@ -1273,9 +1273,9 @@ public static function prepareDocData($params){ ) . '`' ), - //From + // From self::$tables['site_tmplvars'], - //Where + // Where ( "`name` IN ('" . implode( @@ -1329,7 +1329,7 @@ private static function createDocument_prepareAlias($sourceString){ /** * createDocument - * @version 1.5.1 (2024-08-02) + * @version 1.5.2 (2024-08-04) * * @desc Create a new document. * @@ -1344,16 +1344,16 @@ public static function createDocument( $docData = [], $docGroups = false ){ - //Defaults + // Defaults $docData = \DDTools\Tools\Objects::extend([ 'objects' => [ (object) [ 'pagetitle' => 'New resource', - //Autotransliterate from pagetitle + // Autotransliterate from pagetitle 'alias' => '', - //Если не передана дата создания документа, ставим текущую + // Если не передана дата создания документа, ставим текущую 'createdon' => time(), - //Если не передано, кем документ создан, ставим 1 + // Если не передано, кем документ создан, ставим 1 'createdby' => 1 ], $docData @@ -1361,12 +1361,12 @@ public static function createDocument( 'overwriteWithEmpty' => false ]); - //Если группы заданы, то это приватный документ + // Если группы заданы, то это приватный документ if ($docGroups){ $docData->privatemgr = 1; } - //Если надо публиковать, поставим дату публикации текущей + // Если надо публиковать, поставим дату публикации текущей if ($docData->published == 1){ $docData->pub_date = $docData->createdon; } @@ -1393,7 +1393,7 @@ public static function createDocument( ] ]); - //Вставляем новый документ в базу, получаем id, если что-то пошло не так, выкидываем + // Вставляем новый документ в базу, получаем id, если что-то пошло не так, выкидываем $docId = self::$modx->db->insert( $docData->fieldsData, self::$tables['site_content'] @@ -1403,58 +1403,58 @@ public static function createDocument( return false; } - //Если есть хоть одна существующая TV + // Если есть хоть одна существующая TV if (count($docData->tvsAdditionalData) > 0){ - //Перебираем массив TV с ID + // Перебираем массив TV с ID foreach ( $docData->tvsAdditionalData as $tvName => $tvData ){ if ( - //Если это дата + // Если это дата $tvData['type'] == 'date' && - //И она задана как Unixtime + // И она задана как Unixtime is_numeric($docData->tvsData[$tvName]) ){ - //Приведём её к формату системы + // Приведём её к формату системы $docData->tvsData[$tvName] = self::$modx->toDateFormat($docData->tvsData[$tvName]); } - //Добавляем значение TV в базу + // Добавляем значение TV в базу self::$modx->db->insert( - //Fields + // Fields [ 'value' => $docData->tvsData[$tvName], 'tmplvarid' => $tvData['id'], 'contentid' => $docId ], - //Table + // Table self::$tables['site_tmplvar_contentvalues'] ); } } - //Если заданы группы (и на всякий проверим ID) + // Если заданы группы (и на всякий проверим ID) if ($docGroups){ - //Перебираем все группы + // Перебираем все группы foreach ( $docGroups as $docGroupId ){ self::$modx->db->insert( - //Field + // Field [ 'document_group' => $docGroupId, 'document' => $docId ], - //Table + // Table self::$tables['document_groups'] ); } } - //Смотрим родителя нового документа, является ли он папкой и его псевдоним + // Смотрим родителя нового документа, является ли он папкой и его псевдоним $docParent = isset($docData->fieldsData['parent']) ? $docData->fieldsData['parent'] : @@ -1466,10 +1466,10 @@ public static function createDocument( 0 ; - //Пусть созданного документа + // Пусть созданного документа $docPath = ''; - //Собираем путь в зависимости от пути родителя + // Собираем путь в зависимости от пути родителя if(isset(self::$modx->aliasListing[$docParent]['path'])){ $docPath = self::$modx->aliasListing[$docParent]['path']; @@ -1480,7 +1480,7 @@ public static function createDocument( } } - //Добавляем в массивы documentMap и aliasListing информацию о новом документе + // Добавляем в массивы documentMap и aliasListing информацию о новом документе self::$modx->documentMap[] = [$docParent => $docId]; self::$modx->aliasListing[$docId] = [ 'id' => $docId, @@ -1490,7 +1490,7 @@ public static function createDocument( 'isfolder' => $docIsFolder ]; - //Добавляем в documentListing + // Добавляем в documentListing if(self::$modx->aliasListing[$docId]['path'] !== ''){ self::$modx->documentListing[ self::$modx->aliasListing[$docId]['path'] . '/' . @@ -1507,7 +1507,7 @@ public static function createDocument( /** * updateDocument - * @version 1.5.1 (2024-08-02) + * @version 1.5.2 (2024-08-04) * * @desc Update document(s). Cache of the updated docs and their parents will be cleared. * @@ -1524,7 +1524,7 @@ public static function updateDocument( $docData = [], $where = '' ){ - //Required parameters + // Required parameters if ( $docId == 0 && trim($where) == '' @@ -1534,11 +1534,11 @@ public static function updateDocument( $docData = \DDTools\Tools\Objects::extend([ 'objects' => [ - //Defaults + // Defaults (object) [ - //Если не передана дата изменения документа, ставим текущую + // Если не передана дата изменения документа, ставим текущую 'editedon' => time(), - //Если не передано, кем документ изменён, ставим 1 + // Если не передано, кем документ изменён, ставим 1 'editedby' => 1 ], $docData @@ -1552,7 +1552,7 @@ public static function updateDocument( is_array($docId) && count($docId) ){ - //Обрабатываем массив id + // Обрабатываем массив id $whereSql .= '`id` IN ("' . implode( @@ -1565,11 +1565,11 @@ public static function updateDocument( is_numeric($docId) && $docId != 0 ){ - //Обрабатываем числовой id + // Обрабатываем числовой id $whereSql .= '`id`="' . $docId . '"'; } - //Добавляем дополнительное условие + // Добавляем дополнительное условие if ($where != ''){ $whereSql .= ( @@ -1581,7 +1581,7 @@ public static function updateDocument( ; } - //Получаем id документов для обновления + // Получаем id документов для обновления $docIdsToUpdate_dbRes = self::$modx->db->select( 'id', self::$tables['site_content'], @@ -1602,7 +1602,7 @@ public static function updateDocument( $docData->{$fieldName} = self::$modx->db->escape($fieldValue); } - //Разбиваем на поля документа и TV + // Разбиваем на поля документа и TV $docData = self::prepareDocData([ 'data' => $docData, 'tvAdditionalFieldsToGet' => [ @@ -1611,7 +1611,7 @@ public static function updateDocument( ] ]); - //Обновляем информацию по документу + // Обновляем информацию по документу if (count($docData->fieldsData) > 0){ self::$modx->db->update( $docData->fieldsData, @@ -1620,38 +1620,38 @@ public static function updateDocument( ); } - //Если есть хоть одна TV + // Если есть хоть одна TV if (count($docData->tvsAdditionalData) > 0){ - //Обновляем TV всех найденых документов + // Обновляем TV всех найденых документов foreach ( $docIdsToUpdate as $docId ){ - //Перебираем массив существующих TV + // Перебираем массив существующих TV foreach ( $docData->tvsAdditionalData as $tvName => $tvData ){ if ( - //Если это дата + // Если это дата $tvData['type'] == 'date' && - //И она задана как Unixtime + // И она задана как Unixtime is_numeric($docData->tvsData[$tvName]) ){ - //Приведём её к формату системы + // Приведём её к формату системы $docData->tvsData[$tvName] = self::$modx->toDateFormat($docData->tvsData[$tvName]); } - //Пробуем обновить значение нужной TV + // Пробуем обновить значение нужной TV self::$modx->db->update( '`value` = "' . $docData->tvsData[$tvName] . '"', self::$tables['site_tmplvar_contentvalues'], '`tmplvarid` = ' . $tvData['id'] . ' AND `contentid` = ' . $docId ); - //Проверяем сколько строк нашлось при обновлении - //Если используется mysqli + // Проверяем сколько строк нашлось при обновлении + // Если используется mysqli if(is_a( self::$modx->db->conn, 'mysqli' @@ -1662,7 +1662,7 @@ public static function updateDocument( $updatedRows ); }else{ - //Если self::$modx->db->conn не является экземпляром mysqli, то пробуем через устаревший mysql_info + // Если self::$modx->db->conn не является экземпляром mysqli, то пробуем через устаревший mysql_info preg_match( '/Rows matched: (\d+)/', mysql_info(), @@ -1670,9 +1670,9 @@ public static function updateDocument( ); } - //Если ничего не обновилось (не нашлось) + // Если ничего не обновилось (не нашлось) if ($updatedRows[1] == 0){ - //Добавляем значение нужной TV в базу + // Добавляем значение нужной TV в базу self::$modx->db->insert( [ 'value' => $docData->tvsData[$tvName], @@ -1686,7 +1686,7 @@ public static function updateDocument( } } - //Clear cache of updated docs + // Clear cache of updated docs self::clearCache([ 'docIds' => $docIdsToUpdate ]); @@ -1694,13 +1694,13 @@ public static function updateDocument( return true; } - //Нечего обновлять + // Нечего обновлять return false; } /** * getDocuments - * @version 1.2.8 (2020-02-11) + * @version 1.2.9 (2024-08-04) * * @desc Returns required documents (documents fields). * @@ -1730,7 +1730,7 @@ public static function getDocuments( $dir = 'ASC', $limit = '' ){ - //Проверка на устаревшее значение $published + // Проверка на устаревшее значение $published if($published === false){ $published = 'all'; @@ -1739,7 +1739,7 @@ public static function getDocuments( ]); } - //Проверка на устаревшее значение $deleted === false + // Проверка на устаревшее значение $deleted === false if($deleted === false){ $deleted = 'all'; @@ -1815,14 +1815,14 @@ public static function getDocuments( ; $result = self::$modx->db->select( - //Fields + // Fields 'DISTINCT ' . $fields, - //From + // From self::$tables['site_content'] . ' sc LEFT JOIN ' . self::$tables['document_groups'] . ' dg ON dg.document = sc.id ', - //Where + // Where ( '(sc.id IN (' . implode( @@ -1837,13 +1837,13 @@ public static function getDocuments( $where . ') GROUP BY sc.id' ), - //Order + // Order ( $sort ? $sort . ' ' . $dir : '' ), - //Limit + // Limit $limit ); @@ -1855,7 +1855,7 @@ public static function getDocuments( /** * getDocument - * @version 1.1.6 (2018-06-17) + * @version 1.1.7 (2024-08-04) * * @desc Returns required data of a document (document fields). * @@ -1877,7 +1877,7 @@ public static function getDocument( $published = 'all', $deleted = 0 ){ - //Проверка на устаревшее значение $published + // Проверка на устаревшее значение $published if($published === false){ $published = 'all'; @@ -1886,7 +1886,7 @@ public static function getDocument( ]); } - //Проверка на устаревшее значение $deleted === false + // Проверка на устаревшее значение $deleted === false if($deleted === false){ $deleted = 'all'; @@ -1919,7 +1919,7 @@ public static function getDocument( /** * getTemplateVars - * @version 1.3.10 (2021-02-24) + * @version 1.3.11 (2024-08-04) * * @desc Returns the TV and fields array of a document. * @@ -1944,7 +1944,7 @@ public static function getTemplateVars( $sort = 'rank', $dir = 'ASC' ){ - //Проверка на устаревшее значение $published + // Проверка на устаревшее значение $published if($published === false){ $published = 'all'; @@ -2034,26 +2034,26 @@ public static function getTemplateVars( } $rs = self::$modx->db->select( - //Fields + // Fields ( $fields . ', IF(tvc.value != "", tvc.value, tv.default_text) as value' ), - //From + // From self::$tables['site_tmplvars'] . ' tv INNER JOIN ' . self::$tables['site_tmplvar_templates'] . ' tvtpl ON tvtpl.tmplvarid = tv.id LEFT JOIN ' . self::$tables['site_tmplvar_contentvalues'] . ' tvc ON tvc.tmplvarid=tv.id AND tvc.contentid = "' . $docid . '" ', - //Where + // Where ( $query . ' AND tvtpl.templateid = "' . $docRow['template'] . '"' ), - //Order + // Order ( $sort ? $sort . ' ' . $dir : @@ -2094,7 +2094,7 @@ public static function getTemplateVars( /** * getTemplateVarOutput - * @version 1.1.9 (2021-02-24) + * @version 1.1.10 (2024-08-04) * * @desc Returns the associative array of fields and TVs of a document. * @@ -2115,7 +2115,7 @@ public static function getTemplateVarOutput( $published = 'all', $sep = '' ){ - //Проверка на устаревшее значение $published + // Проверка на устаревшее значение $published if($published === false){ $published = 'all'; @@ -2204,7 +2204,7 @@ public static function getTemplateVarOutput( /** * getDocumentChildren - * @version 1.2.7 (2020-02-11) + * @version 1.2.8 (2024-08-04) * * @desc Returns the associative array of a document fields. * @@ -2234,7 +2234,7 @@ public static function getDocumentChildren( $dir = 'ASC', $limit = '' ){ - //Проверка на устаревшее значение $published + // Проверка на устаревшее значение $published if($published === false){ $published = 'all'; @@ -2243,7 +2243,7 @@ public static function getDocumentChildren( ]); } - //Проверка на устаревшее значение $deleted === false + // Проверка на устаревшее значение $deleted === false if($deleted === false){ $deleted = 'all'; @@ -2267,7 +2267,7 @@ public static function getDocumentChildren( $where = 'AND ' . $where; } - // modify field names to use sc. table reference + // Modify field names to use sc. table reference $fields = 'sc.' . implode( @@ -2299,7 +2299,7 @@ public static function getDocumentChildren( ) ; - // get document groups for current user + // Get document groups for current user if ($docgrp = self::$modx->getUserDocGroups()){ $docgrp = implode( ',', @@ -2307,7 +2307,7 @@ public static function getDocumentChildren( ); } - // build query + // Build query $access = ( self::$modx->isFrontend() ? @@ -2322,14 +2322,14 @@ public static function getDocumentChildren( ; $result = self::$modx->db->select( - //Fields + // Fields 'DISTINCT ' . $fields, - //From + // From self::$tables['site_content'] . ' sc LEFT JOIN '.self::$tables['document_groups'] . ' dg ON dg.document = sc.id ', - //Where + // Where ( 'sc.parent = "' . $parentid . @@ -2343,13 +2343,13 @@ public static function getDocumentChildren( $access . ') GROUP BY sc.id' ), - //Order + // Order ( $sort ? $sort . ' ' . $dir : '' ), - //Limit + // Limit $limit ); @@ -2360,7 +2360,7 @@ public static function getDocumentChildren( /** * getDocumentChildrenTVarOutput - * @version 1.3.5 (2021-03-09) + * @version 1.3.6 (2024-08-04) * * @desc Get necessary children of document. * @@ -2390,7 +2390,7 @@ public static function getDocumentChildrenTVarOutput( $where = '', $resultKey = 'id' ){ - //Получаем всех детей + // Получаем всех детей $docs = self::getDocumentChildren( $parentid, $published, @@ -2401,7 +2401,7 @@ public static function getDocumentChildrenTVarOutput( $sortDir ); - //Если ничего не получили, выкидываем + // Если ничего не получили, выкидываем if (!$docs){ return false; }else{ @@ -2433,7 +2433,7 @@ public static function getDocumentChildrenTVarOutput( } } - //Перебираем все документы + // Перебираем все документы for ( $i = 0; $i < count($docs); @@ -2445,9 +2445,9 @@ public static function getDocumentChildrenTVarOutput( $published ); - //Если что-то есть + // Если что-то есть if ($tvs){ - //Если нужно в качестве ключа использовать не индекс и такое поле есть + // Если нужно в качестве ключа использовать не индекс и такое поле есть if ( $resultKey !== false && array_key_exists( @@ -2455,14 +2455,14 @@ public static function getDocumentChildrenTVarOutput( $tvs ) ){ - //Записываем результат с соответствующим ключом + // Записываем результат с соответствующим ключом $result[$tvs[$resultKey]] = $tvs; if ($unsetResultKey){ unset($result[$tvs[$resultKey]][$resultKey]); } }else{ - //Просто накидываем по индексу + // Просто накидываем по индексу $result[] = $tvs; } } @@ -2474,14 +2474,14 @@ public static function getDocumentChildrenTVarOutput( /** * regEmptyClientScript - * @version 1.1.3 (2019-06-22) + * @version 1.1.4 (2024-08-04) * * @desc Adds a required JS-file into a required MODX inner list according to its version and name. The method is used to register the scripts, that has already been connected manually. * Be advised that the method does not add script code, but register its name and version to avoid future connections with $modx->regClientScript and $modx->regClientStartupScript, and the script code will be deleted if the script had been connected with $modx->regClientScript or $modx->regClientStartupScript. * * @see ddRegJsCssLinks snippet (http://code.divandesign.ru/modx/ddregjscsslinks), предназначенный для «правильного» подключения js и css. Даже при «ручном» подключении сниппет регистрирует то, что подключил, используя данный метод. * - * @param $params {stdClass|arrayAssociative} — Parameters, the pass-by-name style is used. @required + * @param $params {stdClass|arrayAssociative} — The parameters object. @required * @param $params->name {string} — Script name. @required * @param $params->version {string} — Script version. Default: '0'. * @param $params->startup {boolean} — Is the script connected in the ? Default: false. @@ -2494,7 +2494,7 @@ public static function getDocumentChildrenTVarOutput( * @return $result['pos'] {integer} — Ключ зарегистрированного скрипта в соответствующем внутреннем массиве MODX. */ public static function regEmptyClientScript($params = []){ - //Defaults + // Defaults $params = (object) array_merge( [ 'name' => '', @@ -2504,69 +2504,69 @@ public static function regEmptyClientScript($params = []){ (array) $params ); - //Required params + // Required params if (empty($params->name)){ return ''; } - //Приведём имя к нижнему регистру (чтоб сравнивать потом проще было, ведь нам пофиг) + // Приведём имя к нижнему регистру (чтоб сравнивать потом проще было, ведь нам пофиг) $name = strtolower($params->name); - //Если версия не задана, будет нулевая (полезно дальше при сравнении version_compare) + // Если версия не задана, будет нулевая (полезно дальше при сравнении version_compare) $version = isset($params->version) ? strtolower($params->version) : '0' ; - //Куда подключён скрипт: перед , или перед + // Куда подключён скрипт: перед , или перед $startup = isset($params->startup) ? $params->startup : false ; - //Ну мало ли + // Ну мало ли unset($overwritepos); - //По дефолту юзаем эту версию + // По дефолту юзаем эту версию $useThisVer = true; - //Если такой скрипт ужебыл подключён + // Если такой скрипт ужебыл подключён if (isset(self::$modx->loadedjscripts[$name])){ - //Если он подключался в
    + // Если он подключался в
    if (self::$modx->loadedjscripts[$name]['startup']){ - //Этот пусть будет так же + // Этот пусть будет так же $startup = true; } - //Сравниваем версию раннее подключённого скрипта с текущей: если старая меньше новой, надо юзать новую, иначе — старую + // Сравниваем версию раннее подключённого скрипта с текущей: если старая меньше новой, надо юзать новую, иначе — старую $useThisVer = version_compare( self::$modx->loadedjscripts[$name]['version'], $version, '<' ); - //Если надо юзать старую версию + // Если надо юзать старую версию if (!$useThisVer){ - //Запомним версию как старую. Здесь нам пофиг на его код, ведь новый код будет подключен мануально. + // Запомним версию как старую. Здесь нам пофиг на его код, ведь новый код будет подключен мануально. $version = self::$modx->loadedjscripts[$name]['version']; } - //Если новая версия должна подключаться в
    , а старая подключалась перед + // Если новая версия должна подключаться в
    , а старая подключалась перед if ( $startup == true && self::$modx->loadedjscripts[$name]['startup'] == false ){ - //Снесём старый скрипт из массива подключения перед (ведь новая подключится в ). Здесь нам пофиг на его код, ведь новый код будет подключен мануально. + // Снесём старый скрипт из массива подключения перед (ведь новая подключится в ). Здесь нам пофиг на его код, ведь новый код будет подключен мануально. unset(self::$modx->jscripts[self::$modx->loadedjscripts[$name]['pos']]); - //Если новая версия должна подключаться перед или старая уже подключалась перед . На самом деле, сработает только если обе перед или обе перед , т.к. если старая была перед , то новая выставится также кодом выше. + // Если новая версия должна подключаться перед или старая уже подключалась перед . На самом деле, сработает только если обе перед или обе перед , т.к. если старая была перед , то новая выставится также кодом выше. }else{ - //Запомним позицию старого скрипта (порядок подключения может быть важен для зависимых скриптов), на новую пофиг. Дальше код старой просто перетрётся в соответсвтии с позицией. + // Запомним позицию старого скрипта (порядок подключения может быть важен для зависимых скриптов), на новую пофиг. Дальше код старой просто перетрётся в соответсвтии с позицией. $overwritepos = self::$modx->loadedjscripts[$name]['pos']; } } - //Если надо подключить перед + // Если надо подключить перед if ($startup){ - //Позиция такова: либо старая (уже вычислена), либо максимальное значение между нолём и одним из ключей массива подключённых скриптов + 1 (это, чтобы заполнить возможные дыры) + // Позиция такова: либо старая (уже вычислена), либо максимальное значение между нолём и одним из ключей массива подключённых скриптов + 1 (это, чтобы заполнить возможные дыры) $pos = isset($overwritepos) ? $overwritepos : @@ -2576,10 +2576,10 @@ public static function regEmptyClientScript($params = []){ )) + 1 ; if ($useThisVer){ - //Запоминаем пустую строку подключения в нужный массив, т.к. подключаем мануально. + // Запоминаем пустую строку подключения в нужный массив, т.к. подключаем мануально. self::$modx->sjscripts[$pos] = ''; } - //Если надо подключить перед , то всё по аналогии, только массив другой + // Если надо подключить перед , то всё по аналогии, только массив другой }else{ $pos = isset($overwritepos) ? @@ -2594,7 +2594,7 @@ public static function regEmptyClientScript($params = []){ } } - //Запомним новоиспечённый скрипт для последующих обработок + // Запомним новоиспечённый скрипт для последующих обработок self::$modx->loadedjscripts[$name]['version'] = $version; self::$modx->loadedjscripts[$name]['startup'] = $startup; self::$modx->loadedjscripts[$name]['pos'] = $pos; @@ -2610,11 +2610,11 @@ public static function regEmptyClientScript($params = []){ /** * getDocumentParentIds - * @version 1.0.1 (2021-03-09) + * @version 1.0.2 (2024-08-04) * * @desc Gets the parent ID(s) of the required level. * - * @param $params {stdClass|arrayAssociative} — Parameters, the pass-by-name style is used. Default: —. + * @param $params {stdClass|arrayAssociative} — The parameters object. Default: —. * @param $params->docId {integer} — Document Id. Default: $modx->documentIdentifier. * @param $params->level {integer} — Parent level (1 — the immediate parent; 2 — the parent of the immediate parent; -1 — the last parent; -2 — the parent before the last; etc). Default: 1. * @param $params->totalResults {integer|'all'} — The number of parents that will be returned. Default: 'all'. @@ -2623,7 +2623,7 @@ public static function regEmptyClientScript($params = []){ * @return $result[i] {integer} — A parent ID. */ public static function getDocumentParentIds($params){ - //Defaults + // Defaults $params = (object) array_merge( [ 'docId' => self::$modx->documentIdentifier, @@ -2633,35 +2633,35 @@ public static function getDocumentParentIds($params){ (array) $params ); - //Получаем всех родителей (на самом деле максимум 10, но да ладно) + // Получаем всех родителей (на самом деле максимум 10, но да ладно) $result = self::$modx->getParentIds($params->docId); $resultLen = count($result); - //Если родители вообще есть + // Если родители вообще есть if ($resultLen > 0){ - //Если уровень задали больше, чем в принципе есть родителей, считаем, что нужен последний + // Если уровень задали больше, чем в принципе есть родителей, считаем, что нужен последний if ($params->level > $resultLen){ $params->level = -1; } - //Если уровень задаётся от начала (не от конца), то его надо бы декриминировать (т.к. самого себя в массиве $result не будет) + // Если уровень задаётся от начала (не от конца), то его надо бы декриминировать (т.к. самого себя в массиве $result не будет) if ($params->level > 0){ $params->level--; } - //Количество возвращаемых родителей + // Количество возвращаемых родителей if ($params->totalResults == 'all'){ - //All parents + // All parents $params->totalResults = $resultLen; }elseif (isset($params->totalResults)){ - //Needed number + // Needed number $params->totalResults = intval($params->totalResults); }else{ - //Immediate + // Immediate $params->totalResults = 1; } - //Получаем необходимых родителей + // Получаем необходимых родителей $result = array_slice( $result, $params->level, @@ -2678,7 +2678,7 @@ public static function getDocumentParentIds($params){ /** * getDocumentIdByUrl - * @version 1.2.1 (2021-03-09) + * @version 1.2.2 (2024-08-04) * * @desc Gets id of a document by its url. * @@ -2690,39 +2690,39 @@ public static function getDocumentIdByUrl($url){ $url = parse_url($url); $path = $url['path']; - //Если в адресе не было хоста, значит он относительный + // Если в адресе не было хоста, значит он относительный if (empty($url['host'])){ - //Получаем хост из конфига + // Получаем хост из конфига $siteHost = parse_url(self::$modx->getConfig('site_url')); - //For domains in IDNA ASCII-compatible format + // For domains in IDNA ASCII-compatible format $siteHost['host'] = function_exists('idn_to_utf8') ? idn_to_utf8($siteHost['host']) : $siteHost['host'] ; - //На всякий случай вышережем host из адреса (а то вдруг url просто без http:// передали) + лишние слэши по краям + // На всякий случай вышережем host из адреса (а то вдруг url просто без http:// передали) + лишние слэши по краям $path = trim( $path, $siteHost['host'] . '/' ); }else{ - //Просто убираем лишние слэши по краям + // Просто убираем лишние слэши по краям $path = trim( $url['path'], '/' ); } - //Если путь пустой, то мы в корне + // Если путь пустой, то мы в корне if ($path == ''){ return self::$modx->getConfig('site_start'); - //Если документ с таким путём есть + // Если документ с таким путём есть }elseif (!empty(self::$modx->documentListing[$path])){ - //Возвращаем его id + // Возвращаем его id return self::$modx->documentListing[$path]; - //В противном случае возвращаем 0 + // В противном случае возвращаем 0 }else{ return 0; } @@ -2730,14 +2730,14 @@ function_exists('idn_to_utf8') ? /** * verifyRenamedParams - * @version 1.7.2 (2024-08-02) + * @version 1.7.3 (2024-08-04) * * @see README.md */ public static function verifyRenamedParams($params){ - //Backward compatibility + // Backward compatibility if (func_num_args() > 1){ - //Convert ordered list of params to named + // Convert ordered list of params to named $params = self::orderedParamsToNamed([ 'paramsList' => func_get_args(), 'compliance' => [ @@ -2749,7 +2749,7 @@ public static function verifyRenamedParams($params){ $params = \DDTools\Tools\Objects::extend([ 'objects' => [ - //Defaults + // Defaults (object) [ 'returnCorrectedOnly' => true, 'writeToLog' => true @@ -2767,30 +2767,30 @@ public static function verifyRenamedParams($params){ $params_names = array_keys($params->params); - //Перебираем таблицу соответствия + // Перебираем таблицу соответствия foreach ( $params->compliance as $newName => $oldNames ){ - //Если параметр с новым именем не задан + // Если параметр с новым именем не задан if (!isset($params->params[$newName])){ - //Если старое имя только одно, всё равно приведём к массиву для удобства + // Если старое имя только одно, всё равно приведём к массиву для удобства if (!is_array($oldNames)){ $oldNames = [$oldNames]; } - //Находим все старые, которые используются + // Находим все старые, которые используются $oldNames = array_values(array_intersect( $params_names, $oldNames )); - //Если что-то нашлось + // Если что-то нашлось if (count($oldNames) > 0){ - //Зададим (берём значение первого попавшегося) + // Зададим (берём значение первого попавшегося) $result[$newName] = $params->params[$oldNames[0]]; - //If need to write to the CMS event log + // If need to write to the CMS event log if ($params->writeToLog){ $logMessageItems[] .= '
  • ' . @@ -2804,16 +2804,16 @@ public static function verifyRenamedParams($params){ ; } } - //If we must return all parameters + // If we must return all parameters }elseif (!$params->returnCorrectedOnly){ $result[$newName] = $params->params[$newName]; } } - //If we must return all parameters + // If we must return all parameters if (!$params->returnCorrectedOnly){ $result = array_merge( - //Get input params which are absent in compliance + // Get input params which are absent in compliance array_diff_key( $params->params, $params->compliance @@ -2822,7 +2822,7 @@ public static function verifyRenamedParams($params){ ); } - //If there is something to write to the CMS event log + // If there is something to write to the CMS event log if (count($logMessageItems) > 0){ self::logEvent([ 'message' => @@ -2844,11 +2844,11 @@ public static function verifyRenamedParams($params){ /** * sendMail - * @version 3.0.3 (2019-06-22) + * @version 3.0.4 (2024-08-04) * * @desc Method for sending e-mails. * - * @param $params {stdClass|arrayAssociative} — Parameters, the pass-by-name style is used. @required + * @param $params {stdClass|arrayAssociative} — The parameters object. @required * @param $params->to {array} — Addresses to mail. @required * @param $params->to[i] {string_email} — An address. @required * @param $params->text {string} — E-mail text. @required @@ -2861,9 +2861,9 @@ public static function verifyRenamedParams($params){ * @return $result[i] {0|1} — Status. */ public static function sendMail($params){ - //For backward compatibility + // For backward compatibility if (func_num_args() > 1){ - //Convert ordered list of params to named + // Convert ordered list of params to named $params = self::orderedParamsToNamed([ 'paramsList' => func_get_args(), 'compliance' => [ @@ -2876,7 +2876,7 @@ public static function sendMail($params){ ]); } - //Defaults + // Defaults $params = (object) array_merge( [ 'from' => self::$modx->getConfig('emailsender'), @@ -2886,31 +2886,31 @@ public static function sendMail($params){ (array) $params ); - //Добавлеям текст в сообщения + // Добавлеям текст в сообщения $message = trim($params->text); if(!empty($params->fileInputNames)){ $attachFiles = []; - //Перебираем имена полей с файлами + // Перебираем имена полей с файлами foreach( $params->fileInputNames as $value ){ - //Проверяем находится ли в POST массив + // Проверяем находится ли в POST массив if(is_array($_FILES[$value]['name'])){ - //Если массив пустой обрываем итерацию + // Если массив пустой обрываем итерацию if(!$_FILES[$value]['tmp_name'][0]){break;} - //Перебираем пост + // Перебираем пост foreach( $_FILES[$value]['name'] as $key => $name ){ - //Если нет ошибок + // Если нет ошибок if ($_FILES[$value]['error'][$key] == 0){ - //Добавляем в массив файлы + // Добавляем в массив файлы $attachFiles[] = [ 'path' => $_FILES[$value]['tmp_name'][$key], 'name' => $_FILES[$value]['name'][$key], @@ -2918,11 +2918,11 @@ public static function sendMail($params){ } } }else{ - //Если массив пустой обрываем итерацию + // Если массив пустой обрываем итерацию if(!$_FILES[$value]['tmp_name']){break;} - //Если нет ошибок + // Если нет ошибок if ($_FILES[$value]['error'] == 0){ - //Если не массив, то добавляем один файл + // Если не массив, то добавляем один файл $attachFiles[] = [ 'path' => $_FILES[$value]['tmp_name'], 'name' => $_FILES[$value]['name'], @@ -2938,7 +2938,7 @@ public static function sendMail($params){ $params->to as $val ){ - //Если адрес валидный + // Если адрес валидный if (filter_var( $val, FILTER_VALIDATE_EMAIL @@ -2951,13 +2951,13 @@ public static function sendMail($params){ self::$modx->mail->Subject = $params->subject; self::$modx->mail->Body = $message; - //Перебираем присоединяемые файлы + // Перебираем присоединяемые файлы if(!empty($attachFiles)){ foreach( $attachFiles as $value ){ - //добавить еще парамет name + // добавить еще парамет name self::$modx->mail->AddAttachment( $value['path'], $value['name'] @@ -2965,7 +2965,7 @@ public static function sendMail($params){ } } - //Отправляем письмо + // Отправляем письмо if(self::$modx->mail->send()){ $result[] = 1; }else{ @@ -2991,7 +2991,7 @@ public static function getResponse(){ /** * encodedStringToArray - * @version 1.2.1 (2024-08-02) + * @version 1.2.2 (2024-08-04) * * @desc Converts encoded strings to arrays. * Supported formats: @@ -3008,7 +3008,7 @@ public static function encodedStringToArray($inputString){ 'type' => 'objectArray' ]); - //The old deprecated format where string is separated by '||' and '::' + // The old deprecated format where string is separated by '||' and '::' if ( count($result) == 1 && array_keys($result)[0] == $inputString @@ -3043,11 +3043,11 @@ public static function unfoldArray( /** * createDir - * @version 1.0.1 (2024-08-02) + * @version 1.0.2 (2024-08-04) * * @desc Makes directory using `$modx->config['new_folder_permissions']`. Nested directories will be created too. Doesn't throw an exception if the folder already exists. * - * @param $params {stdClass|arrayAssociative} — Parameters, the pass-by-name style is used. @required + * @param $params {stdClass|arrayAssociative} — The parameters object. @required * @param $params->path {string} — The directory path. @required * * @return {boolean} — Success status. @@ -3130,15 +3130,15 @@ public static function explodeFieldsArr($fields = []){ 'message' => '

    The “ddTools::explodeFieldsArr” method is deprecated, use “ddTools::prepareDocData” instead.

    ' ]); - //Prepare data + // Prepare data $docData = self::prepareDocData([ 'data' => $fields, 'tvAdditionalFieldsToGet' => ['id'] ]); - //Save fields + // Save fields $result[0] = $docData->fieldsData; - //And TVs + // And TVs foreach ( $docData->tvsData as $tvName => diff --git a/require.php b/require.php index ed03052..d942a14 100644 --- a/require.php +++ b/require.php @@ -5,6 +5,9 @@ require_once('src/Tools/Objects.php'); require_once('src/Tools/Files.php'); require_once('src/Tools/Cache.php'); +require_once('src/Tools/Cache/Storage/Storage.php'); +require_once('src/Tools/Cache/Storage/Quick/Storage.php'); +require_once('src/Tools/Cache/Storage/Stable/Storage.php'); require_once('src/ObjectCollection/ObjectCollection.php'); require_once('src/Response/Response.php'); diff --git a/src/Base/AncestorTrait.php b/src/Base/AncestorTrait.php index 880bf56..9730bce 100644 --- a/src/Base/AncestorTrait.php +++ b/src/Base/AncestorTrait.php @@ -4,14 +4,14 @@ trait AncestorTrait { /** * getChildClassName - * @version 1.0 (2024-02-06) + * @version 1.0.1 (2024-08-04) * * @see README.md * * @throws \Exception */ final public static function getChildClassName($params): string { - //Defaults + // Defaults $params = (object) array_merge( [ 'parentDir' => null, @@ -20,7 +20,7 @@ final public static function getChildClassName($params): string { (array) $params ); - //Capitalize child name if needed + // Capitalize child name if needed if ($params->capitalizeName){ $params->name = ucfirst(strtolower($params->name)); } @@ -42,7 +42,7 @@ final public static function getChildClassName($params): string { ) ); - //Current classname without namespace + // Current classname without namespace $thisClassName = substr( $thisClassNameFull, ( diff --git a/src/Base/Base.php b/src/Base/Base.php index f98d4b7..96b4c97 100644 --- a/src/Base/Base.php +++ b/src/Base/Base.php @@ -15,7 +15,7 @@ abstract class Base { /** * getClassName - * @version 1.0 (2024-06-14) + * @version 1.0.1 (2024-08-04) * * @see README.md * @@ -24,12 +24,12 @@ abstract class Base { public static function getClassName(): \stdClass { $full = get_called_class(); - //Init + // Init if (is_null(self::$ddClassNames)){ self::$ddClassNames = new \stdClass(); } - //If not defined before for this child class + // If not defined before for this child class if ( !property_exists( self::$ddClassNames, @@ -52,10 +52,10 @@ public static function getClassName(): \stdClass { ); static::$ddClassNames->{$full}->full = '\\' . static::$ddClassNames->{$full}->full; - //Extract short class name + // Extract short class name static::$ddClassNames->{$full}->nameShort = array_pop($fullArray); - //If namespace exists + // If namespace exists if (count($fullArray) > 0){ static::$ddClassNames->{$full}->namespaceFull = '\\' @@ -64,10 +64,10 @@ public static function getClassName(): \stdClass { $fullArray ) ; - //Extract namespace + // Extract namespace static::$ddClassNames->{$full}->namespaceShort = array_pop($fullArray); - //If neamespace prefix exists + // If neamespace prefix exists if (count($fullArray) > 0){ static::$ddClassNames->{$full}->namespacePrefix = '\\' @@ -114,11 +114,11 @@ public function setExistingProps($props){ /** * ddSetProp - * @version 1.0.2 (2020-05-06) + * @version 1.0.3 (2024-08-04) * * @throws \ReflectionException * - * @param $params {stdClass|arrayAssociative} — Parameters, the pass-by-name style is used. @required + * @param $params {stdClass|arrayAssociative} — The parameters object. @required * @param $params->object {object} — Объект для модификации. @required * @param $params->propName {string} — Имя поля. @required * @param $params->propValue {mixed} — Значение. @required @@ -127,7 +127,7 @@ public function setExistingProps($props){ * @return {void} */ private function ddSetProp($params){ - //Defaults + // Defaults $params = (object) array_merge( [ 'class' => null diff --git a/src/ObjectCollection/ObjectCollection.php b/src/ObjectCollection/ObjectCollection.php index 342b003..dfcb0b2 100644 --- a/src/ObjectCollection/ObjectCollection.php +++ b/src/ObjectCollection/ObjectCollection.php @@ -22,29 +22,29 @@ public function __construct($params = []){ /** * setItems - * @version 1.0 (2021-11-26) + * @version 1.0.1 (2024-08-04) * * @see README.md */ public function setItems($params = []){ - //Reset items + // Reset items $this->items = []; - //Add new items + // Add new items $this->addItems($params); } /** * addItems - * @version 1.2.1 (2024-08-02) + * @version 1.2.2 (2024-08-04) * * @see README.md */ public function addItems($params = []){ - //# Prepare params + // # Prepare params $params = \DDTools\Tools\Objects::extend([ 'objects' => [ - //Defaults + // Defaults (object) [ 'items' => null, 'itemType' => null @@ -54,9 +54,9 @@ public function addItems($params = []){ ]); - //# Run + // # Run if (!is_null($params->items)){ - //Items must be an array + // Items must be an array if (!is_array($params->items)){ $params->items = \DDTools\Tools\Objects::convertType([ 'object' => $params->items, @@ -64,10 +64,10 @@ public function addItems($params = []){ ]); } - //Reset keys because they are no needed + // Reset keys because they are no needed $params->items = array_values($params->items); - //If need to convert type of items + // If need to convert type of items if (!is_null($params->itemType)){ foreach ( $params->items as @@ -90,15 +90,15 @@ public function addItems($params = []){ /** * convertItemsType - * @version 1.0.4 (2024-08-02) + * @version 1.0.5 (2024-08-04) * * @see README.md */ public function convertItemsType($params = []){ - //# Prepare params + // # Prepare params $params = \DDTools\Tools\Objects::extend([ 'objects' => [ - //Defaults + // Defaults (object) [ 'filter' => '', 'itemType' => 'objectStdClass' @@ -110,14 +110,14 @@ public function convertItemsType($params = []){ $params->filter = $this->prepareItemsFilter($params->filter); - //# Run + // # Run foreach ( $this->items as $itemIndex => $itemObject ){ if ( - //If item is matched to filter + // If item is matched to filter $this->isItemMatchFilter([ 'itemObject' => $itemObject, 'filter' => $params->filter @@ -138,15 +138,15 @@ public function convertItemsType($params = []){ /** * updateItems - * @version 1.0.4 (2024-08-02) + * @version 1.0.5 (2024-08-04) * * @see README.md */ public function updateItems($params = []){ - //# Prepare params + // # Prepare params $params = \DDTools\Tools\Objects::extend([ 'objects' => [ - //Defaults + // Defaults (object) [ 'filter' => '', 'data' => [], @@ -159,7 +159,7 @@ public function updateItems($params = []){ $params->filter = $this->prepareItemsFilter($params->filter); - //# Run + // # Run $affectedCount = 0; foreach ( @@ -168,7 +168,7 @@ public function updateItems($params = []){ $itemObject ){ if ( - //If item is matched to filter + // If item is matched to filter $this->isItemMatchFilter([ 'itemObject' => $itemObject, 'filter' => $params->filter @@ -186,12 +186,12 @@ public function updateItems($params = []){ ]) ]); - //Increment result count + // Increment result count $affectedCount++; - //If next item is no needed + // If next item is no needed if ($affectedCount == $params->limit){ - //Stop the cycle + // Stop the cycle break; } } @@ -200,15 +200,15 @@ public function updateItems($params = []){ /** * getItems - * @version 2.0.3 (2024-08-02) + * @version 2.0.4 (2024-08-04) * * @see README.md */ public function getItems($params = []){ - //# Prepare params + // # Prepare params $params = \DDTools\Tools\Objects::extend([ 'objects' => [ - //Defaults + // Defaults (object) [ 'filter' => '', 'limit' => 0, @@ -222,17 +222,17 @@ public function getItems($params = []){ $params->filter = $this->prepareItemsFilter($params->filter); - //# Run + // # Run $result = []; $resultCount = 0; - //Filter items + // Filter items foreach ( $this->items as $itemObject ){ if ( - //If item is matched to filter + // If item is matched to filter $this->isItemMatchFilter([ 'itemObject' => $itemObject, 'filter' => $params->filter @@ -242,7 +242,7 @@ public function getItems($params = []){ 'itemObject' => $itemObject ]); - //Save only field value instead of object if needed + // Save only field value instead of object if needed if (!is_null($params->propAsResultValue)){ $resultItemObject = \DDTools\Tools\Objects::getPropValue([ 'object' => $itemData, @@ -252,7 +252,7 @@ public function getItems($params = []){ $resultItemObject = $itemObject; } - //Save item + // Save item if (!is_null($params->propAsResultKey)){ $result[ \DDTools\Tools\Objects::getPropValue([ @@ -264,12 +264,12 @@ public function getItems($params = []){ $result[] = $resultItemObject; } - //Increment result count + // Increment result count $resultCount++; - //If next item is no needed + // If next item is no needed if ($resultCount == $params->limit){ - //Stop the cycle + // Stop the cycle break; } } @@ -280,15 +280,15 @@ public function getItems($params = []){ /** * getOneItem - * @version 1.0.2 (2024-08-02) + * @version 1.0.3 (2024-08-04) * * @see README.md */ public function getOneItem($params = []){ - //# Prepare params + // # Prepare params $params = \DDTools\Tools\Objects::extend([ 'objects' => [ - //Defaults + // Defaults (object) [ 'filter' => '', 'notFoundResult' => null @@ -298,7 +298,7 @@ public function getOneItem($params = []){ ]); - //# Run + // # Run $result = $this->getItems([ 'filter' => $params->filter, 'limit' => 1 @@ -315,15 +315,15 @@ public function getOneItem($params = []){ /** * deleteItems - * @version 1.0.2 (2024-08-02) + * @version 1.0.3 (2024-08-04) * * @see README.md */ public function deleteItems($params = []){ - //# Prepare params + // # Prepare params $params = \DDTools\Tools\Objects::extend([ 'objects' => [ - //Defaults + // Defaults (object) [ 'filter' => '', 'limit' => 0 @@ -335,7 +335,7 @@ public function deleteItems($params = []){ $params->filter = $this->prepareItemsFilter($params->filter); - //# Run + // # Run $affectedCount = 0; foreach ( @@ -344,7 +344,7 @@ public function deleteItems($params = []){ $itemObject ){ if ( - //If item is matched to filter + // If item is matched to filter $this->isItemMatchFilter([ 'itemObject' => $itemObject, 'filter' => $params->filter @@ -356,12 +356,12 @@ public function deleteItems($params = []){ 1 ); - //Increment result count + // Increment result count $affectedCount++; - //If next item is no needed + // If next item is no needed if ($affectedCount == $params->limit){ - //Stop the cycle + // Stop the cycle break; } } @@ -370,11 +370,11 @@ public function deleteItems($params = []){ /** * setOneItemData - * @version 1.0.1 (2023-12-25) + * @version 1.0.2 (2024-08-04) * * @desc Sets data of an item object. All setting of an item data inside the class must be use this method. It's convenient to override this method in child classes if items are not plain objects. * - * @param $params {stdClass|arrayAssociative} — Parameters, the pass-by-name style is used. @required + * @param $params {stdClass|arrayAssociative} — The parameters object. @required * @param $params->index {integer} — Item index which data will be set. @required * @param $params->data {array|object} — New item data. @required * @@ -395,11 +395,11 @@ protected function setOneItemData($params){ /** * getOneItemData - * @version 1.0 (2022-12-27) + * @version 1.0.1 (2024-08-04) * * @desc Returns data of an item object. All getting of an item data inside the class must use this method. It's convenient to override this method in child classes if items are not plain objects. * - * @param $params {stdClass|arrayAssociative} — Parameters, the pass-by-name style is used. @required + * @param $params {stdClass|arrayAssociative} — The parameters object. @required * @param $params->itemObject {array|object} — An item object which data will be returned. @required * * @return $result {object|arrayAssociative} @@ -412,9 +412,9 @@ protected function getOneItemData($params){ /** * isItemMatchFilter - * @version 2.0.2 (2024-08-02) + * @version 2.0.3 (2024-08-04) * - * @param $params {stdClass|arrayAssociative} — Parameters, the pass-by-name style is used. @required + * @param $params {stdClass|arrayAssociative} — The parameters object. @required * @param $params->itemObject {array|object} — An item to test. @required * @param $params->filter {array} — Result of $this->prepareItemsFilter. @required * @@ -423,24 +423,24 @@ protected function getOneItemData($params){ private function isItemMatchFilter($params){ $params = (object) $params; - //By default assume that item is matched + // By default assume that item is matched $result = true; $itemData = $this->getOneItemData([ 'itemObject' => $params->itemObject ]); - //Iterate over “or” conditions + // Iterate over “or” conditions foreach ( $params->filter as $orCondition ){ - //Iterate over “and” conditions + // Iterate over “and” conditions foreach ( $orCondition as $andCondition ){ - //If the item has no the property + // If the item has no the property if ( !\DDTools\Tools\Objects::isPropExists([ 'object' => $itemData, @@ -448,10 +448,10 @@ private function isItemMatchFilter($params){ ]) ){ $result = false; - //If filtration by the property value is no needed + // If filtration by the property value is no needed }elseif ($andCondition->operator == 'isset'){ $result = true; - //== + // == }elseif ($andCondition->operator == '=='){ $result = \DDTools\Tools\Objects::getPropValue([ @@ -460,7 +460,7 @@ private function isItemMatchFilter($params){ ]) == $andCondition->propValue ; - //!= + // != }else{ $result = \DDTools\Tools\Objects::getPropValue([ @@ -471,13 +471,13 @@ private function isItemMatchFilter($params){ ; } - //If item is not matched to this “and” condition, check with next “or” + // If item is not matched to this “and” condition, check with next “or” if (!$result){ break; } } - //If the item is matched to all “and” conditions, so it's already success + // If the item is matched to all “and” conditions, so it's already success if ($result){ break; } @@ -488,7 +488,7 @@ private function isItemMatchFilter($params){ /** * prepareItemsFilter - * @version 1.0 (2021-12-01) + * @version 1.0.1 (2024-08-04) * * @param $filter {string} * @@ -503,13 +503,13 @@ private function prepareItemsFilter($filter = ''){ $result = []; if (!empty($filter)){ - //Explode “or” conditions + // Explode “or” conditions $filter = explode( '||', $filter ); - //Iterate over “or” conditions + // Iterate over “or” conditions foreach ( $filter as $orIndex => @@ -517,9 +517,9 @@ private function prepareItemsFilter($filter = ''){ ){ $result[$orIndex] = []; - //Iterate over “and” conditions + // Iterate over “and” conditions foreach ( - //Explode “and” conditions + // Explode “and” conditions explode( '&&', $orCondition @@ -527,13 +527,13 @@ private function prepareItemsFilter($filter = ''){ $andIndex => $andCondition ){ - //Condition object + // Condition object $result[$orIndex][$andIndex] = (object) [ 'operator' => 'isset', 'propName' => '' ]; - //Prepare operator + // Prepare operator if ( strpos( $andCondition, @@ -550,34 +550,34 @@ private function prepareItemsFilter($filter = ''){ $result[$orIndex][$andIndex]->operator = '!='; } - //Prepare condition + // Prepare condition if ($result[$orIndex][$andIndex]->operator == 'isset'){ - //Just save name + // Just save name $result[$orIndex][$andIndex]->propName = $andCondition; }else{ - //Explode to name and value + // Explode to name and value $andCondition = explode( $result[$orIndex][$andIndex]->operator, $andCondition ); - //Save name + // Save name $result[$orIndex][$andIndex]->propName = $andCondition[0]; - //Prepare and save value + // Prepare and save value $result[$orIndex][$andIndex]->propValue = trim( - //Trim whitespaces + // Trim whitespaces trim($andCondition[1]), - //Then trim quotes + // Then trim quotes '"\'' ); } - //Prepare name + // Prepare name $result[$orIndex][$andIndex]->propName = trim( - //Trim whitespaces + // Trim whitespaces trim($result[$orIndex][$andIndex]->propName), - //Then trim quotes + // Then trim quotes '"\'' ); } diff --git a/src/Response/Response.php b/src/Response/Response.php index da210ab..cdf82ff 100644 --- a/src/Response/Response.php +++ b/src/Response/Response.php @@ -41,7 +41,7 @@ class Response { /** * validateMeta - * @version 1.1.1 (2021-03-10) + * @version 1.1.2 (2024-08-04) * * @param $meta {arrayAssociative} — Is an array of meta data. The method excludes any values passed in $meta except “code”, “eTag”, “success”, * and “message”. $meta['code'] and $meta['success'] are required. If defined, $meta['message'] must be an associative array with content @@ -70,29 +70,29 @@ class Response { public function validateMeta($meta){ $result = false; - //Parameter is valid + // Parameter is valid if (is_array($meta)){ $paramKeys = array_keys($meta); if( - //All required items are set + // All required items are set !count(array_diff( static::$requiredMetaKeys, $paramKeys )) && - //And only allowed items are set + // And only allowed items are set !count(array_diff( $paramKeys, static::$allowedMetaKeys )) && - //code is int + // code is int is_int($meta['code']) && - //success is bool + // success is bool is_bool($meta['success']) && ( - //message is not set + // message is not set !isset($meta['message']) || - //Or is valid + // Or is valid $this->validateMetaMessage($meta['message']) ) ){ @@ -105,7 +105,7 @@ public function validateMeta($meta){ /** * validateMetaMessage - * @version 1.1 (2021-03-10) + * @version 1.1.1 (2024-08-04) * * @param $message {arrayAssociative} — @reuired * @param $message['content'] {string} — @required @@ -116,22 +116,22 @@ public function validateMeta($meta){ public function validateMetaMessage($message){ $result = false; - //Parameter is valid + // Parameter is valid if (is_array($message)){ $paramKeys = array_keys($message); if ( - //All required items are set + // All required items are set !count(array_diff( static::$requiredMetaMessageKeys, $paramKeys )) && - //And only allowed items are set + // And only allowed items are set !count(array_diff( $paramKeys, static::$allowedMetaMessageKeys )) && - //content is string + // content is string is_string($message['content']) ){ $result = true; @@ -143,7 +143,7 @@ public function validateMetaMessage($message){ /** * setMeta - * @version 1.4.2 (2024-08-02) + * @version 1.4.3 (2024-08-04) * * @desc Setter for $this->meta. * @@ -152,7 +152,7 @@ public function validateMetaMessage($message){ * @return {boolean} */ public function setMeta($meta = []){ - //If $meta is set as stdClass, stringJsonObject, stringHjsonObject or stringQueryFormatted + // If $meta is set as stdClass, stringJsonObject, stringHjsonObject or stringQueryFormatted if (!is_array($meta)){ $meta = \DDTools\Tools\Objects::convertType([ 'object' => $meta, @@ -160,25 +160,25 @@ public function setMeta($meta = []){ ]); } - //If success is not set + // If success is not set if ( !\DDTools\Tools\Objects::isPropExists([ 'object' => $meta, 'propName' => 'success' ]) ){ - //true by default + // true by default $meta['success'] = true; } - //If code is not set + // If code is not set if ( !\DDTools\Tools\Objects::isPropExists([ 'object' => $meta, 'propName' => 'code' ]) ){ - //Depends on success by default + // Depends on success by default $meta['code'] = $meta['success'] ? 200 : @@ -199,7 +199,7 @@ public function setMeta($meta = []){ /** * setMetaMessage - * @version 1.1 (2021-05-11) + * @version 1.1.1 (2024-08-04) * * @desc Setter for $this->meta['message']. * @@ -210,9 +210,9 @@ public function setMeta($meta = []){ public function setMetaMessage($message){ $result = false; - //If parameter is valid + // If parameter is valid if ($this->validateMetaMessage($message)){ - //Set default meta if it is not set + // Set default meta if it is not set if (!is_array($this->meta)){ $this->setMeta(); } @@ -238,7 +238,7 @@ public function setData($data){ /** * setMetaData - * @version 1.0.2 (2024-08-02) + * @version 1.0.3 (2024-08-04) * * @desc Setter for $this->meta and $this->data. * @@ -247,7 +247,7 @@ public function setData($data){ * @return {void} */ public function setMetaData($params){ - //If $meta is set as stdClass, stringJsonObject, stringHjsonObject or stringQueryFormatted + // If $meta is set as stdClass, stringJsonObject, stringHjsonObject or stringQueryFormatted if (!is_array($params)){ $params = \DDTools\Tools\Objects::convertType([ 'object' => $params, @@ -298,7 +298,7 @@ public function getData(){ /** * isSuccess - * @version 1.0 (2021-03-11) + * @version 1.0.1 (2024-08-04) * * @return {boolean} */ @@ -306,9 +306,9 @@ public function isSuccess(){ $result = false; if ( - //If meta is set + // If meta is set is_array($this->meta) && - //And success + // And success $this->meta['success'] ){ $result = true; diff --git a/src/Snippet/Snippet.php b/src/Snippet/Snippet.php index 5af9654..59caf08 100644 --- a/src/Snippet/Snippet.php +++ b/src/Snippet/Snippet.php @@ -42,15 +42,15 @@ abstract class Snippet { /** * __construct - * @version 1.1.1 (2021-03-10) + * @version 1.1.2 (2024-08-04) * * @param $params {stdClass|arrayAssociative|stringJsonObject|stringQueryFormatted} */ public function __construct($params = []){ - //# Prepare name + // # Prepare name $thisClassName = get_called_class(); - //Get snippet name from namespace + // Get snippet name from namespace $this->name = substr( $thisClassName, 0, @@ -61,11 +61,11 @@ public function __construct($params = []){ ); - //# Prepare paths + // # Prepare paths $this->paths = (object) $this->paths; $this->paths->snippet = - //path to `assets` + // Path to `assets` dirname( __DIR__, 4 @@ -81,13 +81,13 @@ public function __construct($params = []){ ; - //# Prepare params + // # Prepare params $this->prepareParams($params); } /** * prepareParams - * @version 1.1.2 (2024-08-02) + * @version 1.1.3 (2024-08-04) * * @param $params {stdClass|arrayAssociative|stringJsonObject|stringQueryFormatted} * @@ -101,7 +101,7 @@ protected function prepareParams($params = []){ 'type' => 'objectStdClass' ]); - //Renaming params with backward compatibility + // Renaming params with backward compatibility if (!empty($this->renamedParamsCompliance)){ $params = \ddTools::verifyRenamedParams([ 'params' => $params, @@ -118,7 +118,7 @@ protected function prepareParams($params = []){ ){ $paramType = strtolower($paramType); - //Convert defaults + // Convert defaults if ( \DDTools\Tools\Objects::isPropExists([ 'object' => $this->params, @@ -137,7 +137,7 @@ protected function prepareParams($params = []){ } } - //Convert given + // Convert given if ( \DDTools\Tools\Objects::isPropExists([ 'object' => $params, @@ -160,9 +160,9 @@ protected function prepareParams($params = []){ $this->params = \DDTools\Tools\Objects::extend([ 'objects' => [ - //Defaults + // Defaults $this->params, - //Given parameters + // Given parameters $params ] ]); @@ -172,7 +172,7 @@ public abstract function run(); /** * runSnippet - * @version 1.0.1 (2024-08-02) + * @version 1.0.2 (2024-08-04) * * @param $params {stdClass|arrayAssociative|stringJsonObject|stringQueryFormatted} * @param $params->name {string} @@ -186,7 +186,7 @@ public static function runSnippet($params){ $params = \DDTools\Tools\Objects::extend([ 'objects' => [ - //Defaults + // Defaults (object) [ 'name' => '', 'params' => [] @@ -200,7 +200,7 @@ public static function runSnippet($params){ $requireData = (object) [ 'snippetDir' => - //path to `assets` + // Path to `assets` dirname( __DIR__, 4 diff --git a/src/Storage/DB/Storage.php b/src/Storage/DB/Storage.php index 53ca45d..f97d96e 100644 --- a/src/Storage/DB/Storage.php +++ b/src/Storage/DB/Storage.php @@ -45,21 +45,21 @@ class Storage extends \DDTools\Storage\Storage { /** * initStatic - * @version 1.1.2 (2024-08-02) + * @version 1.1.3 (2024-08-04) * * @desc Static “constructor”. * * @return {void} */ private static function initStatic(): void { - //If is not inited before (type of static::$columnsDefaultParams is just used as flag) + // If is not inited before (type of static::$columnsDefaultParams is just used as flag) if (!is_object(static::$columnsDefaultParams)){ - //Merge columnsDefaultParams from parent and child static props + // Merge columnsDefaultParams from parent and child static props static::$columnsDefaultParams = \DDTools\Tools\Objects::extend([ 'objects' => [ - //Parent (\DDTools\DB\Table::$columnsDefaultParams) + // Parent (\DDTools\DB\Table::$columnsDefaultParams) (object) self::$columnsDefaultParams, - //Child (e.g. \Something\Table\Base\Table::$columnsDefaultParams) + // Child (e.g. \Something\Table\Base\Table::$columnsDefaultParams) static::$columnsDefaultParams ] ]); @@ -68,18 +68,18 @@ private static function initStatic(): void { /** * __construct - * @version 3.0.1 (2024-08-02) + * @version 3.0.2 (2024-08-04) * - * @param $params {arrayAssociative|stdClass} — Parameters, the pass-by-name style is used. Default: —. - * @param $params->nameAlias {string} — Short table name (e. g. 'site_content'). You can define it in child classes or pass to the constructor directly. Default: ''. - * @param $params->columns {array} — Additional columns (that not defined in the class). Default: []. + * @param [$params] {arrayAssociative|stdClass} — The parameters object. + * @param [$params->nameAlias=''] {string} — Short table name (e. g. 'site_content'). You can define it in child classes or pass to the constructor directly. + * @param [$params->columns=[]] {array} — Additional columns (that not defined in the class). * @param $params->columns[$i] {stdClass|arrayAssociative|string} — Column parameters. Can be set as a simple string name if other parameters should be set by default. - * @param $params->columns[$i]->name {string} — Column name. @required - * @param $params->columns[$i]->isPublic {boolean} — Can column be used quite safely? Default: true. - * @param $params->columns[$i]->attrs {string} — Column attributes (empty value means static::$columnsDefaultParams->attrs). Default: static::$columnsDefaultParams->attrs. - * @param $params->columns[$i]->isReadOnly {boolean} — Can column be modified? Default: static::$columnsDefaultParams->isReadOnly. - * @param $params->columns[$i]->isComparedCaseSensitive {boolean} — Should column to be compared case-sensitive in where clauses? Default: static::$columnsDefaultParams->isComparedCaseSensitive. - * @param $params->columns[$i]->isTagsAllowed {boolean} — Are HTML and MODX tags allowed? Default: static::$columnsDefaultParams->isTagsAllowed. + * @param $params->columns[$i]->name {string} — Column name. + * @param [$params->columns[$i]->isPublic=true] {boolean} — Can column be used quite safely? + * @param [$params->columns[$i]->attrs=static::$columnsDefaultParams->attrs] {string} — Column attributes (empty value means static::$columnsDefaultParams->attrs). + * @param [$params->columns[$i]->isReadOnly=static::$columnsDefaultParams->isReadOnly] {boolean} — Can column be modified? + * @param [$params->columns[$i]->isComparedCaseSensitive=static::$columnsDefaultParams->isComparedCaseSensitive] {boolean} — Should column to be compared case-sensitive in where clauses? + * @param [$params->columns[$i]->isTagsAllowed=static::$columnsDefaultParams->isTagsAllowed] {boolean} — Are HTML and MODX tags allowed? */ public function __construct($params = []){ $params = \DDTools\Tools\Objects::extend([ @@ -91,7 +91,7 @@ public function __construct($params = []){ ] ]); - //Init static + // Init static static::initStatic(); $this->construct_props($params); @@ -101,9 +101,9 @@ public function __construct($params = []){ /** * construct_props - * @version 2.0.1 (2024-08-02) + * @version 2.0.2 (2024-08-04) * - * @param $params {stdClass} — Parameters, see $this->__construct. @required + * @param $params {stdClass} — Parameters, see $this->__construct. * * @return {void} */ @@ -112,7 +112,7 @@ private function construct_props($params): void { $this->nameAlias = $params->nameAlias; } - //Prepare table name + // Prepare table name $this->nameFull = \ddTools::$modx->getFullTableName($this->nameAlias); $this->columns = new \DDTools\ObjectCollection([ @@ -121,12 +121,12 @@ private function construct_props($params): void { ]); if (!empty($params->columns)){ - //Save additional columns to others + // Save additional columns to others foreach ( $params->columns as $columnParams ){ - //If column is set as a simple string name + // If column is set as a simple string name if (is_string($columnParams)){ $columnParams = [ 'name' => $columnParams @@ -137,9 +137,9 @@ private function construct_props($params): void { 'items' => [ \DDTools\Tools\Objects::extend([ 'objects' => [ - //Column data + // Column data (object) [ - //All additional columns are considered as safe by default + // All additional columns are considered as safe by default 'isPublic' => true, ], $columnParams, @@ -153,12 +153,12 @@ private function construct_props($params): void { /** * construct_db - * @version 1.0.2 (2024-08-02) + * @version 1.0.3 (2024-08-04) * * @return {void} */ private function construct_db(): void { - //We can't do something without table name + // We can't do something without table name if (!empty($this->nameAlias)){ $isTableExist = boolval( \ddTools::$modx->db->getValue( @@ -169,19 +169,19 @@ private function construct_db(): void { ) ); - //By default, consider that columns are absent + // By default, consider that columns are absent $columnsExisting = []; $columnsQuery = []; - //If table exists + // If table exists if ($isTableExist){ - //Получаем существующие колонки + // Получаем существующие колонки $columnsExisting = \ddTools::$modx->db->getColumnNames( \ddTools::$modx->db->select( '*', $this->nameFull, - //Что угодно, -1 выбран, так как таких записей точно быть не должно + // Что угодно, -1 выбран, так как таких записей точно быть не должно '`id` = -1' ) ); @@ -206,7 +206,7 @@ private function construct_db(): void { } } - //If the column is not exist + // If the column is not exist if ( !in_array( $columnData->name, @@ -232,9 +232,9 @@ private function construct_db(): void { $columnsQuery ); - //If table exists + // If table exists if ($isTableExist){ - //Create missing columns + // Create missing columns $resultQuery = 'ALTER TABLE ' . $this->nameFull . @@ -242,7 +242,7 @@ private function construct_db(): void { $columnsQuery ; }else{ - //Create table with needed columns + // Create table with needed columns $resultQuery = 'CREATE TABLE IF NOT EXISTS ' . $this->nameFull . @@ -252,7 +252,7 @@ private function construct_db(): void { ; } - //Create the table or add/change columns + // Create the table or add/change columns \ddTools::$modx->db->query($resultQuery); } } @@ -260,11 +260,11 @@ private function construct_db(): void { /** * cols_getColsParams - * @version 3.0.1 (2024-08-02) + * @version 3.0.2 (2024-08-04) * - * @param $params {arrayAssociative|stdClass} — Parameters, the pass-by-name style is used. Default: —. - * @param $params->paramName {'name'|'attrs'} — Column property to return. Default: 'name'. - * @param $params->filter {string} — Filter clause for column properties, see `\DDTools\ObjectCollection`. Default: ''. + * @param [$params] {arrayAssociative|stdClass} — The parameters object. + * @param [$params->paramName='name'] {'name'|'attrs'} — Column property to return. + * @param [$params->filter=''] {string} — Filter clause for column properties, see `\DDTools\ObjectCollection`. * * @return $result {arrayAssociative} * @return $result[$columnName] {string} — Key is column name, value is column property defined by $params->paramName. @@ -272,7 +272,7 @@ private function construct_db(): void { protected function cols_getColsParams($params = []): array { $params = \DDTools\Tools\Objects::extend([ 'objects' => [ - //Defaults + // Defaults (object) [ 'paramName' => 'name', 'filter' => '', @@ -290,18 +290,18 @@ protected function cols_getColsParams($params = []): array { /** * cols_getOneColParam - * @version 2.0.1 (2024-08-02) + * @version 2.0.2 (2024-08-04) * - * @param $params {arrayAssociative|stdClass} — Parameters, the pass-by-name style is used. Default: —. - * @param $params->filter {string} — Filter clause for column properties, see `\DDTools\ObjectCollection`. Default: ''. - * @param $params->paramName {'name'|'attrs'} — Column property to return. Default: 'name'. + * @param [$params] {arrayAssociative|stdClass} — The parameters object. + * @param [$params->filter=''] {string} — Filter clause for column properties, see `\DDTools\ObjectCollection`. + * @param [$params->paramName='name'] {'name'|'attrs'} — Column property to return. * * @return {mixed|null} — `null` means that column or property is not exist. */ protected function cols_getOneColParam($params = []){ $params = \DDTools\Tools\Objects::extend([ 'objects' => [ - //Defaults + // Defaults (object) [ 'filter' => '', 'paramName' => 'name', @@ -320,13 +320,13 @@ protected function cols_getOneColParam($params = []){ /** * cols_getValidNames - * @version 1.1.3 (2024-08-02) + * @version 1.1.4 (2024-08-04) * * @desc Gets valid column names. * - * @param $params {stdClass|arrayAssociative} — The object of parameters. @required - * @param $params->colNames {array|'*'|stringCommaSeparated} — Required column names. Can be set as array of column names, comma separated string or '*' for all columns. Only valid column names will be returned. Default: '*' (all). - * @param $params->colNames[$i] {string} — A column name. @required + * @param [$params] {stdClass|arrayAssociative} — The parameters object. + * @param [$params->colNames='*'] {array|'*'|stringCommaSeparated} — Required column names. Can be set as array of column names, comma separated string or '*' for all columns. Only valid column names will be returned. + * @param $params->colNames[$i] {string} — A column name. * * @return $result {arrayIndexed} * @return $result[$i] {string} @@ -341,15 +341,15 @@ protected function cols_getValidNames($params = []): array { ] ]); - //Return all exist columns by default + // Return all exist columns by default $result = array_values($this->cols_getColsParams()); - //If we don't need all esixt columns + // If we don't need all esixt columns if ( $params->colNames != '*' && !empty($params->colNames) ){ - //If column names are set as single column name + // If column names are set as single column name if (!is_array($params->colNames)){ $params->colNames = explode( ',', @@ -357,7 +357,7 @@ protected function cols_getValidNames($params = []): array { ); } - //Delete non-existent columns + // Delete non-existent columns $result = array_intersect( $params->colNames, $result @@ -369,10 +369,10 @@ protected function cols_getValidNames($params = []): array { /** * items_add - * @version 1.2.1 (2024-08-02) + * @version 1.2.2 (2024-08-04) * - * @param $params {stdClass|arrayAssociative} — The object of parameters. @required - * @param $params->items {mixed} — An array of items. @required + * @param $params {stdClass|arrayAssociative} — The parameters object. + * @param $params->items {mixed} — An array of items. * {array} — can be indexed or associative, keys will not be used * {object} — also can be set as an object for better convenience, only property values will be used * {stringJsonObject} — [JSON](https://en.wikipedia.org/wiki/JSON) object @@ -380,8 +380,8 @@ protected function cols_getValidNames($params = []): array { * {stringHjsonObject} — [HJSON](https://hjson.github.io/) object * {stringHjsonArray} — [HJSON](https://hjson.github.io/) array * {stringQueryFormatted} — [Query string](https://en.wikipedia.org/wiki/Query_string) - * @param $params->items[$itemIndex] {object|array} — An item. @required - * @param $params->items[$itemIndex]->{$propName} {mixed} — Keys are property names, values are values. @required + * @param $params->items[$itemIndex] {object|array} — An item. + * @param $params->items[$itemIndex]->{$propName} {mixed} — Keys are property names, values are values. * * @return $result {arrayIndexed} — Array of added items. * @return $result[$itemIndex] {stdClass} — A item object. @@ -390,7 +390,7 @@ protected function cols_getValidNames($params = []): array { public function items_add($params): array { $params = (object) $params; - //Items must be an array + // Items must be an array if (!is_array($params->items)){ $params->items = \DDTools\Tools\Objects::convertType([ 'object' => $params->items, @@ -406,7 +406,7 @@ public function items_add($params): array { ){ $itemObject = (object) $itemObject; - //ID can't be inserted + // ID can't be inserted unset($itemObject->id); $itemObject = $this->items_validateData([ @@ -432,15 +432,16 @@ public function items_add($params): array { /** * items_update - * @version 1.3.4 (2024-08-02) + * @version 1.6 (2024-08-06) * - * @param $params {stdClass|arrayAssociative} — The object of parameters. @required - * @param $params->data {object|array} — New item data. Existing item will be extended by this data. @required - * @param $params->data->{$propName} {mixed} — Keys are property names, values are values. @required - * @param $params->where {stdClass|arrayAssociative|string} — SQL 'WHERE' clause. Default: '' (all items will be updated). - * @param $params->where->{$fieldName} {string} — Key is a property name, value is a value. Only valid properties names will be used, others will be ignored. @required - * @param $params->limit {integer|0} — Maximum number of items to delete. `0` means all matching. Default: 0. - * @param $params->offset {integer} — Offset of the first item (can be useful with $params->limit). Default: 0. + * @param $params {stdClass|arrayAssociative} — The parameters object. + * @param $params->data {object|array} — New item data. Existing item will be extended by this data. + * @param $params->data->{$propName} {mixed} — Keys are property names, values are values. + * @param [$params->where=''] {stdClass|arrayAssociative|string|null} — SQL 'WHERE' clause. null or '' means that all items will be updated. + * @param $params->where->{$propName} {string|arrayIndexed} — Key is an item property name, value is a value. Only valid property names will be used, others will be ignored. You can specify multiple value variants through an array (SQL IN() operator), please note that empty arrays will just be ignored. + * @param $params->where->{$propName}[$i] {string} — A value. + * @param [$params->limit=0] {integer|0} — Maximum number of items to delete. `0` means all matching. + * @param [$params->offset=0] {integer} — Offset of the first item (can be useful with $params->limit). * * @return $result {arrayIndexed} — Array of updated items. * @return $result[$itemIndex] {stdClass} — A item object. @@ -449,7 +450,7 @@ public function items_add($params): array { public function items_update($params): array { $params = \DDTools\Tools\Objects::extend([ 'objects' => [ - //Defaults + // Defaults (object) [ 'where' => '', 'data' => [], @@ -464,17 +465,17 @@ public function items_update($params): array { 'data' => $params->data ]); - //Validate data (keep all except unsaveable) + // Validate data (keep all except unsaveable) $params->data = array_diff_key( (array) $params->data, - //ReadOnly props can't be updated + // ReadOnly props can't be updated $this->cols_getColsParams([ 'filter' => 'isReadOnly == 1' ]) ); if (!empty($params->data)){ - //Collect all updated resource IDs to a SQL variable + // Collect all updated resource IDs to a SQL variable \ddTools::$modx->db->query('SET @updated_ids := ""'); \ddTools::$modx->db->query(' UPDATE @@ -483,7 +484,7 @@ public function items_update($params): array { ' . $this->buildSqlSetString(['data' => $params->data]) . ' WHERE ( - ' . $this->buildSqlWhereString($params) . ' + ' . $this->items_prepareWhere($params) . ' ) AND ( @updated_ids := IF ( @@ -504,7 +505,7 @@ public function items_update($params): array { ') ); - //Comma separated string or fail + // Comma separated string or fail if ( is_string($dbResult) && !empty($dbResult) @@ -535,21 +536,22 @@ public function items_update($params): array { /** * items_delete - * @version 1.1.1 (2024-08-02) + * @version 1.4 (2024-08-06) * - * @param $params {stdClass|arrayAssociative} — The object of parameters. Default: —. - * @param $params->where {stdClass|arrayAssociative|string} — SQL 'WHERE' clause. Default: '' (all items will be deleted). - * @param $params->where->{$fieldName} {string} — Key is a property name, value is a value. Only valid properties names will be used, others will be ignored. @required - * @param $params->limit {integer|0} — Maximum number of items to delete. `0` means all matching. Default: 0. - * @param $params->offset {integer} — Offset of the first item (can be useful with $params->limit). Default: 0. - * @param $params->orderBy {string} — SQL 'ORDER BY' clause (can be useful with $params->limit). Default: ''. + * @param [$params] {stdClass|arrayAssociative} — The parameters object. + * @param [$params->where=''] {stdClass|arrayAssociative|string|null} — SQL 'WHERE' clause. null or '' means that all items will be deleted. + * @param $params->where->{$propName} {string|arrayIndexed} — Key is an item property name, value is a value. Only valid property names will be used, others will be ignored. You can specify multiple value variants through an array (SQL IN() operator), please note that empty arrays will just be ignored. + * @param $params->where->{$propName}[$i] {string} — A value. + * @param [$params->limit=0] {integer|0} — Maximum number of items to delete. `0` means all matching. + * @param [$params->offset=''] {integer} — Offset of the first item (can be useful with $params->limit). + * @param [$params->orderBy=''] {string} — SQL 'ORDER BY' clause (can be useful with $params->limit). * * @return {void} */ public function items_delete($params = []): void { $params = \DDTools\Tools\Objects::extend([ 'objects' => [ - //Defaults + // Defaults (object) [ 'where' => '', 'orderBy' => '', @@ -559,31 +561,32 @@ public function items_delete($params = []): void { ]); \ddTools::$modx->db->delete( - //Table + // Table $this->nameFull, - //Where - $this->buildSqlWhereString($params), - //OrderBy + // Where + $this->items_prepareWhere($params), + // OrderBy $params->orderBy, - //Limit + // Limit static::buildSqlLimitString($params) ); } /** * items_get - * @version 1.2.1 (2024-08-02) - * - * @param $params {stdClass|arrayAssociative} — The object of parameters. Default: —. - * @param $params->where {stdClass|arrayAssociative|string} — SQL 'WHERE' clause. Default: '' (all items will be returned). - * @param $params->where->{$fieldName} {string} — Key is a property name, value is a value. Only valid properties names will be used, others will be ignored. @required - * @param $params->orderBy {string} — SQL 'ORDER BY' clause. Default: ''. - * @param $params->limit {integer|0} — Maximum number of items to return. `0` means all matching. Default: 0. - * @param $params->offset {integer} — Offset of the first item (can be useful with $params->limit). Default: 0. - * @param $params->propsToReturn {array|'*'|stringCommaSeparated} — Required item prop names to return. Can be set as array of prop names, comma separated string or '*' for all props. Default: '*' (all). - * @param $params->propsToReturn[$i] {string} — A prop name. @required - * @param $params->propAsResultKey {string|null} — Item property, which value will be an item key in result array instead of an item index. For example, it can be useful if items have an ID property or something like that. `null` — result array will be indexed. Default: null. - * @param $params->propAsResultValue {string|null} — Item property, which value will be an item value in result array instead of an item object. Default: null. + * @version 1.5 (2024-08-06) + * + * @param [$params] {stdClass|arrayAssociative} — The parameters object. + * @param [$params->where=''] {stdClass|arrayAssociative|string|null} — SQL 'WHERE' clause. null or '' means that all items will be returned. + * @param $params->where->{$propName} {string|arrayIndexed} — Key is an item property name, value is a value. Only valid property names will be used, others will be ignored. You can specify multiple value variants through an array (SQL IN() operator), please note that empty arrays will just be ignored. + * @param $params->where->{$propName}[$i] {string} — A value. + * @param [$params->orderBy=''] {string} — SQL 'ORDER BY' clause. + * @param [$params->limit=0] {integer|0} — Maximum number of items to return. `0` means all matching. + * @param [$params->offset=0] {integer} — Offset of the first item (can be useful with $params->limit). + * @param [$params->propsToReturn='*'] {array|'*'|stringCommaSeparated} — Required item prop names to return. Can be set as array of prop names, comma separated string or '*' for all props. + * @param $params->propsToReturn[$i] {string} — A prop name. + * @param [$params->propAsResultKey=null] {string|null} — Item property, which value will be an item key in result array instead of an item index. For example, it can be useful if items have an ID property or something like that. `null` — result array will be indexed. + * @param [$params->propAsResultValue=null] {string|null} — Item property, which value will be an item value in result array instead of an item object. * * @return $result {arrayIndexed|arrayAssociative} — An array of items. Item property values will be used as result keys if `$params->propAsResultKey` is set. * @return $result[$itemIndex|$itemFieldValue] {stdClass|mixed} — A item object or item property value if specified in `$params->propAsResultValue`. @@ -591,7 +594,7 @@ public function items_delete($params = []): void { public function items_get($params = []): array { $params = \DDTools\Tools\Objects::extend([ 'objects' => [ - //Defaults + // Defaults (object) [ 'where' => '', 'orderBy' => '', @@ -611,18 +614,18 @@ public function items_get($params = []): array { if (!empty($params->propsToReturn)){ $sqlResult = \ddTools::$modx->db->select( - //Fields + // Fields implode( ',', $params->propsToReturn ), - //Table + // Table $this->nameFull, - //Where - $this->buildSqlWhereString($params), - //Order by + // Where + $this->items_prepareWhere($params), + // Order by $params->orderBy, - //Limit + // Limit $this->buildSqlLimitString($params) ); @@ -630,7 +633,7 @@ public function items_get($params = []): array { while ($itemData = \ddTools::$modx->db->getRow($sqlResult)){ $itemData = (object) $itemData; - //Save only field value instead of object if needed + // Save only field value instead of object if needed if (!is_null($params->propAsResultValue)){ $resultItemObject = \DDTools\Tools\Objects::getPropValue([ 'object' => $itemData, @@ -640,7 +643,7 @@ public function items_get($params = []): array { $resultItemObject = $itemData; } - //Save item + // Save item if (!is_null($params->propAsResultKey)){ $result[ \DDTools\Tools\Objects::getPropValue([ @@ -660,13 +663,13 @@ public function items_get($params = []): array { /** * items_validateData - * @version 1.0.1 (2023-12-28) + * @version 1.0.2 (2024-08-04) * * @desc Returns only used properties (columns) of $params->data. * - * @param $params {stdClass|arrayAssociative} — The object of parameters. @required - * @param $params->data {stdClass|arrayAssociative} — An array/object of item properties (e. g. you can use $_POST). Properties with only valid names will be returned, others will be deleted. @required - * @param $params->data->{$fieldName} {mixed} — Key is an item property name, value is a value. @required + * @param $params {stdClass|arrayAssociative} — The parameters object. + * @param $params->data {stdClass|arrayAssociative} — An array/object of item properties (e. g. you can use $_POST). Properties with only valid names will be returned, others will be deleted. + * @param $params->data->{$fieldName} {mixed} — Key is an item property name, value is a value. * * @return {stdClass} */ @@ -675,15 +678,15 @@ protected function items_validateData($params = []) :\stdClass { $params->data = (array) $params->data; - //Filter data (keep only used field names) + // Filter data (keep only used field names) $params->data = array_intersect_key( $params->data, array_fill_keys( - //Only used field names + // Only used field names $this->cols_getValidNames([ 'colNames' => array_keys($params->data) ]), - //No matter because the only keys will be used for comparison + // No matter because the only keys will be used for comparison null ) ); @@ -692,18 +695,19 @@ protected function items_validateData($params = []) :\stdClass { } /** - * buildSqlWhereString - * @version 1.1.3 (2024-08-02) + * items_prepareWhere + * @version 1.4 (2024-08-06) * - * @desc Builds where clause string from array. + * @desc Builds a where clause in the required internal format from externally passed parameters. * - * @param $params {stdClass|arrayAssociative} — The object of parameters. - * @param $params->where {stdClass|arrayAssociative|string} — Data for SQL where. Default: ''. - * @param $params->where->{$propName} {string} — Key is an item property name, value is a value. Only valid property names will be used, others will be ignored. @required + * @param [$params] {stdClass|arrayAssociative} — The parameters object. + * @param [$params->where=''] {stdClass|arrayAssociative|string|null} — Data for SQL where. null or '' means that it is not used at all. + * @param $params->where->{$propName} {string|arrayIndexed} — Key is an item property name, value is a value. Only valid property names will be used, others will be ignored. You can specify multiple value variants through an array (SQL IN() operator), please note that empty arrays will just be ignored. + * @param $params->where->{$propName}[$i] {string} — A value. * * @return {string} */ - final protected function buildSqlWhereString($params = []): string { + final protected function items_prepareWhere($params = []): string { $params = \DDTools\Tools\Objects::extend([ 'objects' => [ (object) [ @@ -713,11 +717,13 @@ final protected function buildSqlWhereString($params = []): string { ] ]); - if (is_string($params->where)){ + if (\ddTools::isEmpty($params->where)){ + $result = ''; + }elseif (is_string($params->where)){ $result = $params->where; - //If it is array or object + // If it is array or object }else{ - //Validate where conditions (keep only used field names) + // Validate where conditions (keep only used field names) $params->where = $this->items_validateData([ 'data' => $params->where ]); @@ -729,22 +735,51 @@ final protected function buildSqlWhereString($params = []): string { $propName => $propValue ){ - $result[] = - $propName . ' = ' . - //Case-sensitive comparison or not? - ( - $this->cols_getOneColParam([ - 'filter' => 'name == ' . $propName, - 'paramName' => 'isComparedCaseSensitive', - ]) ? - 'BINARY ' : - '' - ) . - '"' . $this->escapeItemPropValue([ - 'propName' => $propName, - 'propValue' => $propValue, - ]) . '"' - ; + if (!is_array($propValue)){ + $propValue = [$propValue]; + } + + //If an empty array was passed, it's best to just ignore it + if (!empty($propValue)){ + foreach ( + $propValue + as $propValue_variantIndex + => $propValue_variantValue + ){ + $propValue[$propValue_variantIndex] = + // Case-sensitive comparison or not? + ( + $this->cols_getOneColParam([ + 'filter' => 'name == ' . $propName, + 'paramName' => 'isComparedCaseSensitive', + ]) ? + 'BINARY ' : + '' + ) . + '"' . $this->escapeItemPropValue([ + 'propName' => $propName, + 'propValue' => $propValue_variantValue, + ]) . '"' + ; + } + + $resultItem = $propName . ' '; + + if (count($propValue) > 1){ + $resultItem .= + 'IN (' + . implode( + ',', + $propValue + ) + . ')' + ; + }else{ + $resultItem .= '= ' . $propValue[0]; + } + + $result[] = $resultItem; + } } $result = implode( @@ -758,18 +793,18 @@ final protected function buildSqlWhereString($params = []): string { /** * escapeItemPropValue - * @version 2.0.2 (2023-12-28) + * @version 2.0.3 (2024-08-04) * - * @param $params {stdClass|arrayAssociative} — The object of parameters. @required - * @param $params->propName {string} — Name of item property. @required - * @param $params->propValue {string} — Value of item property. @required + * @param $params {stdClass|arrayAssociative} — The parameters object. + * @param $params->propName {string} — Name of item property. + * @param $params->propValue {string} — Value of item property. * * @return {string} */ final protected function escapeItemPropValue($params): string { $params = (object) $params; - //Strip tags if required + // Strip tags if required if ( !$this->cols_getColsParams([ 'filter' => 'name == ' . $params->propName, @@ -784,11 +819,11 @@ final protected function escapeItemPropValue($params): string { /** * buildSqlSetString - * @version 1.0.2 (2023-12-26) + * @version 1.0.3 (2024-08-04) * - * @param $params {stdClass|arrayAssociative} — The object of parameters. @required - * @param $params->data {object|array} — Item data. @required - * @param $params->data->{$propName} {mixed} — Keys are property names, values are values. @required + * @param $params {stdClass|arrayAssociative} — The parameters object. + * @param $params->data {object|array} — Item data. + * @param $params->data->{$propName} {mixed} — Keys are property names, values are values. * * @return {string} */ @@ -818,18 +853,18 @@ final protected function buildSqlSetString($params): string { /** * buildSqlLimitString - * @version 1.0.1 (2024-08-02) + * @version 1.0.2 (2024-08-04) * - * @param $params {stdClass|arrayAssociative} — The object of parameters. Default: —. - * @param $params->limit {integer|0} — Maximum number of items to return. `0` means all matching. Default: 0. - * @param $params->offset {integer} — Offset of the first item. Default: 0. + * @param [$params] {stdClass|arrayAssociative} — The parameters object. + * @param [$params->limit=0] {integer|0} — Maximum number of items to return. `0` means all matching. + * @param [$params->offset=0] {integer} — Offset of the first item. * * @return {string} */ final protected static function buildSqlLimitString($params = []): string { $params = \DDTools\Tools\Objects::extend([ 'objects' => [ - //Defaults + // Defaults (object) [ 'limit' => 0, 'offset' => 0, @@ -839,22 +874,29 @@ final protected static function buildSqlLimitString($params = []): string { ]); return - //If limit is used + // If limit is used $params->limit > 0 ? ( 'LIMIT ' . - //Offset + // Offset ( $params->offset > 0 ? $params->offset . ', ' : '' ) . - //Count + // Count $params->limit ) : - //Without limit + // Without limit '' ; } + + /** + * @deprecated Use $this->items_prepareWhere + */ + final protected function buildSqlWhereString($params = []): string { + return $this->items_prepareWhere($params); + } } ?> \ No newline at end of file diff --git a/src/Storage/Storage.php b/src/Storage/Storage.php index e826470..fb44be9 100644 --- a/src/Storage/Storage.php +++ b/src/Storage/Storage.php @@ -6,10 +6,10 @@ abstract class Storage { /** * items_add - * @version 1.0 (2024-01-16) + * @version 1.0.1 (2024-08-04) * - * @param $params {stdClass|arrayAssociative} — The object of parameters. @required - * @param $params->items {mixed} — An array of items. @required + * @param $params {stdClass|arrayAssociative} — The parameters object. + * @param $params->items {mixed} — An array of items. * {array} — can be indexed or associative, keys will not be used * {object} — also can be set as an object for better convenience, only property values will be used * {stringJsonObject} — [JSON](https://en.wikipedia.org/wiki/JSON) object @@ -17,8 +17,8 @@ abstract class Storage { * {stringHjsonObject} — [HJSON](https://hjson.github.io/) object * {stringHjsonArray} — [HJSON](https://hjson.github.io/) array * {stringQueryFormatted} — [Query string](https://en.wikipedia.org/wiki/Query_string) - * @param $params->items[$itemIndex] {object|array} — An item. @required - * @param $params->items[$itemIndex]->{$propName} {mixed} — Keys are property names, values are values. @required + * @param $params->items[$itemIndex] {object|array} — An item. + * @param $params->items[$itemIndex]->{$propName} {mixed} — Keys are property names, values are values. * * @return $result {arrayIndexed} — Array of added items. * @return $result[$itemIndex] {stdClass} — A item object. @@ -28,11 +28,11 @@ abstract public function items_add($params): array; /** * items_addOne - * @version 2.0 (2023-12-25) + * @version 2.0.1 (2024-08-04) * - * @param $params {stdClass|arrayAssociative} — The object of parameters. @required - * @param $params->data {object|array} — An item. @required - * @param $params->data->{$propName} {mixed} — Keys are property names, values are values. @required + * @param $params {stdClass|arrayAssociative} — The parameters object. + * @param $params->data {object|array} — An item. + * @param $params->data->{$propName} {mixed} — Keys are property names, values are values. * * @return $result {stdClass|null} — An added item object or `null` if fail. * @return $result->id {integer} — ID of added item (if ID is used). @@ -57,15 +57,16 @@ public function items_addOne($params): ?\stdClass { /** * items_update - * @version 1.0 (2024-01-16) + * @version 1.6 (2024-08-06) * - * @param $params {stdClass|arrayAssociative} — The object of parameters. @required - * @param $params->data {object|array} — New item data. Existing item will be extended by this data. @required - * @param $params->data->{$propName} {mixed} — Keys are property names, values are values. @required - * @param $params->where {stdClass|arrayAssociative|string} — SQL 'WHERE' clause. Default: '' (all items will be updated). - * @param $params->where->{$fieldName} {string} — Key is a property name, value is a value. Only valid properties names will be used, others will be ignored. @required - * @param $params->limit {integer|0} — Maximum number of items to delete. `0` means all matching. Default: 0. - * @param $params->offset {integer} — Offset of the first item (can be useful with $params->limit). Default: 0. + * @param $params {stdClass|arrayAssociative} — The parameters object. + * @param $params->data {object|array} — New item data. Existing item will be extended by this data. + * @param $params->data->{$propName} {mixed} — Keys are property names, values are values. + * @param [$params->where=''] {stdClass|arrayAssociative|string|null} — SQL 'WHERE' clause. null or '' means that all items will be updated. + * @param $params->where->{$propName} {string|arrayIndexed} — Key is an item property name, value is a value. Only valid property names will be used, others will be ignored. You can specify multiple value variants through an array (SQL IN() operator), please note that empty arrays will just be ignored. + * @param $params->where->{$propName}[$i] {string} — A value. + * @param [$params->limit=0] {integer|0} — Maximum number of items to delete. `0` means all matching. + * @param [$params->offset=0] {integer} — Offset of the first item (can be useful with $params->limit). * * @return $result {arrayIndexed} — Array of updated items. * @return $result[$itemIndex] {stdClass} — A item object. @@ -75,13 +76,13 @@ abstract public function items_update($params): array; /** * items_updateOne - * @version 1.1.1 (2024-08-02) + * @version 1.2.1 (2024-08-04) * - * @param $params {stdClass|arrayAssociative} — The object of parameters. @required - * @param $params->data {object|array} — New item data. Existing item will be extended by this data. @required - * @param $params->data->{$propName} {mixed} — Keys are property names, values are values. @required - * @param $params->where {string} — SQL 'WHERE' clause. Default: '' (first found item will be updated). - * @param $params->isEnabledAddNotFound {boolean} — Is allowed to add item if it is not exist? Default: false. + * @param $params {stdClass|arrayAssociative} — The parameters object. + * @param $params->data {object|array} — New item data. Existing item will be extended by this data. + * @param $params->data->{$propName} {mixed} — Keys are property names, values are values. + * @param [$params->where=''] {string|null} — SQL 'WHERE' clause. null or '' means that first found item will be updated. + * @param [$params->isEnabledAddNotFound=false] {boolean} — Is allowed to add item if it is not exist? * * @return $result {stdClass|null} — An added item object or `null` if fail. * @return $result->id {integer} — ID of added item. @@ -89,7 +90,7 @@ abstract public function items_update($params): array; public function items_updateOne($params): ?\stdClass { $params = \DDTools\Tools\Objects::extend([ 'objects' => [ - //Defaults + // Defaults (object) [ 'isEnabledAddNotFound' => false, 'data' => [], @@ -126,14 +127,15 @@ public function items_updateOne($params): ?\stdClass { /** * items_delete - * @version 1.0 (2024-01-16) + * @version 1.3 (2024-08-06) * - * @param $params {stdClass|arrayAssociative} — The object of parameters. Default: —. - * @param $params->where {stdClass|arrayAssociative|string} — SQL 'WHERE' clause. Default: '' (all items will be deleted). - * @param $params->where->{$fieldName} {string} — Key is a property name, value is a value. Only valid properties names will be used, others will be ignored. @required - * @param $params->limit {integer|0} — Maximum number of items to delete. `0` means all matching. Default: 0. - * @param $params->offset {integer} — Offset of the first item (can be useful with $params->limit). Default: 0. - * @param $params->orderBy {string} — SQL 'ORDER BY' clause (can be useful with $params->limit). Default: ''. + * @param [$params] {stdClass|arrayAssociative} — The parameters object. Default: —. + * @param [$params->where=''] {stdClass|arrayAssociative|string|null} — SQL 'WHERE' clause. null or '' means that all items will be deleted. + * @param $params->where->{$propName} {string|arrayIndexed} — Key is an item property name, value is a value. Only valid property names will be used, others will be ignored. You can specify multiple value variants through an array (SQL IN() operator), please note that empty arrays will just be ignored. + * @param $params->where->{$propName}[$i] {string} — A value. + * @param [$params->limit=0] {integer|0} — Maximum number of items to delete. `0` means all matching. + * @param [$params->offset=0] {integer} — Offset of the first item (can be useful with $params->limit). + * @param [$params->orderBy=''] {string} — SQL 'ORDER BY' clause (can be useful with $params->limit). * * @return {void} */ @@ -141,12 +143,13 @@ abstract public function items_delete($params = []): void; /** * items_deleteOne - * @version 1.0.1 (2024-08-02) + * @version 1.3 (2024-08-08) * - * @param $params {stdClass|arrayAssociative} — The object of parameters. Default: —. - * @param $params->where {stdClass|arrayAssociative|string} — SQL 'WHERE' clause. Default: '' (first found item will be deleted). - * @param $params->where->{$fieldName} {string} — Key is a property name, value is a value. Only valid properties names will be used, others will be ignored. @required - * @param $params->orderBy {string} — SQL 'ORDER BY' clause. Default: ''. + * @param [$params] {stdClass|arrayAssociative} — The parameters object. Default: —. + * @param [$params->where=''] {stdClass|arrayAssociative|string|null} — SQL 'WHERE' clause. null or '' means that first found item will be deleted. + * @param $params->where->{$propName} {string|arrayIndexed} — Key is an item property name, value is a value. Only valid property names will be used, others will be ignored. You can specify multiple value variants through an array (SQL IN() operator), please note that empty arrays will just be ignored. + * @param $params->where->{$propName}[$i] {string} — A value. + * @param [$params->orderBy=''] {string} — SQL 'ORDER BY' clause. * * @return {void} */ @@ -165,18 +168,19 @@ public function items_deleteOne($params = []): void { /** * items_get - * @version 1.0 (2024-01-16) - * - * @param $params {stdClass|arrayAssociative} — The object of parameters. Default: —. - * @param $params->where {stdClass|arrayAssociative|string} — SQL 'WHERE' clause. Default: '' (all items will be returned). - * @param $params->where->{$fieldName} {string} — Key is a property name, value is a value. Only valid properties names will be used, others will be ignored. @required - * @param $params->orderBy {string} — SQL 'ORDER BY' clause. Default: ''. - * @param $params->limit {integer|0} — Maximum number of items to return. `0` means all matching. Default: 0. - * @param $params->offset {integer} — Offset of the first item (can be useful with $params->limit). Default: 0. - * @param $params->propsToReturn {array|'*'|stringCommaSeparated} — Required item prop names to return. Can be set as array of prop names, comma separated string or '*' for all props. Default: '*' (all). - * @param $params->propsToReturn[$i] {string} — A prop name. @required - * @param $params->propAsResultKey {string|null} — Item property, which value will be an item key in result array instead of an item index. For example, it can be useful if items have an ID property or something like that. `null` — result array will be indexed. Default: null. - * @param $params->propAsResultValue {string|null} — Item property, which value will be an item value in result array instead of an item object. Default: null. + * @version 1.3 (2024-08-06) + * + * @param [$params] {stdClass|arrayAssociative} — The parameters object. + * @param [$params->where=''] {stdClass|arrayAssociative|string|null} — SQL 'WHERE' clause. null or '' means that all items will be returned. + * @param $params->where->{$propName} {string|arrayIndexed} — Key is an item property name, value is a value. Only valid property names will be used, others will be ignored. You can specify multiple value variants through an array (SQL IN() operator), please note that empty arrays will just be ignored. + * @param $params->where->{$propName}[$i] {string} — A value. + * @param [$params->orderBy=''] {string} — SQL 'ORDER BY' clause. + * @param [$params->limit=0] {integer|0} — Maximum number of items to return. `0` means all matching. + * @param [$params->offset=0] {integer} — Offset of the first item (can be useful with $params->limit). + * @param [$params->propsToReturn='*'] {array|'*'|stringCommaSeparated} — Required item prop names to return. Can be set as array of prop names, comma separated string or '*' for all props. + * @param $params->propsToReturn[$i] {string} — A prop name. + * @param [$params->propAsResultKey=null] {string|null} — Item property, which value will be an item key in result array instead of an item index. For example, it can be useful if items have an ID property or something like that. `null` — result array will be indexed. + * @param [$params->propAsResultValue=null] {string|null} — Item property, which value will be an item value in result array instead of an item object. * * @return $result {arrayIndexed|arrayAssociative} — An array of items. Item property values will be used as result keys if `$params->propAsResultKey` is set. * @return $result[$itemIndex|$itemFieldValue] {stdClass|mixed} — A item object or item property value if specified in `$params->propAsResultValue`. @@ -185,21 +189,21 @@ abstract public function items_get($params = []): array; /** * items_getOne - * @version 1.0.1 (2024-08-02) + * @version 1.1.1 (2024-08-04) * - * @param $params {stdClass|arrayAssociative} — The object of parameters. Default: —. - * @param $params->where {string} — SQL 'WHERE' clause. Default: '' (first found item will be returned). - * @param $params->orderBy {string} — SQL 'ORDER BY' clause. Default: ''. - * @param $params->propsToReturn {array|'*'|stringCommaSeparated} — Required item prop names to return. Can be set as array of prop names, comma separated string or '*' for all props. Default: '*' (all). - * @param $params->propsToReturn[$i] {string} — A prop name. @required - * @param $params->notFoundResult {mixed} — What will be returned when no items found. Default: null. + * @param [$params] {stdClass|arrayAssociative} — The parameters object. + * @param [$params->where=''] {string|null} — SQL 'WHERE' clause. null or '' means that first found item will be returned. + * @param [$params->orderBy=''] {string} — SQL 'ORDER BY' clause. + * @param [$params->propsToReturn='*'] {array|'*'|stringCommaSeparated} — Required item prop names to return. Can be set as array of prop names, comma separated string or '*' for all props. + * @param $params->propsToReturn[$i] {string} — A prop name. + * @param [$params->notFoundResult=null] {mixed} — What will be returned when no items found. * * @return {stdClass|mixed} — Found item object or $params->notFoundResult. */ public function items_getOne($params = []){ $params = \DDTools\Tools\Objects::extend([ 'objects' => [ - //Defaults + // Defaults (object) [ 'where' => '', 'orderBy' => '', @@ -228,25 +232,40 @@ public function items_getOne($params = []){ /** * items_validateData - * @version 1.0 (2024-01-16) + * @version 1.0.1 (2024-08-04) * * @desc Returns only used properties (columns) of $params->data. * - * @param $params {stdClass|arrayAssociative} — The object of parameters. @required - * @param $params->data {stdClass|arrayAssociative} — An array/object of item properties (e. g. you can use $_POST). Properties with only valid names will be returned, others will be deleted. @required - * @param $params->data->{$fieldName} {mixed} — Key is an item property name, value is a value. @required + * @param $params {stdClass|arrayAssociative} — The parameters object. + * @param $params->data {stdClass|arrayAssociative} — An array/object of item properties (e. g. you can use $_POST). Properties with only valid names will be returned, others will be deleted. + * @param $params->data->{$fieldName} {mixed} — Key is an item property name, value is a value. * * @return {stdClass} */ abstract protected function items_validateData($params = []) :\stdClass; + /** + * items_prepareWhere + * @version 1.2 (2024-08-06) + * + * @desc Builds a where clause in the required internal format from externally passed parameters. + * + * @param [$params] {stdClass|arrayAssociative} — The parameters object. + * @param [$params->where=''] {stdClass|arrayAssociative|string|null} — Data for SQL where. null or '' means that it is not used at all. + * @param $params->where->{$propName} {string|arrayIndexed} — Key is an item property name, value is a value. Only valid property names will be used, others will be ignored. You can specify multiple value variants through an array (SQL IN() operator), please note that empty arrays will just be ignored. + * @param $params->where->{$propName}[$i] {string} — A value. + * + * @return {string} + */ + abstract protected function items_prepareWhere($params = []): string; + /** * escapeItemPropValue - * @version 1.0 (2024-01-16) + * @version 1.0.1 (2024-08-04) * - * @param $params {stdClass|arrayAssociative} — The object of parameters. @required - * @param $params->propName {string} — Name of item property. @required - * @param $params->propValue {string} — Value of item property. @required + * @param $params {stdClass|arrayAssociative} — The parameters object. + * @param $params->propName {string} — Name of item property. + * @param $params->propValue {string} — Value of item property. * * @return {string} */ diff --git a/src/Tools/Cache.php b/src/Tools/Cache.php index ef42c2e..d16ad82 100644 --- a/src/Tools/Cache.php +++ b/src/Tools/Cache.php @@ -2,147 +2,211 @@ namespace DDTools\Tools; class Cache { - private static ?string $cacheDir = null; - private static string $contentPrefix = ''; - private static int $contentPrefixLen = 37; + private static $theStableStorageClass = '\DDTools\Tools\Cache\Storage\Stable\Storage'; + private static $theQuickStorageClass = '\DDTools\Tools\Cache\Storage\Quick\Storage'; + + private static bool $isStaticInited = false; /** * initStatic - * @version 2.0.1 (2024-08-02) + * @version 2.1.5 (2024-08-07) * * @desc Static “constructor”. * * @return {void} */ private static function initStatic(): void { - if (is_null(static::$cacheDir)){ - static::$cacheDir = - //path to `assets` - dirname( - __DIR__, - 4 - ) - . '/cache/ddCache' - ; + if (!static::$isStaticInited){ + static::$isStaticInited = true; - if (!is_dir(static::$cacheDir)){ - \DDTools\Tools\Files::createDir([ - 'path' => static::$cacheDir, - ]); - } + static::$theStableStorageClass::initStatic(); + static::$theQuickStorageClass::initStatic(); } } /** * save - * @version 3.0.2 (2024-08-02) + * @version 3.2.8 (2024-08-19) * - * @param $params {stdClass|arrayAssociative} — The object of parameters. - * @param $params->resourceId {integer} — Resource ID related to cache (e. g. document ID). - * @param $params->suffix {string} — Cache suffix. You can use several suffixes with the same `$params->resourceId` to cache some parts within a resource. + * @param $params {stdClass|arrayAssociative} — The parameters object. * @param $params->data {string|array|stdClass} — Data to save. + * @param $params->resourceId {string} — Resource ID related to cache (e. g. document ID). + * @param $params->suffix {string} — Cache suffix. You can use several suffixes with the same `$params->resourceId` to cache some parts within a resource. * @param [$params->prefix='doc'] {string} — Cache prefix. + * @param [$params->isExtendEnabled=false] {boolean} — Should existing data be extended by $params->data or overwritten? * * @return {void} */ public static function save($params): void { + $params = (object) $params; + + static::saveSeveral( + \DDTools\Tools\Objects::extend([ + 'objects' => [ + (object) [ + 'items' => [ + $params->resourceId => $params->data, + ], + ], + $params, + ], + 'extendableProperties' => [ + 'resourceId', + 'suffix', + 'prefix', + 'isExtendEnabled', + ], + ]) + ); + } + + /** + * saveSeveral + * @version 1.0 (2024-08-19) + * + * @param $params {stdClass|arrayAssociative} — The parameters object. + * @param $params->items {stdClass|arrayAssociative} — Items to save. + * @param $params->items->{$resourceId} {string|array|stdClass} — Item data to save. Key is resource ID related to cache (e. g. document ID). + * @param $params->suffix {string} — Cache suffix. + * @param [$params->prefix='doc'] {string} — Cache prefix. + * @param [$params->isExtendEnabled=false] {boolean} — Should existing items data be extended by `$params->items` or overwritten? + * + * @return {void} + */ + public static function saveSeveral($params): void { static::initStatic(); - $params = (object) $params; + $params = \DDTools\Tools\Objects::extend([ + 'objects' => [ + (object) [ + 'prefix' => 'doc', + 'isExtendEnabled' => false, + ], + $params, + ], + ]); - //str|obj|arr - $dataType = - is_object($params->data) - ? 'obj' - : ( - is_array($params->data) - ? 'arr' - //All other types are considered as string (because of this we don't use the gettype function) - : 'str' - ) - ; + $saveParams = (object) [ + 'items' => new \stdClass(), + 'isExtendEnabled' => $params->isExtendEnabled, + ]; - if ($dataType != 'str'){ - $params->data = \DDTools\Tools\Objects::convertType([ - 'object' => $params->data, - 'type' => 'stringJsonAuto', + foreach ( + $params->items + as $itemName_resourceId + => $itemData + ){ + $cacheNameData = static::buildCacheNameData([ + 'resourceId' => $itemName_resourceId, + 'prefix' => $params->prefix, + 'suffix' => $params->suffix, ]); + + // We can't save something containing '*' in name + if (!$cacheNameData->advancedSearchData->isEnabled){ + $saveParams->items->{$cacheNameData->name} = $itemData; + } } - //Save cache file - file_put_contents( - //Cache file path - static::buildCacheFilePath($params), - //Cache content - ( - static::$contentPrefix - . $dataType - . $params->data - ) - ); + if (!\ddTools::isEmpty($saveParams->items)){ + // Save to quick storage + static::$theQuickStorageClass::save($saveParams); + + // Save to stable storage + static::$theStableStorageClass::save($saveParams); + } } /** * get - * @version 3.0 (2024-08-01) + * @version 3.1.10 (2024-08-13) * - * @param $params {stdClass|arrayAssociative} — The object of parameters. - * @param $params->resourceId {integer} — Document ID related to cache. - * @param $params->suffix {string} — Cache suffix. You can use several suffixes with the same `$params->resourceId` to cache some parts within a resource. + * @param $params {stdClass|arrayAssociative} — The parameters object. + * @param $params->resourceId {string} — Resource ID related to cache (e. g. document ID). + * @param $params->suffix {string} — Cache suffix. * @param [$params->prefix='doc'] {string} — Cache prefix. * * @return {null|string|array|stdClass} — `null` means that the cache file does not exist. */ public static function get($params){ + $resultCollection = static::getSeveral($params); + + return + !is_null($resultCollection) + ? current((array) $resultCollection) + : null + ; + } + + /** + * getSeveral + * @version 1.1.4 (2024-08-17) + * + * @param $params {stdClass|arrayAssociative} — The parameters object. + * @param $params->resourceId {string|'*'|array} — Resource ID(s) related to cache (e. g. document ID). Pass multiple IDs via array. + * @param $params->resourceId[$i] {string} — Resource ID. + * @param $params->suffix {string} — Cache suffix. + * @param [$params->prefix='doc'] {string} — Cache prefix. + * + * @return $result {stdClass|null} — `null` means that the cache of specified items does not exist. + * @return $result->{$resourceName} {string|array|stdClass} + */ + public static function getSeveral($params): ?\stdClass { static::initStatic(); - $result = null; + $params = \DDTools\Tools\Objects::extend([ + 'objects' => [ + (object) [ + 'prefix' => 'doc', + ], + $params, + ], + ]); + + $cacheNameData = static::buildCacheNameData($params); - $filePath = static::buildCacheFilePath($params); + // First try to get from quick storage + $resultCollection = static::$theQuickStorageClass::get($cacheNameData); - if (is_file($filePath)){ - //Cut PHP-code prefix - $result = substr( - file_get_contents($filePath), - static::$contentPrefixLen - ); - - //str|obj|arr - $dataType = substr( - $result, - 0, - 3 - ); - - //Cut dataType - $result = substr( - $result, - 3 - ); - - if ($dataType != 'str'){ - $result = \DDTools\Tools\Objects::convertType([ - 'object' => $result, - 'type' => - $dataType == 'obj' - ? 'objectStdClass' - : 'objectArray' - , + $isQuickStorageDataExist = !is_null($resultCollection); + + if (!$isQuickStorageDataExist){ + $resultCollection = static::$theStableStorageClass::get($cacheNameData); + } + + // Save absent items to quick storage from stable storage + if ( + !$isQuickStorageDataExist + && !is_null($resultCollection) + ){ + // Save to quick storage + foreach ( + $resultCollection + as $itemName + => $itemData + ){ + static::$theQuickStorageClass::save([ + 'items' => [ + $itemName => $itemData, + ], + // Nothing to extend + 'isExtendEnabled' => false, ]); } } - return $result; + return $resultCollection; } /** * delete - * @version 2.2.2 (2024-08-02) + * @version 2.5 (2024-08-14) * - * @param Clear cache files for specified document or every documents. + * @param Clear cache for specified resource or every resources. * - * @param [$params] {stdClass|arrayAssociative} — The object of parameters. - * @param [$params->resourceId=null] {integer|null} — Resource ID related to cache (e. g. document ID). Default: null (cache of all resources will be cleared independent of `$params->prefix`). + * @param [$params] {stdClass|arrayAssociative} — The parameters object. + * @param [$params->resourceId=null] {string|'*'|array|null} — Resource ID(s) related to cache (e. g. document ID). Pass multiple IDs via array. If the parameter is null or empty, cache of all resources will be cleared. + * @param [$params->resourceId[$i]] {string} — Resource ID. * @param [$params->prefix='doc'] {string|'*'} — Cache prefix. * @param [$params->suffix='*'] {string|'*'} — Cache suffix. * @@ -162,48 +226,69 @@ public static function delete($params = []): void { ], ]); - //Clear all cache - if (empty($params->resourceId)){ - \DDTools\Tools\Files::removeDir(static::$cacheDir); - //Clear cache for specified documents + // Clear all cache + if ( + empty($params->resourceId) + || ( + $params->resourceId == '*' + && $params->prefix == '*' + && $params->suffix == '*' + ) + ){ + // Clear quick storage + static::$theQuickStorageClass::delete(); + // Clear stable storage + static::$theStableStorageClass::delete(); + // Clear cache for specified resources }else{ - $files = glob( - static::buildCacheFilePath($params) - ); + $cacheNameData = static::buildCacheNameData($params); - foreach ( - $files - as $filepath - ){ - unlink($filepath); - } + // Clear quick storage + static::$theQuickStorageClass::delete($cacheNameData); + // Clear stable storage + static::$theStableStorageClass::delete($cacheNameData); } } /** - * buildCacheFilePath - * @version 4.0 (2024-08-01) + * buildCacheNameData + * @version 10.0 (2024-08-17) * - * @param $params {stdClass|arrayAssociative} — The object of parameters. - * @param $params->resourceId {integer} — Document ID related to cache. - * @param $params->suffix {string} — Cache suffix. You can use several suffixes with the same `$params->resourceId` to cache some parts within a resource. - * @param [$params->prefix='doc'] {string} — Cache prefix. + * @param $params {stdClass|arrayAssociative} — The parameters object. + * @param $params->resourceId {string|'*'|array} — Resource ID(s) related to cache (e. g. document ID). Pass multiple IDs via array. + * @param $params->resourceId[$i] {string} — Resource ID. + * @param $params->suffix {string|'*'} — Cache suffix. You can use several suffixes with the same `$params->resourceId` to cache some parts within a resource. + * @param $params->prefix {string|'*'} — Cache prefix. * - * @return {string} + * @return $result {stdClass} + * @return $result->name {string} — Cache name, e. g. 'prefix-resourceId-suffix'. If $params->resourceId is array, '*' will be used as resourceId. + * @return $result->advancedSearchData {stdClass} — Advanced search data. + * @return $result->advancedSearchData->isEnabled {boolean} — Is $params->resourceId, $params->suffix or $params->prefix equal to '*'? + * @return $result->advancedSearchData->resourceId {string} — $params->resourceId. + * @return $result->advancedSearchData->prefix {string} — $params->prefix. + * @return $result->advancedSearchData->suffix {string} — $params->suffix. */ - private static function buildCacheFilePath($params): string { - $params = \DDTools\Tools\Objects::extend([ - 'objects' => [ - (object) [ - 'prefix' => 'doc', - ], - $params, - ], - ]); + private static function buildCacheNameData($params): \stdClass { + $params = (object) $params; - return - static::$cacheDir - . '/' . $params->prefix . '-' . $params->resourceId . '-' . $params->suffix . '.php' + $resourceId = + is_array($params->resourceId) + ? '*' + : $params->resourceId ; + + return (object) [ + 'name' => $params->prefix . '-' . $resourceId . '-' . $params->suffix, + 'advancedSearchData' => (object) [ + 'isEnabled' => ( + $resourceId == '*' + || $params->prefix == '*' + || $params->suffix == '*' + ), + 'resourceId' => $params->resourceId, + 'prefix' => $params->prefix, + 'suffix' => $params->suffix, + ], + ]; } } \ No newline at end of file diff --git a/src/Tools/Cache/Storage/Quick/Storage.php b/src/Tools/Cache/Storage/Quick/Storage.php new file mode 100644 index 0000000..61a63bc --- /dev/null +++ b/src/Tools/Cache/Storage/Quick/Storage.php @@ -0,0 +1,163 @@ + $_SESSION, + 'propName' => 'ddCache', + ]) + ){ + $_SESSION['ddCache'] = new \stdClass(); + } + + static::$targetObject = &$_SESSION['ddCache']; + } + } + + /** + * save + * @version 3.0 (2024-08-15) + * + * @param $params {stdClass|arrayAssociative} — The parameters object. + * @param $params->items {stdClass|arrayAssociative} — Item's data to save. + * @param $params->items->{$name} {string|array|stdClass} — Key is a cache name, value is a data. + * @param $params->isExtendEnabled {boolean} — Should existing data be extended by $params->data or overwritten? + * + * @return {void} + */ + public static function save($params): void { + $params = (object) $params; + + foreach ( + $params->items + as $itemName + => $itemData + ){ + // Save to quick storage + static::$targetObject->{$itemName} = static::save_prepareData([ + 'name' => $itemName, + 'data' => $itemData, + 'isExtendEnabled' => $params->isExtendEnabled, + ]); + } + } + + /** + * get + * @version 4.0.2 (2024-08-15) + * + * @param $params {stdClass|arrayAssociative} — The parameters object. + * @param [$params->name] {string} — Cache name (required if $params->advancedSearchData->isEnabled == false). + * @param $params->advancedSearchData {stdClass} — Advanced search data. + * @param $params->advancedSearchData->isEnabled {boolean} — Is advanced search enabled? + * @param $params->advancedSearchData->resourceId {string|'*'|array} — Resource ID(s) related to cache (e. g. document ID). Pass multiple IDs via array. + * @param $params->advancedSearchData->resourceId[$i] {string} — Resource ID. + * @param $params->advancedSearchData->prefix {string|'*'} — Cache prefix. + * @param $params->advancedSearchData->suffix {string|'*'} — Cache suffix. + * + * @return $result {stdClass|null} — `null` means that the cache does not exist. + * @return $result->{$itemName} {string|array|stdClass} + */ + public static function get($params): ?\stdClass { + $params = (object) $params; + + $result = new \stdClass(); + + // Simple get one item if pattern is not used + if (!$params->advancedSearchData->isEnabled){ + $result_resource = \DDTools\Tools\Objects::getPropValue([ + 'object' => static::$targetObject, + 'propName' => $params->name, + ]); + + if (!is_null($result_resource)){ + $result->{$params->name} = $result_resource; + } + // Advanced search + }else{ + // Find needed cache items + foreach( + static::$targetObject + as $itemName + => $itemData + ){ + if ( + static::isOneItemNameMatched([ + 'name' => $itemName, + 'advancedSearchData' => $params->advancedSearchData, + ]) + ){ + $result->{$itemName} = $itemData; + } + } + } + + return + !\ddTools::isEmpty($result) + ? $result + : null + ; + } + + /** + * delete + * @version 4.0.2 (2024-08-15) + * + * @param Clear cache for specified resource or every resources. + * + * @param [$params] {stdClass|arrayAssociative} — The parameters object. If the parameter is omitted or empty, cache of all resources will be cleared. + * @param $params->name {string} — Cache name. + * @param $params->advancedSearchData {stdClass} — Advanced search data. + * @param $params->advancedSearchData->isEnabled {boolean} — Is advanced search enabled? + * @param $params->advancedSearchData->resourceId {string|'*'|array} — Resource ID(s) related to cache (e. g. document ID). Pass multiple IDs via array. + * @param $params->advancedSearchData->resourceId[$i] {string} — Resource ID. + * @param $params->advancedSearchData->prefix {string|'*'} — Cache prefix. + * @param $params->advancedSearchData->suffix {string|'*'} — Cache suffix. + * + * @return {void} + */ + public static function delete($params = []): void { + $params = (object) $params; + + // Clear all cache + if (\ddTools::isEmpty($params)){ + static::$targetObject = new \stdClass(); + // Clear cache for specified resources + }else{ + // Simple clear one item if pattern is not used + if (!$params->advancedSearchData->isEnabled){ + unset(static::$targetObject->{$params->name}); + // Advanced search + }else{ + // Find needed cache items + foreach( + static::$targetObject + as $itemName + => $itemData + ){ + if ( + static::isOneItemNameMatched([ + 'name' => $itemName, + 'advancedSearchData' => $params->advancedSearchData, + ]) + ){ + unset(static::$targetObject->{$itemName}); + } + } + } + } + } +} \ No newline at end of file diff --git a/src/Tools/Cache/Storage/Stable/Storage.php b/src/Tools/Cache/Storage/Stable/Storage.php new file mode 100644 index 0000000..1f9d4ee --- /dev/null +++ b/src/Tools/Cache/Storage/Stable/Storage.php @@ -0,0 +1,291 @@ +'; + private static int $contentPrefixLen = 37; + + /** + * initStatic + * @version 1.0 (2024-08-07) + * + * @desc Static “constructor”. + * + * @return {void} + */ + public static function initStatic(): void { + if (!isset(static::$targetDir)){ + static::$targetDir = + // Path to `assets` + dirname( + __DIR__, + 7 + ) + . '/cache/ddCache' + ; + + if (!is_dir(static::$targetDir)){ + \DDTools\Tools\Files::createDir([ + 'path' => static::$targetDir, + ]); + } + } + } + + /** + * save + * @version 3.0 (2024-08-15) + * + * @param $params {stdClass|arrayAssociative} — The parameters object. + * @param $params {stdClass|arrayAssociative} — The parameters object. + * @param $params->items {stdClass|arrayAssociative} — Item's data to save. + * @param $params->items->{$name} {string|array|stdClass} — Key is a cache name, value is a data. + * @param $params->isExtendEnabled {boolean} — Should existing data be extended by $params->data or overwritten? + * + * @return {void} + */ + public static function save($params): void { + $params = (object) $params; + + foreach ( + $params->items + as $itemName + => $itemData + ){ + // Save cache file + file_put_contents( + // Cache file path + static::buildCacheNamePath($itemName), + // Cache content + static::save_prepareData([ + 'name' => $itemName, + 'data' => $itemData, + 'isExtendEnabled' => $params->isExtendEnabled, + ]) + ); + } + } + + /** + * save_prepareData + * @version 2.0 (2024-08-15) + * + * @param $params {stdClass|arrayAssociative} — The parameters object. + * @param $params->name {string} — Cache name. + * @param $params->data {string|array|stdClass} — Data to prepare. + * @param $params->isExtendEnabled {boolean} — Should existing data be extended by $params->data or overwritten? + * + * @return {string} + */ + protected static function save_prepareData($params): string { + $result = parent::save_prepareData($params); + + // str|obj|arr + $dataType = + is_object($result) + ? 'obj' + : ( + is_array($result) + ? 'arr' + // All other types are considered as string (because of this we don't use the gettype function) + : 'str' + ) + ; + + if ($dataType != 'str'){ + $result = \DDTools\Tools\Objects::convertType([ + 'object' => $result, + 'type' => 'stringJsonAuto', + ]); + } + + return + static::$contentPrefix + . $dataType + . $result + ; + } + + /** + * get + * @version 4.0.2 (2024-08-15) + * + * @param $params {stdClass|arrayAssociative} — The parameters object. + * @param $params->name {string} — Cache name. + * @param $params->advancedSearchData {stdClass} — Advanced search data. + * @param $params->advancedSearchData->isEnabled {boolean} — Is advanced search enabled? + * @param $params->advancedSearchData->resourceId {string|'*'|array} — Resource ID(s) related to cache (e. g. document ID). Pass multiple IDs via array. + * @param $params->advancedSearchData->resourceId[$i] {string} — Resource ID. + * + * @return $result {stdClass|null} + * @return $result->{$itemName} {null|string|array|stdClass} — `null` means that the cache does not exist. + */ + public static function get($params): ?\stdClass { + $params = (object) $params; + + $result = new \stdClass(); + + $filePath = static::buildCacheNamePath($params->name); + + // Simple get one item if pattern is not used + if (!$params->advancedSearchData->isEnabled){ + $result_resource = static::get_oneItem($filePath); + + if (!is_null($result_resource)){ + $result->{$params->name} = $result_resource; + } + // Advanced search + }else{ + $files = glob($filePath); + + $isResourceIdSingle = !is_array($params->advancedSearchData->resourceId); + + foreach ( + $files + as $filePath + ){ + $itemName = basename( + $filePath, + '.php' + ); + + if ( + // Single + $isResourceIdSingle + // Multiple + || static::isOneItemNameMatched([ + 'name' => $itemName, + 'advancedSearchData' => $params->advancedSearchData, + ]) + ){ + $result->{$itemName} = static::get_oneItem($filePath); + } + } + } + + return + !\ddTools::isEmpty($result) + ? $result + : null + ; + } + + /** + * get_oneItem + * @version 1.0 (2024-08-12) + * + * @param $filePath {string} — Cache file path. + * + * @return $result {null|string|array|stdClass} — `null` means that the cache does not exist. + */ + private static function get_oneItem($filePath){ + $result = null; + + if (is_file($filePath)){ + // Cut PHP-code prefix + $result = substr( + file_get_contents($filePath), + static::$contentPrefixLen + ); + + // str|obj|arr + $dataType = substr( + $result, + 0, + 3 + ); + + // Cut dataType + $result = substr( + $result, + 3 + ); + + if ($dataType != 'str'){ + $result = \DDTools\Tools\Objects::convertType([ + 'object' => $result, + 'type' => + $dataType == 'obj' + ? 'objectStdClass' + : 'objectArray' + , + ]); + } + } + + return $result; + } + + /** + * delete + * @version 4.0.1 (2024-08-15) + * + * @param Clear cache for specified resource or every resources. + * + * @param [$params] {stdClass|arrayAssociative} — The parameters object. + * @param $params->name {string} — Cache name. + * @param $params->advancedSearchData {stdClass} — Advanced search data. + * @param $params->advancedSearchData->isEnabled {boolean} — Is advanced search enabled? + * @param $params->advancedSearchData->resourceId {string|'*'|array} — Resource ID(s) related to cache (e. g. document ID). Pass multiple IDs via array. + * @param $params->advancedSearchData->resourceId[$i] {string} — Resource ID. + * + * @return {void} + */ + public static function delete($params = []): void { + $params = (object) $params; + + // Clear all cache + if (empty($params->name)){ + \DDTools\Tools\Files::removeDir(static::$targetDir); + // Clear cache for specified resources + }else{ + $filePath = static::buildCacheNamePath($params->name); + + // Simple clear one item if pattern is not used + if (!$params->advancedSearchData->isEnabled){ + unlink($filePath); + }else{ + $files = glob($filePath); + + $isResourceIdSingle = !is_array($params->advancedSearchData->resourceId); + + foreach ( + $files + as $filePath + ){ + if ( + // Single + $isResourceIdSingle + // Multiple + || static::isOneItemNameMatched([ + 'name' => basename( + $filePath, + '.php' + ), + 'advancedSearchData' => $params->advancedSearchData, + ]) + ){ + unlink($filePath); + } + } + } + } + } + + /** + * buildCacheNamePath + * @version 1.0.1 (2024-08-07) + * + * @param $itemName {string} — Cache name. + * + * @return {string} + */ + private static function buildCacheNamePath($itemName): string { + return + static::$targetDir + . '/' . $itemName . '.php' + ; + } +} \ No newline at end of file diff --git a/src/Tools/Cache/Storage/Storage.php b/src/Tools/Cache/Storage/Storage.php new file mode 100644 index 0000000..b80334e --- /dev/null +++ b/src/Tools/Cache/Storage/Storage.php @@ -0,0 +1,152 @@ +items {stdClass|arrayAssociative} — Item's data to save. + * @param $params->items->{$name} {string|array|stdClass} — Key is a cache name, value is a data. + * @param $params->isExtendEnabled {boolean} — Should existing data be extended by $params->data or overwritten? + * + * @return {void} + */ + abstract public static function save($params): void; + + /** + * save_prepareData + * @version 2.0 (2024-08-15) + * + * @param $params {stdClass|arrayAssociative} — The parameters object. + * @param $params->name {string} — Cache name. + * @param $params->data {string|array|stdClass} — Data to prepare. + * @param $params->isExtendEnabled {boolean} — Should existing data be extended by $params->data or overwritten? + * + * @return {string|array|stdClass} + */ + protected static function save_prepareData($params){ + $params = (object) $params; + + return + $params->isExtendEnabled + // Extend existing + ? \DDTools\Tools\Objects::extend([ + 'objects' => [ + \DDTools\Tools\Objects::getPropValue([ + 'object' => static::get([ + 'name' => $params->name, + 'advancedSearchData' => (object) [ + 'isEnabled' => false, + ], + ]), + 'propName' => $params->name, + ]), + $params->data, + ], + ]) + // Overwrite existing + : $params->data + ; + } + + /** + * get + * @version 4.0.1 (2024-08-15) + * + * @param $params {stdClass|arrayAssociative} — The parameters object. + * @param $params->name {string} — Cache name. + * @param $params->advancedSearchData {stdClass} — Advanced search data. + * @param $params->advancedSearchData->isEnabled {boolean} — Is advanced search enabled? + * @param $params->advancedSearchData->resourceId {string|'*'|array} — Resource ID(s) related to cache (e. g. document ID). Pass multiple IDs via array. + * @param $params->advancedSearchData->resourceId[$i] {string} — Resource ID. + * @param $params->advancedSearchData->prefix {string|'*'} — Cache prefix. + * @param $params->advancedSearchData->suffix {string|'*'} — Cache suffix. + * + * @return $result {stdClass|null} — `null` means that the cache does not exist. + * @return $result->{$itemName} {string|array|stdClass} + */ + abstract public static function get($params): ?\stdClass; + + /** + * delete + * @version 4.0 (2024-08-15) + * + * @param Clear cache for specified resource or every resources. + * + * @param [$params] {stdClass|arrayAssociative} — The parameters object. If the parameter is omitted or empty, cache of all resources will be cleared. + * @param $params->name {string} — Cache name. + * @param $params->advancedSearchData {stdClass} — Advanced search data. + * @param $params->advancedSearchData->isEnabled {boolean} — Is advanced search enabled? + * @param $params->advancedSearchData->resourceId {string|'*'|array} — Resource ID(s) related to cache (e. g. document ID). Pass multiple IDs via array. + * @param $params->advancedSearchData->resourceId[$i] {string} — Resource ID. + * @param $params->advancedSearchData->prefix {string|'*'} — Cache prefix. + * @param $params->advancedSearchData->suffix {string|'*'} — Cache suffix. + * + * @return {void} + */ + abstract public static function delete($params = []): void; + + /** + * isOneItemNameMatched + * @version 2.0.1 (2024-08-15) + * + * @param $params {stdClass|arrayAssociative} — The parameters object. + * @param $params->name {string} — Cache name. + * @param $params->advancedSearchData {stdClass} — Advanced search data. + * @param $params->advancedSearchData->resourceId {string|'*'|array} — Resource ID(s) related to cache (e. g. document ID). Pass multiple IDs via array. + * @param $params->advancedSearchData->resourceId[$i] {string} — Resource ID. + * @param $params->advancedSearchData->prefix {string|'*'} — Cache prefix. + * @param $params->advancedSearchData->suffix {string|'*'} — Cache suffix. + * + * @return {boolean} + */ + protected static function isOneItemNameMatched($params): bool { + $params = (object) $params; + + $itemNameArray = explode( + '-', + $params->name + ); + + return + // resourceId + ( + // Any + $params->advancedSearchData->resourceId == '*' + // Specified + || ( + is_array($params->advancedSearchData->resourceId) + // Multiple + ? in_array( + $itemNameArray[1], + $params->advancedSearchData->resourceId + ) + // Single + : $itemNameArray[1] == $params->advancedSearchData->resourceId + ) + ) + // prefix + && ( + $params->advancedSearchData->prefix == '*' + || $itemNameArray[0] == $params->advancedSearchData->prefix + ) + // suffix + && ( + $params->advancedSearchData->suffix == '*' + || $itemNameArray[2] == $params->advancedSearchData->suffix + ) + ; + } +} \ No newline at end of file diff --git a/src/Tools/Files.php b/src/Tools/Files.php index e43f3db..430ba75 100644 --- a/src/Tools/Files.php +++ b/src/Tools/Files.php @@ -4,11 +4,11 @@ class Files { /** * createDir - * @version 1.3.1 (2019-09-03) + * @version 1.3.2 (2024-08-04) * * @desc Makes directory using `$modx->config['new_folder_permissions']`. Nested directories will be created too. Doesn't throw an exception if the folder already exists. * - * @param $params {stdClass|arrayAssociative} — Parameters, the pass-by-name style is used. @required + * @param $params {stdClass|arrayAssociative} — The parameters object. @required * @param $params->path {string} — The directory path. @required * * @return {boolean} — Success status. @@ -16,10 +16,10 @@ class Files { public static function createDir($params){ $params = (object) $params; - //True by default + // True by default $result = true; - //На всякий случай проверим, что необходимой папки ещё нет + // На всякий случай проверим, что необходимой папки ещё нет if (!file_exists($params->path)){ $result = mkdir( $params->path, @@ -36,11 +36,11 @@ public static function createDir($params){ /** * copyDir - * @version 2.0.3 (2020-06-17) + * @version 2.0.4 (2024-08-04) * * @desc Copies a required folder with all contents recursively. * - * @param $params {stdClass|arrayAssociative} — Parameters, the pass-by-name style is used. @required + * @param $params {stdClass|arrayAssociative} — The parameters object. @required * @param $params->sourcePath {string} — Path to the directory, that should copied. @required * @param $params->destinationPath {string} — The destination path. @required * @@ -49,7 +49,7 @@ public static function createDir($params){ public static function copyDir($params){ $params = (object) $params; - //Допишем папкам недостающие '/' при необходимости + // Допишем папкам недостающие '/' при необходимости if ( substr( $params->sourcePath, @@ -67,16 +67,16 @@ public static function copyDir($params){ $params->destinationPath .= '/'; } - //Проверяем существование + // Проверяем существование if (!file_exists($params->sourcePath)){ return false; } - //Если папки назначения нет, создадим её + // Если папки назначения нет, создадим её if (!file_exists($params->destinationPath)){ mkdir($params->destinationPath); } - //Получаем файлы в директории + // Получаем файлы в директории $fileNames = array_diff( scandir($params->sourcePath), [ @@ -89,7 +89,7 @@ public static function copyDir($params){ $fileNames as $fileName ){ - //Если это папка, обработаем её + // Если это папка, обработаем её if (is_dir($params->sourcePath . $fileName)){ self::copyDir([ 'sourcePath' => $params->sourcePath . $fileName, @@ -108,7 +108,7 @@ public static function copyDir($params){ /** * removeDir - * @version 1.0.7 (2020-06-17) + * @version 1.0.8 (2024-08-04) * * @desc Removes a required folder with all contents recursively. * @@ -117,12 +117,12 @@ public static function copyDir($params){ * @return {boolean} */ public static function removeDir($path){ - //Если не существует, ок + // Если не существует, ок if (!file_exists($path)){ return true; } - //Получаем файлы в директории + // Получаем файлы в директории $fileNames = array_diff( scandir($path), [ @@ -135,7 +135,7 @@ public static function removeDir($path){ $fileNames as $fileName ){ - //Если это папка, обработаем её + // Если это папка, обработаем её if (is_dir($path . '/' . $fileName)){ self::removeDir($path . '/' . $fileName); }else{ @@ -148,14 +148,14 @@ public static function removeDir($path){ /** * modifyImage - * @version 2.6.4 (2024-08-02) + * @version 2.6.5 (2024-08-04) * * @see README.md * * @return {void} */ public static function modifyImage($params){ - //Defaults + // Defaults $params = \DDTools\Tools\Objects::extend([ 'objects' => [ (object) [ @@ -176,7 +176,7 @@ public static function modifyImage($params){ } - //Include PHP.libraries.phpThumb + // Include PHP.libraries.phpThumb require_once( 'Files' . DIRECTORY_SEPARATOR . @@ -185,7 +185,7 @@ public static function modifyImage($params){ 'phpthumb.class.php' ); - //Prepare source image addresses + // Prepare source image addresses foreach ( [ 'sourceFullPathName', @@ -195,12 +195,12 @@ public static function modifyImage($params){ $paramName ){ if ( - //If the parameter is set + // If the parameter is set \DDTools\Tools\Objects::isPropExists([ 'object' => $params, 'propName' => $paramName ]) && - //And set as relative path + // And set as relative path substr( $params->{$paramName}, 0, @@ -208,7 +208,7 @@ public static function modifyImage($params){ ) != \ddTools::$modx->getConfig('base_path') ){ - //Convert relative path to absolute if needed + // Convert relative path to absolute if needed $params->{$paramName} = \ddTools::$modx->getConfig('base_path') . $params->{$paramName} @@ -217,7 +217,7 @@ public static function modifyImage($params){ } - //If source image is not exists + // If source image is not exists if (!file_exists($params->sourceFullPathName)){ return; } @@ -228,13 +228,13 @@ public static function modifyImage($params){ 'ratio' => 1 ]; - //Вычислим размеры оригинаольного изображения + // Вычислим размеры оригинаольного изображения list( $originalImg->width, $originalImg->height ) = getimagesize($params->sourceFullPathName); - //Если хотя бы один из размеров оригинала оказался нулевым (например, это не изображение) — на(\s?)бок + // Если хотя бы один из размеров оригинала оказался нулевым (например, это не изображение) — на(\s?)бок if ( $originalImg->width == 0 || $originalImg->height == 0 @@ -242,36 +242,36 @@ public static function modifyImage($params){ return; } - //Пропрорции реального изображения + // Пропрорции реального изображения $originalImg->ratio = $originalImg->width / $originalImg->height ; - //Если по каким-то причинам высота не задана + // Если по каким-то причинам высота не задана if ( $params->height == '' || $params->height == 0 ){ - //Вычислим соответственно пропорциям + // Вычислим соответственно пропорциям $params->height = $params->width / $originalImg->ratio ; } - //Если по каким-то причинам ширина не задана + // Если по каким-то причинам ширина не задана if ( $params->width == '' || $params->width == 0 ){ - //Вычислим соответственно пропорциям + // Вычислим соответственно пропорциям $params->width = $params->height * $originalImg->ratio ; } - //Если превьюшка уже есть и имеет нужный размер, ничего делать не нужно + // Если превьюшка уже есть и имеет нужный размер, ничего делать не нужно if ( $originalImg->width == $params->width && $originalImg->height == $params->height && @@ -281,40 +281,40 @@ public static function modifyImage($params){ } $thumb = new \phpThumb(); - //зачистка формата файла на выходе + // Зачистка формата файла на выходе $thumb->setParameter( 'config_output_format', null ); - //Путь к оригиналу + // Путь к оригиналу $thumb->setSourceFilename($params->sourceFullPathName); - //Качество (для JPEG) + // Качество (для JPEG) $thumb->setParameter( 'q', $params->quality ); - //Разрешить ли увеличивать изображение + // Разрешить ли увеличивать изображение $thumb->setParameter( 'aoe', intval($params->allowEnlargement) ); - //Если нужно просто обрезать + // Если нужно просто обрезать if($params->transformMode == 'crop'){ - //Ширина превьюшки + // Ширина превьюшки $thumb->setParameter( 'sw', $params->width ); - //Высота превьюшки + // Высота превьюшки $thumb->setParameter( 'sh', $params->height ); - //Если ширина оригинального изображения больше + // Если ширина оригинального изображения больше if ($originalImg->width > $params->width){ - //Позиция по оси x оригинального изображения (чтобы было по центру) + // Позиция по оси x оригинального изображения (чтобы было по центру) $thumb->setParameter( 'sx', ( @@ -325,9 +325,9 @@ public static function modifyImage($params){ ); } - //Если высота оригинального изображения больше + // Если высота оригинального изображения больше if ($originalImg->height > $params->height){ - //Позиция по оси y оригинального изображения (чтобы было по центру) + // Позиция по оси y оригинального изображения (чтобы было по центру) $thumb->setParameter( 'sy', ( @@ -338,26 +338,26 @@ public static function modifyImage($params){ ); } }else{ - //Ширина превьюшки + // Ширина превьюшки $thumb->setParameter( 'w', $params->width ); - //Высота превьюшки + // Высота превьюшки $thumb->setParameter( 'h', $params->height ); - //Если нужно уменьшить + отрезать + // Если нужно уменьшить + отрезать if($params->transformMode == 'resizeAndCrop'){ $thumb->setParameter( 'zc', '1' ); - //Если нужно пропорционально уменьшить, заполнив поля цветом + // Если нужно пропорционально уменьшить, заполнив поля цветом }elseif($params->transformMode == 'resizeAndFill'){ - //Устанавливаем фон (без решётки) + // Устанавливаем фон (без решётки) $thumb->setParameter( 'bg', str_replace( @@ -366,7 +366,7 @@ public static function modifyImage($params){ $params->backgroundColor ) ); - //Превьюшка должна точно соответствовать размеру и находиться по центру (недостающие области зальются цветом) + // Превьюшка должна точно соответствовать размеру и находиться по центру (недостающие области зальются цветом) $thumb->setParameter( 'far', 'c' @@ -375,7 +375,7 @@ public static function modifyImage($params){ } - //If need to overlay image with watermark + // If need to overlay image with watermark if (\DDTools\Tools\Objects::isPropExists([ 'object' => $params, 'propName' => 'watermarkImageFullPathName' @@ -385,13 +385,13 @@ public static function modifyImage($params){ implode( '|', [ - //WaterMarkImage + // WaterMarkImage 'wmi', - //Src + // Src $params->watermarkImageFullPathName, - //Alignment — center + // Alignment — center 'C', - //Opacity — 100 + // Opacity — 100 '100' ] ) @@ -399,9 +399,9 @@ public static function modifyImage($params){ } - //Создаём превьюшку + // Создаём превьюшку $thumb->GenerateThumbnail(); - //Сохраняем в файл + // Сохраняем в файл $thumb->RenderToFile($params->outputFullPathName); } } \ No newline at end of file diff --git a/src/Tools/Objects.php b/src/Tools/Objects.php index e73e91d..849a089 100644 --- a/src/Tools/Objects.php +++ b/src/Tools/Objects.php @@ -4,7 +4,7 @@ class Objects { /** * isObjectOrArray - * @version 0.1 (2020-04-30) + * @version 0.1.1 (2024-08-18) * * @todo Should it get $object directly or as $params->object? * @@ -12,14 +12,14 @@ class Objects { */ private static function isObjectOrArray($object){ return - is_object($object) || - is_array($object) + is_object($object) + || is_array($object) ; } /** * isPropExists - * @version 1.0.1 (2023-12-03) + * @version 1.0.3 (2024-08-18) * * @see README.md * @@ -29,30 +29,30 @@ public static function isPropExists($params){ $params = (object) $params; return - is_object($params->object) ? - //Objects - property_exists( + is_object($params->object) + // Objects + ? property_exists( $params->object, $params->propName - ) : - ( - is_array($params->object) ? - //Arrays - array_key_exists( + ) + : ( + is_array($params->object) + // Arrays + ? array_key_exists( $params->propName, $params->object - ) : - //Always not exist for other types for less fragility - false + ) + // Always not exist for other types for less fragility + : false ) ; } /** * getSingleLevelPropValue - * @version 1.0 (2023-03-09) + * @version 1.0.2 (2024-08-18) * - * @param $params {stdClass|arrayAssociative} — Parameters, the pass-by-name style is used. @required + * @param $params {stdClass|arrayAssociative} — The parameters object. @required * @param $params->object {stdClass|array} — Source object or array.. @required * @param $params->propName {string|integer} — Object property name or array key. @required * @@ -62,23 +62,23 @@ private static function getSingleLevelPropValue($params){ $params = (object) $params; return - !self::isPropExists($params) ? - //Non-existing properties - null : - //Existing properties - ( - is_object($params->object) ? - //Objects - $params->object->{$params->propName} : - //Arrays - $params->object[$params->propName] + !self::isPropExists($params) + // Non-existing properties + ? null + // Existing properties + : ( + is_object($params->object) + // Objects + ? $params->object->{$params->propName} + // Arrays + : $params->object[$params->propName] ) ; } /** * getPropValue - * @version 1.2.1 (2024-08-02) + * @version 1.2.3 (2024-08-18) * * @see README.md * @@ -87,46 +87,46 @@ private static function getSingleLevelPropValue($params){ public static function getPropValue($params){ $params = \DDTools\Tools\Objects::extend([ 'objects' => [ - //Defaults + // Defaults (object) [ - 'notFoundResult' => null + 'notFoundResult' => null, ], - $params - ] + $params, + ], ]); - //First try to get value by original propName + // First try to get value by original propName $result = self::getSingleLevelPropValue($params); if (is_null($result)){ - //Unfolding support (e. g. `parentKey.someKey.0`) + // Unfolding support (e. g. `parentKey.someKey.0`) $propNames = explode( '.', $params->propName ); - //If first-level exists + // If first-level exists if ( \DDTools\Tools\Objects::isPropExists([ 'object' => $params->object, - 'propName' => $propNames[0] + 'propName' => $propNames[0], ]) ){ $result = $params->object; - //Find needed value + // Find needed value foreach ( - $propNames as - $propName + $propNames + as $propName ){ - //If need to see deeper + // If need to see deeper if (self::isObjectOrArray($result)){ $result = self::getSingleLevelPropValue([ 'object' => $result, - 'propName' => $propName + 'propName' => $propName, ]); }else{ - //We need to look deeper, but we can't + // We need to look deeper, but we can't $result = null; break; @@ -136,8 +136,8 @@ public static function getPropValue($params){ } if ( - !is_null($params->notFoundResult) && - is_null($result) + !is_null($params->notFoundResult) + && is_null($result) ){ $result = $params->notFoundResult; } @@ -147,31 +147,31 @@ public static function getPropValue($params){ /** * convertType - * @version 1.3.1 (2024-08-02) + * @version 1.3.3 (2024-08-18) * * @see README.md */ public static function convertType($params){ - //Defaults + // Defaults $params = (object) array_merge( [ - 'type' => 'objectAuto' + 'type' => 'objectAuto', ], (array) $params ); - //Case insensitive parameter value + // Case insensitive parameter value $params->type = strtolower($params->type); $result = $params->object; - //If string is passed, we need to parse it first + // If string is passed, we need to parse it first if (!self::isObjectOrArray($params->object)){ if (empty($params->object)){ $result = new \stdClass(); }else{ $isObjectJson = - //JSON first letter is `{` or `[` + // JSON first letter is `{` or `[` in_array( substr( ltrim($params->object), @@ -180,7 +180,7 @@ public static function convertType($params){ ), [ '{', - '[' + '[', ] ) ; @@ -192,27 +192,27 @@ public static function convertType($params){ ); if (is_null($result)){ - //Include PHP.libraries.hjson + // Include PHP.libraries.hjson require_once( - 'Objects' . - DIRECTORY_SEPARATOR . - 'hjson' . - DIRECTORY_SEPARATOR . - 'HJSONException.php' + 'Objects' + . DIRECTORY_SEPARATOR + . 'hjson' + . DIRECTORY_SEPARATOR + . 'HJSONException.php' ); require_once( - 'Objects' . - DIRECTORY_SEPARATOR . - 'hjson' . - DIRECTORY_SEPARATOR . - 'HJSONUtils.php' + 'Objects' + . DIRECTORY_SEPARATOR + . 'hjson' + . DIRECTORY_SEPARATOR + . 'HJSONUtils.php' ); require_once( - 'Objects' . - DIRECTORY_SEPARATOR . - 'hjson' . - DIRECTORY_SEPARATOR . - 'HJSONParser.php' + 'Objects' + . DIRECTORY_SEPARATOR + . 'hjson' + . DIRECTORY_SEPARATOR + . 'HJSONParser.php' ); try { @@ -221,19 +221,19 @@ public static function convertType($params){ $result = $hjsonParser->parse( $params->object, [ - 'assoc' => $params->type == 'objectarray' + 'assoc' => $params->type == 'objectarray', ] ); }catch (\Exception $e){ - //Flag + // Flag $isObjectJson = false; } } } - //Not JSON + // Not JSON if (!$isObjectJson){ - //Query string + // Query string parse_str( $params->object, $result @@ -242,49 +242,50 @@ public static function convertType($params){ } } - //stdClass + // stdClass if ($params->type == 'objectstdclass'){ $result = (object) $result; - //array + // array }elseif ($params->type == 'objectarray'){ $result = (array) $result; - //stringQueryFormatted + // stringQueryFormatted }elseif ( - $params->type == 'stringqueryformatted' || - //Backward compatibility with typo - $params->type == 'stringqueryformated' + $params->type == 'stringqueryformatted' + // Backward compatibility with typo + || $params->type == 'stringqueryformated' ){ $result = http_build_query($result); - //stringHtmlAttrs + // stringHtmlAttrs }elseif ($params->type == 'stringhtmlattrs'){ $resultObject = $result; - //Temporary use an array + // Temporary use an array $result = []; foreach ( - $resultObject as - $result_itemAttrName => - $result_itemAttrValue + $resultObject + as $result_itemAttrName + => $result_itemAttrValue ){ - //Prepare value - //Boolean to 0|1 + // Prepare value + // Boolean to 0|1 if (is_bool($result_itemAttrValue)){ $result_itemAttrValue = intval($result_itemAttrValue); - //Objects to JSON + // Objects to JSON }elseif(self::isObjectOrArray($result_itemAttrValue)){ $result_itemAttrValue = self::convertType([ 'object' => $result_itemAttrValue, 'type' => 'stringJsonAuto', ]); - //Other to string + // Other to string }else{ $result_itemAttrValue = strval($result_itemAttrValue); } $result[] = - $result_itemAttrName . '=\'' . - $result_itemAttrValue . - '\'' + $result_itemAttrName + . '=\'' + . $result_itemAttrValue + . '\'' ; } @@ -292,13 +293,14 @@ public static function convertType($params){ ' ', $result ); - //stringJson + // stringJson }elseif( substr( $params->type, 0, 10 - ) == 'stringjson' + ) + == 'stringjson' ){ if ($params->type == 'stringjsonobject'){ $result = (object) $result; @@ -308,7 +310,7 @@ public static function convertType($params){ $result = json_encode( $result, - //JSON_UNESCAPED_UNICODE — Не кодировать многобайтные символы Unicode | JSON_UNESCAPED_SLASHES — Не экранировать / + // JSON_UNESCAPED_UNICODE — Не кодировать многобайтные символы Unicode | JSON_UNESCAPED_SLASHES — Не экранировать / JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES ); } @@ -318,25 +320,44 @@ public static function convertType($params){ /** * extend - * @version 1.3.10 (2023-03-09) + * @version 1.4 (2024-08-19) * * @see README.md * * @return {object|array} */ public static function extend($params){ - //Defaults + // # Prepare params $params = (object) array_merge( + // Defaults [ 'deep' => true, - 'overwriteWithEmpty' => true + 'overwriteWithEmpty' => true, + 'extendableProperties' => null, ], (array) $params ); - //The first item is the target + // $params->extendableProperties + if ( + // Not all properties + !is_null($params->extendableProperties) + // But invalid + && ( + !is_array($params->extendableProperties) + || empty($params->extendableProperties) + ) + ){ + // Means all properties + $params->extendableProperties = null; + } + + + // # Run + + // The first item is the target $result = array_shift($params->objects); - //Empty or invalid target + // Empty or invalid target if (!self::isObjectOrArray($result)){ $result = new \stdClass(); } @@ -344,126 +365,52 @@ public static function extend($params){ $isResultObject = is_object($result); foreach ( - $params->objects as - $additionalProps + $params->objects + as $additionalProps ){ - //Invalid objects will not be used + // Invalid objects will not be used if (self::isObjectOrArray($additionalProps)){ foreach ( - $additionalProps as - $additionalPropName => - $additionalPropValue + $additionalProps + as $additionalPropName + => $additionalPropValue ){ - //Is the source property exists - $isSourcePropExists = self::isPropExists([ - 'object' => $result, - 'propName' => $additionalPropName - ]); - - if ($isSourcePropExists){ - //Source property value - $sourcePropValue = self::getSingleLevelPropValue([ - 'object' => $result, - 'propName' => $additionalPropName - ]); + $propMetadata = static::extend_getPropMetadata([ + 'resultObject' => $result, - //Is the source property object or array - $isSourcePropObjectOrArray = self::isObjectOrArray($sourcePropValue); - }else{ - $sourcePropValue = null; - $isSourcePropObjectOrArray = false; - } - - //Is the additional property object or array - $isAdditionalPropObject = is_object($additionalPropValue); - $isAdditionalPropObjectOrArray = - $isAdditionalPropObject || - is_array($additionalPropValue) - ; - - //The additional property value will be used by default - $isAdditionalPropUsed = true; - - if ( - //Overwriting with empty value is disabled - !$params->overwriteWithEmpty && - //And source property exists. Because if not exists we must set it in anyway (an empty value is better than nothing, right?) - $isSourcePropExists - ){ - //Check if additional property value is empty - $isAdditionalPropUsed = - ( - //Empty object or array - ( - $isAdditionalPropObjectOrArray && - count((array) $additionalPropValue) == 0 - ) || - //Empty string - ( - is_string($additionalPropValue) && - $additionalPropValue == '' - ) || - //NULL - is_null($additionalPropValue) - ) ? - //Additional is empty — don't use it - false: - //Additional is not empty — use it - true - ; + 'additionalPropName' => $additionalPropName, + 'additionalPropValue' => $additionalPropValue, - if ( - //Additional property value is empty - !$isAdditionalPropUsed && - //And source property value is empty too - ( - //Empty object or array - ( - $isSourcePropObjectOrArray && - count((array) $sourcePropValue) == 0 - ) || - //Empty string - ( - is_string($sourcePropValue) && - $sourcePropValue == '' - ) || - //NULL - is_null($sourcePropValue) - ) && - //But they have different types - $sourcePropValue !== $additionalPropValue - ){ - //Okay, overwrite source in this case - $isAdditionalPropUsed = true; - } - } + 'extendableProperties' => $params->extendableProperties, + 'overwriteWithEmpty' => $params->overwriteWithEmpty, + ]); - //If additional value must be used - if ($isAdditionalPropUsed){ + // If additional value must be used + if ($propMetadata->isAdditionalPropUsed){ if ( - //If recursive merging is needed - $params->deep && - //And the value is an object or array - $isAdditionalPropObjectOrArray + // If recursive merging is needed + $params->deep + // And the value is an object or array + && $propMetadata->isAdditionalPropObjectOrArray ){ - //Start recursion (`clone` must be called for all nested additional props, so recursion must be called even if `$sourcePropValue` is not an object or array) + // Start recursion (`clone` must be called for all nested additional props, so recursion must be called even if `$propMetadata->sourcePropValue` is not an object or array) $additionalPropValue = self::extend([ 'objects' => [ ( - $isSourcePropObjectOrArray ? - $sourcePropValue : - //If `$sourcePropValue` is not an array or object it isn't be used - ( - //Type of resulting prop depends on `$additionalPropValue` type - $isAdditionalPropObject ? - new \stdClass() : - [] + $propMetadata->isSourcePropObjectOrArray + ? $propMetadata->sourcePropValue + // If `$propMetadata->sourcePropValue` is not an array or object it isn't be used + : ( + // Type of resulting prop depends on `$additionalPropValue` type + $propMetadata->isAdditionalPropObject + ? new \stdClass() + : [] ) ), - $additionalPropValue + $additionalPropValue, ], 'deep' => true, - 'overwriteWithEmpty' => $params->overwriteWithEmpty + 'overwriteWithEmpty' => $params->overwriteWithEmpty, ]); } @@ -471,7 +418,7 @@ public static function extend($params){ $additionalPropValue = clone $additionalPropValue; } - //Save the new value (replace preverious or create the new property) + // Save the new value (replace preverious or create the new property) if ($isResultObject){ $result->{$additionalPropName} = $additionalPropValue; }else{ @@ -485,9 +432,134 @@ public static function extend($params){ return $result; } + /** + * extend_getPropMetadata + * @version 1.1 (2024-08-19) + * + * @param $params {stdClass|arrayAssociative} — The parameters object. + * @param $params->resultObject {object|array} + * @param $params->additionalPropName {string|integer} + * @param $params->additionalPropValue {mixed} + * @param $params->extendableProperties {array|null} + * @param $params->overwriteWithEmpty {boolean} + * + * @param $result {stdClass|arrayAssociative} + * @param $result->isAdditionalPropUsed {boolean} + * @param $result->isAdditionalPropObject {boolean} + * @param $result->isAdditionalPropObjectOrArray {boolean} + * @param $result->sourcePropValue {mixed} + * @param $result->isSourcePropObjectOrArray {boolean} + * @param $result->overwriteWithEmpty {boolean} — Equal to $params->overwriteWithEmpty. + * + * @return {boolean} + */ + private static function extend_getPropMetadata($params): \stdClass { + $params = (object) $params; + + $result = (object) [ + // First approximation + 'isAdditionalPropUsed' => + is_null($params->extendableProperties) + || in_array( + $params->additionalPropName, + $params->extendableProperties + ) + , + 'isAdditionalPropObject' => false, + 'isAdditionalPropObjectOrArray' => false, + + 'sourcePropValue' => null, + 'isSourcePropObjectOrArray' => false, + + 'overwriteWithEmpty' => $params->overwriteWithEmpty, + ]; + + if ($result->isAdditionalPropUsed){ + // Is the source property exists + $isSourcePropExists = self::isPropExists([ + 'object' => $params->resultObject, + 'propName' => $params->additionalPropName, + ]); + + if ($isSourcePropExists){ + // Source property value + $result->sourcePropValue = self::getSingleLevelPropValue([ + 'object' => $params->resultObject, + 'propName' => $params->additionalPropName, + ]); + + // Is the source property object or array + $result->isSourcePropObjectOrArray = self::isObjectOrArray($result->sourcePropValue); + } + + // Is the additional property object or array + $result->isAdditionalPropObject = is_object($params->additionalPropValue); + $result->isAdditionalPropObjectOrArray = + $result->isAdditionalPropObject + || is_array($params->additionalPropValue) + ; + + if ( + // Overwriting with empty value is disabled + !$params->overwriteWithEmpty + // And source property exists. Because if not exists we must set it in anyway (an empty value is better than nothing, right?) + && $isSourcePropExists + ){ + // Check if additional property value is empty + $result->isAdditionalPropUsed = + ( + // Empty object or array + ( + $result->isAdditionalPropObjectOrArray + && count((array) $params->additionalPropValue) == 0 + ) + // Empty string + || ( + is_string($params->additionalPropValue) + && $params->additionalPropValue == '' + ) + // NULL + || is_null($params->additionalPropValue) + ) ? + // Additional is empty — don't use it + false: + // Additional is not empty — use it + true + ; + + if ( + // Additional property value is empty + !$result->isAdditionalPropUsed + // And source property value is empty too + && ( + // Empty object or array + ( + $result->isSourcePropObjectOrArray + && count((array) $result->sourcePropValue) == 0 + ) + // Empty string + || ( + is_string($result->sourcePropValue) + && $result->sourcePropValue == '' + ) + // NULL + || is_null($result->sourcePropValue) + ) + // But they have different types + && $result->sourcePropValue !== $params->additionalPropValue + ){ + // Okay, overwrite source in this case + $result->isAdditionalPropUsed = true; + } + } + } + + return $result; + } + /** * unfold - * @version 1.2 (2024-06-06) + * @version 1.2.2 (2024-08-18) * * @see README.md * @@ -496,53 +568,53 @@ public static function extend($params){ public static function unfold($params){ $params = self::extend([ 'objects' => [ - //Defaults + // Defaults (object) [ 'isCrossTypeEnabled' => false, 'keySeparator' => '.', 'keyPrefix' => '', - //The internal parameter, should not be used outside. Used only in child calls of recursion. - 'isSourceObject' => null + // The internal parameter, should not be used outside. Used only in child calls of recursion. + 'isSourceObject' => null, ], $params ] ]); - //Array is used as base and it always be returned in child calls of recursion + // Array is used as base and it always be returned in child calls of recursion $result = []; $isSourceObject = - //If it's the first call of recurson - is_null($params->isSourceObject) ? - //Use original type - is_object($params->object) : - //Use from parent call of recursion - $params->isSourceObject + // If it's the first call of recurson + is_null($params->isSourceObject) + // Use original type + ? is_object($params->object) + // Use from parent call of recursion + : $params->isSourceObject ; - //Iterate over source + // Iterate over source foreach ( - $params->object as - $key => - $value + $params->object + as $key + => $value ){ - //If the value must be unfolded + // If the value must be unfolded if ( - //Arrays can unfold objects and vice versa + // Arrays can unfold objects and vice versa ( - $params->isCrossTypeEnabled && - ( - is_object($value) || - is_array($value) + $params->isCrossTypeEnabled + && ( + is_object($value) + || is_array($value) ) - ) || - ( - $isSourceObject && - is_object($value) - ) || - ( - !$isSourceObject && - is_array($value) + ) + || ( + $isSourceObject + && is_object($value) + ) + || ( + !$isSourceObject + && is_array($value) ) ){ $result = array_merge( @@ -550,28 +622,28 @@ public static function unfold($params){ self::unfold([ 'object' => $value, 'keyPrefix' => - $params->keyPrefix . - $key . - $params->keySeparator + $params->keyPrefix + . $key + . $params->keySeparator , 'isSourceObject' => $isSourceObject, 'isCrossTypeEnabled' => $params->isCrossTypeEnabled, ]) ); - //Если значение — не массив + // Если значение — не массив }else{ - //Запоминаем (в соответствии с ключом родителя) + // Запоминаем (в соответствии с ключом родителя) $result[$params->keyPrefix . $key] = $value; } } if ( - //If it's first call of recurson - is_null($params->isSourceObject) && - //And the final result must be an object - $isSourceObject + // If it's first call of recurson + is_null($params->isSourceObject) + // And the final result must be an object + && $isSourceObject ){ - //Only the first call of recursion can return an object + // Only the first call of recursion can return an object $result = (object) $result; }