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 | 1 | View Code Duplication | public function __construct( |
47 | Response $response, |
||
48 | RestUtilsInterface $restUtils, |
||
49 | Router $router, |
||
50 | ValidatorInterface $validator, |
||
51 | EngineInterface $templating, |
||
52 | FormFactory $formFactory, |
||
53 | DocumentType $formType, |
||
54 | ContainerInterface $container, |
||
55 | SchemaUtils $schemaUtils, |
||
56 | FileManager $fileManager |
||
57 | ) { |
||
58 | 1 | parent::__construct( |
|
59 | $response, |
||
60 | $restUtils, |
||
61 | $router, |
||
62 | $validator, |
||
63 | $templating, |
||
64 | $formFactory, |
||
65 | $formType, |
||
66 | $container, |
||
67 | $schemaUtils |
||
68 | ); |
||
69 | 1 | $this->fileManager = $fileManager; |
|
70 | 1 | } |
|
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 | 1 | public function postAction(Request $request) |
|
80 | { |
||
81 | 1 | $response = $this->getResponse(); |
|
82 | 1 | $fileData = $this->validateRequest($request, $response, $request->get('metadata')); |
|
83 | 1 | $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 | 1 | $request->attributes->set('id', $files[0]); |
|
87 | |||
88 | // Set status code and content |
||
89 | 1 | $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 | 1 | $locations = $this->determineRoutes($request->get('_route'), $files, ['post', 'postNoSlash']); |
|
94 | 1 | $response->headers->set( |
|
95 | 1 | 'Location', |
|
96 | 1 | $locations[0] |
|
97 | ); |
||
98 | |||
99 | 1 | 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 | 1 | public function getAction(Request $request, $id) |
|
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 | public function putAction($id, Request $request) |
||
146 | { |
||
147 | $contentType = $request->headers->get('Content-Type'); |
||
148 | if (substr(strtolower($contentType), 0, 16) === 'application/json') { |
||
149 | return parent::putAction($id, $request); |
||
150 | } |
||
151 | if (0 === strpos($contentType, 'multipart/form-data')) { |
||
152 | $request = $this->normalizeRequest($request); |
||
153 | } |
||
154 | |||
155 | $response = $this->getResponse(); |
||
156 | $fileData = $this->validateRequest($request, $response, $request->get('metadata')); |
||
157 | $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 | $request->attributes->set('id', $files[0]); |
||
161 | |||
162 | $response->setStatusCode(Response::HTTP_NO_CONTENT); |
||
163 | |||
164 | // no service sends Location headers on PUT - /file shouldn't as well |
||
165 | |||
166 | 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 | 1 | 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 | 1 | 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 | 1 | private function validateRequest(Request $request, Response $response, $fileData = '') |
|
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 |