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.
Completed
Push — master ( 764334...261594 )
by Alexey
33:15
created

ImportHelper   A

Complexity

Total Complexity 42

Size/Duplication

Total Lines 277
Duplicated Lines 6.5 %

Coupling/Cohesion

Components 2
Dependencies 3

Importance

Changes 0
Metric Value
dl 18
loc 277
rs 9.0399
c 0
b 0
f 0
wmc 42
lcom 2
cbo 3

13 Methods

Rating   Name   Duplication   Size   Complexity  
A getFileLastModified() 0 14 4
A getFiles() 0 12 2
A lettersToNumber() 0 12 3
A numberToLetters() 0 15 3
A getLettersRange() 0 19 3
A getModelWithoutBehaviors() 0 14 2
A convertColumnIndexes() 0 19 6
A wrapInSlash() 0 4 1
A wrapInSlashBegin() 9 9 2
A wrapInSlashEnd() 9 9 2
B createUniqueUrl() 0 37 10
A clearUrlCache() 0 7 2
A getUrls() 0 12 2

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like ImportHelper 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 ImportHelper, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * @author Alexey Tatarinov <[email protected]>
4
 * @link https://github.com/shogodev/argilla/
5
 * @copyright Copyright &copy; 2003-2015 Shogo
6
 * @license http://argilla.ru/LICENSE
7
 */
