/var/www/vhosts/ihelp.ro/_OLD/vendor/cakephp/cakephp/src/ORM
NameSizeModeActions
Association/-0755rm
Behavior/-0755rm
Exception/-0755rm
Locator/-0755rm
Rule/-0755rm
Association.php406730644editdlrm
AssociationCollection.php118650644editdlrm
AssociationsNormalizerTrait.php23190644editdlrm
Behavior.php142110644editdlrm
BehaviorRegistry.php92990644editdlrm
composer.json13040644editdlrm
EagerLoadable.php80440644editdlrm
EagerLoader.php312430644editdlrm
Entity.php27630644editdlrm
LazyEagerLoader.php66700644editdlrm
LICENSE.txt12040644editdlrm
Marshaller.php333660644editdlrm
PropertyMarshalInterface.php14150644editdlrm
Query.php469990644editdlrm
README.md68480644editdlrm
ResultSet.php152890644editdlrm
RulesChecker.php102760644editdlrm
SaveOptionsBuilder.php57080644editdlrm
Table.php1085540644editdlrm
TableRegistry.php49660644editdlrm
Edit: /var/www/vhosts/ihelp.ro/_OLD/vendor/cakephp/cakephp/src/ORM/Association.php (40673B)
{'_' . $property} = $options[$property]; } } if (empty($this->_className)) { $this->_className = $alias; } [, $name] = pluginSplit($alias); $this->_name = $name; $this->_options($options); if (!empty($options['strategy'])) { $this->setStrategy($options['strategy']); } } /** * Sets the name for this association, usually the alias * assigned to the target associated table * * @param string $name Name to be assigned * @return $this */ public function setName(string $name) { if ($this->_targetTable !== null) { $alias = $this->_targetTable->getAlias(); if ($alias !== $name) { throw new InvalidArgumentException(sprintf( 'Association name "%s" does not match target table alias "%s".', $name, $alias )); } } $this->_name = $name; return $this; } /** * Gets the name for this association, usually the alias * assigned to the target associated table * * @return string */ public function getName(): string { return $this->_name; } /** * Sets whether or not cascaded deletes should also fire callbacks. * * @param bool $cascadeCallbacks cascade callbacks switch value * @return $this */ public function setCascadeCallbacks(bool $cascadeCallbacks) { $this->_cascadeCallbacks = $cascadeCallbacks; return $this; } /** * Gets whether or not cascaded deletes should also fire callbacks. * * @return bool */ public function getCascadeCallbacks(): bool { return $this->_cascadeCallbacks; } /** * Sets the class name of the target table object. * * @param string $className Class name to set. * @return $this * @throws \InvalidArgumentException In case the class name is set after the target table has been * resolved, and it doesn't match the target table's class name. */ public function setClassName(string $className) { if ( $this->_targetTable !== null && get_class($this->_targetTable) !== App::className($className, 'Model/Table', 'Table') ) { throw new InvalidArgumentException(sprintf( 'The class name "%s" doesn\'t match the target table class name of "%s".', $className, get_class($this->_targetTable) )); } $this->_className = $className; return $this; } /** * Gets the class name of the target table object. * * @return string */ public function getClassName(): string { return $this->_className; } /** * Sets the table instance for the source side of the association. * * @param \Cake\ORM\Table $table the instance to be assigned as source side * @return $this */ public function setSource(Table $table) { $this->_sourceTable = $table; return $this; } /** * Gets the table instance for the source side of the association. * * @return \Cake\ORM\Table */ public function getSource(): Table { return $this->_sourceTable; } /** * Sets the table instance for the target side of the association. * * @param \Cake\ORM\Table $table the instance to be assigned as target side * @return $this */ public function setTarget(Table $table) { $this->_targetTable = $table; return $this; } /** * Gets the table instance for the target side of the association. * * @return \Cake\ORM\Table */ public function getTarget(): Table { if ($this->_targetTable === null) { if (strpos($this->_className, '.')) { [$plugin] = pluginSplit($this->_className, true); $registryAlias = (string)$plugin . $this->_name; } else { $registryAlias = $this->_name; } $tableLocator = $this->getTableLocator(); $config = []; $exists = $tableLocator->exists($registryAlias); if (!$exists) { $config = ['className' => $this->_className]; } $this->_targetTable = $tableLocator->get($registryAlias, $config); if ($exists) { $className = App::className($this->_className, 'Model/Table', 'Table') ?: Table::class; if (!$this->_targetTable instanceof $className) { $errorMessage = '%s association "%s" of type "%s" to "%s" doesn\'t match the expected class "%s". '; $errorMessage .= 'You can\'t have an association of the same name with a different target '; $errorMessage .= '"className" option anywhere in your app.'; throw new RuntimeException(sprintf( $errorMessage, $this->_sourceTable === null ? 'null' : get_class($this->_sourceTable), $this->getName(), $this->type(), get_class($this->_targetTable), $className )); } } } return $this->_targetTable; } /** * Sets a list of conditions to be always included when fetching records from * the target association. * * @param array|\Closure $conditions list of conditions to be used * @see \Cake\Database\Query::where() for examples on the format of the array * @return \Cake\ORM\Association */ public function setConditions($conditions) { $this->_conditions = $conditions; return $this; } /** * Gets a list of conditions to be always included when fetching records from * the target association. * * @see \Cake\Database\Query::where() for examples on the format of the array * @return array|\Closure */ public function getConditions() { return $this->_conditions; } /** * Sets the name of the field representing the binding field with the target table. * When not manually specified the primary key of the owning side table is used. * * @param string|string[] $key the table field or fields to be used to link both tables together * @return $this */ public function setBindingKey($key) { $this->_bindingKey = $key; return $this; } /** * Gets the name of the field representing the binding field with the target table. * When not manually specified the primary key of the owning side table is used. * * @return string|string[] */ public function getBindingKey() { if ($this->_bindingKey === null) { $this->_bindingKey = $this->isOwningSide($this->getSource()) ? $this->getSource()->getPrimaryKey() : $this->getTarget()->getPrimaryKey(); } return $this->_bindingKey; } /** * Gets the name of the field representing the foreign key to the target table. * * @return string|string[] */ public function getForeignKey() { return $this->_foreignKey; } /** * Sets the name of the field representing the foreign key to the target table. * * @param string|string[] $key the key or keys to be used to link both tables together * @return $this */ public function setForeignKey($key) { $this->_foreignKey = $key; return $this; } /** * Sets whether the records on the target table are dependent on the source table. * * This is primarily used to indicate that records should be removed if the owning record in * the source table is deleted. * * If no parameters are passed the current setting is returned. * * @param bool $dependent Set the dependent mode. Use null to read the current state. * @return $this */ public function setDependent(bool $dependent) { $this->_dependent = $dependent; return $this; } /** * Sets whether the records on the target table are dependent on the source table. * * This is primarily used to indicate that records should be removed if the owning record in * the source table is deleted. * * @return bool */ public function getDependent(): bool { return $this->_dependent; } /** * Whether this association can be expressed directly in a query join * * @param array $options custom options key that could alter the return value * @return bool */ public function canBeJoined(array $options = []): bool { $strategy = $options['strategy'] ?? $this->getStrategy(); return $strategy === $this::STRATEGY_JOIN; } /** * Sets the type of join to be used when adding the association to a query. * * @param string $type the join type to be used (e.g. INNER) * @return $this */ public function setJoinType(string $type) { $this->_joinType = $type; return $this; } /** * Gets the type of join to be used when adding the association to a query. * * @return string */ public function getJoinType(): string { return $this->_joinType; } /** * Sets the property name that should be filled with data from the target table * in the source table record. * * @param string $name The name of the association property. Use null to read the current value. * @return $this */ public function setProperty(string $name) { $this->_propertyName = $name; return $this; } /** * Gets the property name that should be filled with data from the target table * in the source table record. * * @return string */ public function getProperty(): string { if (!$this->_propertyName) { $this->_propertyName = $this->_propertyName(); if (in_array($this->_propertyName, $this->_sourceTable->getSchema()->columns(), true)) { $msg = 'Association property name "%s" clashes with field of same name of table "%s".' . ' You should explicitly specify the "propertyName" option.'; trigger_error( sprintf($msg, $this->_propertyName, $this->_sourceTable->getTable()), E_USER_WARNING ); } } return $this->_propertyName; } /** * Returns default property name based on association name. * * @return string */ protected function _propertyName(): string { [, $name] = pluginSplit($this->_name); return Inflector::underscore($name); } /** * Sets the strategy name to be used to fetch associated records. Keep in mind * that some association types might not implement but a default strategy, * rendering any changes to this setting void. * * @param string $name The strategy type. Use null to read the current value. * @return $this * @throws \InvalidArgumentException When an invalid strategy is provided. */ public function setStrategy(string $name) { if (!in_array($name, $this->_validStrategies, true)) { throw new InvalidArgumentException(sprintf( 'Invalid strategy "%s" was provided. Valid options are (%s).', $name, implode(', ', $this->_validStrategies) )); } $this->_strategy = $name; return $this; } /** * Gets the strategy name to be used to fetch associated records. Keep in mind * that some association types might not implement but a default strategy, * rendering any changes to this setting void. * * @return string */ public function getStrategy(): string { return $this->_strategy; } /** * Gets the default finder to use for fetching rows from the target table. * * @return string|array */ public function getFinder() { return $this->_finder; } /** * Sets the default finder to use for fetching rows from the target table. * * @param string|array $finder the finder name to use or array of finder name and option. * @return $this */ public function setFinder($finder) { $this->_finder = $finder; return $this; } /** * Override this function to initialize any concrete association class, it will * get passed the original list of options used in the constructor * * @param array $options List of options used for initialization * @return void */ protected function _options(array $options): void { } /** * Alters a Query object to include the associated target table data in the final * result * * The options array accept the following keys: * * - includeFields: Whether to include target model fields in the result or not * - foreignKey: The name of the field to use as foreign key, if false none * will be used * - conditions: array with a list of conditions to filter the join with, this * will be merged with any conditions originally configured for this association * - fields: a list of fields in the target table to include in the result * - type: The type of join to be used (e.g. INNER) * the records found on this association * - aliasPath: A dot separated string representing the path of association names * followed from the passed query main table to this association. * - propertyPath: A dot separated string representing the path of association * properties to be followed from the passed query main entity to this * association * - joinType: The SQL join type to use in the query. * - negateMatch: Will append a condition to the passed query for excluding matches. * with this association. * * @param \Cake\ORM\Query $query the query to be altered to include the target table data * @param array $options Any extra options or overrides to be taken in account * @return void * @throws \RuntimeException if the query builder passed does not return a query * object */ public function attachTo(Query $query, array $options = []): void { $target = $this->getTarget(); $joinType = empty($options['joinType']) ? $this->getJoinType() : $options['joinType']; $table = $target->getTable(); $options += [ 'includeFields' => true, 'foreignKey' => $this->getForeignKey(), 'conditions' => [], 'fields' => [], 'type' => $joinType, 'table' => $table, 'finder' => $this->getFinder(), ]; if (!empty($options['foreignKey'])) { $joinCondition = $this->_joinCondition($options); if ($joinCondition) { $options['conditions'][] = $joinCondition; } } [$finder, $opts] = $this->_extractFinder($options['finder']); $dummy = $this ->find($finder, $opts) ->eagerLoaded(true); if (!empty($options['queryBuilder'])) { $dummy = $options['queryBuilder']($dummy); if (!($dummy instanceof Query)) { throw new RuntimeException(sprintf( 'Query builder for association "%s" did not return a query', $this->getName() )); } } if ( !empty($options['matching']) && $this->_strategy === static::STRATEGY_JOIN && $dummy->getContain() ) { throw new RuntimeException( "`{$this->getName()}` association cannot contain() associations when using JOIN strategy." ); } $dummy->where($options['conditions']); $this->_dispatchBeforeFind($dummy); $joinOptions = ['table' => 1, 'conditions' => 1, 'type' => 1]; $options['conditions'] = $dummy->clause('where'); $query->join([$this->_name => array_intersect_key($options, $joinOptions)]); $this->_appendFields($query, $dummy, $options); $this->_formatAssociationResults($query, $dummy, $options); $this->_bindNewAssociations($query, $dummy, $options); $this->_appendNotMatching($query, $options); } /** * Conditionally adds a condition to the passed Query that will make it find * records where there is no match with this association. * * @param \Cake\ORM\Query $query The query to modify * @param array $options Options array containing the `negateMatch` key. * @return void */ protected function _appendNotMatching(Query $query, array $options): void { $target = $this->_targetTable; if (!empty($options['negateMatch'])) { $primaryKey = $query->aliasFields((array)$target->getPrimaryKey(), $this->_name); $query->andWhere(function ($exp) use ($primaryKey) { array_map([$exp, 'isNull'], $primaryKey); return $exp; }); } } /** * Correctly nests a result row associated values into the correct array keys inside the * source results. * * @param array $row The row to transform * @param string $nestKey The array key under which the results for this association * should be found * @param bool $joined Whether or not the row is a result of a direct join * with this association * @param string|null $targetProperty The property name in the source results where the association * data shuld be nested in. Will use the default one if not provided. * @return array */ public function transformRow(array $row, string $nestKey, bool $joined, ?string $targetProperty = null): array { $sourceAlias = $this->getSource()->getAlias(); $nestKey = $nestKey ?: $this->_name; $targetProperty = $targetProperty ?: $this->getProperty(); if (isset($row[$sourceAlias])) { $row[$sourceAlias][$targetProperty] = $row[$nestKey]; unset($row[$nestKey]); } return $row; } /** * Returns a modified row after appending a property for this association * with the default empty value according to whether the association was * joined or fetched externally. * * @param array $row The row to set a default on. * @param bool $joined Whether or not the row is a result of a direct join * with this association * @return array */ public function defaultRowValue(array $row, bool $joined): array { $sourceAlias = $this->getSource()->getAlias(); if (isset($row[$sourceAlias])) { $row[$sourceAlias][$this->getProperty()] = null; } return $row; } /** * Proxies the finding operation to the target table's find method * and modifies the query accordingly based of this association * configuration * * @param string|array|null $type the type of query to perform, if an array is passed, * it will be interpreted as the `$options` parameter * @param array $options The options to for the find * @see \Cake\ORM\Table::find() * @return \Cake\ORM\Query */ public function find($type = null, array $options = []): Query { $type = $type ?: $this->getFinder(); [$type, $opts] = $this->_extractFinder($type); return $this->getTarget() ->find($type, $options + $opts) ->where($this->getConditions()); } /** * Proxies the operation to the target table's exists method after * appending the default conditions for this association * * @param array|\Closure|\Cake\Database\ExpressionInterface $conditions The conditions to use * for checking if any record matches. * @see \Cake\ORM\Table::exists() * @return bool */ public function exists($conditions): bool { $conditions = $this->find() ->where($conditions) ->clause('where'); return $this->getTarget()->exists($conditions); } /** * Proxies the update operation to the target table's updateAll method * * @param array $fields A hash of field => new value. * @param mixed $conditions Conditions to be used, accepts anything Query::where() * can take. * @see \Cake\ORM\Table::updateAll() * @return int Count Returns the affected rows. */ public function updateAll(array $fields, $conditions): int { $expression = $this->find() ->where($conditions) ->clause('where'); return $this->getTarget()->updateAll($fields, $expression); } /** * Proxies the delete operation to the target table's deleteAll method * * @param mixed $conditions Conditions to be used, accepts anything Query::where() * can take. * @return int Returns the number of affected rows. * @see \Cake\ORM\Table::deleteAll() */ public function deleteAll($conditions): int { $expression = $this->find() ->where($conditions) ->clause('where'); return $this->getTarget()->deleteAll($expression); } /** * Returns true if the eager loading process will require a set of the owning table's * binding keys in order to use them as a filter in the finder query. * * @param array $options The options containing the strategy to be used. * @return bool true if a list of keys will be required */ public function requiresKeys(array $options = []): bool { $strategy = $options['strategy'] ?? $this->getStrategy(); return $strategy === static::STRATEGY_SELECT; } /** * Triggers beforeFind on the target table for the query this association is * attaching to * * @param \Cake\ORM\Query $query the query this association is attaching itself to * @return void */ protected function _dispatchBeforeFind(Query $query): void { $query->triggerBeforeFind(); } /** * Helper function used to conditionally append fields to the select clause of * a query from the fields found in another query object. * * @param \Cake\ORM\Query $query the query that will get the fields appended to * @param \Cake\ORM\Query $surrogate the query having the fields to be copied from * @param array $options options passed to the method `attachTo` * @return void */ protected function _appendFields(Query $query, Query $surrogate, array $options): void { if ($query->getEagerLoader()->isAutoFieldsEnabled() === false) { return; } $fields = $surrogate->clause('select') ?: $options['fields']; $target = $this->_targetTable; $autoFields = $surrogate->isAutoFieldsEnabled(); if (empty($fields) && !$autoFields) { if ($options['includeFields'] && ($fields === null || $fields !== false)) { $fields = $target->getSchema()->columns(); } } if ($autoFields === true) { $fields = array_filter((array)$fields); $fields = array_merge($fields, $target->getSchema()->columns()); } if ($fields) { $query->select($query->aliasFields($fields, $this->_name)); } $query->addDefaultTypes($target); } /** * Adds a formatter function to the passed `$query` if the `$surrogate` query * declares any other formatter. Since the `$surrogate` query correspond to * the associated target table, the resulting formatter will be the result of * applying the surrogate formatters to only the property corresponding to * such table. * * @param \Cake\ORM\Query $query the query that will get the formatter applied to * @param \Cake\ORM\Query $surrogate the query having formatters for the associated * target table. * @param array $options options passed to the method `attachTo` * @return void */ protected function _formatAssociationResults(Query $query, Query $surrogate, array $options): void { $formatters = $surrogate->getResultFormatters(); if (!$formatters || empty($options['propertyPath'])) { return; } $property = $options['propertyPath']; $propertyPath = explode('.', $property); $query->formatResults(function ($results) use ($formatters, $property, $propertyPath, $query) { $extracted = []; foreach ($results as $result) { foreach ($propertyPath as $propertyPathItem) { if (!isset($result[$propertyPathItem])) { $result = null; break; } $result = $result[$propertyPathItem]; } $extracted[] = $result; } $extracted = new Collection($extracted); foreach ($formatters as $callable) { $extracted = new ResultSetDecorator($callable($extracted)); } /** @var \Cake\Collection\CollectionInterface $results */ $results = $results->insert($property, $extracted); if ($query->isHydrationEnabled()) { $results = $results->map(function ($result) { $result->clean(); return $result; }); } return $results; }, Query::PREPEND); } /** * Applies all attachable associations to `$query` out of the containments found * in the `$surrogate` query. * * Copies all contained associations from the `$surrogate` query into the * passed `$query`. Containments are altered so that they respect the associations * chain from which they originated. * * @param \Cake\ORM\Query $query the query that will get the associations attached to * @param \Cake\ORM\Query $surrogate the query having the containments to be attached * @param array $options options passed to the method `attachTo` * @return void */ protected function _bindNewAssociations(Query $query, Query $surrogate, array $options): void { $loader = $surrogate->getEagerLoader(); $contain = $loader->getContain(); $matching = $loader->getMatching(); if (!$contain && !$matching) { return; } $newContain = []; foreach ($contain as $alias => $value) { $newContain[$options['aliasPath'] . '.' . $alias] = $value; } $eagerLoader = $query->getEagerLoader(); if ($newContain) { $eagerLoader->contain($newContain); } foreach ($matching as $alias => $value) { $eagerLoader->setMatching( $options['aliasPath'] . '.' . $alias, $value['queryBuilder'], $value ); } } /** * Returns a single or multiple conditions to be appended to the generated join * clause for getting the results on the target table. * * @param array $options list of options passed to attachTo method * @return array * @throws \RuntimeException if the number of columns in the foreignKey do not * match the number of columns in the source table primaryKey */ protected function _joinCondition(array $options): array { $conditions = []; $tAlias = $this->_name; $sAlias = $this->getSource()->getAlias(); $foreignKey = (array)$options['foreignKey']; $bindingKey = (array)$this->getBindingKey(); if (count($foreignKey) !== count($bindingKey)) { if (empty($bindingKey)) { $table = $this->getTarget()->getTable(); if ($this->isOwningSide($this->getSource())) { $table = $this->getSource()->getTable(); } $msg = 'The "%s" table does not define a primary key, and cannot have join conditions generated.'; throw new RuntimeException(sprintf($msg, $table)); } $msg = 'Cannot match provided foreignKey for "%s", got "(%s)" but expected foreign key for "(%s)"'; throw new RuntimeException(sprintf( $msg, $this->_name, implode(', ', $foreignKey), implode(', ', $bindingKey) )); } foreach ($foreignKey as $k => $f) { $field = sprintf('%s.%s', $sAlias, $bindingKey[$k]); $value = new IdentifierExpression(sprintf('%s.%s', $tAlias, $f)); $conditions[$field] = $value; } return $conditions; } /** * Helper method to infer the requested finder and its options. * * Returns the inferred options from the finder $type. * * ### Examples: * * The following will call the finder 'translations' with the value of the finder as its options: * $query->contain(['Comments' => ['finder' => ['translations']]]); * $query->contain(['Comments' => ['finder' => ['translations' => []]]]); * $query->contain(['Comments' => ['finder' => ['translations' => ['locales' => ['en_US']]]]]); * * @param string|array $finderData The finder name or an array having the name as key * and options as value. * @return array */ protected function _extractFinder($finderData): array { $finderData = (array)$finderData; if (is_numeric(key($finderData))) { return [current($finderData), []]; } return [key($finderData), current($finderData)]; } /** * Proxies property retrieval to the target table. This is handy for getting this * association's associations * * @param string $property the property name * @return \Cake\ORM\Association * @throws \RuntimeException if no association with such name exists */ public function __get($property) { return $this->getTarget()->{$property}; } /** * Proxies the isset call to the target table. This is handy to check if the * target table has another association with the passed name * * @param string $property the property name * @return bool true if the property exists */ public function __isset($property) { return isset($this->getTarget()->{$property}); } /** * Proxies method calls to the target table. * * @param string $method name of the method to be invoked * @param array $argument List of arguments passed to the function * @return mixed * @throws \BadMethodCallException */ public function __call($method, $argument) { return $this->getTarget()->$method(...$argument); } /** * Get the relationship type. * * @return string Constant of either ONE_TO_ONE, MANY_TO_ONE, ONE_TO_MANY or MANY_TO_MANY. */ abstract public function type(): string; /** * Eager loads a list of records in the target table that are related to another * set of records in the source table. Source records can specified in two ways: * first one is by passing a Query object setup to find on the source table and * the other way is by explicitly passing an array of primary key values from * the source table. * * The required way of passing related source records is controlled by "strategy" * When the subquery strategy is used it will require a query on the source table. * When using the select strategy, the list of primary keys will be used. * * Returns a closure that should be run for each record returned in a specific * Query. This callable will be responsible for injecting the fields that are * related to each specific passed row. * * Options array accepts the following keys: * * - query: Query object setup to find the source table records * - keys: List of primary key values from the source table * - foreignKey: The name of the field used to relate both tables * - conditions: List of conditions to be passed to the query where() method * - sort: The direction in which the records should be returned * - fields: List of fields to select from the target table * - contain: List of related tables to eager load associated to the target table * - strategy: The name of strategy to use for finding target table records * - nestKey: The array key under which results will be found when transforming the row * * @param array $options The options for eager loading. * @return \Closure */ abstract public function eagerLoader(array $options): Closure; /** * Handles cascading a delete from an associated model. * * Each implementing class should handle the cascaded delete as * required. * * @param \Cake\Datasource\EntityInterface $entity The entity that started the cascaded delete. * @param array $options The options for the original delete. * @return bool Success */ abstract public function cascadeDelete(EntityInterface $entity, array $options = []): bool; /** * Returns whether or not the passed table is the owning side for this * association. This means that rows in the 'target' table would miss important * or required information if the row in 'source' did not exist. * * @param \Cake\ORM\Table $side The potential Table with ownership * @return bool */ abstract public function isOwningSide(Table $side): bool; /** * Extract the target's association data our from the passed entity and proxies * the saving operation to the target table. * * @param \Cake\Datasource\EntityInterface $entity the data to be saved * @param array $options The options for saving associated data. * @return \Cake\Datasource\EntityInterface|false false if $entity could not be saved, otherwise it returns * the saved entity * @see \Cake\ORM\Table::save() */ abstract public function saveAssociated(EntityInterface $entity, array $options = []); }