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.

Meta::replaceVariables()   A
last analyzed

Complexity

Conditions 4
Paths 3

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
nc 3
nop 1
dl 0
loc 19
rs 9.6333
c 0
b 0
f 0
ccs 14
cts 14
cp 1
crap 4
1
<?php
2
/**
3
 * @author Alexey Tatarinov <[email protected]>
4
 * @link https://github.com/shogodev/argilla/
5
 * @copyright Copyright &copy; 2003-2014 Shogo
6
 * @license http://argilla.ru/LICENSE
7
 * @package frontend.components
8
 *
9
 * @property string $header
10
 * @property string $title
11
 * @property string $description
12
 * @property string $keywords
13
 * @property string $custom
14
 */
15
class Meta extends CApplicationComponent
16
{
17
  const VARIABLE_PATTERN = "/{([\w:]+)}/";
18
19
  const COMMAND_PATTERN = "/([a-z]+)\(([^()]+)\)/";
20
21
  /**
22
   * @var array
23
   */
24
  public $exceptedModels = array('ProductAssignment', 'ProductParameterAssignment', 'ProductTreeAssignment');
25
26
  /**
27
   * @var array
28
   */
29
  public $replaces = array();
30
31
  /**
32
   * @var int
33
   */
34
  public $maxSearchDepth = 1;
35
36
  /**
37
   * @var FController
38
   */
39
  private $controller;
40
41
  /**
42
   * @var string
43
   */
44
  private $route;
45
46
  /**
47
   * @var string
48
   */
49
  private $requestUri;
50
51
  /**
52
   * @var FActiveRecord[]
53
   */
54
  private $renderedModels = array();
55
56
  /**
57
   * @var array
58
   */
59
  private $renderedClips = array();
60
61
  private $header;
62
63
  private $title;
64
65
  private $description;
66
67
  private $keywords;
68
69
  private $custom;
70
71
  private $noindex;
72
73 2
  public function init()
74
  {
75 2
    parent::init();
76
77 2
    if( $controller = Yii::app()->controller )
78 2
    {
79 2
      $this->setController($controller);
80 2
      $this->controller->attachEventHandler('onBeforeRender', array($this, 'setRenderedModels'));
81 2
      $this->controller->attachEventHandler('onBeforeRenderLayout', array($this, 'registerMeta'));
82 2
    }
83
84 2
    Yii::app()->attachEventHandler('onEndRequest', array($this, 'updateRenderedModels'));
85
86 2
    if( isset(Yii::app()->request) )
87 2
      $this->setRequestUri(Yii::app()->request->requestUri);
88
89 2
    $this->replaces = array(
90 2
      '{project}' => Arr::get(Yii::app()->params, 'project'),
91
    );
92 2
  }
93
94
  /**
95
   * @return string
96
   */
97 18
  public function getTitle()
98
  {
99 18
    return CHtml::encode($this->clear($this->title));
100
  }
101
102
  /**
103
   * @return string
104
   */
105 3
  public function getDescription()
106
  {
107 3
    return $this->clear($this->description);
108
  }
109
110
  /**
111
   * @return string
112
   */
113 3
  public function getKeywords()
114
  {
115 3
    return $this->clear($this->keywords);
116
  }
117
118
  /**
119
   * @return string
120
   */
121 7
  public function getCustom()
122
  {
123 7
    return $this->clear($this->custom);
124
  }
125
126
  /**
127
   * @param $header
128
   *
129
   * @return string
130
   */
131 6
  public function setHeader($header)
132
  {
133 6
    if( !empty($this->header) )
134 6
    {
135
      $header = $this->clear($this->header);
136
    }
137
138 6
    $this->registerClip('h1', $header);
139 6
    return $header;
140
  }
141
142
  /**
143
   * @param FController $controller
144
   */
145 7
  public function setController(FController $controller)
146
  {
147 7
    if( !isset($this->controller) )
148 7
    {
149 7
      $this->controller = $controller;
150 7
      $this->setRoute();
151 7
    }
152 7
  }
153
154
  /**
155
   * @param string $uri
156
   */
157 10
  public function setRequestUri($uri)
158
  {
159 10
    $this->requestUri = preg_replace('/\?.*/', '', $uri);
160 10
  }
161
162 14
  public function setMeta()
163
  {
164
    /**
165
     * @var MetaMask $metaMask
166
     * @var MetaRoute $metaRoute
167
     */
168 14
    $metaMask = MetaMask::model()->findByUri($this->requestUri);
169 14
    $metaRoute = MetaRoute::model()->findByRoute($this->route);
170
171 14
    foreach(array('header', 'title', 'keywords', 'description', 'noindex', 'custom') as $property)
172
    {
173
      if( $metaRoute )
174 14
        $this->$property = Arr::get($metaRoute, $property);
175
176 14
      if( $metaMask && trim($metaMask->$property) !== '' )
177 14
        $this->$property = $metaMask->$property;
178 14
    }
179
180 14
    if( empty($this->title) )
181 14
    {
182
      $this->title = $this->controller->getPageTitle();
183
    }
184 14
  }
185
186
  /**
187
   * Собираем все модели, переданные в render()
188
   *
189
   * @param CEvent $event
190
   */
191 2
  public function setRenderedModels(CEvent $event)
192
  {
193 2
    $this->setRoute();
194 2
    $this->setMeta();
195
196 2
    $this->processModels(Arr::get($event->params, 'data', array()));
197 2
  }
198
199
  /**
200
   * @param FActiveRecord[] $models
201
   */
202 3
  public function addModels(array $models)
203
  {
204 3
    $this->processModels($models);
205 3
  }
206
207 10
  public function registerClip($id, $value)
208
  {
209 10
    $this->replaces['{'.$id.'}'] = $value;
210 10
    $this->renderedClips[$id] = $id;
211
212 10
    return $value;
213
  }
214
215
  /**
216
   * Запись в базу моделей, найденных во время рендеринга
217
   */
218 1
  public function updateRenderedModels()
219
  {
220 1
    if( strpos($this->route, '/') !== false )
221 1
    {
222 1
      if( !$model = MetaRoute::model()->resetScope()->findByRoute($this->route, false) )
223 1
        $model = new MetaRoute();
224
225 1
      $model->route  = $this->route;
226 1
      $model->models = implode(',', array_keys($this->renderedModels));
227 1
      $model->clips  = implode(',', array_keys($this->renderedClips));
228 1
      $model->save();
229 1
    }
230 1
  }
231
232 2
  public function registerMeta()
233
  {
234 2
    if( $clientScript = Yii::app()->clientScript )
235 2
    {
236 2
      $clientScript->registerMetaTag($this->getDescription(), 'description', null, array(), 'description');
237 2
      $clientScript->registerMetaTag($this->getKeywords(), 'keywords', null, array(), 'keywords');
238
239 2
      if( $this->noindex )
240 2
      {
241 1
        $clientScript->registerMetaTag('noindex, nofollow', 'robots', null, array(), 'robots');
242 1
      }
243 2
    }
244 2
  }
245
246 7
  private function setRoute()
247
  {
248 7
    if( isset($this->controller) )
249 7
      $this->route = $this->controller->route;
250 7
  }
251
252
  /**
253
   * Удаление переменных моделей в строке метатегов
254
   *
255
   * @param string $string
256
   *
257
   * @return string
258
   */
259 19
  private function clear($string)
260
  {
261 19
    $string = $this->replaceVariables($string);
262 19
    $string = $this->replaceCommands($string);
263 19
    $string = preg_replace(self::VARIABLE_PATTERN, '', $string);
264 19
    $string = preg_replace('/\s+/', ' ', $string);
265
266 19
    return trim($string);
267
  }
268
269
  /**
270
   * @param FActiveRecord[] $data
271
   */
272 5
  private function processModels(array $data)
273
  {
274 5
    static $depth;
275
276 5
    foreach($data as $model)
277
    {
278 4
      if( $model instanceof FActiveRecord )
279 4
        $modelName = get_class($model);
280 2
      else if( $model instanceof FForm )
281 2
      {
282 1
        $model = $model->model;
283 1
        $modelName = get_class($model);
284 1
      }
285
      else
286
        continue;
287
288 4
      if( in_array($modelName, $this->exceptedModels) )
289 4
        continue;
290
291 4
      $this->renderedModels[$modelName] = $model;
292
293 4
      if( $model instanceof FActiveRecord && $depth <= $this->maxSearchDepth )
294 4
      {
295 2
        $depth++;
296 2
        $this->processRelations($model);
297 2
      }
298 5
    }
299 5
  }
300
301
  /**
302
   * @param FActiveRecord $model
303
   */
304 2
  private function processRelations(FActiveRecord $model)
305
  {
306 2
    foreach($model->relations() as $name => $relation)
307
    {
308
      if( in_array($relation[0], array(FActiveRecord::HAS_ONE, FActiveRecord::BELONGS_TO)) )
309
      {
310
        if( !isset($this->renderedModels[$relation[1]]) )
311
        {
312
          $this->processModels(array($model->{$name}));
313
        }
314
      }
315 2
    }
316 2
  }
317
318
  /**
319
   * Замена встречающиеся переменных на значения свойств $model
320
   *
321
   * @param $string
322
   *
323
   * @return string
324
   */
325 19
  private function replaceVariables($string)
326
  {
327 19
    if( preg_match_all(self::VARIABLE_PATTERN, $string, $matches) )
328 19
    {
329 17
      if( !empty($matches[0]) )
330 17
      {
331 17
        foreach($matches[0] as $key => $value)
332
        {
333 17
          $replace = $matches[0][$key];
334 17
          $value = $matches[1][$key];
335 17
          $this->processValue($value, $replace);
336 17
        }
337 17
      }
338
339 17
      $string = strtr($string, $this->replaces);
340 17
    }
341
342 19
    return $string;
343
  }
344
345 19
  private function replaceCommands($string)
346
  {
347 19
    if( preg_match(self::COMMAND_PATTERN, $string, $matches) )
348 19
    {
349 5
      if( !empty($matches[0]) )
350 5
      {
351 5
        $command = $matches[1];
352 5
        $args = $matches[2];
353 5
        $value = $this->processCommand($command, $args);
354
355 5
        $string = strtr($string, array($matches[0] => $value));
356 5
        $string = $this->replaceCommands($string);
357 5
      }
358 5
    }
359
360 19
    return $string;
361
  }
362
363
  /**
364
   * @param $value
365
   * @param $replace
366
   */
367 17
  private function processValue($value, $replace)
368
  {
369 17
    if( strpos($value, ':') !== false )
370 17
    {
371 2
      list($modelName, $attribute) = explode(':', $value);
372 2
      $model = Arr::get($this->renderedModels, $modelName);
373
374 2
      if( $model && ($property = $this->getPropertyValue($model, $attribute)) )
375 2
      {
376 2
        $this->replaces[$replace] = $property;
377 2
      }
378 2
    }
379 17
  }
380
381
  /**
382
   * @param string $command
383
   * @param string $args
384
   *
385
   * @return string
386
   */
387 5
  private function processCommand($command, $args)
388
  {
389 5
    $args = Arr::trim(explode(',', $args));
390
391
    switch($command)
392
    {
393 5
      case 'ucfirst':
394 1
        return Utils::ucfirst($args[0]);
395
        break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
396
397 5
      case 'upper':
398 1
        return mb_strtoupper($args[0]);
399
        break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
400
401 5
      case 'lower':
402 1
        return mb_strtolower($args[0]);
403
        break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
404
405 4
      case 'wrap':
406 3
        $left = Arr::get($args, 1, '(');
407 3
        $right = Arr::get($args, 2, ')');
408 3
        return $left.$args[0].$right;
409
        break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
410
411 2
      case 'implode':
412 1
        return implode(trim(Arr::cut($args, 0), '\'"'), $args);
413
        break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
414
415 1
      default:
416 1
        return $args[0];
417 1
    }
418
  }
419
420
  /**
421
   * @param FActiveRecord $model
422
   * @param string $property
423
   *
424
   * @return string
425
   */
426 2
  private function getPropertyValue($model, $property)
427
  {
428 2
    return isset($model->$property) && !is_object($model->$property) && !is_array($model->$property) ? $model->$property : null;
429
  }
430
}