| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318 |
- <?php
- /**
- * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
- * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
- *
- * Licensed under The MIT License
- * For full copyright and license information, please see the LICENSE.txt
- * Redistributions of files must retain the above copyright notice.
- *
- * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
- * @link https://cakephp.org CakePHP(tm) Project
- * @since 3.0.0
- * @license https://opensource.org/licenses/mit-license.php MIT License
- */
- namespace Cake\Datasource;
- use Cake\Collection\Collection;
- use Cake\Utility\Inflector;
- use InvalidArgumentException;
- use Traversable;
- /**
- * An entity represents a single result row from a repository. It exposes the
- * methods for retrieving and storing properties associated in this row.
- */
- trait EntityTrait
- {
- /**
- * Holds all properties and their values for this entity
- *
- * @var array
- */
- protected $_properties = [];
- /**
- * Holds all properties that have been changed and their original values for this entity
- *
- * @var array
- */
- protected $_original = [];
- /**
- * List of property names that should **not** be included in JSON or Array
- * representations of this Entity.
- *
- * @var array
- */
- protected $_hidden = [];
- /**
- * List of computed or virtual fields that **should** be included in JSON or array
- * representations of this Entity. If a field is present in both _hidden and _virtual
- * the field will **not** be in the array/json versions of the entity.
- *
- * @var array
- */
- protected $_virtual = [];
- /**
- * Holds the name of the class for the instance object
- *
- * @var string
- *
- * @deprecated 3.2 This field is no longer being used
- */
- protected $_className;
- /**
- * Holds a list of the properties that were modified or added after this object
- * was originally created.
- *
- * @var array
- */
- protected $_dirty = [];
- /**
- * Holds a cached list of getters/setters per class
- *
- * @var array
- */
- protected static $_accessors = [];
- /**
- * Indicates whether or not this entity is yet to be persisted.
- * Entities default to assuming they are new. You can use Table::persisted()
- * to set the new flag on an entity based on records in the database.
- *
- * @var bool
- */
- protected $_new = true;
- /**
- * List of errors per field as stored in this object
- *
- * @var array
- */
- protected $_errors = [];
- /**
- * List of invalid fields and their data for errors upon validation/patching
- *
- * @var array
- */
- protected $_invalid = [];
- /**
- * Map of properties in this entity that can be safely assigned, each
- * property name points to a boolean indicating its status. An empty array
- * means no properties are accessible
- *
- * The special property '\*' can also be mapped, meaning that any other property
- * not defined in the map will take its value. For example, `'\*' => true`
- * means that any property not defined in the map will be accessible by default
- *
- * @var array
- */
- protected $_accessible = ['*' => true];
- /**
- * The alias of the repository this entity came from
- *
- * @var string
- */
- protected $_registryAlias;
- /**
- * Magic getter to access properties that have been set in this entity
- *
- * @param string $property Name of the property to access
- * @return mixed
- */
- public function &__get($property)
- {
- return $this->get($property);
- }
- /**
- * Magic setter to add or edit a property in this entity
- *
- * @param string $property The name of the property to set
- * @param mixed $value The value to set to the property
- * @return void
- */
- public function __set($property, $value)
- {
- $this->set($property, $value);
- }
- /**
- * Returns whether this entity contains a property named $property
- * regardless of if it is empty.
- *
- * @param string $property The property to check.
- * @return bool
- * @see \Cake\ORM\Entity::has()
- */
- public function __isset($property)
- {
- return $this->has($property);
- }
- /**
- * Removes a property from this entity
- *
- * @param string $property The property to unset
- * @return void
- */
- public function __unset($property)
- {
- $this->unsetProperty($property);
- }
- /**
- * Sets a single property inside this entity.
- *
- * ### Example:
- *
- * ```
- * $entity->set('name', 'Andrew');
- * ```
- *
- * It is also possible to mass-assign multiple properties to this entity
- * with one call by passing a hashed array as properties in the form of
- * property => value pairs
- *
- * ### Example:
- *
- * ```
- * $entity->set(['name' => 'andrew', 'id' => 1]);
- * echo $entity->name // prints andrew
- * echo $entity->id // prints 1
- * ```
- *
- * Some times it is handy to bypass setter functions in this entity when assigning
- * properties. You can achieve this by disabling the `setter` option using the
- * `$options` parameter:
- *
- * ```
- * $entity->set('name', 'Andrew', ['setter' => false]);
- * $entity->set(['name' => 'Andrew', 'id' => 1], ['setter' => false]);
- * ```
- *
- * Mass assignment should be treated carefully when accepting user input, by default
- * entities will guard all fields when properties are assigned in bulk. You can disable
- * the guarding for a single set call with the `guard` option:
- *
- * ```
- * $entity->set(['name' => 'Andrew', 'id' => 1], ['guard' => true]);
- * ```
- *
- * You do not need to use the guard option when assigning properties individually:
- *
- * ```
- * // No need to use the guard option.
- * $entity->set('name', 'Andrew');
- * ```
- *
- * @param string|array $property the name of property to set or a list of
- * properties with their respective values
- * @param mixed $value The value to set to the property or an array if the
- * first argument is also an array, in which case will be treated as $options
- * @param array $options options to be used for setting the property. Allowed option
- * keys are `setter` and `guard`
- * @return $this
- * @throws \InvalidArgumentException
- */
- public function set($property, $value = null, array $options = [])
- {
- $isString = is_string($property);
- if ($isString && $property !== '') {
- $guard = false;
- $property = [$property => $value];
- } else {
- $guard = true;
- $options = (array)$value;
- }
- if (!is_array($property)) {
- throw new InvalidArgumentException('Cannot set an empty property');
- }
- $options += ['setter' => true, 'guard' => $guard];
- foreach ($property as $p => $value) {
- if ($options['guard'] === true && !$this->isAccessible($p)) {
- continue;
- }
- $this->setDirty($p, true);
- if (!array_key_exists($p, $this->_original) &&
- array_key_exists($p, $this->_properties) &&
- $this->_properties[$p] !== $value
- ) {
- $this->_original[$p] = $this->_properties[$p];
- }
- if (!$options['setter']) {
- $this->_properties[$p] = $value;
- continue;
- }
- $setter = static::_accessor($p, 'set');
- if ($setter) {
- $value = $this->{$setter}($value);
- }
- $this->_properties[$p] = $value;
- }
- return $this;
- }
- /**
- * Returns the value of a property by name
- *
- * @param string $property the name of the property to retrieve
- * @return mixed
- * @throws \InvalidArgumentException if an empty property name is passed
- */
- public function &get($property)
- {
- if (!strlen((string)$property)) {
- throw new InvalidArgumentException('Cannot get an empty property');
- }
- $value = null;
- $method = static::_accessor($property, 'get');
- if (isset($this->_properties[$property])) {
- $value =& $this->_properties[$property];
- }
- if ($method) {
- $result = $this->{$method}($value);
- return $result;
- }
- return $value;
- }
- /**
- * Returns the value of an original property by name
- *
- * @param string $property the name of the property for which original value is retrieved.
- * @return mixed
- * @throws \InvalidArgumentException if an empty property name is passed.
- */
- public function getOriginal($property)
- {
- if (!strlen((string)$property)) {
- throw new InvalidArgumentException('Cannot get an empty property');
- }
- if (array_key_exists($property, $this->_original)) {
- return $this->_original[$property];
- }
- return $this->get($property);
- }
- /**
- * Gets all original values of the entity.
- *
- * @return array
- */
- public function getOriginalValues()
- {
- $originals = $this->_original;
- $originalKeys = array_keys($originals);
- foreach ($this->_properties as $key => $value) {
- if (!in_array($key, $originalKeys)) {
- $originals[$key] = $value;
- }
- }
- return $originals;
- }
- /**
- * Returns whether this entity contains a property named $property
- * that contains a non-null value.
- *
- * ### Example:
- *
- * ```
- * $entity = new Entity(['id' => 1, 'name' => null]);
- * $entity->has('id'); // true
- * $entity->has('name'); // false
- * $entity->has('last_name'); // false
- * ```
- *
- * You can check multiple properties by passing an array:
- *
- * ```
- * $entity->has(['name', 'last_name']);
- * ```
- *
- * All properties must not be null to get a truthy result.
- *
- * When checking multiple properties. All properties must not be null
- * in order for true to be returned.
- *
- * @param string|array $property The property or properties to check.
- * @return bool
- */
- public function has($property)
- {
- foreach ((array)$property as $prop) {
- if ($this->get($prop) === null) {
- return false;
- }
- }
- return true;
- }
- /**
- * Removes a property or list of properties from this entity
- *
- * ### Examples:
- *
- * ```
- * $entity->unsetProperty('name');
- * $entity->unsetProperty(['name', 'last_name']);
- * ```
- *
- * @param string|array $property The property to unset.
- * @return $this
- */
- public function unsetProperty($property)
- {
- $property = (array)$property;
- foreach ($property as $p) {
- unset($this->_properties[$p], $this->_dirty[$p]);
- }
- return $this;
- }
- /**
- * Get/Set the hidden properties on this entity.
- *
- * If the properties argument is null, the currently hidden properties
- * will be returned. Otherwise the hidden properties will be set.
- *
- * @deprecated 3.4.0 Use EntityTrait::setHidden() and EntityTrait::getHidden()
- * @param null|array $properties Either an array of properties to hide or null to get properties
- * @return array|$this
- */
- public function hiddenProperties($properties = null)
- {
- if ($properties === null) {
- return $this->_hidden;
- }
- $this->_hidden = $properties;
- return $this;
- }
- /**
- * Sets hidden properties.
- *
- * @param array $properties An array of properties to treat as virtual.
- * @param bool $merge Merge the new properties with the existing. By default false.
- * @return $this
- */
- public function setHidden(array $properties, $merge = false)
- {
- if ($merge === false) {
- $this->_hidden = $properties;
- return $this;
- }
- $properties = array_merge($this->_hidden, $properties);
- $this->_hidden = array_unique($properties);
- return $this;
- }
- /**
- * Gets the hidden properties.
- *
- * @return array
- */
- public function getHidden()
- {
- return $this->_hidden;
- }
- /**
- * Get/Set the virtual properties on this entity.
- *
- * If the properties argument is null, the currently virtual properties
- * will be returned. Otherwise the virtual properties will be set.
- *
- * @deprecated 3.4.0 Use EntityTrait::getVirtual() and EntityTrait::setVirtual()
- * @param null|array $properties Either an array of properties to treat as virtual or null to get properties
- * @return array|$this
- */
- public function virtualProperties($properties = null)
- {
- if ($properties === null) {
- return $this->getVirtual();
- }
- return $this->setVirtual($properties);
- }
- /**
- * Sets the virtual properties on this entity.
- *
- * @param array $properties An array of properties to treat as virtual.
- * @param bool $merge Merge the new properties with the existing. By default false.
- * @return $this
- */
- public function setVirtual(array $properties, $merge = false)
- {
- if ($merge === false) {
- $this->_virtual = $properties;
- return $this;
- }
- $properties = array_merge($this->_virtual, $properties);
- $this->_virtual = array_unique($properties);
- return $this;
- }
- /**
- * Gets the virtual properties on this entity.
- *
- * @return array
- */
- public function getVirtual()
- {
- return $this->_virtual;
- }
- /**
- * Get the list of visible properties.
- *
- * The list of visible properties is all standard properties
- * plus virtual properties minus hidden properties.
- *
- * @return array A list of properties that are 'visible' in all
- * representations.
- */
- public function visibleProperties()
- {
- $properties = array_keys($this->_properties);
- $properties = array_merge($properties, $this->_virtual);
- return array_diff($properties, $this->_hidden);
- }
- /**
- * Returns an array with all the properties that have been set
- * to this entity
- *
- * This method will recursively transform entities assigned to properties
- * into arrays as well.
- *
- * @return array
- */
- public function toArray()
- {
- $result = [];
- foreach ($this->visibleProperties() as $property) {
- $value = $this->get($property);
- if (is_array($value)) {
- $result[$property] = [];
- foreach ($value as $k => $entity) {
- if ($entity instanceof EntityInterface) {
- $result[$property][$k] = $entity->toArray();
- } else {
- $result[$property][$k] = $entity;
- }
- }
- } elseif ($value instanceof EntityInterface) {
- $result[$property] = $value->toArray();
- } else {
- $result[$property] = $value;
- }
- }
- return $result;
- }
- /**
- * Returns the properties that will be serialized as JSON
- *
- * @return array
- */
- public function jsonSerialize()
- {
- return $this->extract($this->visibleProperties());
- }
- /**
- * Implements isset($entity);
- *
- * @param mixed $offset The offset to check.
- * @return bool Success
- */
- public function offsetExists($offset)
- {
- return $this->has($offset);
- }
- /**
- * Implements $entity[$offset];
- *
- * @param mixed $offset The offset to get.
- * @return mixed
- */
- public function &offsetGet($offset)
- {
- return $this->get($offset);
- }
- /**
- * Implements $entity[$offset] = $value;
- *
- * @param mixed $offset The offset to set.
- * @param mixed $value The value to set.
- * @return void
- */
- public function offsetSet($offset, $value)
- {
- $this->set($offset, $value);
- }
- /**
- * Implements unset($result[$offset]);
- *
- * @param mixed $offset The offset to remove.
- * @return void
- */
- public function offsetUnset($offset)
- {
- $this->unsetProperty($offset);
- }
- /**
- * Fetch accessor method name
- * Accessor methods (available or not) are cached in $_accessors
- *
- * @param string $property the field name to derive getter name from
- * @param string $type the accessor type ('get' or 'set')
- * @return string method name or empty string (no method available)
- */
- protected static function _accessor($property, $type)
- {
- $class = static::class;
- if (isset(static::$_accessors[$class][$type][$property])) {
- return static::$_accessors[$class][$type][$property];
- }
- if (!empty(static::$_accessors[$class])) {
- return static::$_accessors[$class][$type][$property] = '';
- }
- if ($class === 'Cake\ORM\Entity') {
- return '';
- }
- foreach (get_class_methods($class) as $method) {
- $prefix = substr($method, 1, 3);
- if ($method[0] !== '_' || ($prefix !== 'get' && $prefix !== 'set')) {
- continue;
- }
- $field = lcfirst(substr($method, 4));
- $snakeField = Inflector::underscore($field);
- $titleField = ucfirst($field);
- static::$_accessors[$class][$prefix][$snakeField] = $method;
- static::$_accessors[$class][$prefix][$field] = $method;
- static::$_accessors[$class][$prefix][$titleField] = $method;
- }
- if (!isset(static::$_accessors[$class][$type][$property])) {
- static::$_accessors[$class][$type][$property] = '';
- }
- return static::$_accessors[$class][$type][$property];
- }
- /**
- * Returns an array with the requested properties
- * stored in this entity, indexed by property name
- *
- * @param array $properties list of properties to be returned
- * @param bool $onlyDirty Return the requested property only if it is dirty
- * @return array
- */
- public function extract(array $properties, $onlyDirty = false)
- {
- $result = [];
- foreach ($properties as $property) {
- if (!$onlyDirty || $this->isDirty($property)) {
- $result[$property] = $this->get($property);
- }
- }
- return $result;
- }
- /**
- * Returns an array with the requested original properties
- * stored in this entity, indexed by property name.
- *
- * Properties that are unchanged from their original value will be included in the
- * return of this method.
- *
- * @param array $properties List of properties to be returned
- * @return array
- */
- public function extractOriginal(array $properties)
- {
- $result = [];
- foreach ($properties as $property) {
- $result[$property] = $this->getOriginal($property);
- }
- return $result;
- }
- /**
- * Returns an array with only the original properties
- * stored in this entity, indexed by property name.
- *
- * This method will only return properties that have been modified since
- * the entity was built. Unchanged properties will be omitted.
- *
- * @param array $properties List of properties to be returned
- * @return array
- */
- public function extractOriginalChanged(array $properties)
- {
- $result = [];
- foreach ($properties as $property) {
- $original = $this->getOriginal($property);
- if ($original !== $this->get($property)) {
- $result[$property] = $original;
- }
- }
- return $result;
- }
- /**
- * Sets the dirty status of a single property. If called with no second
- * argument, it will return whether the property was modified or not
- * after the object creation.
- *
- * When called with no arguments it will return whether or not there are any
- * dirty property in the entity
- *
- * @deprecated 3.4.0 Use EntityTrait::setDirty() and EntityTrait::isDirty()
- * @param string|null $property the field to set or check status for
- * @param null|bool $isDirty true means the property was changed, false means
- * it was not changed and null will make the function return current state
- * for that property
- * @return bool Whether the property was changed or not
- */
- public function dirty($property = null, $isDirty = null)
- {
- if ($property === null) {
- return $this->isDirty();
- }
- if ($isDirty === null) {
- return $this->isDirty($property);
- }
- $this->setDirty($property, $isDirty);
- return true;
- }
- /**
- * Sets the dirty status of a single property.
- *
- * @param string $property the field to set or check status for
- * @param bool $isDirty true means the property was changed, false means
- * it was not changed
- * @return $this
- */
- public function setDirty($property, $isDirty)
- {
- if ($isDirty === false) {
- unset($this->_dirty[$property]);
- return false;
- }
- $this->_dirty[$property] = true;
- unset($this->_errors[$property], $this->_invalid[$property]);
- return $this;
- }
- /**
- * Checks if the entity is dirty or if a single property of it is dirty.
- *
- * @param string $property the field to check the status for
- * @return bool Whether the property was changed or not
- */
- public function isDirty($property = null)
- {
- if ($property === null) {
- return !empty($this->_dirty);
- }
- return isset($this->_dirty[$property]);
- }
- /**
- * Gets the dirty properties.
- *
- * @return array
- */
- public function getDirty()
- {
- return array_keys($this->_dirty);
- }
- /**
- * Sets the entire entity as clean, which means that it will appear as
- * no properties being modified or added at all. This is an useful call
- * for an initial object hydration
- *
- * @return void
- */
- public function clean()
- {
- $this->_dirty = [];
- $this->_errors = [];
- $this->_invalid = [];
- $this->_original = [];
- }
- /**
- * Returns whether or not this entity has already been persisted.
- * This method can return null in the case there is no prior information on
- * the status of this entity.
- *
- * If called with a boolean it will set the known status of this instance,
- * true means that the instance is not yet persisted in the database, false
- * that it already is.
- *
- * @param bool|null $new true if it is known this instance was not yet persisted
- * @return bool Whether or not the entity has been persisted.
- */
- public function isNew($new = null)
- {
- if ($new === null) {
- return $this->_new;
- }
- $new = (bool)$new;
- if ($new) {
- foreach ($this->_properties as $k => $p) {
- $this->_dirty[$k] = true;
- }
- }
- return $this->_new = $new;
- }
- /**
- * Returns all validation errors.
- *
- * @return array
- */
- public function getErrors()
- {
- $diff = array_diff_key($this->_properties, $this->_errors);
- return $this->_errors + (new Collection($diff))
- ->filter(function ($value) {
- return is_array($value) || $value instanceof EntityInterface;
- })
- ->map(function ($value) {
- return $this->_readError($value);
- })
- ->filter()
- ->toArray();
- }
- /**
- * Returns validation errors of a field
- *
- * @param string $field Field name to get the errors from
- * @return array
- */
- public function getError($field)
- {
- $errors = isset($this->_errors[$field]) ? $this->_errors[$field] : [];
- if ($errors) {
- return $errors;
- }
- return $this->_nestedErrors($field);
- }
- /**
- * Sets error messages to the entity
- *
- * ## Example
- *
- * ```
- * // Sets the error messages for multiple fields at once
- * $entity->errors(['salary' => ['message'], 'name' => ['another message']);
- * ```
- *
- * @param array $fields The array of errors to set.
- * @param bool $overwrite Whether or not to overwrite pre-existing errors for $fields
- * @return $this
- */
- public function setErrors(array $fields, $overwrite = false)
- {
- foreach ($fields as $f => $error) {
- $this->_errors += [$f => []];
- $this->_errors[$f] = $overwrite ?
- (array)$error :
- array_merge($this->_errors[$f], (array)$error);
- }
- return $this;
- }
- /**
- * Sets errors for a single field
- *
- * ### Example
- *
- * ```
- * // Sets the error messages for a single field
- * $entity->errors('salary', ['must be numeric', 'must be a positive number']);
- * ```
- *
- * @param string $field The field to get errors for, or the array of errors to set.
- * @param string|array $errors The errors to be set for $field
- * @param bool $overwrite Whether or not to overwrite pre-existing errors for $field
- * @return $this
- */
- public function setError($field, $errors, $overwrite = false)
- {
- if (is_string($errors)) {
- $errors = [$errors];
- }
- return $this->setErrors([$field => $errors], $overwrite);
- }
- /**
- * Sets the error messages for a field or a list of fields. When called
- * without the second argument it returns the validation
- * errors for the specified fields. If called with no arguments it returns
- * all the validation error messages stored in this entity and any other nested
- * entity.
- *
- * ### Example
- *
- * ```
- * // Sets the error messages for a single field
- * $entity->errors('salary', ['must be numeric', 'must be a positive number']);
- *
- * // Returns the error messages for a single field
- * $entity->errors('salary');
- *
- * // Returns all error messages indexed by field name
- * $entity->errors();
- *
- * // Sets the error messages for multiple fields at once
- * $entity->errors(['salary' => ['message'], 'name' => ['another message']);
- * ```
- *
- * When used as a setter, this method will return this entity instance for method
- * chaining.
- *
- * @deprecated 3.4.0 Use EntityTrait::setError(), EntityTrait::setErrors(), EntityTrait::getError() and EntityTrait::getErrors()
- * @param string|array|null $field The field to get errors for, or the array of errors to set.
- * @param string|array|null $errors The errors to be set for $field
- * @param bool $overwrite Whether or not to overwrite pre-existing errors for $field
- * @return array|$this
- */
- public function errors($field = null, $errors = null, $overwrite = false)
- {
- if ($field === null) {
- return $this->getErrors();
- }
- if (is_string($field) && $errors === null) {
- return $this->getError($field);
- }
- if (!is_array($field)) {
- $field = [$field => $errors];
- }
- return $this->setErrors($field, $overwrite);
- }
- /**
- * Auxiliary method for getting errors in nested entities
- *
- * @param string $field the field in this entity to check for errors
- * @return array errors in nested entity if any
- */
- protected function _nestedErrors($field)
- {
- $path = explode('.', $field);
- // Only one path element, check for nested entity with error.
- if (count($path) === 1) {
- return $this->_readError($this->get($path[0]));
- }
- $entity = $this;
- $len = count($path);
- while ($len) {
- $part = array_shift($path);
- $len = count($path);
- $val = null;
- if ($entity instanceof EntityInterface) {
- $val = $entity->get($part);
- } elseif (is_array($entity)) {
- $val = isset($entity[$part]) ? $entity[$part] : false;
- }
- if (is_array($val) ||
- $val instanceof Traversable ||
- $val instanceof EntityInterface
- ) {
- $entity = $val;
- } else {
- $path[] = $part;
- break;
- }
- }
- if (count($path) <= 1) {
- return $this->_readError($entity, array_pop($path));
- }
- return [];
- }
- /**
- * Read the error(s) from one or many objects.
- *
- * @param array|\Cake\Datasource\EntityTrait $object The object to read errors from.
- * @param string|null $path The field name for errors.
- * @return array
- */
- protected function _readError($object, $path = null)
- {
- if ($object instanceof EntityInterface) {
- return $object->errors($path);
- }
- if (is_array($object)) {
- $array = array_map(function ($val) {
- if ($val instanceof EntityInterface) {
- return $val->errors();
- }
- }, $object);
- return array_filter($array);
- }
- return [];
- }
- /**
- * Get a list of invalid fields and their data for errors upon validation/patching
- *
- * @return array
- */
- public function getInvalid()
- {
- return $this->_invalid;
- }
- /**
- * Get a single value of an invalid field. Returns null if not set.
- *
- * @param string $field The name of the field.
- * @return mixed
- */
- public function getInvalidField($field)
- {
- $value = isset($this->_invalid[$field]) ? $this->_invalid[$field] : null;
- return $value;
- }
- /**
- * Set fields as invalid and not patchable into the entity.
- *
- * This is useful for batch operations when one needs to get the original value for an error message after patching.
- * This value could not be patched into the entity and is simply copied into the _invalid property for debugging purposes
- * or to be able to log it away.
- *
- * @param array $fields The values to set.
- * @param bool $overwrite Whether or not to overwrite pre-existing values for $field.
- * @return $this
- */
- public function setInvalid(array $fields, $overwrite = false)
- {
- foreach ($fields as $field => $value) {
- if ($overwrite === true) {
- $this->_invalid[$field] = $value;
- continue;
- }
- $this->_invalid += [$field => $value];
- }
- return $this;
- }
- /**
- * Sets a field as invalid and not patchable into the entity.
- *
- * @param string $field The value to set.
- * @param mixed $value The invalid value to be set for $field.
- * @return $this
- */
- public function setInvalidField($field, $value)
- {
- $this->_invalid[$field] = $value;
- return $this;
- }
- /**
- * Sets a field as invalid and not patchable into the entity.
- *
- * This is useful for batch operations when one needs to get the original value for an error message after patching.
- * This value could not be patched into the entity and is simply copied into the _invalid property for debugging purposes
- * or to be able to log it away.
- *
- * @deprecated 3.5 Use getInvalid()/getInvalidField()/setInvalid() instead.
- * @param string|array|null $field The field to get invalid value for, or the value to set.
- * @param mixed|null $value The invalid value to be set for $field.
- * @param bool $overwrite Whether or not to overwrite pre-existing values for $field.
- * @return $this|mixed
- */
- public function invalid($field = null, $value = null, $overwrite = false)
- {
- if ($field === null) {
- return $this->_invalid;
- }
- if (is_string($field) && $value === null) {
- $value = isset($this->_invalid[$field]) ? $this->_invalid[$field] : null;
- return $value;
- }
- if (!is_array($field)) {
- $field = [$field => $value];
- }
- foreach ($field as $f => $value) {
- if ($overwrite) {
- $this->_invalid[$f] = $value;
- continue;
- }
- $this->_invalid += [$f => $value];
- }
- return $this;
- }
- /**
- * Stores whether or not a property value can be changed or set in this entity.
- * The special property `*` can also be marked as accessible or protected, meaning
- * that any other property specified before will take its value. For example
- * `$entity->accessible('*', true)` means that any property not specified already
- * will be accessible by default.
- *
- * You can also call this method with an array of properties, in which case they
- * will each take the accessibility value specified in the second argument.
- *
- * ### Example:
- *
- * ```
- * $entity->accessible('id', true); // Mark id as not protected
- * $entity->accessible('author_id', false); // Mark author_id as protected
- * $entity->accessible(['id', 'user_id'], true); // Mark both properties as accessible
- * $entity->accessible('*', false); // Mark all properties as protected
- * ```
- *
- * When called without the second param it will return whether or not the property
- * can be set.
- *
- * ### Example:
- *
- * ```
- * $entity->accessible('id'); // Returns whether it can be set or not
- * ```
- *
- * @deprecated 3.4.0 Use EntityTrait::setAccess() and EntityTrait::isAccessible()
- * @param string|array $property single or list of properties to change its accessibility
- * @param bool|null $set true marks the property as accessible, false will
- * mark it as protected.
- * @return $this|bool
- */
- public function accessible($property, $set = null)
- {
- if ($set === null) {
- return $this->isAccessible($property);
- }
- return $this->setAccess($property, $set);
- }
- /**
- * Stores whether or not a property value can be changed or set in this entity.
- * The special property `*` can also be marked as accessible or protected, meaning
- * that any other property specified before will take its value. For example
- * `$entity->accessible('*', true)` means that any property not specified already
- * will be accessible by default.
- *
- * You can also call this method with an array of properties, in which case they
- * will each take the accessibility value specified in the second argument.
- *
- * ### Example:
- *
- * ```
- * $entity->setAccess('id', true); // Mark id as not protected
- * $entity->setAccess('author_id', false); // Mark author_id as protected
- * $entity->setAccess(['id', 'user_id'], true); // Mark both properties as accessible
- * $entity->setAccess('*', false); // Mark all properties as protected
- * ```
- *
- * @param string|array $property single or list of properties to change its accessibility
- * @param bool $set true marks the property as accessible, false will
- * mark it as protected.
- * @return $this
- */
- public function setAccess($property, $set)
- {
- if ($property === '*') {
- $this->_accessible = array_map(function ($p) use ($set) {
- return (bool)$set;
- }, $this->_accessible);
- $this->_accessible['*'] = (bool)$set;
- return $this;
- }
- foreach ((array)$property as $prop) {
- $this->_accessible[$prop] = (bool)$set;
- }
- return $this;
- }
- /**
- * Checks if a property is accessible
- *
- * ### Example:
- *
- * ```
- * $entity->isAccessible('id'); // Returns whether it can be set or not
- * ```
- *
- * @param string $property Property name to check
- * @return bool
- */
- public function isAccessible($property)
- {
- $value = isset($this->_accessible[$property]) ?
- $this->_accessible[$property] :
- null;
- return ($value === null && !empty($this->_accessible['*'])) || $value;
- }
- /**
- * Returns the alias of the repository from which this entity came from.
- *
- * @return string
- */
- public function getSource()
- {
- return $this->_registryAlias;
- }
- /**
- * Sets the source alias
- *
- * @param string $alias the alias of the repository
- * @return $this
- */
- public function setSource($alias)
- {
- $this->_registryAlias = $alias;
- return $this;
- }
- /**
- * Returns the alias of the repository from which this entity came from.
- *
- * If called with no arguments, it returns the alias of the repository
- * this entity came from if it is known.
- *
- * @deprecated 3.4.0 Use EntityTrait::getSource() and EntityTrait::setSource()
- * @param string|null $alias the alias of the repository
- * @return string|$this
- */
- public function source($alias = null)
- {
- if (is_null($alias)) {
- return $this->getSource();
- }
- $this->setSource($alias);
- return $this;
- }
- /**
- * Returns a string representation of this object in a human readable format.
- *
- * @return string
- */
- public function __toString()
- {
- return json_encode($this, JSON_PRETTY_PRINT);
- }
- /**
- * Returns an array that can be used to describe the internal state of this
- * object.
- *
- * @return array
- */
- public function __debugInfo()
- {
- return $this->_properties + [
- '[new]' => $this->isNew(),
- '[accessible]' => $this->_accessible,
- '[dirty]' => $this->_dirty,
- '[original]' => $this->_original,
- '[virtual]' => $this->_virtual,
- '[errors]' => $this->_errors,
- '[invalid]' => $this->_invalid,
- '[repository]' => $this->_registryAlias
- ];
- }
- }
|