处理多态一对多更新

@param \Imi\Model\Model $model
@param string $propertyName
@param \Imi\Model\Annotation\Relation\PolymorphicOneToMany $annotation
@return void
2553
public static function parseByPolymorphicOneToMany($model, $propertyName, $annotation)
    {
        $className = BeanFactory::getObjectClass($model);

        $struct = new PolymorphicOneToMany($className, $propertyName, $annotation);
        $leftField = $struct->getLeftField();
        $rightField = $struct->getRightField();
        $rightModel = $struct->getRightModel();

        $autoUpdate = AnnotationManager::getPropertyAnnotations($className, $propertyName, AutoUpdate::class)[0] ?? null;
        $autoSave = AnnotationManager::getPropertyAnnotations($className, $propertyName, AutoSave::class)[0] ?? null;
        // 是否删除无关数据
        if($autoUpdate)
        {
            $orphanRemoval = $autoUpdate->orphanRemoval;
        }
        else if($autoSave)
        {
            $orphanRemoval = $autoSave->orphanRemoval;
        }
        else
        {
            $orphanRemoval = false;
        }

        if($orphanRemoval)
        {
            // 删除无关联数据
            $pks = ModelManager::getId($rightModel);
            if(is_array($pks))
            {
                if(isset($pks[1]))
                {
                    throw new \RuntimeException(sprintf('%s can not OneToMany, because has more than 1 primary keys', $rightModel));
                }
                $pk = $pks[0];
            }
            else
            {
                $pk = $pks;
            }

            $oldIDs = $rightModel::query()->where($annotation->type, '=', $annotation->typeValue)->where($rightField, '=', $model->$leftField)->field($pk)->select()->getColumn();

            $updateIDs = [];
            foreach($model->$propertyName as $row)
            {
                if(null !== $row->$pk)
                {
                    $updateIDs[] = $row->$pk;
                }
                $row->$rightField = $model->$leftField;
                $row->{$annotation->type} = $annotation->typeValue;
                $row->save();
            }

            $deleteIDs = array_diff($oldIDs, $updateIDs);

            if($deleteIDs)
            {
                // 批量删除
                $rightModel::deleteBatch(function(IQuery $query) use($pk, $deleteIDs){
                    $query->whereIn($pk, $deleteIDs);
                });
            }
        }
        else
        {
            // 直接更新
            foreach($model->$propertyName as $row)
            {
                $row->$rightField = $model->$leftField;
                $row->save();
            }
        }
    }
830758
public static function collect(string $className, $objectAnnotation = null, string $propertyName = '', string $methodName = '', $propertyValue = null)
    {
        // collect service
        if ($objectAnnotation instanceof Service) {

            $rc = new \ReflectionClass($className);
            $interfaces = $rc->getInterfaceNames();
            $methods = $rc->getMethods(\ReflectionMethod::IS_PUBLIC);
            $version = $objectAnnotation->getVersion();

            foreach ($interfaces as $interfaceClass){
                foreach ($methods as $method){
                    $methodName = $method->getName();
                    self::$serviceMapping[$interfaceClass][$version][$methodName] = [$className, $methodName];
                }
            }

            return;
        }
    }
1169806
protected function setForeignAttributesForCreate(Model $model)
    {
        $property = $this->getPlainForeignKey();

        $model->{$property} = $this->getParentKey();

        //
        $property = $this->getPlainMorphType();

        $model->{$property} = $this->morphClass;
    }
749088
public function setProperty($propertyName, $value)
    {
        if ($value !== $this->getProperty($propertyName)) {
            $this->setMeta(static::IS_CHANGED, true);
            $this->setPropertyRaw($propertyName, $value);
        }
    }
79466
public function setCustomProperty($propertyName, $propertyValue = '', $propertyType = null)
    {
        if (($propertyType === null) || (!in_array($propertyType, array(self::PROPERTY_TYPE_INTEGER,
                                                                        self::PROPERTY_TYPE_FLOAT,
                                                                        self::PROPERTY_TYPE_STRING,
                                                                        self::PROPERTY_TYPE_DATE,
                                                                        self::PROPERTY_TYPE_BOOLEAN)))) {
            if ($propertyValue === null) {
                $propertyType = self::PROPERTY_TYPE_STRING;
            } elseif (is_float($propertyValue)) {
                $propertyType = self::PROPERTY_TYPE_FLOAT;
            } elseif (is_int($propertyValue)) {
                $propertyType = self::PROPERTY_TYPE_INTEGER;
            } elseif (is_bool($propertyValue)) {
                $propertyType = self::PROPERTY_TYPE_BOOLEAN;
            } else {
                $propertyType = self::PROPERTY_TYPE_STRING;
            }
        }

        $this->customProperties[$propertyName] = array(
            'value' => $propertyValue,
            'type' => $propertyType
        );
        return $this;
    }
