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