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:
1 | <?php |
||
26 | class Router extends ExternalModule |
||
27 | { |
||
28 | /** Event showing that new gather resource file was created */ |
||
29 | const EVENT_CREATED = 'resource.created'; |
||
30 | |||
31 | /** Event showing that new gather resource file was created */ |
||
32 | const EVENT_START_GENERATE_RESOURCES = 'resource.start.generate.resources'; |
||
33 | |||
34 | /** Identifier */ |
||
35 | protected $id = STATIC_RESOURCE_HANDLER; |
||
36 | |||
37 | /** @var string Marker for inserting generated javascript link */ |
||
38 | public $javascriptMarker = '</body>'; |
||
39 | |||
40 | /** Cached resources path collection */ |
||
41 | public $cached = array(); |
||
42 | |||
43 | /** Collection of updated cached resources for notification of changes */ |
||
44 | public $updated = array(); |
||
45 | |||
46 | /** Pointer to processing module */ |
||
47 | private $currentModule; |
||
48 | |||
49 | /** @var string Current processed resource */ |
||
50 | private $currentResource; |
||
51 | |||
52 | |||
53 | /** @see ModuleConnector::init() */ |
||
54 | public function init(array $params = array()) |
||
67 | |||
68 | public function generateResources($moduleList, $templatePath = 'default') |
||
69 | { |
||
70 | // Cache main web resources |
||
71 | foreach (array(array('js'), array('css', 'less'), array('coffee')) as $rts) { |
||
72 | // Get first resource type as extension |
||
73 | $rt = $rts[0]; |
||
74 | |||
75 | $hash_name = ''; |
||
76 | |||
77 | // Iterate gathered namespaces for their resources |
||
78 | /** @var Module $module */ |
||
79 | foreach ($moduleList as $id => $module) { |
||
80 | // If necessary resources has been collected |
||
81 | foreach ($rts as $_rt) { |
||
82 | if (isset($module->resourceMap->$_rt)) { |
||
83 | foreach ($module->resourceMap->$_rt as $resource) { |
||
84 | // Created string with last resource modification time |
||
85 | $hash_name .= filemtime($resource); |
||
86 | } |
||
87 | } |
||
88 | } |
||
89 | } |
||
90 | |||
91 | // Get hash that's describes resource status |
||
92 | $hash_name = md5($hash_name) . '.' . $rt; |
||
93 | |||
94 | $file = $hash_name; |
||
95 | |||
96 | $dir = str_replace(array('/', '.'), '_', $templatePath); |
||
97 | |||
98 | // If cached file does not exists |
||
99 | if ($this->cache_refresh($file, true, $dir)) { |
||
|
|||
100 | // Read content of resource files |
||
101 | $content = ''; |
||
102 | foreach ($moduleList as $id => $module) { |
||
103 | $this->currentModule = $module; |
||
104 | // If this ns has resources of specified type |
||
105 | foreach ($rts as $_rt) { |
||
106 | if (isset($module->resourceMap->$_rt)) { |
||
107 | //TODO: If you will remove & from iterator - system will fail at last element |
||
108 | foreach ($module->resourceMap->$_rt as $resource) { |
||
109 | // Store current processing resource |
||
110 | $this->currentResource = $resource; |
||
111 | // Read resource file |
||
112 | $c = file_get_contents($resource); |
||
113 | // Rewrite url in css |
||
114 | if ($rt == 'css') { |
||
115 | $c = preg_replace_callback('/url\s*\(\s*(\'|\")?([^\)\s\'\"]+)(\'|\")?\s*\)/i', |
||
116 | array($this, 'src_replace_callback'), $c); |
||
117 | } |
||
118 | // Gather processed resource text together |
||
119 | $content .= "\n\r" . $c; |
||
120 | } |
||
121 | } |
||
122 | } |
||
123 | } |
||
124 | |||
125 | // Fire event that new resource has been generated |
||
126 | Event::fire(self::EVENT_CREATED, array($rt, &$content, &$file, &$this)); |
||
127 | |||
128 | // Fix updated resource file with new path to it |
||
129 | $this->updated[$rt] = $file; |
||
130 | |||
131 | // Запишем содержание нового "собранного" ресурса |
||
132 | file_put_contents($file, $content); |
||
133 | } |
||
134 | |||
135 | // Save path to resource cache |
||
136 | $this->cached[$rt][$templatePath] = __SAMSON_CACHE_PATH . $this->id . '/' . $dir . '/' . $hash_name; |
||
137 | } |
||
138 | } |
||
139 | |||
140 | /** |
||
141 | * Core render handler for including CSS and JS resources to html |
||
142 | * |
||
143 | * @param sting $view View content |
||
144 | * @param array $data View data |
||
145 | * |
||
146 | * @return string Processed view content |
||
147 | */ |
||
148 | public function renderer(&$view, $data = array(), iModule $m = null) |
||
177 | |||
178 | /** |
||
179 | * Callback for CSS url(...) rewriting. |
||
180 | * |
||
181 | * @param array $matches Regular expression matches collection |
||
182 | * |
||
183 | * @return string Rewritten url(..) with static resource handler url |
||
184 | * @throws ResourceNotFound |
||
185 | */ |
||
186 | public function src_replace_callback($matches) |
||
217 | } |
||
218 |
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.