Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
41 / 41
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
UpdateSchema
100.00% covered (success)
100.00%
41 / 41
100.00% covered (success)
100.00%
2 / 2
13
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 create
100.00% covered (success)
100.00%
40 / 40
100.00% covered (success)
100.00%
1 / 1
12
1<?php
2
3/**
4 * @license MIT
5 * @author hazuki3417<hazuki3417@gmail.com>
6 * @copyright 2022 hazuki3417 all rights reserved.
7 */
8
9namespace Selen\MongoDB\Builder;
10
11use LogicException;
12use ReflectionClass;
13use Selen\MongoDB\Attribute\SchemaLoader;
14use Selen\MongoDB\Attributes\Nest;
15use Selen\MongoDB\Builder\Attributes\Build;
16
17class UpdateSchema implements SchemaBuilderInterface
18{
19    /** @var SchemaLoader */
20    private $schemaLoader;
21
22    public function __construct(SchemaLoader $schemaLoader)
23    {
24        $this->schemaLoader = $schemaLoader;
25    }
26
27    /**
28     * @param array<mixed,mixed> $input updateする値を渡します
29     *
30     * @return array<mixed,mixed> updateする値を返します
31     */
32    public function create(array $input): array
33    {
34        if ($input === []) {
35            $mes = 'Invalid value. An empty array cannot be specified';
36            throw new LogicException($mes);
37        }
38
39        $schema = [];
40
41        foreach ($input as $key => $inputValue) {
42            if (!\array_key_exists($key, $this->schemaLoader->fieldLoaders)) {
43                // 入力側のkeyが定義側に存在しないとき
44                continue;
45            }
46
47            // 入力側のkeyが定義側に存在したとき
48            $fieldLoader = $this->schemaLoader->fieldLoaders[$key];
49
50            $attributeNest  = $fieldLoader->attributeNest;
51            $attributeBuild = $fieldLoader->fetchAttribute(Build::class);
52
53            $isNestedValueBuild = $attributeNest !== null && $attributeBuild !== null;
54
55            if (!$isNestedValueBuild) {
56                // ネストされていない定義のときの処理
57                $key          = $fieldLoader->reflectionProperty->getName();
58                $value        = $inputValue;
59                $schema[$key] = $value;
60                continue;
61            }
62
63            // ネストされた定義のときの処理
64
65            /** @var Nest */
66            $nestInstance = $attributeNest->newInstance();
67            $updateSchema = new self(new SchemaLoader(new ReflectionClass($nestInstance->schemaClassName)));
68
69            if ($nestInstance->type === Nest::TYPE_OBJECT) {
70                /**
71                 * ネストされた値の形式がObject
72                 * 上書きする値がリテラル値の場合、定義の形式に合わないため上書き処理をしない。
73                 * ネストした定義の値を上書きするには1次元配列で指定する必要がある。
74                 */
75                $passInput = $inputValue;
76
77                if (!\is_array($passInput)) {
78                    continue;
79                }
80
81                $key          = $fieldLoader->reflectionProperty->getName();
82                $value        = $updateSchema->create($passInput);
83                $schema[$key] = $value;
84                continue;
85            }
86
87            /**
88             * ネストされた値の形式がArrayObject
89             * 上書きする値がリテラル値の場合、定義の形式に合わないため上書き処理をしない。
90             * ネストした定義の値を上書きするには2次元配列で指定する必要がある。
91             * (1次はObjectを持つ要素, 2次はObjectのフィールドを持つ要素)
92             */
93            $inputObjectItems = $inputValue;
94
95            // ObjectItemsを想定した値かどうか確認
96            if (!\is_array($inputObjectItems)) {
97                // ObjectItemsを想定した値がリテラル値のときは処理しない
98                continue;
99            }
100
101            $writeObjectItems = [];
102
103            foreach ($inputObjectItems as $index => $inputObjectItem) {
104                // ObjectItemを想定した値かどうか確認
105                if (!\is_array($inputObjectItem)) {
106                    // ObjectItemを想定した値がリテラル値のときは処理しない
107                    continue;
108                }
109                $writeObjectItems[] = $updateSchema->create($inputObjectItem);
110            }
111
112            if ($writeObjectItems === []) {
113                continue;
114            }
115
116            $key          = $fieldLoader->reflectionProperty->getName();
117            $value        = $writeObjectItems;
118            $schema[$key] = $value;
119        }
120
121        return $schema;
122    }
123}