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 |
||
29 | class FileController extends RestController |
||
30 | { |
||
31 | /** |
||
32 | * @var FileManager |
||
33 | */ |
||
34 | private $fileManager; |
||
35 | |||
36 | /** |
||
37 | * @param Response $response Response |
||
38 | * @param RestUtilsInterface $restUtils Rest utils |
||
39 | * @param Router $router Router |
||
40 | * @param ValidatorInterface $validator Validator |
||
41 | * @param EngineInterface $templating Templating |
||
42 | * @param FormFactory $formFactory form factory |
||
43 | * @param DocumentType $formType generic form |
||
44 | * @param ContainerInterface $container Container |
||
45 | * @param SchemaUtils $schemaUtils schema utils |
||
46 | * @param FileManager $fileManager Handles file specific tasks |
||
47 | */ |
||
48 | 7 | View Code Duplication | public function __construct( |
73 | |||
74 | /** |
||
75 | * Writes a new Entry to the database |
||
76 | * |
||
77 | * @param Request $request Current http request |
||
78 | * |
||
79 | * @return Response $response Result of action with data (if successful) |
||
80 | */ |
||
81 | 4 | public function postAction(Request $request) |
|
103 | |||
104 | /** |
||
105 | * respond with document if non json mime-type is requested |
||
106 | * |
||
107 | * @param Request $request Current http request |
||
108 | * @param string $id id of file |
||
109 | * |
||
110 | * @return Response |
||
111 | */ |
||
112 | 4 | public function getAction(Request $request, $id) |
|
113 | { |
||
114 | 4 | $accept = $request->headers->get('accept'); |
|
115 | 4 | if (substr(strtolower($accept), 0, 16) === 'application/json') { |
|
116 | 4 | return parent::getAction($request, $id); |
|
117 | } |
||
118 | 1 | $response = $this->getResponse(); |
|
119 | |||
120 | 1 | if (!$this->fileManager->has($id)) { |
|
121 | $response->setStatusCode(Response::HTTP_NOT_FOUND); |
||
122 | |||
123 | return $response; |
||
124 | } |
||
125 | |||
126 | 1 | $record = $this->findRecord($id); |
|
127 | 1 | $data = $this->fileManager->read($id); |
|
128 | |||
129 | 1 | $response->setStatusCode(Response::HTTP_OK); |
|
130 | 1 | $response->headers->set('Content-Type', $record->getMetadata()->getMime()); |
|
131 | |||
132 | 1 | return $this->render( |
|
133 | 1 | 'GravitonFileBundle:File:index.raw.twig', |
|
134 | 1 | ['data' => $data], |
|
135 | $response |
||
136 | 1 | ); |
|
137 | } |
||
138 | |||
139 | /** |
||
140 | * Update a record |
||
141 | * |
||
142 | * @param Number $id ID of record |
||
143 | * @param Request $request Current http request |
||
144 | * |
||
145 | * @return Response $response Result of action with data (if successful) |
||
146 | */ |
||
147 | 3 | public function putAction($id, Request $request) |
|
148 | { |
||
149 | 3 | $contentType = $request->headers->get('Content-Type'); |
|
150 | 3 | if (substr(strtolower($contentType), 0, 16) === 'application/json') { |
|
151 | 1 | return parent::putAction($id, $request); |
|
152 | } |
||
153 | 3 | if (0 === strpos($contentType, 'multipart/form-data')) { |
|
154 | $request = $this->normalizeRequest($request); |
||
155 | } |
||
156 | |||
157 | 3 | $response = $this->getResponse(); |
|
158 | 3 | $fileData = $this->validateRequest($request, $response, $request->get('metadata')); |
|
159 | 3 | $files = $this->fileManager->saveFiles($request, $this->getModel(), $fileData); |
|
160 | |||
161 | // store id of new record so we don't need to re-parse body later when needed |
||
162 | 3 | $request->attributes->set('id', $files[0]); |
|
163 | |||
164 | 3 | $response->setStatusCode(Response::HTTP_NO_CONTENT); |
|
165 | |||
166 | // no service sends Location headers on PUT - /file shouldn't as well |
||
167 | |||
168 | 3 | return $response; |
|
169 | } |
||
170 | |||
171 | /** |
||
172 | * Deletes a record |
||
173 | * |
||
174 | * @param Number $id ID of record |
||
175 | * |
||
176 | * @return Response $response Result of the action |
||
177 | */ |
||
178 | 1 | public function deleteAction($id) |
|
186 | |||
187 | /** |
||
188 | * Determines the routes and replaces the http method |
||
189 | * |
||
190 | * @param string $routeName Name of the route to be generated |
||
191 | * @param array $files Set of uploaded files |
||
192 | * @param array $routeTypes Set of route types to be recognized |
||
193 | * |
||
194 | * @return array |
||
195 | */ |
||
196 | 4 | private function determineRoutes($routeName, array $files, array $routeTypes) |
|
218 | |||
219 | /** |
||
220 | * Validates the provided request |
||
221 | * |
||
222 | * @param Request $request Http request to be validated |
||
223 | * @param Response $response Http response to be returned in case of an error |
||
224 | * @param string $fileData Alternative content to be validated |
||
225 | * |
||
226 | * @throws \Exception |
||
227 | * @return File|null |
||
228 | */ |
||
229 | 5 | private function validateRequest(Request $request, Response $response, $fileData = '') |
|
230 | { |
||
231 | 5 | if (!empty($fileData)) { |
|
232 | 1 | $this->formValidator->checkJsonRequest($request, $response, $fileData); |
|
233 | 1 | $model = $this->getModel(); |
|
234 | 1 | return $this->formValidator->checkForm( |
|
235 | 1 | $this->formValidator->getForm($request, $model), |
|
236 | 1 | $model, |
|
237 | 1 | $this->formDataMapper, |
|
238 | $fileData |
||
239 | 1 | ); |
|
240 | } |
||
241 | 5 | } |
|
242 | |||
243 | /** |
||
244 | * Gathers information into a request |
||
245 | * |
||
246 | * @param Request $request master request sent by client. |
||
247 | * |
||
248 | * @return Request |
||
249 | */ |
||
250 | private function normalizeRequest(Request $request) |
||
263 | } |
||
264 |