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 |
||
23 | class ParameterHelper extends AbstractHelper |
||
24 | { |
||
25 | /** |
||
26 | * @var Validator |
||
27 | */ |
||
28 | private $validator; |
||
29 | |||
30 | /** |
||
31 | * Returns the canonical name of this helper. |
||
32 | * |
||
33 | * @return string The canonical name |
||
34 | * |
||
35 | * @api |
||
36 | */ |
||
37 | public function getName() |
||
41 | |||
42 | /** |
||
43 | * @param InputInterface $input |
||
44 | * @param OutputInterface $output |
||
45 | * @param string $argumentName |
||
46 | * @param bool $withDefaultStore [optional] |
||
47 | * |
||
48 | * @return mixed |
||
49 | * |
||
50 | * @throws InvalidArgumentException |
||
51 | */ |
||
52 | View Code Duplication | public function askStore( |
|
|
|||
53 | InputInterface $input, |
||
54 | OutputInterface $output, |
||
55 | $argumentName = 'store', |
||
56 | $withDefaultStore = false |
||
57 | ) { |
||
58 | /* @var $storeManager \Mage_Core_Model_App */ |
||
59 | $storeManager = \Mage::app(); |
||
60 | |||
61 | try { |
||
62 | if ($input->getArgument($argumentName) === null) { |
||
63 | throw new RuntimeException('No store given'); |
||
64 | } |
||
65 | /** @var $store \Mage_Core_Model_Store */ |
||
66 | $store = $storeManager->getStore($input->getArgument($argumentName)); |
||
67 | } catch (Exception $e) { |
||
68 | $stores = array(); |
||
69 | $i = 0; |
||
70 | |||
71 | foreach ($storeManager->getStores($withDefaultStore) as $store) { |
||
72 | $stores[$i] = $store->getId(); |
||
73 | $question[] = '<comment>[' . ($i + 1) . ']</comment> ' . $store->getCode() . ' - ' . $store->getName() . PHP_EOL; |
||
74 | $i++; |
||
75 | } |
||
76 | |||
77 | if (count($stores) > 1) { |
||
78 | $question[] = '<question>Please select a store: </question>'; |
||
79 | $storeId = $this->askAndValidate($output, $question, |
||
80 | function($typeInput) use ($stores) { |
||
81 | if (!isset($stores[$typeInput - 1])) { |
||
82 | throw new InvalidArgumentException('Invalid store'); |
||
83 | } |
||
84 | |||
85 | return $stores[$typeInput - 1]; |
||
86 | }); |
||
87 | } else { |
||
88 | // only one store view available -> take it |
||
89 | $storeId = $stores[0]; |
||
90 | } |
||
91 | |||
92 | $store = $storeManager->getStore($storeId); |
||
93 | } |
||
94 | |||
95 | return $store; |
||
96 | } |
||
97 | |||
98 | /** |
||
99 | * @param InputInterface $input |
||
100 | * @param OutputInterface $output |
||
101 | * @param string $argumentName |
||
102 | * |
||
103 | * @return mixed |
||
104 | * @throws InvalidArgumentException |
||
105 | * @throws RuntimeException |
||
106 | */ |
||
107 | View Code Duplication | public function askWebsite(InputInterface $input, OutputInterface $output, $argumentName = 'website') |
|
108 | { |
||
109 | /* @var $storeManager \Mage_Core_Model_App */ |
||
110 | $storeManager = \Mage::app(); |
||
111 | |||
112 | try { |
||
113 | if ($input->getArgument($argumentName) === null) { |
||
114 | throw new RuntimeException('No website given'); |
||
115 | } |
||
116 | /** @var $website \Mage_Core_Model_Website */ |
||
117 | $website = $storeManager->getWebsite($input->getArgument($argumentName)); |
||
118 | } catch (Exception $e) { |
||
119 | $i = 0; |
||
120 | $websites = array(); |
||
121 | foreach ($storeManager->getWebsites() as $website) { |
||
122 | $websites[$i] = $website->getId(); |
||
123 | $question[] = '<comment>[' . ($i + 1) . ']</comment> ' . $website->getCode() . ' - ' . $website->getName() . PHP_EOL; |
||
124 | $i++; |
||
125 | } |
||
126 | if (count($websites) == 1) { |
||
127 | return $storeManager->getWebsite($websites[0]); |
||
128 | } |
||
129 | $question[] = '<question>Please select a website: </question>'; |
||
130 | |||
131 | $websiteId = $this->askAndValidate($output, $question, |
||
132 | function($typeInput) use ($websites) { |
||
133 | if (!isset($websites[$typeInput - 1])) { |
||
134 | throw new InvalidArgumentException('Invalid store'); |
||
135 | } |
||
136 | |||
137 | return $websites[$typeInput - 1]; |
||
138 | }); |
||
139 | |||
140 | $website = $storeManager->getWebsite($websiteId); |
||
141 | } |
||
142 | |||
143 | return $website; |
||
144 | } |
||
145 | |||
146 | /** |
||
147 | * @param InputInterface $input |
||
148 | * @param OutputInterface $output |
||
149 | * @param string $argumentName |
||
150 | * |
||
151 | * @return string |
||
152 | */ |
||
153 | public function askEmail(InputInterface $input, OutputInterface $output, $argumentName = 'email') |
||
154 | { |
||
155 | $constraints = new Constraints\Collection( |
||
156 | array( |
||
157 | 'email' => array( |
||
158 | new Constraints\NotBlank(), |
||
159 | new Constraints\Email() |
||
160 | ) |
||
161 | ) |
||
162 | ); |
||
163 | |||
164 | return $this->validateArgument($output, $argumentName, $input->getArgument($argumentName), $constraints); |
||
165 | } |
||
166 | |||
167 | /** |
||
168 | * @param InputInterface $input |
||
169 | * @param OutputInterface $output |
||
170 | * @param string $argumentName |
||
171 | * |
||
172 | * @param bool $needDigits [optional] |
||
173 | * @return string |
||
174 | */ |
||
175 | public function askPassword( |
||
176 | InputInterface $input, |
||
177 | OutputInterface $output, |
||
178 | $argumentName = 'password', |
||
179 | $needDigits = true |
||
180 | ) { |
||
181 | $validators = array(); |
||
182 | |||
183 | if ($needDigits) { |
||
184 | $regex = array( |
||
185 | 'pattern' => '/^(?=.*\d)(?=.*[a-zA-Z])/', |
||
186 | 'message' => 'Password must contain letters and at least one digit' |
||
187 | ); |
||
188 | $validators[] = new Constraints\Regex($regex); |
||
189 | } |
||
190 | |||
191 | $validators[] = new Constraints\Length(array('min' => 6)); |
||
192 | |||
193 | $constraints = new Constraints\Collection( |
||
194 | array( |
||
195 | 'password' => $validators |
||
196 | ) |
||
197 | ); |
||
198 | |||
199 | return $this->validateArgument($output, $argumentName, $input->getArgument($argumentName), $constraints); |
||
200 | } |
||
201 | |||
202 | /** |
||
203 | * @param OutputInterface $output |
||
204 | * @param $question |
||
205 | * @param callable $callback |
||
206 | * |
||
207 | * @return string |
||
208 | */ |
||
209 | private function askAndValidate(OutputInterface $output, $question, $callback) |
||
210 | { |
||
211 | /** @var DialogHelper $dialog */ |
||
212 | $dialog = $this->getHelperSet()->get('dialog'); |
||
213 | |||
214 | return $dialog->askAndValidate($output, $question, $callback); |
||
215 | } |
||
216 | |||
217 | /** |
||
218 | * @param OutputInterface $output |
||
219 | * @param string $name |
||
220 | * @param string $value |
||
221 | * @param Constraints\Collection $constraints The constraint(s) to validate against. |
||
222 | * |
||
223 | * @return string |
||
224 | */ |
||
225 | private function validateArgument(OutputInterface $output, $name, $value, $constraints) |
||
226 | { |
||
227 | |||
228 | if (strlen($value)) { |
||
229 | $errors = $this->validateValue($name, $value, $constraints); |
||
230 | if ($errors->count() > 0) { |
||
231 | $output->writeln('<error>' . $errors[0]->getMessage() . '</error>'); |
||
232 | } else { |
||
233 | |||
234 | return $value; |
||
235 | } |
||
236 | } |
||
237 | |||
238 | $question = '<question>' . ucfirst($name) . ': </question>'; |
||
239 | |||
240 | $value = $this->askAndValidate( |
||
241 | $output, $question, |
||
242 | function($inputValue) use ($constraints, $name) { |
||
243 | $errors = $this->validateValue($name, $inputValue, $constraints); |
||
244 | if ($errors->count() > 0) { |
||
245 | throw new InvalidArgumentException($errors[0]->getMessage()); |
||
246 | } |
||
247 | |||
248 | return $inputValue; |
||
249 | } |
||
250 | ); |
||
251 | |||
252 | return $value; |
||
253 | } |
||
254 | |||
255 | /** |
||
256 | * @param string $name |
||
257 | * @param string $value |
||
258 | * @param Constraints\Collection $constraints The constraint(s) to validate against. |
||
259 | * |
||
260 | * @return \Symfony\Component\Validator\ConstraintViolationInterface[]|ConstraintViolationListInterface |
||
261 | */ |
||
262 | private function validateValue($name, $value, $constraints) |
||
263 | { |
||
264 | $validator = $this->getValidator(); |
||
265 | /** @var ConstraintViolationListInterface|ConstraintViolationInterface[] $errors */ |
||
266 | $errors = $validator->validateValue(array($name => $value), $constraints); |
||
267 | |||
268 | return $errors; |
||
269 | } |
||
270 | |||
271 | /** |
||
272 | * @return Validator |
||
273 | */ |
||
274 | private function getValidator() |
||
278 | |||
279 | /** |
||
280 | * @return Validator |
||
281 | */ |
||
282 | private function createValidator() |
||
283 | { |
||
284 | $factory = new ConstraintValidatorFactory(); |
||
285 | $validator = new Validator(new FakeMetadataFactory(), $factory, new Translator('en')); |
||
289 | } |
||
290 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.