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