912179
public function isPropertyAnnotatedWith($className, $propertyName, $annotationClassName)
    {
        $className = $this->prepareClassReflectionForUsage($className);
        return isset($this->classReflectionData[$className][self::DATA_CLASS_PROPERTIES][$propertyName][self::DATA_PROPERTY_ANNOTATIONS][$annotationClassName]);
    }
875682
public static function parseByManyToMany($model, $propertyName, $annotation)
    {
        $className = BeanFactory::getObjectClass($model);

        $struct = new ManyToMany($className, $propertyName, $annotation);
        $middleModel = $struct->getMiddleModel();
        $middleLeftField = $struct->getMiddleLeftField();
        $leftField = $struct->getLeftField();

        foreach($model->$propertyName as $index => $row)
        {
            if(!$row instanceof $middleModel)
            {
                $row = $middleModel::newInstance($row);
                $model->$propertyName[$index] = $row;
            }
            $row[$middleLeftField] = $model->$leftField;
            $row->insert();
        }
    }
245420
public static function collect(string $className, $objectAnnotation = null, string $propertyName = '', string $methodName = '', $propertyValue = null)
    {
        if ($objectAnnotation instanceof Connection) {
            $type   = $objectAnnotation->getType();
            $driver = $objectAnnotation->getDriver();
            self::$connects[$driver][$type] = $className;
        }
    }
727812
public static void setProperty(String propertyName, String propertyValue) {
		try {
			FreeMarkerRender.getConfiguration().setSetting(propertyName, propertyValue);
		} catch (TemplateException e) {
			throw new RuntimeException(e);
		}
	}
1294993
protected function setProperty($entity, $propertyName, $propertyValue)
    {
        if ($this->getReflection()->hasProperty($propertyName)) {
            $property = $this->getReflection()->getProperty($propertyName);
            $property->setValue($entity, $propertyValue);
        } else {
            $entity->setVirtual($propertyName, $propertyValue);
        }
        
        return $this;
    }
188017
public function newVirtualProperty(string $propertyName, ?Closure $getter, ?Closure $setter): void
    {
        if ($this->propertyExists($propertyName)) {
            throw new DuplicatePropertyException($propertyName);
        }
        if (is_null($getter) && is_null($setter)) {
            throw new InvalidPropertyException($propertyName);
        }
        $this->properties[$propertyName] = self::PROPERTY_VIRTUAL;
        $this->virtualGetters[$propertyName] = $getter;
        $this->virtualSetters[$propertyName] = $setter;
        $this->setterHooks[$propertyName] = [];
        $this->getterHooks[$propertyName] = [];
    }
961221
public static function initByManyToMany($model, $propertyName, $annotation)
    {
        $className = BeanFactory::getObjectClass($model);

        if(class_exists($annotation->model))
        {
            $modelClass = $annotation->model;
        }
        else
        {
            $modelClass = Imi::getClassNamespace($className) . '\\' . $annotation->model;
        }

        $struct = new ManyToMany($className, $propertyName, $annotation);
        $leftField = $struct->getLeftField();
        $rightField = $struct->getRightField();
        $middleTable = ModelManager::getTable($struct->getMiddleModel());
        $rightTable = ModelManager::getTable($struct->getRightModel());

        static::parseManyToManyQueryFields($struct->getMiddleModel(), $struct->getRightModel(), $middleFields, $rightFields);
        $fields = static::mergeManyToManyFields($middleTable, $middleFields, $rightTable, $rightFields);
        
        $model->$propertyName = new ArrayList($struct->getMiddleModel());
        $model->{$annotation->rightMany} = new ArrayList($struct->getRightModel());
        
        if(null !== $model->$leftField)
        {
            $list = Db::query(ModelManager::getDbPoolName($className))
                        ->table($rightTable)
                        ->field(...$fields)
                        ->join($middleTable, $middleTable . '.' . $struct->getMiddleRightField(), '=', $rightTable . '.' . $rightField)
                        ->where($middleTable . '.' . $struct->getMiddleLeftField(), '=', $model->$leftField)
                        ->select()
                        ->getArray();
            if(null !== $list)
            {
                // 关联数据
                static::appendMany($model->$propertyName, $list, $middleFields, $struct->getMiddleModel());

                // 右侧表数据
                static::appendMany($model->{$annotation->rightMany}, $list, $rightFields, $struct->getRightModel());

            }
        }
    }