8
class ImportHelper
9
{
10
  private static $urlCache;
11
12
  /**
13
   * @param $folder
14
   * @param array $extensions
15
   *
16
   * @return null
17
   * @internal param string $extension
18
   */
19
  public static function getFileLastModified($folder, $extensions = array('csv'))
20
  {
21
    $extensions = is_array($extensions) ? $extensions : array($extensions);
22
    $files = CFileHelper::findFiles($folder, array(
23
      'level' => 0,
24
      'fileTypes' => $extensions,
25
    ));
26
27
    $filesWithDate = array();
28
    foreach($files as $file)
29
      $filesWithDate[filemtime($file)] = $file;
30
31
    return !empty($filesWithDate) ? $filesWithDate[max(array_keys($filesWithDate))] : null;
32
  }
33
34
  /**
35
   * @param $folder
36
   * @param array $extensions
37
   *
38
   * @return array
39
   * @internal param string $extension
40
   */
41
  public static function getFiles($folder, $extensions = array('csv'))
42
  {
43
    $extensions = is_array($extensions) ? $extensions : array($extensions);
44
45
    $files = array_reverse(CFileHelper::findFiles($folder, array(
46
      'fileTypes' => $extensions
47
    )));
48
49
    asort($files, SORT_NATURAL);
50
51
    return $files;
52
  }
53
54
  /**
55
   * Преобразует номер столбца в индекс колонки exсel таблици A - 0, B - 1
56
   *
57
   * @param $letters
58
   * @param bool $firstZero индексация начинается с 0
59
   *
60
   * @return int
61
   */
62
  public static function lettersToNumber($letters, $firstZero = true)
63
  {
64
    $num = 0;
65
    $arr = array_reverse(str_split($letters));
66
67
    for($i = 0; $i < count($arr); $i++)
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
68
    {
69
      $num += (ord(strtolower($arr[$i])) - 96) * (pow(26, $i));
70
    }
71
72
    return $firstZero ? $num - 1 : $num;
73
  }
74
75
  /**
76
   * Преобразует индекс колонки exсel в номер столбца в 1 - A, 2 - B
77
   *
78
   * @param $number
79
   *
80
   * @return string
81
   */
82
  public static function numberToLetters($number)
83
  {
84
    $letter = "";
85
    if( $number <= 0 )
86
      return '';
87
88
    while($number != 0)
89
    {
90
      $p = ($number - 1) % 26;
91
      $number = intval(($number - $p) / 26);
92
      $letter = chr(65 + $p).$letter;
93
    }
94
95
    return $letter;
96
  }
97
98
  /**
99
   * Преобразует дивпазон индексов колонок exсel в массив
100
   * например 'a-c' в array('A', 'B', 'C');
101
   *
102
   * @param $string
103
   *
104
   * @return array
105
   */
106
  public static function getLettersRange($string)
107
  {
108
    list($begin, $end) = explode('-', $string);
109
110
    $array = array();
111
112
    $current = self::lettersToNumber($begin);
113
    $end = self::lettersToNumber($end);
114
115
    while(1)
116
    {
117
      $array[] = self::numberToLetters(($current++) + 1);
118
119
      if( $current > $end )
120
        break;
121
    }
122
123
    return $array;
124
  }
125
126
  public static function getModelWithoutBehaviors($className, $scenario = null)
127
  {
128
    /**
129
     * @var CActiveRecord $model
130
     */
131
    $model = new $className(null);
132
    if( $scenario )
133
      $model->setScenario($scenario);
134
135
    $model->setIsNewRecord(true);
136
    $model->init();
137
138
    return $model;
139
  }
140
141
  /**
142
   * @param $array
143
   *
144
   * @return mixed
145
   */
146
  public static function convertColumnIndexes($array)
147
  {
148
    foreach($array as $key => $columnIndex)
149
    {
150
      if( !empty($columnIndex) && !is_numeric($columnIndex) && !is_array($columnIndex) )
151
      {
152
        $array[$key] = self::lettersToNumber($columnIndex);
153
      }
154
      else if(is_array($columnIndex))
155
      {
156
        $columnIndex[0] = self::lettersToNumber(Arr::get($columnIndex, 0));
157
        $array[$key] = $columnIndex;
158
      }
159
      else
160
        unset($array[$key]);
161
    }
162
163
    return $array;
164
  }
165
166
  /**
167
   * Оборачивает путь в слеши, исключаея дублирование
168
   *
169
   * @param $path
170
   * @param string $wrapper
171
   *
172
   * @return string
173
   */
174
  public static function wrapInSlash($path, $wrapper = DIRECTORY_SEPARATOR)
175
  {
176
    return self::wrapInSlashBegin(self::wrapInSlashEnd($path, $wrapper, false), $wrapper);
177
  }
178
179
  /**
180
   * Оборачивает начало путь в слеш, исключаея дублирование
181
   *
182
   * @param $path
183
   * @param string $wrapper
184
   * @param bool $clearEnd
185
   *
186
   * @return string
187
   */
188 View Code Duplication
  public static function wrapInSlashBegin($path, $wrapper = DIRECTORY_SEPARATOR, $clearEnd = true)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
189
  {
190
    $path = preg_replace("/(^\\{$wrapper})/", '', $path);
191
192
    if( $clearEnd )
193
      preg_replace("/(\\{$wrapper})$/", '', $path);
194
195
    return $wrapper.$path;
196
  }
197
198
  /**
199
   * Оборачивает конец путь в слеш, исключаея дублирование
200
   * @param $path
201
   * @param string $wrapper
202
   * @param bool $clearBegin
203
   *
204
   * @return string
205
   */
206 View Code Duplication
  public static function wrapInSlashEnd($path, $wrapper = DIRECTORY_SEPARATOR, $clearBegin = true)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
207
  {
208
    $path = preg_replace("/(\\{$wrapper}$)/", '', $path);
209
210
    if( $clearBegin )
211
      preg_replace("/(^\\{$wrapper})/", '', $path);
212
213
    return $path.$wrapper;
214
  }
215
216
  /**
217
   * @param string $table
218
   * @param $url
219
   * @param bool|false $warmUpCache - прогреть
220
   *
221
   * @return mixed|string
222
   */
223
  public static function createUniqueUrl($table, $url, $warmUpCache = false)
224
  {
225
    if( !isset(self::$urlCache[$table]) )
226
    {
227
      self::$urlCache[$table] = array();
228
229
      if( $warmUpCache )
230
      {
231
        foreach(self::getUrls($table) as $itemUrl)
232
          self::$urlCache[$table][$itemUrl] = $itemUrl;
233
      }
234
    }
235
236
    if( !$warmUpCache )
237
    {
238
      if( $itemUrl = Arr::get(self::getUrls($table, $url), 0 ) )
239
        self::$urlCache[$table][$itemUrl] = $itemUrl;
240
    }
241
242
    $uniqueUrl = Utils::translite(trim($url));
243
    $suffix = 1;
244
    while( isset(self::$urlCache[$table][$uniqueUrl]) )
245
    {
246
      $uniqueUrl = $url.'_'.$suffix++;
247
248
      if( !$warmUpCache )
249
      {
250
        if( $checkUrl = Arr::get(self::getUrls($table, $uniqueUrl), 0 ) )
251
          self::$urlCache[$table][$checkUrl] = $checkUrl;
252
      }
253
    }
254
255
    if( $warmUpCache )
256
      self::$urlCache[$table][$uniqueUrl] = $uniqueUrl;
257
258
    return $uniqueUrl;
259
  }
260
261
  /**
262
   * @param $table|null "null" clears all
263
   */
264
  public static function clearUrlCache($table)
265
  {
266
    if( is_null($table) )
267
      self::$urlCache = null;
268
    else
269
      self::$urlCache[$table] = null;
270
  }
271
272
  private static function getUrls($table, $url = null)
273
  {
274
    $criteria = new CDbCriteria();
275
    $criteria->select = 'url';
276
277
    if( isset($url) )
278
      $criteria->compare('url', $url);
279
280
    $command = Yii::app()->db->schema->commandBuilder->createFindCommand($table, $criteria);
281
282
    return $command->queryColumn();
283
  }
284
}