Passed
Push — v3 ( aa020c...76b551 )
by Andrew
16:38 queued 10:28
created

Schema   A

Complexity

Total Complexity 34

Size/Duplication

Total Lines 230
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 230
rs 9.2
c 0
b 0
f 0
wmc 34

8 Methods

Rating   Name   Duplication   Size   Complexity  
A getSingleSchemaMenu() 0 9 2
A getSchemaArray() 0 18 4
B makeSchemaAssociative() 0 21 6
C getDecomposedSchemaType() 0 31 8
A getSchemaMenu() 0 5 1
A getSchemaType() 0 18 4
A flattenSchemaArray() 0 15 3
B orphanChildren() 0 22 6
1
<?php
2
/**
3
 * SEOmatic plugin for Craft CMS 3.x
4
 *
5
 * A turnkey SEO implementation for Craft CMS that is comprehensive, powerful,
6
 * and flexible
7
 *
8
 * @link      https://nystudio107.com
9
 * @copyright Copyright (c) 2017 nystudio107
10
 */
11
12
namespace nystudio107\seomatic\helpers;
13
14
use nystudio107\seomatic\models\MetaJsonLd;
15
16
use Craft;
17
use craft\helpers\Json as JsonHelper;
18
19
/**
20
 * @author    nystudio107
21
 * @package   Seomatic
22
 * @since     3.0.0
23
 */
