@@ -410,97 +410,15 @@ abstract class Model extends AbstractInjectionAware implements EntityInterface,
410410 */
411411 public function __set (string property, value )
412412 {
413- var lowerProperty, modelName, manager, relation, referencedModel, item,
414- dirtyState;
415- array related;
413+ var manager, related;
416414
417415 /**
418416 * Values are probably relationships if they are objects
419417 */
420- if typeof value === " object" && value instanceof ModelInterface {
421- let lowerProperty = strtolower(property),
422- modelName = get_class(this ),
423- manager = this -> getModelsManager(),
424- relation = <RelationInterface> manager-> getRelationByAlias(
425- modelName,
426- lowerProperty
427- );
428-
429- if typeof relation === " object" {
430- let dirtyState = this -> dirtyState;
431-
432- if (value-> getDirtyState() != dirtyState) {
433- let dirtyState = self :: DIRTY_STATE_TRANSIENT ;
434- }
435-
436- unset this -> related[lowerProperty];
437-
438- let this -> dirtyRelated[lowerProperty] = value,
439- this -> dirtyState = dirtyState;
440-
441- return value;
442- }
443- }
444-
445- /**
446- * Check if the value is an array
447- */
448- elseif typeof value === " array" {
449- let lowerProperty = strtolower(property),
450- modelName = get_class(this ),
451- manager = this -> getModelsManager(),
452- relation = <RelationInterface> manager-> getRelationByAlias(
453- modelName,
454- lowerProperty
455- );
456-
457- if typeof relation === " object" {
458- switch relation-> getType() {
459- case Relation:: BELONGS_TO :
460- case Relation:: HAS_ONE :
461- /**
462- * Load referenced model from local cache if its possible
463- */
464- let referencedModel = manager-> load(
465- relation-> getReferencedModel()
466- );
467-
468- if typeof referencedModel === " object" {
469- referencedModel-> assign(value);
470-
471- unset this -> related[lowerProperty];
472-
473- let this -> dirtyRelated[lowerProperty] = referencedModel,
474- this -> dirtyState = self :: DIRTY_STATE_TRANSIENT ;
475-
476- return value;
477- }
478-
479- break ;
480-
481- case Relation:: HAS_MANY :
482- case Relation:: HAS_MANY_THROUGH :
483- let related = [];
484-
485- for item in value {
486- if typeof item === " object" {
487- if item instanceof ModelInterface {
488- let related[] = item;
489- }
490- }
491- }
492-
493- unset this -> related[lowerProperty];
494-
495- if count(related) > 0 {
496- let this -> dirtyRelated[lowerProperty] = related,
497- this -> dirtyState = self :: DIRTY_STATE_TRANSIENT ;
498- } else {
499- unset this -> dirtyRelated[lowerProperty];
500- }
501-
502- return value;
503- }
418+ if (typeof value === " object" && value instanceof ModelInterface ) || typeof value === " array" {
419+ let related = this -> setRelated(property, value);
420+ if null !== related {
421+ return related;
504422 }
505423 }
506424
@@ -2113,6 +2031,105 @@ abstract class Model extends AbstractInjectionAware implements EntityInterface,
21132031 return result;
21142032 }
21152033
2034+ /**
2035+ * Sets related objects based on Alias and type of value (Model or array),
2036+ * by setting relations, the dirtyState are set acordingly to Transient has opt-in
2037+ *
2038+ * @param string alias
2039+ * @param mixed value
2040+ * @return \Phalcon\Mvc\Model|array|null Null is returned if no relation was found
2041+ */
2042+ public function setRelated (string alias, value ) -> mixed
2043+ {
2044+ var relation, className, manager, lowerAlias, referencedModel, item, related;
2045+
2046+ let manager = this -> getModelsManager();
2047+ let className = get_class(this );
2048+ let lowerAlias = strtolower(alias);
2049+ /**
2050+ * Query the relation by alias
2051+ */
2052+ let relation = <RelationInterface> manager-> getRelationByAlias(
2053+ className,
2054+ lowerAlias
2055+ );
2056+
2057+ if likely typeof relation === " object" {
2058+ let className = get_class(this ),
2059+ manager = <ManagerInterface> this -> modelsManager,
2060+ lowerAlias = strtolower(alias);
2061+
2062+ if typeof value === " object" && value instanceof ModelInterface {
2063+ /**
2064+ * Opt-in dirty state
2065+ */
2066+ value-> setDirtyState(self :: DIRTY_STATE_TRANSIENT );
2067+ let this -> dirtyState = self :: DIRTY_STATE_TRANSIENT ;
2068+ /**
2069+ * Add to dirtyRelated and remove from related.
2070+ */
2071+ let this -> dirtyRelated[lowerAlias] = value;
2072+ unset (this -> related[lowerAlias]);
2073+ return value;
2074+ }
2075+
2076+ /**
2077+ * Check if the value is an array
2078+ */
2079+ elseif typeof value === " array" {
2080+ switch relation-> getType() {
2081+ case Relation:: BELONGS_TO :
2082+ case Relation:: HAS_ONE :
2083+ /**
2084+ * Load referenced model from local cache if its possible
2085+ */
2086+ let referencedModel = manager-> load(
2087+ relation-> getReferencedModel()
2088+ );
2089+
2090+ if typeof referencedModel === " object" {
2091+ referencedModel-> assign(value);
2092+ let this -> dirtyRelated[lowerAlias] = referencedModel;
2093+ /**
2094+ * Add to dirtyRelated and remove from related.
2095+ */
2096+ unset (this -> related[lowerAlias]);
2097+ return referencedModel;
2098+ }
2099+ break ;
2100+
2101+ case Relation:: HAS_MANY :
2102+ case Relation:: HAS_MANY_THROUGH :
2103+ let related = [];
2104+ /**
2105+ * this is probably not needed
2106+ */
2107+ for item in value {
2108+ if typeof item === " object" {
2109+ if item instanceof ModelInterface {
2110+ let related[] = item;
2111+ }
2112+ }
2113+ }
2114+ /**
2115+ * Add to dirtyRelated and remove from related.
2116+ */
2117+ unset this -> related[lowerAlias];
2118+
2119+ if count(related) > 0 {
2120+ let this -> dirtyRelated[lowerAlias] = related,
2121+ this -> dirtyState = self :: DIRTY_STATE_TRANSIENT ;
2122+ } else {
2123+ unset this -> dirtyRelated[lowerAlias];
2124+ }
2125+
2126+ return value;
2127+ }
2128+ }
2129+ }
2130+ return null ;
2131+ }
2132+
21162133 /**
21172134 * Checks if saved related records have already been loaded.
21182135 *
0 commit comments