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 classes like PostVote 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 PostVote, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
8 | class PostVote extends Game implements ServiceManagerAwareInterface |
||
9 | { |
||
10 | protected $postvoteMapper; |
||
11 | protected $postvoteformMapper; |
||
12 | protected $postVotePostMapper; |
||
13 | protected $postVoteVoteMapper; |
||
14 | protected $postVotePostElementMapper; |
||
15 | |||
16 | public function getGameEntity() |
||
20 | |||
21 | public function getPath($post) |
||
35 | |||
36 | public function getMediaUrl($post) |
||
43 | |||
44 | public function checkPost($entry) |
||
45 | { |
||
46 | $post = $this->getPostVotePostMapper()->findOneBy(array('entry' => $entry)); |
||
47 | |||
48 | if (! $post) { |
||
49 | $post = new \PlaygroundGame\Entity\PostVotePost(); |
||
50 | $post->setPostvote($entry->getGame()); |
||
51 | $post->setUser($entry->getUser()); |
||
52 | $post->setEntry($entry); |
||
53 | $post = $this->getPostVotePostMapper()->insert($post); |
||
54 | } |
||
55 | |||
56 | return $post; |
||
57 | } |
||
58 | |||
59 | public function uploadFileToPost($data, $game, $user) |
||
91 | |||
92 | public function deleteFilePosted($data, $game, $user) |
||
117 | |||
118 | /** |
||
119 | * |
||
120 | * @param array $data |
||
121 | * @return \PlaygroundGame\Entity\Game |
||
122 | */ |
||
123 | public function createPost(array $data, $game, $user, $form) |
||
124 | { |
||
125 | $postvotePostMapper = $this->getPostVotePostMapper(); |
||
126 | $postVotePostElementMapper = $this->getPostVotePostElementMapper(); |
||
127 | |||
128 | $entry = $this->findLastActiveEntry($game, $user); |
||
129 | |||
130 | if (!$entry) { |
||
131 | return false; |
||
132 | } |
||
133 | |||
134 | $post = $this->checkPost($entry); |
||
135 | $path = $this->getPath($post); |
||
136 | $media_url = $this->getMediaUrl($post); |
||
137 | $position=1; |
||
138 | |||
139 | foreach ($data as $name => $value) { |
||
140 | $postElement = $postVotePostElementMapper->findOneBy(array('post' => $post, 'name' => $name)); |
||
141 | if (! $postElement) { |
||
142 | $postElement = new \PlaygroundGame\Entity\PostVotePostElement(); |
||
143 | } |
||
144 | $postElement->setName($name); |
||
145 | $postElement->setPosition($position); |
||
146 | |||
147 | if (is_array($value) && isset($value['tmp_name'])) { |
||
148 | // The file upload has been done in ajax but some weird bugs remain without it |
||
149 | |||
150 | if (! $value['error']) { |
||
151 | ErrorHandler::start(); |
||
152 | $value['name'] = $this->fileNewname($path, $value['name'], true); |
||
153 | move_uploaded_file($value['tmp_name'], $path . $value['name']); |
||
154 | $image = $this->getServiceManager()->get('playgroundcore_image_service'); |
||
155 | $image->setImage($path . $value['name']); |
||
156 | |||
157 | if ($image->canCorrectOrientation()) { |
||
158 | $image->correctOrientation()->save(); |
||
159 | } |
||
160 | $postElement->setValue($media_url . $value['name']); |
||
161 | |||
162 | if (class_exists("Imagick")) { |
||
163 | $ext = pathinfo($value['name'], PATHINFO_EXTENSION); |
||
164 | $img = new \Imagick($path . $value['name']); |
||
165 | $img->cropThumbnailImage(100, 100); |
||
166 | $img->setImageCompression(\Imagick::COMPRESSION_JPEG); |
||
167 | $img->setImageCompressionQuality(75); |
||
168 | // Strip out unneeded meta data |
||
169 | $img->stripImage(); |
||
170 | $img->writeImage($path . str_replace('.'.$ext, '-thumbnail.'.$ext, $value['name'])); |
||
171 | ErrorHandler::stop(true); |
||
172 | } |
||
173 | } |
||
174 | } elseif (is_array($value)) { |
||
175 | $arValues = $form->get($name)->getValueOptions(); |
||
176 | $postElement->setValue($arValues[$value[0]]); |
||
177 | } elseif (!empty($value)) { |
||
178 | $postElement->setValue($value); |
||
179 | } |
||
180 | $postElement->setPost($post); |
||
181 | $postVotePostElementMapper->insert($postElement); |
||
182 | $position++; |
||
183 | } |
||
184 | |||
185 | $postvotePostMapper->update($post); |
||
186 | |||
187 | // If a preview step is not proposed, I confirmPost on this step |
||
188 | $steps = $game->getStepsArray(); |
||
189 | $previewKey = array_search('preview', $steps); |
||
190 | if (!$previewKey) { |
||
191 | $post = $this->confirmPost($game, $user); |
||
192 | } |
||
193 | |||
194 | $this->getEventManager()->trigger(__FUNCTION__ . '.post', $this, array( |
||
195 | 'user' => $user, |
||
196 | 'game' => $game, |
||
197 | 'post' => $post, |
||
198 | 'entry' => $entry |
||
199 | )); |
||
200 | |||
201 | return $post; |
||
202 | } |
||
203 | |||
204 | /** |
||
205 | * |
||
206 | * @return \PlaygroundGame\Entity\Game |
||
207 | */ |
||
208 | public function confirmPost($game, $user) |
||
209 | { |
||
210 | $postvotePostMapper = $this->getPostVotePostMapper(); |
||
211 | |||
212 | $entryMapper = $this->getEntryMapper(); |
||
213 | $entry = $this->findLastActiveEntry($game, $user); |
||
214 | |||
215 | if (!$entry) { |
||
216 | return false; |
||
217 | } |
||
218 | |||
219 | $post = $postvotePostMapper->findOneBy(array('entry' => $entry)); |
||
220 | |||
221 | if (! $post) { |
||
222 | return false; |
||
223 | } |
||
224 | |||
225 | // The post is confirmed by user. I update the status and close the associated entry |
||
226 | // Post are validated by default, unless pre-moderation is enable for the game |
||
227 | if ($game->getModerationType()) { |
||
228 | $post->setStatus(1); |
||
229 | } else { |
||
230 | $post->setStatus(2); |
||
231 | } |
||
232 | |||
233 | $postvotePostMapper->update($post); |
||
234 | |||
235 | $entry->setActive(0); |
||
236 | $entryMapper->update($entry); |
||
237 | |||
238 | $this->getEventManager()->trigger(__FUNCTION__ . '.post', $this, array( |
||
239 | 'user' => $user, |
||
240 | 'game' => $game, |
||
241 | 'entry' => $entry, |
||
242 | 'post' => $post |
||
243 | )); |
||
244 | |||
245 | if ($user) { |
||
246 | // send mail for participation |
||
247 | $this->sendGameMail($game, $user, $post, 'postvote'); |
||
248 | } |
||
249 | |||
250 | return $post; |
||
251 | } |
||
252 | |||
253 | /** |
||
254 | * |
||
255 | * This service is ready for all types of games |
||
256 | * |
||
257 | * @param array $data |
||
258 | * @return \PlaygroundGame\Entity\Game |
||
259 | */ |
||
260 | View Code Duplication | public function createForm(array $data, $game, $form = null) |
|
261 | { |
||
262 | $title =''; |
||
263 | $description = ''; |
||
264 | |||
265 | if ($data['form_jsonified']) { |
||
266 | $jsonPV = json_decode($data['form_jsonified']); |
||
267 | foreach ($jsonPV as $element) { |
||
268 | if ($element->form_properties) { |
||
269 | $attributes = $element->form_properties[0]; |
||
270 | $title = $attributes->title; |
||
271 | $description = $attributes->description; |
||
272 | |||
273 | break; |
||
274 | } |
||
275 | } |
||
276 | } |
||
277 | if (!$form) { |
||
278 | $form = new \PlaygroundGame\Entity\PostVoteForm(); |
||
279 | } |
||
280 | $form->setPostvote($game); |
||
281 | $form->setTitle($title); |
||
282 | $form->setDescription($description); |
||
283 | $form->setForm($data['form_jsonified']); |
||
284 | $form->setFormTemplate($data['form_template']); |
||
285 | |||
286 | $form = $this->getPostVoteFormMapper()->insert($form); |
||
287 | |||
288 | return $form; |
||
289 | } |
||
290 | |||
291 | public function findArrayOfValidatedPosts($game, $filter, $search = '') |
||
370 | |||
371 | public function addVote($user, $ipAddress, $post) |
||
403 | |||
404 | public function getEntriesHeader($game) |
||
420 | |||
421 | View Code Duplication | public function getEntriesQuery($game) |
|
459 | |||
460 | /** |
||
461 | * getGameEntries : All entries of a game |
||
462 | * |
||
463 | * @return Array of PlaygroundGame\Entity\Game |
||
464 | */ |
||
465 | public function getGameEntries($header, $entries, $game) |
||
494 | |||
495 | public function getPostVoteFormMapper() |
||
503 | |||
504 | public function setPostVoteFormMapper($postvoteformMapper) |
||
510 | |||
511 | public function getPostVotePostElementMapper() |
||
521 | |||
522 | public function setPostVotePostElementMapper($postVotePostElementMapper) |
||
528 | |||
529 | public function getPostVoteVoteMapper() |
||
537 | |||
538 | public function setPostVoteVoteMapper($postVoteVoteMapper) |
||
544 | |||
545 | public function getPostVotePostMapper() |
||
553 | |||
554 | public function setPostVotePostMapper($postVotePostMapper) |
||
560 | |||
561 | public function getPostVoteMapper() |
||
569 | |||
570 | /** |
||
571 | * setQuizQuestionMapper |
||
572 | * |
||
573 | * @return PostVote |
||
574 | */ |
||
575 | public function setPostVoteMapper($postvoteMapper) |
||
581 | } |
||
582 |
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.
Both the
$myVar
assignment in line 1 and the$higher
assignment in line 2 are dead. The first because$myVar
is never used and the second because$higher
is always overwritten for every possible time line.