64481
public function setCustomProperty($propertyName,$propertyValue='',$propertyType=NULL) {
        if (($propertyType === NULL) || (!in_array($propertyType,array(self::PROPERTY_TYPE_INTEGER,
                                                                       self::PROPERTY_TYPE_FLOAT,
                                                                       self::PROPERTY_TYPE_STRING,
                                                                       self::PROPERTY_TYPE_DATE,
                                                                       self::PROPERTY_TYPE_BOOLEAN)))) {
            if ($propertyValue === NULL) {
                $propertyType = self::PROPERTY_TYPE_STRING;
            } elseif (is_float($propertyValue)) {
                $propertyType = self::PROPERTY_TYPE_FLOAT;
            } elseif(is_int($propertyValue)) {
                $propertyType = self::PROPERTY_TYPE_INTEGER;
            } elseif (is_bool($propertyValue)) {
                $propertyType = self::PROPERTY_TYPE_BOOLEAN;
            } else {
                $propertyType = self::PROPERTY_TYPE_STRING;
            }
        }

        $this->_customProperties[$propertyName] = array('value' => $propertyValue, 'type' => $propertyType);
        return $this;
    }
301181
protected function addProperty($nodeType, $propertyName, array $propertyConfiguration)
    {
        if (isset($this->properties[$propertyName])) {
            $this->properties[$propertyName]->domains[] = $nodeType;
        } else {
            $propertyLabel = isset($propertyConfiguration['ui']['label']) ? $propertyConfiguration['ui']['label'] : $propertyName;
            $this->properties[$propertyName] = (object) [
                'comment' => $propertyLabel,
                'comment_plain' => $propertyLabel,
                'domains' => [$nodeType],
                'id' => $propertyName,
                'label' => $propertyName,
                'ranges' => [],
                'min' => 0,
                'max' => -1
            ];
        }
    }
128104
public static function collect(
        string $className,
        $objectAnnotation = null,
        string $propertyName = '',
        string $methodName = '',
        $propertyValue = null
    ) {
        if ($objectAnnotation instanceof Column) {
            self::collectColumn($objectAnnotation, $className, $propertyName, $propertyValue);
        } elseif ($objectAnnotation instanceof Entity) {
            self::collectEntity($objectAnnotation, $className);
        } elseif ($objectAnnotation instanceof Id) {
            self::collectId($className, $propertyName);
        } elseif ($objectAnnotation instanceof Required) {
            self::collectRequired($className, $propertyName);
        } elseif ($objectAnnotation instanceof Table) {
            self::collectTable($objectAnnotation, $className);
        }
    }
667672
public function nodePropertyChanged(NodeInterface $node, $propertyName, $oldValue, $value)
    {
        if (!$this->eventEmittingService->isEnabled()) {
            return;
        }

        if ($oldValue === $value) {
            return;
        }

        $this->changedNodes[$node->getContextPath()]['newLabel'] = $node->getLabel();
        $this->changedNodes[$node->getContextPath()]['node'] = $node;
    }
387714
public static function collect(
        string $className,
        $objectAnnotation = null,
        string $propertyName = '',
        string $methodName = '',
        $propertyValue = null
    ) {
        if ($objectAnnotation instanceof Strings) {
            self::collectString($objectAnnotation, $className, $methodName);
        } elseif ($objectAnnotation instanceof Floats) {
            self::collectFloats($objectAnnotation, $className, $methodName);
        } elseif ($objectAnnotation instanceof Number) {
            self::collectNumber($objectAnnotation, $className, $methodName);
        } elseif ($objectAnnotation instanceof Integer) {
            self::collectInteger($objectAnnotation, $className, $methodName);
        } elseif ($objectAnnotation instanceof Enum) {
            self::collectEnum($objectAnnotation, $className, $methodName);
        }
    }