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 |
||
20 | class ViewManager extends Component implements ViewsInterface, SingletonInterface |
||
21 | { |
||
22 | use BenchmarkTrait; |
||
23 | |||
24 | /** |
||
25 | * Active view environment might define behaviour of engines and etc. |
||
26 | * |
||
27 | * @var EnvironmentInterface |
||
28 | */ |
||
29 | private $environment = null; |
||
30 | |||
31 | /** |
||
32 | * Loader used to locate view files using simple notation (where no extension is included). |
||
33 | * |
||
34 | * @var LoaderInterface |
||
35 | */ |
||
36 | private $loader = null; |
||
37 | |||
38 | /** |
||
39 | * View engines cache. |
||
40 | * |
||
41 | * @var EngineInterface[] |
||
42 | */ |
||
43 | private $engines = []; |
||
44 | |||
45 | /** |
||
46 | * @var ViewsConfig |
||
47 | */ |
||
48 | protected $config = null; |
||
49 | |||
50 | /** |
||
51 | * @var FilesInterface |
||
52 | */ |
||
53 | protected $files = null; |
||
54 | |||
55 | /** |
||
56 | * @invisible |
||
57 | * @var ContainerInterface |
||
58 | */ |
||
59 | protected $container = null; |
||
60 | |||
61 | /** |
||
62 | * @param ViewsConfig $config |
||
63 | * @param FilesInterface $files |
||
64 | * @param ContainerInterface $container |
||
65 | */ |
||
66 | public function __construct( |
||
79 | |||
80 | /** |
||
81 | * Creates copy of view manager with new environment. |
||
82 | * |
||
83 | * @param EnvironmentInterface $environment |
||
84 | * |
||
85 | * @return ViewManager |
||
86 | */ |
||
87 | View Code Duplication | public function withEnvironment(EnvironmentInterface $environment): ViewManager |
|
98 | |||
99 | /** |
||
100 | * Current view environment. |
||
101 | * |
||
102 | * @return EnvironmentInterface |
||
103 | */ |
||
104 | public function getEnvironment(): EnvironmentInterface |
||
108 | |||
109 | /** |
||
110 | * @param LoaderInterface $loader |
||
111 | * |
||
112 | * @return ViewManager |
||
113 | */ |
||
114 | View Code Duplication | public function withLoader(LoaderInterface $loader): ViewManager |
|
125 | |||
126 | /** |
||
127 | * View loader. |
||
128 | * |
||
129 | * @return LoaderInterface |
||
130 | */ |
||
131 | public function getLoader(): LoaderInterface |
||
135 | |||
136 | /** |
||
137 | * {@inheritdoc} |
||
138 | */ |
||
139 | public function get(string $path): ViewInterface |
||
145 | |||
146 | /** |
||
147 | * {@inheritdoc} |
||
148 | */ |
||
149 | public function render(string $path, array $context = []): string |
||
155 | |||
156 | /** |
||
157 | * Pre-compile desired view file. |
||
158 | * |
||
159 | * @param string $path |
||
160 | */ |
||
161 | public function compile(string $path) |
||
167 | |||
168 | /** |
||
169 | * Get engine by it's type. |
||
170 | * |
||
171 | * @param string $engine |
||
172 | * |
||
173 | * @return EngineInterface |
||
174 | */ |
||
175 | public function engine(string $engine): EngineInterface |
||
184 | |||
185 | /** |
||
186 | * Detect engine by view path (automatically resolved based on extension). |
||
187 | * |
||
188 | * @todo this method might require some optimizations, for example utilizing memory cache for |
||
189 | * @todo associations will be a nice idea. |
||
190 | * |
||
191 | * @param string $path |
||
192 | * |
||
193 | * @return string |
||
194 | */ |
||
195 | protected function detectEngine(string $path): string |
||
228 | |||
229 | /** |
||
230 | * Create engine instance. |
||
231 | * |
||
232 | * @param string $engine |
||
233 | * |
||
234 | * @return EngineInterface |
||
235 | * |
||
236 | * @throws ViewsException |
||
237 | */ |
||
238 | protected function createEngine(string $engine): EngineInterface |
||
260 | |||
261 | /** |
||
262 | * @param ViewsConfig $config |
||
263 | * |
||
264 | * @return EnvironmentInterface |
||
265 | */ |
||
266 | protected function createEnvironment(ViewsConfig $config): EnvironmentInterface |
||
275 | |||
276 | /** |
||
277 | * Getting isolated view loader (class responsible for locating files and isolating view |
||
278 | * namespaces). Isolation is done by forcing specific file extension. MUST NOT return same |
||
279 | * instance for different engines! |
||
280 | * |
||
281 | * @param string $engine Forced extension value. |
||
282 | * |
||
283 | * @return LoaderInterface |
||
284 | * |
||
285 | * @throws ViewsException |
||
286 | */ |
||
287 | protected function isolateLoader(string $engine = null): LoaderInterface |
||
300 | } |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.