GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

ObjectRule   D
last analyzed

Complexity

Total Complexity 59

Size/Duplication

Total Lines 296
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 14

Importance

Changes 0
Metric Value
wmc 59
lcom 1
cbo 14
dl 0
loc 296
rs 4.08
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A canonical() 0 5 1
F createUrl() 0 82 18
B defineBlocksTitleAndView() 0 21 7
F parseRequest() 0 155 29
A getRoutes() 0 24 4

How to fix   Complexity   

Complex Class

Complex classes like ObjectRule often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ObjectRule, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace app\components;
4
5
use app\modules\shop\models\Category;
6
use app\models\BaseObject;
7
use app\models\PrefilteredPages;
8
use app\models\Route;
9
use app\properties\url\StaticPart;
10
use app\properties\url\UrlPart;
11
use devgroup\TagDependencyHelper\ActiveRecordHelper;
12
use Yii;
13
use yii\caching\TagDependency;
14
use yii\db\ActiveRecord;
15
use yii\helpers\ArrayHelper;
16
use yii\helpers\Json;
17
use yii\helpers\Url;
18
use yii\web\NotFoundHttpException;
19
use yii\web\UrlRuleInterface;
20
21
class ObjectRule implements UrlRuleInterface
22
{
23
    private static $routes = null;
24
25
    public static function canonical($params)
26
    {
27
        $params[0] = Yii::$app->controller->getRoute();
28
        return Url::to($params, true);
29
    }
30
31
    public function createUrl($manager, $route, $params)
32
    {
33
34
        $handler_model = null;
35
        $handler_object = null;
36
37
        $cacheKey = null;
38
39
        if (isset($params['model'])) {
40
            /** @var ActiveRecord $handler_model */
41
            $handler_model = $params['model'];
42
            unset($params['model']);
43
            $cacheKey = 'ObjectRule:'.$handler_model->tableName().':' . $handler_model->id . json_encode($params);
44
            $cached = Yii::$app->cache->get($cacheKey);
45
            if ($cached !== false) {
46
                return $cached;
47
            }
48
49
            $handler_object = BaseObject::getForClass(get_class($handler_model));
50
        }
51
52
        $cacheTags = [];
53
        if (is_object($handler_model)) {
54
            $cacheTags[]=ActiveRecordHelper::getObjectTag($handler_model->className(), $handler_model->id);
0 ignored issues
show
Deprecated Code introduced by
The method yii\base\BaseObject::className() has been deprecated with message: since 2.0.14. On PHP >=5.5, use `::class` instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
55
        }
56
        foreach (ObjectRule::getRoutes() as $model) {
57
            $used_params = ['categories'];
58
59
            $break_rule = false;
60
            if ($route == $model->route) {
61
                $url_parts = [];
62
                /** @var UrlPart[] $handlers */
63
                $handlers = [];
64
                foreach ($model->template as $t) {
65
                    $h = Yii::createObject($t);
66
                    $h->model = $handler_model;
67
                    $h->object = $handler_object;
68
                    $handlers[] = $h;
69
                }
70
                foreach ($handlers as $handler) {
71
                    $new_part = $handler->appendPart($route, $params, $used_params, $cacheTags);
72
                    if ($handler instanceof StaticPart && $new_part === false) {
73
                        $break_rule = true;
74
                    }
75
                    if ($new_part !== false && !empty($new_part)) {
76
                        $url_parts[] = $new_part;
77
                    }
78
                }
79
                $url = implode("/", $url_parts);
80
                if (!empty($url) && $break_rule === false) {
81
                    $used_params = array_unique($used_params);
82
                    $allowed = array_filter(
83
                        array_keys($params),
84
                        function ($key) use ($used_params) {
85
                            return !in_array($key, $used_params);
86
                        }
87
                    );
88
                    $additionalParams = array_intersect_key($params, array_flip($allowed));
89
                    $additionalParams = (!empty($additionalParams)) ? http_build_query($additionalParams) : '';
90
                    $finalUrl = $url.((!empty($additionalParams)) ? "?$additionalParams" : '');
91
92
                    if (isset($cacheKey)) {
93
                        Yii::$app->cache->set(
94
                            $cacheKey,
95
                            $finalUrl,
96
                            86400,
97
                            new TagDependency([
98
                                'tags' => $cacheTags,
99
                            ])
100
                        );
101
                    }
102
103
                    return $finalUrl;
104
                }
105
                $cacheTags=[];
106
                if (is_object($handler_model)) {
107
                    $cacheTags[]=ActiveRecordHelper::getObjectTag($handler_model->className(), $handler_model->id);
0 ignored issues
show
Deprecated Code introduced by
The method yii\base\BaseObject::className() has been deprecated with message: since 2.0.14. On PHP >=5.5, use `::class` instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
108
                }
109
            }
110
        }
111
        return false;  // this rule does not apply
112
    }
113
114
    private function defineBlocksTitleAndView($data)
115
    {
116
        if (isset($data['blocks'])) {
117
            foreach ($data['blocks'] as $block_name=>$block_value) {
118
                Yii::$app->response->blocks[$block_name] = $block_value;
119
            }
120
        }
121
        if (isset($data['title'])) {
122
            Yii::$app->response->title = $data['title'];
123
        }
124
        if (isset($data['meta_description'])) {
125
            Yii::$app->response->meta_description = $data['meta_description'];
126
        }
127
        if (isset($data['viewId'])) {
128
            Yii::$app->response->view_id = $data['viewId'];
129
        }
130
        if (isset($data['is_prefiltered_page'])) {
131
            Yii::$app->response->is_prefiltered_page = true;
132
            Yii::$app->response->blocks['announce'] = '';
133
        }
134
    }
135
136
    public function parseRequest($manager, $request)
137
    {
138
        Yii::beginProfile("ObjectRule::parseRequest");
139
140
        $url = $request->getPathInfo();
141
        if (empty($url)) {
142
            Yii::endProfile("ObjectRule::parseRequest");
143
            return false;
144
        }
145
146
        $cacheKey = 'ObjectRule:'.$url.':'.Json::encode($request->getQueryParams());
147
        $result = Yii::$app->cache->get($cacheKey);
148
        if ($result !== false) {
149
            Yii::endProfile("ObjectRule::parseRequest");
150
            $this->defineBlocksTitleAndView($result);
151
            return $result['result'];
152
        }
153
154
        $prefilteredPage = PrefilteredPages::getActiveByUrl($url);
155
156
        if ($prefilteredPage !== null) {
157
            $params = [
158
                'properties' => Json::decode($prefilteredPage['params'])
159
            ];
160
            $category = Category::findById($prefilteredPage['last_category_id']);
161
            if ($category === null) {
162
                throw new NotFoundHttpException;
163
            }
164
            $params['category_group_id'] = $category->category_group_id;
165
            $params['last_category_id'] = $category->id;
166
            $data = ['blocks'=>[]];
167
            if (!empty($prefilteredPage['title'])) {
168
                $data['title'] = $prefilteredPage['title'];
169
            }
170
            if (!empty($prefilteredPage['meta_description'])) {
171
                $data['meta_description'] = $prefilteredPage['meta_description'];
172
            }
173
            $blocks = [
174
                'content',
175
                'announce',
176
                'breadcrumbs_label',
177
                'h1',
178
            ];
179
180
            foreach ($blocks as $block_name) {
181
182
                if (!empty($prefilteredPage[$block_name])) {
183
                    $data['blocks'][$block_name] = $prefilteredPage[$block_name];
184
                }
185
            }
186
            $data['is_prefiltered_page'] = true;
187
188
            if ($prefilteredPage['view_id']>0) {
189
                $data['viewId'] = $prefilteredPage['view_id'];
190
            }
191
192
            $data['result'] = [
193
                'shop/product/list',
194
                $params
195
            ];
196
            $this->defineBlocksTitleAndView($data);
197
            Yii::$app->cache->set(
198
                $cacheKey,
199
                $data,
200
                86400,
201
                new TagDependency([
202
                    'tags' => [
203
                        ActiveRecordHelper::getObjectTag(PrefilteredPages::className(), $prefilteredPage['id']),
0 ignored issues
show
Deprecated Code introduced by
The method yii\base\BaseObject::className() has been deprecated with message: since 2.0.14. On PHP >=5.5, use `::class` instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
204
                        ActiveRecordHelper::getObjectTag(Category::className(), $category->id),
0 ignored issues
show
Deprecated Code introduced by
The method yii\base\BaseObject::className() has been deprecated with message: since 2.0.14. On PHP >=5.5, use `::class` instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
205
                    ]
206
                ])
207
            );
208
            return $data['result'];
209
        }
210
211
        $routes = ObjectRule::getRoutes();
212
        $cacheTags = [];
213
        foreach ($routes as $model) {
214
            /** @var UrlPart[] $handlers */
215
            $handlers = [];
216
            $object = BaseObject::findById($model->object_id);
217
            foreach ($model->template as $t) {
218
                $handler = Yii::createObject($t);
219
                $handler->object = $object;
220
                $handlers[] = $handler;
221
            }
222
            $url_parts = [];
223
            $parameters = [];
224
            $next_part = $url;
225
            foreach ($handlers as $handler) {
226
                if (empty($next_part)) {
227
                    //break;
228
                }
229
                $result = $handler->getNextPart($url, $next_part, $url_parts);
230
                if ($result !== false && is_object($result) === true) {
231
                    $parameters = ArrayHelper::merge($parameters, $result->parameters);
232
                    $cacheTags = ArrayHelper::merge($cacheTags, $result->cacheTags);
233
                    // удалим leading slash
234
                    $next_part = ltrim($result->rest_part, '/');
235
                    $url_parts[] = $result;
236
                } elseif ($result === false && $handler->optional===false) {
237
                    continue;
238
                }
239
            }
240
            if (count($url_parts)==0) {
241
                continue;
242
            }
243
244
            // в конце удачного парсинга next_part должен остаться пустым
245
            if (empty($next_part)) {
246
                $resultForCache = ['result'=>[$model->route, $parameters]];
247
                if (isset($_POST['properties'], $parameters['properties'])) {
248
249
                    foreach ($_POST['properties'] as $key=>$value) {
250
                        if (isset($parameters['properties'][$key])) {
251
                            $parameters['properties'][$key] = array_unique(ArrayHelper::merge($parameters['properties'][$key], $value));
252
                        } else {
253
                            $parameters['properties'][$key] = array_unique($value);
254
                        }
255
                    }
256
257
258
                } elseif (isset($_POST['properties'])) {
259
                    $parameters['properties'] = $_POST['properties'];
260
                }
261
                Yii::endProfile("ObjectRule::parseRequest");
262
                if (isset($parameters['properties'])) {
263
                    foreach ($parameters['properties'] as $key => $values) {
264
                        foreach ($parameters['properties'][$key] as $index => $value) {
265
                            if ($value === '') {
266
                                unset($parameters['properties'][$key][$index]);
267
                            }
268
                        }
269
                        if (count($parameters['properties'][$key]) === 0) {
270
                            unset($parameters['properties'][$key]);
271
                        }
272
                    }
273
                }
274
                $result = [$model->route, $parameters];
275
276
                Yii::$app->cache->set(
277
                    $cacheKey,
278
                    $resultForCache,
279
                    86400,
280
                    new TagDependency([
281
                        'tags' => $cacheTags,
282
                    ])
283
                );
284
285
                return $result;
286
            }
287
        }
288
        Yii::endProfile("ObjectRule::parseRequest");
289
        return false;  // this rule does not apply
290
    }
291
292
    public static function getRoutes()
293
    {
294
        if (static::$routes === null) {
295
            $cacheKey = "Routes:all";
296
            static::$routes = Yii::$app->cache->get($cacheKey);
297
            if (!is_array(static::$routes)) {
298
                static::$routes = Route::find()->all();
299
                foreach (static::$routes as $key => $route) {
300
                    static::$routes[$key]['template'] = json_decode($route->url_template, true);
301
                }
302
                Yii::$app->cache->set(
303
                    $cacheKey,
304
                    static::$routes,
305
                    86400,
306
                    new TagDependency([
307
                        'tags' => [
308
                            \devgroup\TagDependencyHelper\ActiveRecordHelper::getCommonTag(Route::className())
0 ignored issues
show
Deprecated Code introduced by
The method yii\base\BaseObject::className() has been deprecated with message: since 2.0.14. On PHP >=5.5, use `::class` instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
309
                        ]
310
                    ])
311
                );
312
            }
313
        }
314
        return static::$routes;
315
    }
316
}
317