24
class Schema
25
{
26
    // Constants
27
    // =========================================================================
28
29
    const SCHEMA_PATH_DELIMITER = '.';
30
    const MENU_INDENT_STEP = 4;
31
32
    // Static Properties
33
    // =========================================================================
34
35
    protected static $schemaTypes = [];
36
37
    // Static Methods
38
    // =========================================================================
39
40
    /**
41
     * Get the fully composed schema type
42
     *
43
     * @param $schemaType
44
     *
45
     * @return array
46
     */
47
    public static function getSchemaType(string $schemaType): array
48
    {
49
        $result = [];
50
        $jsonLdType = MetaJsonLd::create($schemaType);
51
52
        if ($jsonLdType) {
53
            // Get the static properties
54
            try {
55
                $classRef = new \ReflectionClass(get_class($jsonLdType));
56
            } catch (\ReflectionException $e) {
57
                $classRef = null;
58
            }
59
            if ($classRef) {
60
                $result = $classRef->getStaticProperties();
61
            }
62
        }
63
64
        return $result;
65
    }
66
67
    /**
68
     * Get the decomposed schema type
69
     *
70
     * @param string $schemaType
71
     *
72
     * @return array
73
     */
74
    public static function getDecomposedSchemaType(string $schemaType): array
75
    {
76
        $result = [];
77
        while ($schemaType) {
78
            $className = 'nystudio107\\seomatic\\models\\jsonld\\'.$schemaType;
79
            if (class_exists($className)) {
80
                try {
81
                    $classRef = new \ReflectionClass($className);
82
                } catch (\ReflectionException $e) {
83
                    $classRef = null;
84
                }
85
                if ($classRef) {
86
                    $staticProps = $classRef->getStaticProperties();
87
88
                    foreach ($staticProps as $key => $value) {
89
                        if ($key[0] == '_') {
90
                            $newKey = ltrim($key, '_');
91
                            $staticProps[$newKey] = $value;
92
                            unset($staticProps[$key]);
93
                        }
94
                    }
95
                    $result[$schemaType] = $staticProps;
96
                    $schemaType = $staticProps['schemaTypeExtends'];
97
                    if ($schemaType == "JsonLdType") {
98
                        $schemaType = null;
99
                    }
100
                }
101
            }
102
        }
103
104
        return $result;
105
    }
106
107
    /**
108
     * Return a flattened, indented menu of the given $path
109
     *
110
     * @param string $path
111
     *
112
     * @return array
113
     */
114
    public static function getSchemaMenu($path = ''): array
115
    {
116
        $schemaTypes = self::getSchemaArray($path);
117
118
        return self::flattenSchemaArray($schemaTypes, 0);
119
    }
120
121
    /**
122
     * Return a single menu of schemas starting at $path
123
     *
124
     * @param string $path
125
     *
126
     * @return array
127
     */
128
    public static function getSingleSchemaMenu($path = ''): array
129
    {
130
        $result = [];
131
        $schemaTypes = self::getSchemaArray($path);
132
        foreach ($schemaTypes as $key => $value) {
133
            $result[$key] = $key;
134
        }
135
136
        return $result;
137
    }
138
139
    /**
140
     * Return a hierarchical array of schema types, starting at $path. The $path
141
     * is specified as SchemaType.SubSchemaType using SCHEMA_PATH_DELIMITER as
142
     * the delimiter.
143
     *
144
     * @param string $path
145
     *
146
     * @return array
147
     */
148
    public static function getSchemaArray($path = ''): array
149
    {
150
        if (empty(self::$schemaTypes)) {
151
            $filePath = Craft::getAlias('@nystudio107/seomatic/resources/schema/tree.jsonld');
152
            self::$schemaTypes = JsonHelper::decode(@file_get_contents($filePath));
153
            self::$schemaTypes = self::makeSchemaAssociative(self::$schemaTypes);
0 ignored issues
show
Bug introduced by
It seems like self::schemaTypes can also be of type null; however, parameter $typesArray of nystudio107\seomatic\hel...makeSchemaAssociative() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

153
            self::$schemaTypes = self::makeSchemaAssociative(/** @scrutinizer ignore-type */ self::$schemaTypes);
Loading history...
154
            self::$schemaTypes = self::orphanChildren(self::$schemaTypes);
155
        }
156
        // Get just the appropriate sub-array
157
        $typesArray = self::$schemaTypes;
158
        if (!empty($path)) {
159
            $keys = explode(self::SCHEMA_PATH_DELIMITER, $path);
160
            foreach ($keys as $key) {
161
                $typesArray = $typesArray[$key];
162
            }
163
        }
164
165
        return $typesArray;
166
    }
167
168
    /**
169
     * @param array $typesArray
170
     * @param       $indentLevel
171
     *
172
     * @return array
173
     */
174
    protected static function flattenSchemaArray(array $typesArray, int $indentLevel): array
175
    {
176
        $result = [];
177
        foreach ($typesArray as $key => $value) {
178
            $indent = str_repeat('&nbsp;', $indentLevel);
179
            if (is_array($value)) {
180
                $result[$key] = $indent . $key;
181
                $value = self::flattenSchemaArray($value, $indentLevel + self::MENU_INDENT_STEP);
182
                $result = array_merge($result, $value);
183
            } else {
184
                $result[$key] = $indent . $value;
185
            }
186
        }
187
188
        return $result;
189
    }
190
191
    /**
192
     * Reduce everything in the $schemaTypes array to a simple hierarchical array
193
     * as "SchemaType" => "SchemaType" if it has no children, and if it has
194
     * children, as "SchemaType" = [] with an array of sub-types
195
     *
196
     * @param array $typesArray
197
     *
198
     * @return array
199
     */
200
    protected static function orphanChildren(array $typesArray): array
201
    {
202
        $result = [];
203
204
        if (!empty($typesArray['children'])) {
205
            foreach ($typesArray['children'] as $key => $value) {
206
                $key = '';
207
                if (!empty($value['name'])) {
208
                    $key = $value['name'];
209
                }
210
                if (!empty($value['children'])) {
211
                    $value = self::orphanChildren($value);
212
                } else {
213
                    $value = $key;
214
                }
215
                if (!empty($key)) {
216
                    $result[$key] = $value;
217
                }
218
            }
219
        }
220
221
        return $result;
222
    }
223
224
    /**
225
     * Return a new array that has each type returned as an associative array
226
     * as "SchemaType" => [] rather than the way the tree.jsonld file has it
227
     * stored as a non-associative array
228
     *
229
     * @param array $typesArray
230
     *
231
     * @return array
232
     */
233
    protected static function makeSchemaAssociative(array $typesArray)
234
    {
235
        $result = [];
236
237
        foreach ($typesArray as $key => $value) {
238
            if (isset($value['name'])) {
239
                $key = $value['name'];
240
            }
241
            if (is_array($value)) {
242
                $value = self::makeSchemaAssociative($value);
243
            }
244
            if (isset($value['layer'])) {
245
                if ($value['layer'] == 'core') {
246
                    $result[$key] = $value;
247
                }
248
            } else {
249
                $result[$key] = $value;
250
            }
251
        }
252
253
        return $result;
254
    }
255
}
256