src/Eccube/Entity/AbstractEntity.php line 29

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of EC-CUBE
  4.  *
  5.  * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved.
  6.  *
  7.  * http://www.ec-cube.co.jp/
  8.  *
  9.  * For the full copyright and license information, please view the LICENSE
  10.  * file that was distributed with this source code.
  11.  */
  12. namespace Eccube\Entity;
  13. use Doctrine\Common\Collections\Collection;
  14. use Doctrine\Inflector\Inflector;
  15. use Doctrine\Inflector\NoopWordInflector;
  16. use Doctrine\ORM\Mapping\Id;
  17. use Doctrine\ORM\Mapping\MappedSuperclass;
  18. use Doctrine\ORM\Proxy\Proxy;
  19. use Eccube\DependencyInjection\Facade\AnnotationReaderFacade;
  20. use Eccube\Util\StringUtil;
  21. use Symfony\Component\Serializer\Encoder\XmlEncoder;
  22. use Symfony\Component\Serializer\Normalizer\PropertyNormalizer;
  23. use Symfony\Component\Serializer\Serializer;
  24. /** @MappedSuperclass */
  25. abstract class AbstractEntity implements \ArrayAccess
  26. {
  27.     #[\ReturnTypeWillChange]
  28.     public function offsetExists($offset)
  29.     {
  30.         $inflector = new Inflector(new NoopWordInflector(), new NoopWordInflector());
  31.         $method $inflector->classify($offset);
  32.         return method_exists($this$method)
  33.             || method_exists($this"get$method")
  34.             || method_exists($this"is$method")
  35.             || method_exists($this"has$method");
  36.     }
  37.     #[\ReturnTypeWillChange]
  38.     public function offsetSet($offset$value)
  39.     {
  40.     }
  41.     #[\ReturnTypeWillChange]
  42.     public function offsetGet($offset)
  43.     {
  44.         $inflector = new Inflector(new NoopWordInflector(), new NoopWordInflector());
  45.         $method $inflector->classify($offset);
  46.         if (method_exists($this$method)) {
  47.             return $this->$method();
  48.         } elseif (method_exists($this"get$method")) {
  49.             return $this->{"get$method"}();
  50.         } elseif (method_exists($this"is$method")) {
  51.             return $this->{"is$method"}();
  52.         } elseif (method_exists($this"has$method")) {
  53.             return $this->{"has$method"}();
  54.         }
  55.     }
  56.     #[\ReturnTypeWillChange]
  57.     public function offsetUnset($offset)
  58.     {
  59.     }
  60.     /**
  61.      * 引数の連想配列を元にプロパティを設定します.
  62.      * DBから取り出した連想配列を, プロパティへ設定する際に使用します.
  63.      *
  64.      * @param array $arrProps プロパティの情報を格納した連想配列
  65.      * @param \ReflectionClass $parentClass 親のクラス. 本メソッドの内部的に使用します.
  66.      * @param string[] $excludeAttribute 除外したいフィールド名の配列
  67.      */
  68.     public function setPropertiesFromArray(array $arrProps, array $excludeAttribute = [], \ReflectionClass $parentClass null)
  69.     {
  70.         if (is_object($parentClass)) {
  71.             $objReflect $parentClass;
  72.         } else {
  73.             $objReflect = new \ReflectionClass($this);
  74.         }
  75.         $arrProperties $objReflect->getProperties();
  76.         foreach ($arrProperties as $objProperty) {
  77.             $objProperty->setAccessible(true);
  78.             $name $objProperty->getName();
  79.             if (in_array($name$excludeAttribute) || !array_key_exists($name$arrProps)) {
  80.                 continue;
  81.             }
  82.             $objProperty->setValue($this$arrProps[$name]);
  83.         }
  84.         // 親クラスがある場合は再帰的にプロパティを取得
  85.         $parentClass $objReflect->getParentClass();
  86.         if (is_object($parentClass)) {
  87.             self::setPropertiesFromArray($arrProps$excludeAttribute$parentClass);
  88.         }
  89.     }
  90.     /**
  91.      * Convert to associative array.
  92.      *
  93.      * Symfony Serializer Component is expensive, and hard to implementation.
  94.      * Use for encoder only.
  95.      *
  96.      * @param \ReflectionClass $parentClass parent class. Use internally of this method..
  97.      * @param array $excludeAttribute Array of field names to exclusion.
  98.      *
  99.      * @return array
  100.      */
  101.     public function toArray(array $excludeAttribute = ['__initializer__''__cloner__''__isInitialized__'], \ReflectionClass $parentClass null)
  102.     {
  103.         if (is_object($parentClass)) {
  104.             $objReflect $parentClass;
  105.         } else {
  106.             $objReflect = new \ReflectionClass($this);
  107.         }
  108.         $arrProperties $objReflect->getProperties();
  109.         $arrResults = [];
  110.         foreach ($arrProperties as $objProperty) {
  111.             $objProperty->setAccessible(true);
  112.             $name $objProperty->getName();
  113.             if (in_array($name$excludeAttribute)) {
  114.                 continue;
  115.             }
  116.             $arrResults[$name] = $objProperty->getValue($this);
  117.         }
  118.         $parentClass $objReflect->getParentClass();
  119.         if (is_object($parentClass)) {
  120.             $arrParents self::toArray($excludeAttribute$parentClass);
  121.             if (!is_array($arrParents)) {
  122.                 $arrParents = [];
  123.             }
  124.             if (!is_array($arrResults)) {
  125.                 $arrResults = [];
  126.             }
  127.             $arrResults array_merge($arrParents$arrResults);
  128.         }
  129.         return $arrResults;
  130.     }
  131.     /**
  132.      * Convert to associative array, and normalize to association properties.
  133.      *
  134.      * The type conversion such as:
  135.      * - Datetime ::  W3C datetime format string
  136.      * - AbstractEntity :: associative array such as [id => value]
  137.      * - PersistentCollection :: associative array of [[id => value], [id => value], ...]
  138.      *
  139.      * @param array $excludeAttribute Array of field names to exclusion.
  140.      *
  141.      * @return array
  142.      */
  143.     public function toNormalizedArray(array $excludeAttribute = ['__initializer__''__cloner__''__isInitialized__'])
  144.     {
  145.         $arrResult $this->toArray($excludeAttribute);
  146.         foreach ($arrResult as &$value) {
  147.             if ($value instanceof \DateTime) {
  148.                 // see also https://stackoverflow.com/a/17390817/4956633
  149.                 $value->setTimezone(new \DateTimeZone('UTC'));
  150.                 $value $value->format('Y-m-d\TH:i:s\Z');
  151.             } elseif ($value instanceof AbstractEntity) {
  152.                 // Entity の場合は [id => value] の配列を返す
  153.                 $value $this->getEntityIdentifierAsArray($value);
  154.             } elseif ($value instanceof Collection) {
  155.                 // Collection の場合は ID を持つオブジェクトの配列を返す
  156.                 $Collections $value;
  157.                 $value = [];
  158.                 foreach ($Collections as $Child) {
  159.                     $value[] = $this->getEntityIdentifierAsArray($Child);
  160.                 }
  161.             }
  162.         }
  163.         return $arrResult;
  164.     }
  165.     /**
  166.      * Convert to JSON.
  167.      *
  168.      * @param array $excludeAttribute Array of field names to exclusion.
  169.      *
  170.      * @return string
  171.      */
  172.     public function toJSON(array $excludeAttribute = ['__initializer__''__cloner__''__isInitialized__'])
  173.     {
  174.         return json_encode($this->toNormalizedArray($excludeAttribute));
  175.     }
  176.     /**
  177.      * Convert to XML.
  178.      *
  179.      * @param array $excludeAttribute Array of field names to exclusion.
  180.      *
  181.      * @return string
  182.      */
  183.     public function toXML(array $excludeAttribute = ['__initializer__''__cloner__''__isInitialized__'])
  184.     {
  185.         $ReflectionClass = new \ReflectionClass($this);
  186.         $serializer = new Serializer([new PropertyNormalizer()], [new XmlEncoder([XmlEncoder::ROOT_NODE_NAME => $ReflectionClass->getShortName()])]);
  187.         $xml $serializer->serialize($this->toNormalizedArray($excludeAttribute), 'xml');
  188.         if ('\\' === DIRECTORY_SEPARATOR) {
  189.             // The m modifier of the preg functions converts the end-of-line to '\n'
  190.             $xml StringUtil::convertLineFeed($xml"\r\n");
  191.         }
  192.         return $xml;
  193.     }
  194.     /**
  195.      * コピー元のオブジェクトのフィールド名を指定して、同名のフィールドに値をコピー
  196.      *
  197.      * @param object $srcObject コピー元のオブジェクト
  198.      * @param string[] $excludeAttribute 除外したいフィールド名の配列
  199.      *
  200.      * @return AbstractEntity
  201.      */
  202.     public function copyProperties($srcObject, array $excludeAttribute = [])
  203.     {
  204.         $this->setPropertiesFromArray($srcObject->toArray($excludeAttribute), $excludeAttribute);
  205.         return $this;
  206.     }
  207.     /**
  208.      * Convert to Entity of Identity value to associative array.
  209.      *
  210.      * @param AbstractEntity $Entity
  211.      *
  212.      * @return array associative array of [[id => value], [id => value], ...]
  213.      */
  214.     public function getEntityIdentifierAsArray(AbstractEntity $Entity)
  215.     {
  216.         $Result = [];
  217.         $PropReflect = new \ReflectionClass($Entity);
  218.         if ($Entity instanceof Proxy) {
  219.             // Doctrine Proxy の場合は親クラスを取得
  220.             $PropReflect $PropReflect->getParentClass();
  221.         }
  222.         $Properties $PropReflect->getProperties();
  223.         foreach ($Properties as $Property) {
  224.             $AnnotationReader AnnotationReaderFacade::create();
  225.             $anno $AnnotationReader->getPropertyAnnotation($PropertyId::class);
  226.             if ($anno) {
  227.                 $Property->setAccessible(true);
  228.                 $Result[$Property->getName()] = $Property->getValue($Entity);
  229.             }
  230.         }
  231.         return $Result;
  232.     }
  233. }