diff --git a/CHANGELOG.md b/CHANGELOG.md index 04bdbe4..4d4a6be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,14 @@ # (MODX)EvolutionCMS.libraries.ddTools changelog +## Version 0.53 (2021-12-13) +* \+ `\DDTools\ObjectCollection`: The new class representing a collection of some objects or arrays. See more info and examples in README. +* \* `\ddTools::parseText` → Parameters → `$params->data`: A bug with multidimensional objects has been fixed. +* \* README: + * \- Documentation: Useless header level has been removed. + * \* Examples: Several missed characters have been added. + + ## Version 0.52.1 (2021-11-17) * \* `\ddTools::parseText`: Fixed working when `$params->data` is a multidimensional object. diff --git a/CHANGELOG_ru.md b/CHANGELOG_ru.md index f585535..38003be 100644 --- a/CHANGELOG_ru.md +++ b/CHANGELOG_ru.md @@ -1,6 +1,14 @@ # (MODX)EvolutionCMS.libraries.ddTools changelog +## Версия 0.53 (2021-12-13) +* \+ `\DDTools\ObjectCollection`: Новый класс, представляющий коллекцию некоторых объектов или массивов. См. больше информации и примеры в README. +* \* `\ddTools::parseText` → Параметры → `$params->data`: Исправлена ошибка с многомерными объектами. +* \* README: + * \- Документация: Бесполезный уровень заголовков удален. + * \* Примеры: Добавлены пропущенные символы. + + ## Версия 0.52.1 (2021-11-17) * \* `\ddTools::parseText`: Исправлена работа, Когда `$params->data` является многомерным объектом. diff --git a/README.md b/README.md index 82b97ff..8d74ac7 100644 --- a/README.md +++ b/README.md @@ -11,29 +11,26 @@ A library with various tools facilitating your work. * [PHP.libraries.hjson](https://github.com/hjson/hjson-php) 2.1 (included) -## Documentation +## Installation -### Installation - - -#### Manual +### Manual 1. Create a new folder `assets/libs/ddTools/`. 2. Extract the archive to the folder. -#### Using [Composer](https://getcomposer.org/) +### Using [Composer](https://getcomposer.org/) Just add `dd/evolutioncms-libraries-ddtools` to your `composer.json`. _ddTools version must be 0.14 or higher to use this method. If you use it, the compatibility with all your snippets, modules, etc. that use ddTools versions under 0.14 will be maintained._ -### Parameters description +## Parameters description -#### `\ddTools::parseText($params)` +### `\ddTools::parseText($params)` Replaces placeholders in a text with required values. Like `$modx->parseChunk`, but takes a text and has some features. @@ -93,14 +90,14 @@ Like `$modx->parseChunk`, but takes a text and has some features. * Default value: `true` -##### Returns +#### Returns * `$result` * Desctription: Parsed text. * Valid values: `string` -#### `\ddTools::verifyRenamedParams($params)` +### `\ddTools::verifyRenamedParams($params)` The method checks an array for deprecated parameters and writes warning messages into the MODX event log. It returns an associative array, in which the correct parameter names are the keys and the parameter values are the values. @@ -151,7 +148,7 @@ You can use the `exctract` function to turn the array into variables of the curr * Default value: `true` -##### Returns +#### Returns * `$result` * Desctription: An array or object, in which the correct parameter names are the keys and the parameter values are the values. @@ -165,10 +162,10 @@ You can use the `exctract` function to turn the array into variables of the curr * Valid values: `mixed` -#### `\DDTools\FilesTools` +### `\DDTools\FilesTools` -##### `\DDTools\FilesTools::modifyImage($params)` +#### `\DDTools\FilesTools::modifyImage($params)` Modify your images: create thumbnails, crop, resize, fill background color or add watermark. @@ -240,10 +237,10 @@ Modify your images: create thumbnails, crop, resize, fill background color or ad * Default value: — -#### `\DDTools\ObjectTools` +### `\DDTools\ObjectTools` -##### `\DDTools\ObjectTools::isPropExists($params)` +#### `\DDTools\ObjectTools::isPropExists($params)` Checks if the object, class or array has a property / element. This is a “syntactic sugar” for checking an element in one way regardless of the “object” type. @@ -273,7 +270,7 @@ Second, the different order of parameters in the native PHP functions makes us c * **Required** -##### `\DDTools\ObjectTools::getPropValue($params)` +#### `\DDTools\ObjectTools::getPropValue($params)` Get the value of an object property or an array element. This is a “syntactic sugar” for getting an element in one way regardless of the “object” type. @@ -300,7 +297,7 @@ This is a “syntactic sugar” for getting an element in one way regardless of * **Required** -###### Returns +##### Returns * `$result` * Desctription: Value of an object property or an array element. @@ -309,7 +306,7 @@ This is a “syntactic sugar” for getting an element in one way regardless of * `NULL` — if property not exists -##### `\DDTools\ObjectTools::convertType($params)` +#### `\DDTools\ObjectTools::convertType($params)` 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. @@ -347,7 +344,7 @@ Arrays, [JSON](https://en.wikipedia.org/wiki/JSON) and [Query string](https://en * Default value: `'objectAuto'` -###### Returns +##### Returns * `$result` * Desctription: Result type depends on `$params->type`. @@ -358,7 +355,7 @@ Arrays, [JSON](https://en.wikipedia.org/wiki/JSON) and [Query string](https://en * `stringJsonArray` -##### `\DDTools\ObjectTools::extend($params)` +#### `\DDTools\ObjectTools::extend($params)` Merge the contents of two or more objects or arrays together into the first one. @@ -405,7 +402,7 @@ Merge the contents of two or more objects or arrays together into the first one. * Default value: `true` -##### `\DDTools\ObjectTools::unfold($params)` +#### `\DDTools\ObjectTools::unfold($params)` Converts a multidimensional array/object into an one-dimensional one joining the keys with `$params->keySeparator`. For example, it can be helpful while using placeholders like `[+size.width+]`. @@ -435,7 +432,7 @@ For example, it can be helpful while using placeholders like `[+size.width+]`. * Default value: `''` -###### Returns +##### Returns * `$result` * Desctription: Unfolded object/array. Type of results depends on `$params->object`. @@ -444,7 +441,262 @@ For example, it can be helpful while using placeholders like `[+size.width+]`. * `array` -#### `\DDTools\BaseClass` +### `\DDTools\ObjectCollection` + +Class representing a collection of some objects or arrays. + + +#### `\DDTools\ObjectCollection::__construct($params)` + +* `$params` + * Desctription: Parameters, the pass-by-name style is used. + * Valid values: + * `stdClass` + * `arrayAssociative` + * Default value: — + +* `$params->items` + * Desctription: An array of items. + You can avoid this parameter to create an empty collection and set items later. + * Valid values: + * `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 + * `stringJsonArray` — [JSON](https://en.wikipedia.org/wiki/JSON) array + * `stringHjsonObject` — [HJSON](https://hjson.github.io/) object + * `stringHjsonArray` — [HJSON](https://hjson.github.io/) array + * `stringQueryFormated` — [Query string](https://en.wikipedia.org/wiki/Query_string) + * Default value: — + +* `$params->items[$itemIndex]` + * Desctription: An item. + * Valid values: + * `array` — indexed arrays are supported as well as associative + * `object` + * **Required** + +* `$params->itemType` + * Desctription: Allows to convert item type. If set, each item of `$params->items` will be converted to needed type. + Values are case insensitive (the following names are equal: `'objectstdclass'`, `'objectStdClass'`, `'OBJECTSTDCLASS'`, etc). + * Valid values: + * `'objectStdClass'` + * `'objectArray'` + * `null` — do not convert type of items, use them as is + * Default value: `null` + + +#### `\DDTools\ObjectCollection::setItems($params)` + +Sets new collection items. Existing items will be removed. + +Has the same parameters as `\DDTools\ObjectCollection::__construct($params)`. + + +#### `\DDTools\ObjectCollection::addItems($params)` + +Appends items onto the end of collection. + +Has the same parameters as `\DDTools\ObjectCollection::__construct($params)`. + + +#### `\DDTools\ObjectCollection::getItems($params)` + +Gets an array of required collection items. + +* `$params` + * Desctription: Parameters, the pass-by-name style is used. + * Valid values: + * `stdClass` + * `arrayAssociative` + * Default value: — + +* `$params->filter` + * Desctription: Filter clause for item properties. + * Thus, + ``` + ' + "gender" == "female" || + "gender" == "male" && + "firstName" != "Bill" && + "lastName" + ' + ``` + returns: + * All items with the `gender` property equal to `'female'`. + * All items: + * with the `gender` property equal to `'male'` **and** + * with the `firstName` property not equal to `'Bill'` **and** + * with the `lastName` property is exist with any value. + * Quoted property names and values are optional, this is valid too: + ``` + ' + gender == female || + gender == male && + firstName != Bill && + lastName + ' + ``` + * Single quotes are also supported as double quotes: + ``` + " + gender == 'a' || + gender == 'b' && + firstName != 'Bill' && + lastName + " + ``` + * Spaces, tabs and line breaks are optional, this is valid too: `gender==female||gender==male&&firstName!=Bill&&lastName`. + * Valid values: `stringSeparated` + * Default value: `''` (without filtration) + +* `$params->limit` + * Desctription: Maximum number of items to return. + * Valid values: + * `integer` + * `0` — all matching items + * Default value: `0` + +* `$params->propAsResultKey` + * Desctription: 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. + * Valid values: + * `string` + * `null` — result array will be indexed + * Default value: `null` + +* `$params->propAsResultValue` + * Desctription: Item property, which value will be an item value in result array instead of an item object. + * Valid values: + * `string` + * `null` — result array values will item objects + * Default value: `null` + + +##### Returns + +* `$result` + * Desctription: An array of items. + * Valid values: + * `arrayIndexed` + * `arrayAssociative` — item property values will be used as result keys if `$params->propAsResultKey` is set + +* `$result[$itemIndex|$itemFieldValue]` + * Desctription: An item object or item property value if specified in `$params->propAsResultValue`. + * Valid values: `mixed` + + +#### `\DDTools\ObjectCollection::getOneItem($params)` + +Gets required item. + +* `$params` + * Desctription: Parameters, the pass-by-name style is used. + * Valid values: + * `stdClass` + * `arrayAssociative` + * Default value: — + +* `$params->filter` + * Desctription: Filter clause for item properties. The same parameter as `\DDTools\ObjectCollection::getItems($params)`. + * Valid values: `stringSeparated` + * Default value: `''` (first found item will be returned) + +* `$params->notFoundResult` + * Desctription: What will be returned when no items found. + * Valid values: `mixed` + * Default value: `null` + + +#### `\DDTools\ObjectCollection::count()` + +Counts all items. + + +#### `\DDTools\ObjectCollection::convertItemsType($params)` + +Converts type of needed items in collection. + +* `$params` + * Desctription: Parameters, the pass-by-name style is used. + * Valid values: + * `stdClass` + * `arrayAssociative` + * Default value: — + +* `$params->itemType` + * Desctription: Result item type. + Values are case insensitive (the following names are equal: `'objectstdclass'`, `'objectStdClass'`, `'OBJECTSTDCLASS'`, etc). + * Valid values: + * `'objectStdClass'` + * `'objectArray'` + * **Required** + +* `$params->filter` + * Desctription: Filter clause for item properties. The same parameter as `\DDTools\ObjectCollection::getItems($params)`. + * Valid values: `stringSeparated` + * Default value: `''` (all items will be converted) + + +#### `\DDTools\ObjectCollection::updateItems($params)` + +Undates properties of existing items with new values. + +* `$params` + * Desctription: Parameters, the pass-by-name style is used. + * Valid values: + * `stdClass` + * `arrayAssociative` + * **Required** + +* `$params->data` + * Desctription: New item data. Existing item will be extended by this data, it means: + * Type of existing item will not be changed. + * All given property values will overwrite existing. + * Non-existing given properties will be created. + * Existing properties that absent in `$params->data` will remain as is. + * Valid values: + * `array` + * `object` + * **Required** + +* `$params->filter` + * Desctription: Filter clause for item properties. The same parameter as `\DDTools\ObjectCollection::getItems($params)`. + * Valid values: `stringSeparated` + * Default value: `''` (any items will be updated) + +* `$params->limit` + * Desctription: Maximum number of items can be updated. + * Valid values: + * `integer` + * `0` — all matching items + * Default value: `0` + + +#### `\DDTools\ObjectCollection::deleteItems($params)` + +Deletes required items from collection. + +* `$params` + * Desctription: Parameters, the pass-by-name style is used. + * Valid values: + * `stdClass` + * `arrayAssociative` + * Default value: — + +* `$params->filter` + * Desctription: Filter clause for item properties. The same parameter as `\DDTools\ObjectCollection::getItems($params)`. + * Valid values: `stringSeparated` + * Default value: `''` (any items will be deleted) + +* `$params->limit` + * Desctription: Maximum number of items can be deleted. + * Valid values: + * `integer` + * `0` — all matching items + * Default value: `0` + + +### `\DDTools\BaseClass` Simple class with some small methods facilitating your work. It is convenient to inherit your classes from this. @@ -452,7 +704,7 @@ It is convenient to inherit your classes from this. You can see an example of how it works in the [(MODX)EvolutionCMS.snippets.ddGetDocumentField](https://code.divandesign.biz/modx/ddgetdocumentfield) code. -##### `\DDTools\BaseClass::setExistingProps($props)` +#### `\DDTools\BaseClass::setExistingProps($props)` Sets existing object properties. @@ -471,12 +723,12 @@ Sets existing object properties. * **Required** -##### `\DDTools\BaseClass::toArray()` +#### `\DDTools\BaseClass::toArray()` Returns all properties of this object as an associative array independent of their visibility. -###### Returns +##### Returns * `$result` * Desctription: An associative array representation of this object. @@ -488,12 +740,12 @@ Returns all properties of this object as an associative array independent of the * Valid values: `mixed` -##### `\DDTools\BaseClass::toJSON()` +#### `\DDTools\BaseClass::toJSON()` Returns all properties of this object as an JSON string independent of their visibility. -###### Returns +##### Returns * `$result` * Desctription: An JSON string representation of this object. @@ -505,12 +757,12 @@ Returns all properties of this object as an JSON string independent of their vis * Valid values: `mixed` -##### `\DDTools\BaseClass::__toString()` +#### `\DDTools\BaseClass::__toString()` The same as `\DDTools\BaseClass::toJSON()`. -##### `\DDTools\BaseClass::createChildInstance($params)` +#### `\DDTools\BaseClass::createChildInstance($params)` * `$params` * Desctription: Parameters, the pass-by-name style is used. @@ -542,19 +794,19 @@ The same as `\DDTools\BaseClass::toJSON()`. * Default value: `true` -###### Returns +##### Returns * `$result` * Desctription: The new object instance. * Valid values: `object` -#### `\DDTools\Snippet` +### `\DDTools\Snippet` Abstract class for snippets. -##### Properties +#### Properties * `\DDTools\Snippet::$name` * Desctription: Snippet name (e. g. `ddGetDocuments`). @@ -620,7 +872,7 @@ Abstract class for snippets. * Visibility: `protected` -##### `\DDTools\Snippet::__construct($params)` +#### `\DDTools\Snippet::__construct($params)` * `$params` * Desctription: Snippet parameters, the pass-by-name style is used. @@ -637,14 +889,14 @@ Abstract class for snippets. * **Required** -##### `\DDTools\Snippet::run()` +#### `\DDTools\Snippet::run()` Abstract method for main snippet action. You **must** define it in your child class declaration. -##### `\DDTools\Snippet::runSnippet($params)` +#### `\DDTools\Snippet::runSnippet($params)` Static method for easy running needed snippet using only it's name and parameters (if needed). @@ -677,10 +929,10 @@ Static method for easy running needed snippet using only it's name and parameter * **Required** -### Examples +## Examples -#### Verify renamed snippet params (`\ddTools::verifyRenamedParams($params)`) +### Verify renamed snippet params (`\ddTools::verifyRenamedParams($params)`) Suppose we have the snippet `ddSendFeedback` with the `getEmail` and `getId` parameters. Over time, we decided to rename the parameters as `docField` and `docId` respectively (as it happened in version 1.9). @@ -730,10 +982,10 @@ extract(\ddTools::verifyRenamedParams([ ``` -#### `\DDTools\ObjectTools::convertType($params)` +### `\DDTools\ObjectTools::convertType($params)` -##### Convert a JSON or Query encoded string to an array +#### Convert a JSON or Query encoded string to an array For example, some snippet supports 2 formats in one of parameters: JSON or Query string. Users use the format that is convenient to them and we support both. @@ -766,7 +1018,7 @@ Both calls return: ``` -##### Convert a Query encoded string to a JSON object string +#### Convert a Query encoded string to a JSON object string ```php \DDTools\ObjectTools::convertType([ @@ -785,7 +1037,7 @@ Returns: ``` -##### Convert a JSON object to a JSON array +#### Convert a JSON object to a JSON array ```php \DDTools\ObjectTools::convertType([ @@ -807,7 +1059,7 @@ Returns: ``` -##### Convert a HJSON encoded string to an object +#### Convert a HJSON encoded string to an object ```php \DDTools\ObjectTools::convertType([ @@ -837,10 +1089,10 @@ A simple syntax and easy to read.', ``` -#### `\DDTools\ObjectTools::extend($params)` +### `\DDTools\ObjectTools::extend($params)` -##### Merge two objects, modifying the first +#### Merge two objects, modifying the first ```php var_export(\DDTools\ObjectTools::extend([ @@ -878,7 +1130,7 @@ stdClass::__set_state(array( ``` -##### Also you can extend arrays +#### Also you can extend arrays ```php var_export(\DDTools\ObjectTools::extend([ @@ -916,7 +1168,7 @@ array( ``` -##### Moreover, objects can extend arrays and vice versa +#### Moreover, objects can extend arrays and vice versa ```php var_export(\DDTools\ObjectTools::extend([ @@ -942,7 +1194,7 @@ Returns: ```php //The object expanded the source array array( - name' => 'jokes', + 'name' => 'jokes', //The array expanded the source object 'countries' => stdClass::__set_state( 'usa' => 'democracy', @@ -952,7 +1204,7 @@ array( ``` -##### Don't overwrite fields with empty values (`$params->overwriteWithEmpty` == `false`) +#### Don't overwrite fields with empty values (`$params->overwriteWithEmpty` == `false`) By default, empty field values (e. g. `''`) are treated as other values and will replace non-empty ones. @@ -1014,10 +1266,10 @@ stdClass::__set_state(array( ``` -#### `\DDTools\ObjectTools::unfold($params)` +### `\DDTools\ObjectTools::unfold($params)` -##### Unfold an object +#### Unfold an object ```php var_export(\DDTools\ObjectTools::unfold([ @@ -1046,7 +1298,7 @@ stdClass::__set_state(array ( ``` -##### Unfold an array +#### Unfold an array ```php var_export(\DDTools\ObjectTools::unfold([ @@ -1077,7 +1329,7 @@ array ( ``` -##### Use custom key separator +#### Use custom key separator ```php var_export(\DDTools\ObjectTools::unfold([ @@ -1100,9 +1352,397 @@ stdClass::__set_state(array ( 'parents_mother' => 'Maye Musk', 'parents_father' => 'Errol Musk' )) +``` -#### `\DDTools\ObjectTools::isPropExists($params)` +### `\DDTools\ObjectCollection` + + +#### Create a collection with items + +```php +$collection = new \DDTools\ObjectCollection([ + 'items' => [ + [ + 'name' => 'Mary Teresa', + 'isHuman' => 1, + 'gender' => 'female', + 'nobelPeacePrize' => 1, + 'religion' => 'Catholicism' + ], + [ + 'name' => 'Mahatma Gandhi', + 'isHuman' => 1, + 'gender' => 'male', + 'nobelPeacePrize' => 0 + ], + [ + 'name' => 'Tenzin Gyatso', + 'isHuman' => 1, + 'gender' => 'male', + 'nobelPeacePrize' => 1, + 'religion' => 'Tibetan Buddhism' + ], + [ + 'name' => 'ICAN', + 'isHuman' => 0, + 'nobelPeacePrize' => 1 + ] + ] +]); +``` + + +#### Set items as a JSON string + +```php +$collection->setItems([ + 'items' => '[ + { + "name": "Mary Teresa", + "isHuman": 1, + "gender": "female", + "nobelPeacePrize": 1, + "religion": "Catholicism" + }, + { + "name": "Mahatma Gandhi", + "isHuman": 1, + "gender": "male", + "nobelPeacePrize": 0 + }, + { + "name": "Tenzin Gyatso", + "isHuman": 1, + "gender": "male", + "nobelPeacePrize": 1, + "religion": "Tibetan Buddhism" + }, + { + "name": "ICAN", + "isHuman": 0, + "nobelPeacePrize": 1 + } + ]' +]); +``` + + +#### `\DDTools\ObjectCollection::getItems($params)` + + +##### Get an array of items using filter (`$params->filter`) + + +###### Filter by existence of a property + +```php +$collection->getItems([ + 'filter' => 'religion' +]); +``` + +Returns: + +```php +array( + 0 => array( + 'name' => 'Mary Teresa', + 'isHuman' => 1, + 'gender' => 'female', + 'nobelPeacePrize' => 1, + 'religion' => 'Catholicism' + ), + 1 => array( + 'name' => 'Tenzin Gyatso', + 'isHuman' => 1, + 'gender' => 'male', + 'nobelPeacePrize' => 1, + 'religion' => 'Tibetan Buddhism' + ) +) +``` + + +###### Filter by a property value + +```php +$collection->getItems([ + 'filter' => 'gender==male' +]); +``` + +Returns: + +```php +array( + 0 => array( + 'name' => 'Mahatma Gandhi', + 'isHuman' => 1, + 'gender' => 'male', + 'nobelPeacePrize' => 0 + ), + 1 => array( + 'name' => 'Tenzin Gyatso', + 'isHuman' => 1, + 'gender' => 'male', + 'nobelPeacePrize' => 1, + 'religion' => 'Tibetan Buddhism' + ) +) +``` + + +###### Filter using several conditions + +```php +$collection->getItems([ + //Spaces, tabs and line breaks are also allowed and do not matter + 'filter' => ' + gender == female || + nobelPeacePrize == 1 && isHuman == 0 + ' +]); +``` + +Returns: + +```php +array( + //gender == female + 0 => array( + 'name' => 'Mary Teresa', + 'isHuman' => 1, + 'gender' => 'female', + 'nobelPeacePrize' => 1, + 'religion' => 'Catholicism' + ), + //nobelPeacePrize == 1 && isHuman == 0 + 1 => array( + 'name' => 'ICAN', + 'isHuman' => 0, + 'nobelPeacePrize' => 1 + ), +) +``` + + +##### Get an associative array of items using a property value as a result key + +```php +$collection->getItems([ + 'propAsResultKey' => 'name' +]); +``` + +Returns: + +```php +array( + 'Mary Teresa' => array( + 'name' => 'Mary Teresa', + 'isHuman' => 1, + 'gender' => 'female', + 'nobelPeacePrize' => 1, + 'religion' => 'Catholicism' + ), + 'Mahatma Gandhi' => array( + 'name' => 'Mahatma Gandhi', + 'isHuman' => 1, + 'gender' => 'male', + 'nobelPeacePrize' => 0 + ), + 'Tenzin Gyatso' => array( + 'name' => 'Tenzin Gyatso', + 'isHuman' => 1, + 'gender' => 'male', + 'nobelPeacePrize' => 1, + 'religion' => 'Tibetan Buddhism' + ), + 'ICAN' => array( + 'name' => 'ICAN', + 'isHuman' => 0, + 'nobelPeacePrize' => 1 + ) +) +``` + + +##### Get a one-dimensional array of item property values + +```php +$collection->getItems([ + 'propAsResultKey' => 'name', + 'propAsResultValue' => 'isHuman' +]); +``` + +Returns: + +```php +array( + 'Mary Teresa' => 1, + 'Mahatma Gandhi' => 1, + 'Tenzin Gyatso' => 1, + 'ICAN' => 0 +) +``` + + +#### `\DDTools\ObjectCollection::getOneItem($params)` + +```php +$collection->getOneItem([ + 'filter' => 'name == Mahatma Gandhi' +]); +``` + +Returns: + +```php +array( + 'name' => 'Mahatma Gandhi', + 'isHuman' => 1, + 'gender' => 'male', + 'nobelPeacePrize' => 0 +) +``` + + +##### Custom results when no items found + + +```php +$collection->getOneItem([ + 'filter' => 'name == European Union', + notFoundResult' => [ + 'name' => 'Default item', + 'nobelPeacePrize' => 0 + ] +]); +``` + +Returns: + +```php +array( + 'name' => 'Default item', + 'nobelPeacePrize' => 0 +) +``` + + +#### `\DDTools\ObjectCollection::convertItemsType($params)` + +```php +$collection->convertItemsType([ + 'filter' => 'gender==male', + 'itemType' => 'objectStdClass' +]); + +$collection->getItems(); +``` + +Returns: + +```php +array( + 0 => array( + 'name' => 'Mary Teresa', + 'isHuman' => 1, + 'gender' => 'female', + 'nobelPeacePrize' => 1, + 'religion' => 'Catholicism' + ), + 1 => stdClass::__set_state(array( + 'name' => 'Mahatma Gandhi', + 'isHuman' => 1, + 'gender' => 'male', + 'nobelPeacePrize' => 0 + )), + 2 => stdClass::__set_state(array( + 'name' => 'Tenzin Gyatso', + 'isHuman' => 1, + 'gender' => 'male', + 'nobelPeacePrize' => 1, + 'religion' => 'Tibetan Buddhism' + )), + 3 => array( + 'name' => 'ICAN', + 'isHuman' => 0, + 'nobelPeacePrize' => 1 + ) +) +``` + + +#### `\DDTools\ObjectCollection::updateItems($params)` + +```php +$collection->updateItems([ + 'filter' => 'name==Mahatma Gandhi', + 'data' => [ + 'nobelPeacePrize' => 1, + 'birthday' => '2 October 1869' + ] +]); + +$collection->getItems( + 'filter' => 'name==Mahatma Gandhi' +); +``` + +Returns: + +```php +array( + 0 => stdClass::__set_state(array( + //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 + 'nobelPeacePrize' => 1, + //Non-existing properties have been created + 'birthday' => '2 October 1869' + )) +) +``` + + +#### `\DDTools\ObjectCollection::deleteItems($params)` + +```php +$collection->updateItems([ + 'filter' => 'isHuman==1', + 'limit' => 2 +]); + +$collection->getItems(); +``` + +Returns: + +```php +array( + //2 humans have been deleted, 1 have remained + 0 => stdClass::__set_state(array( + 'name' => 'Tenzin Gyatso', + 'isHuman' => 1, + 'gender' => 'male', + 'nobelPeacePrize' => 1, + 'religion' => 'Tibetan Buddhism' + )), + 1 => array( + 'name' => 'ICAN', + 'isHuman' => 0, + 'nobelPeacePrize' => 1 + ) +) +``` + + +### `\DDTools\ObjectTools::isPropExists($params)` Checks if the object, class or array has a property / element using the same syntax. @@ -1133,7 +1773,7 @@ var_export(\DDTools\ObjectTools::isPropExists([ Both calls return `true`. -#### `\DDTools\ObjectTools::getPropValue($params)` +### `\DDTools\ObjectTools::getPropValue($params)` Get the value of an object property or an array element using the same syntax. diff --git a/composer.json b/composer.json index e5646f7..118c902 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "dd/evolutioncms-libraries-ddtools", "type": "modxevo-library-ddtools", - "version": "0.52.1", + "version": "0.53.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 18351a4..ce62679 100644 --- a/modx.ddtools.class.php +++ b/modx.ddtools.class.php @@ -1,7 +1,7 @@ '', - 'data' => [], + 'data' => null, 'placeholderPrefix' => '[+', 'placeholderSuffix' => '+]', 'removeEmptyPlaceholders' => false, diff --git a/require.php b/require.php index 8534cec..ba46219 100644 --- a/require.php +++ b/require.php @@ -2,6 +2,7 @@ require_once('src/BaseClass/BaseClass.php'); require_once('src/ObjectTools/ObjectTools.php'); require_once('src/FilesTools/FilesTools.php'); +require_once('src/ObjectCollection/ObjectCollection.php'); require_once('src/Response/Response.php'); require_once('src/Snippet/Snippet.php'); diff --git a/src/ObjectCollection/ObjectCollection.php b/src/ObjectCollection/ObjectCollection.php new file mode 100644 index 0000000..12498ec --- /dev/null +++ b/src/ObjectCollection/ObjectCollection.php @@ -0,0 +1,540 @@ +setItems($params); + } + + /** + * setItems + * @version 1.0 (2021-11-26) + * + * @see README.md + */ + public function setItems($params = []){ + //Reset items + $this->items = []; + + //Add new items + $this->addItems($params); + } + + /** + * addItems + * @version 1.2 (2021-12-02) + * + * @see README.md + */ + public function addItems($params = []){ + //# Prepare params + $params = \DDTools\ObjectTools::extend([ + 'objects' => [ + //Defaults + (object) [ + 'items' => null, + 'itemType' => null + ], + $params + ] + ]); + + + //# Run + if (!is_null($params->items)){ + //Items must be an array + if (!is_array($params->items)){ + $params->items = \DDTools\ObjectTools::convertType([ + 'object' => $params->items, + 'type' => 'objectArray' + ]); + } + + //Reset keys because they are no needed + $params->items = array_values($params->items); + + //If need to convert type of items + if (!is_null($params->itemType)){ + foreach ( + $params->items as + $itemIndex => + $itemObject + ){ + $params->items[$itemIndex] = \DDTools\ObjectTools::convertType([ + 'object' => $itemObject, + 'type' => $params->itemType + ]); + } + } + + $this->items = array_merge( + $this->items, + $params->items + ); + } + } + + /** + * convertItemsType + * @version 1.0 (2021-12-02) + * + * @see README.md + */ + public function convertItemsType($params = []){ + //# Prepare params + $params = \DDTools\ObjectTools::extend([ + 'objects' => [ + //Defaults + (object) [ + 'filter' => '', + 'itemType' => 'objectStdClass' + ], + $params + ] + ]); + + $params->filter = $this->prepareItemsFilter($params->filter); + + + //# Run + foreach ( + $this->items as + $itemIndex => + $itemObject + ){ + if ( + //If item is matched to filter + $this->isItemMatchFilter([ + 'item' => $itemObject, + 'filter' => $params->filter + ]) + ){ + $this->items[$itemIndex] = \DDTools\ObjectTools::convertType([ + 'object' => $itemObject, + 'type' => $params->itemType + ]); + } + } + } + + /** + * updateItems + * @version 1.0 (2021-12-02) + * + * @see README.md + */ + public function updateItems($params = []){ + //# Prepare params + $params = \DDTools\ObjectTools::extend([ + 'objects' => [ + //Defaults + (object) [ + 'filter' => '', + 'data' => [], + 'limit' => 0 + ], + $params + ] + ]); + + $params->filter = $this->prepareItemsFilter($params->filter); + + + //# Run + $affectedCount = 0; + + foreach ( + $this->items as + $itemIndex => + $itemObject + ){ + if ( + //If item is matched to filter + $this->isItemMatchFilter([ + 'item' => $itemObject, + 'filter' => $params->filter + ]) + ){ + $this->items[$itemIndex] = \DDTools\ObjectTools::extend([ + 'objects' => [ + $itemObject, + $params->data + ] + ]); + + //Increment result count + $affectedCount++; + + //If next item is no needed + if ($affectedCount == $params->limit){ + //Stop the cycle + break; + } + } + } + } + + /** + * getItems + * @version 2.0 (2021-12-02) + * + * @see README.md + */ + public function getItems($params = []){ + //# Prepare params + $params = \DDTools\ObjectTools::extend([ + 'objects' => [ + //Defaults + (object) [ + 'filter' => '', + 'limit' => 0, + 'propAsResultKey' => null, + 'propAsResultValue' => null + ], + $params + ] + ]); + + $params->filter = $this->prepareItemsFilter($params->filter); + + + //# Run + $result = []; + $resultCount = 0; + + //Filter items + foreach ( + $this->items as + $itemObject + ){ + if ( + //If item is matched to filter + $this->isItemMatchFilter([ + 'item' => $itemObject, + 'filter' => $params->filter + ]) + ){ + //Save only field value instead of object if needed + if (!is_null($params->propAsResultValue)){ + $resultItemObject = \DDTools\ObjectTools::getPropValue([ + 'object' => $itemObject, + 'propName' => $params->propAsResultValue + ]); + }else{ + $resultItemObject = $itemObject; + } + + //Save item + if (!is_null($params->propAsResultKey)){ + $result[ + \DDTools\ObjectTools::getPropValue([ + 'object' => $itemObject, + 'propName' => $params->propAsResultKey + ]) + ] = $resultItemObject; + }else{ + $result[] = $resultItemObject; + } + + //Increment result count + $resultCount++; + + //If next item is no needed + if ($resultCount == $params->limit){ + //Stop the cycle + break; + } + } + } + + return $result; + } + + /** + * getOneItem + * @version 1.0.1 (2021-12-02) + * + * @see README.md + */ + public function getOneItem($params = []){ + //# Prepare params + $params = \DDTools\ObjectTools::extend([ + 'objects' => [ + //Defaults + (object) [ + 'filter' => '', + 'notFoundResult' => null + ], + $params + ] + ]); + + + //# Run + $result = $this->getItems([ + 'filter' => $params->filter, + 'limit' => 1 + ]); + + if (!empty($result)){ + $result = $result[0]; + }else{ + $result = $params->notFoundResult; + } + + return $result; + } + + /** + * deleteItems + * @version 1.0 (2021-12-02) + * + * @see README.md + */ + public function deleteItems($params = []){ + //# Prepare params + $params = \DDTools\ObjectTools::extend([ + 'objects' => [ + //Defaults + (object) [ + 'filter' => '', + 'limit' => 0 + ], + $params + ] + ]); + + $params->filter = $this->prepareItemsFilter($params->filter); + + + //# Run + $affectedCount = 0; + + foreach ( + $this->items as + $itemIndex => + $itemObject + ){ + if ( + //If item is matched to filter + $this->isItemMatchFilter([ + 'item' => $itemObject, + 'filter' => $params->filter + ]) + ){ + array_splice( + $this->items, + $itemIndex - $affectedCount, + 1 + ); + + //Increment result count + $affectedCount++; + + //If next item is no needed + if ($affectedCount == $params->limit){ + //Stop the cycle + break; + } + } + } + } + + /** + * isItemMatchFilter + * @version 1.0 (2021-12-01) + * + * @param $params {array} — Parameters, the pass-by-name style is used. @required + * @param $params->item {array|object} — An item to test. @required + * @param $params->filter {array} — Result of $this->prepareItemsFilter. @required + * + * @return $result {boolean} + */ + private function isItemMatchFilter($params){ + $params = (object) $params; + + //By default assume that item is matched + $result = true; + + //Iterate over “or” conditions + foreach ( + $params->filter as + $orCondition + ){ + //Iterate over “and” conditions + foreach ( + $orCondition as + $andCondition + ){ + //If the item has no the property + if ( + !\DDTools\ObjectTools::isPropExists([ + 'object' => $params->item, + 'propName' => $andCondition->propName + ]) + ){ + $result = false; + //If filtration by the property value is no needed + }elseif ($andCondition->operator == 'isset'){ + $result = true; + //== + }elseif ($andCondition->operator == '=='){ + $result = + \DDTools\ObjectTools::getPropValue([ + 'object' => $params->item, + 'propName' => $andCondition->propName + ]) == + $andCondition->propValue + ; + //!= + }else{ + $result = + \DDTools\ObjectTools::getPropValue([ + 'object' => $params->item, + 'propName' => $andCondition->propName + ]) != + $andCondition->propValue + ; + } + + //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 ($result){ + break; + } + } + + return $result; + } + + /** + * prepareItemsFilter + * @version 1.0 (2021-12-01) + * + * @param $filter {string} + * + * @return $result {array} — “Or” conditions + * @return $result[$orIndex] {array} — “And” conditions. + * @return $result[$orIndex][$andIndex] {stdClass} — A condition. @required + * @return $result[$orIndex][$andIndex]->operator {'isset'|'=='|'!='} — A condition operator. @required + * @return $result[$orIndex][$andIndex]->propName {string} — A condition property name. @required + * @return $result[$orIndex][$andIndex]->propValue {string} — A condition property value if exists. Default: —. + */ + private function prepareItemsFilter($filter = ''){ + $result = []; + + if (!empty($filter)){ + //Explode “or” conditions + $filter = explode( + '||', + $filter + ); + + //Iterate over “or” conditions + foreach ( + $filter as + $orIndex => + $orCondition + ){ + $result[$orIndex] = []; + + //Iterate over “and” conditions + foreach ( + //Explode “and” conditions + explode( + '&&', + $orCondition + ) as + $andIndex => + $andCondition + ){ + //Condition object + $result[$orIndex][$andIndex] = (object) [ + 'operator' => 'isset', + 'propName' => '' + ]; + + //Prepare operator + if ( + strpos( + $andCondition, + '==' + ) !== false + ){ + $result[$orIndex][$andIndex]->operator = '=='; + }else if( + strpos( + $andCondition, + '!=' + ) !== false + ){ + $result[$orIndex][$andIndex]->operator = '!='; + } + + //Prepare condition + if ($result[$orIndex][$andIndex]->operator == 'isset'){ + //Just save name + $result[$orIndex][$andIndex]->propName = $andCondition; + }else{ + //Explode to name and value + $andCondition = explode( + $result[$orIndex][$andIndex]->operator, + $andCondition + ); + + //Save name + $result[$orIndex][$andIndex]->propName = $andCondition[0]; + + //Prepare and save value + $result[$orIndex][$andIndex]->propValue = trim( + //Trim whitespaces + trim($andCondition[1]), + //Then trim quotes + '"\'' + ); + } + + //Prepare name + $result[$orIndex][$andIndex]->propName = trim( + //Trim whitespaces + trim($result[$orIndex][$andIndex]->propName), + //Then trim quotes + '"\'' + ); + } + } + } + + return $result; + } + + /** + * count + * @version 1.0 (2021-11-30) + * + * @see README.md + */ + public function count(){ + return count($this->items); + } +} +?> \ No newline at end of file