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 Application 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 Application, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
40 | class Application extends ApplicationTrait |
||
|
|||
41 | { |
||
42 | public function __construct(array $values = array()) |
||
52 | |||
53 | 704 | public function initConfig() |
|
135 | |||
136 | 704 | public function initLogger() |
|
137 | { |
||
138 | 704 | $app = $this; |
|
139 | $this->register(new ServiceProvider\EccubeMonologServiceProvider($app)); |
||
140 | $this['monolog.logfile'] = __DIR__.'/../../app/log/site.log'; |
||
141 | $this['monolog.name'] = 'eccube'; |
||
142 | 704 | } |
|
143 | |||
144 | 689 | public function initialize() |
|
145 | { |
||
146 | // init locale |
||
147 | $this->initLocale(); |
||
148 | |||
149 | // init session |
||
150 | $this->initSession(); |
||
151 | |||
152 | // init twig |
||
153 | $this->initRendering(); |
||
154 | |||
155 | // init provider |
||
156 | $this->register(new \Silex\Provider\HttpFragmentServiceProvider()); |
||
157 | $this->register(new \Silex\Provider\UrlGeneratorServiceProvider()); |
||
158 | $this->register(new \Silex\Provider\FormServiceProvider()); |
||
159 | $this->register(new \Silex\Provider\SerializerServiceProvider()); |
||
160 | $this->register(new \Eccube\ServiceProvider\ValidatorServiceProvider()); |
||
161 | |||
162 | 689 | $app = $this; |
|
163 | $this->error(function(\Exception $e, $code) use ($app) { |
||
164 | if ($app['debug']) { |
||
165 | 2 | return; |
|
166 | } |
||
167 | |||
168 | switch ($code) { |
||
169 | case 403: |
||
170 | $title = 'アクセスできません。'; |
||
171 | $message = 'お探しのページはアクセスができない状況にあるか、移動もしくは削除された可能性があります。'; |
||
172 | break; |
||
173 | case 404: |
||
174 | $title = 'ページがみつかりません。'; |
||
175 | $message = 'URLに間違いがないかご確認ください。'; |
||
176 | break; |
||
177 | default: |
||
178 | $title = 'システムエラーが発生しました。'; |
||
179 | $message = '大変お手数ですが、サイト管理者までご連絡ください。'; |
||
180 | break; |
||
181 | } |
||
182 | |||
183 | return $app['twig']->render('error.twig', array( |
||
184 | 'error_title' => $title, |
||
185 | 'error_message' => $message, |
||
186 | )); |
||
187 | }); |
||
188 | |||
189 | // init mailer |
||
190 | $this->initMailer(); |
||
191 | |||
192 | // init doctrine orm |
||
193 | $this->initDoctrine(); |
||
194 | |||
195 | // init security |
||
196 | $this->initSecurity(); |
||
197 | |||
198 | // init ec-cube service provider |
||
199 | $this->register(new ServiceProvider\EccubeServiceProvider()); |
||
200 | |||
201 | // mount controllers |
||
202 | $this->register(new \Silex\Provider\ServiceControllerServiceProvider()); |
||
203 | $this->mount('', new ControllerProvider\FrontControllerProvider()); |
||
204 | $this->mount('/'.trim($this['config']['admin_route'], '/').'/', new ControllerProvider\AdminControllerProvider()); |
||
205 | Request::enableHttpMethodParameterOverride(); // PUTやDELETEできるようにする |
||
206 | 689 | } |
|
207 | |||
208 | 689 | public function initLocale() |
|
209 | { |
||
210 | |||
211 | // timezone |
||
212 | if (!empty($this['config']['timezone'])) { |
||
213 | date_default_timezone_set($this['config']['timezone']); |
||
214 | } |
||
215 | |||
216 | $this->register(new \Silex\Provider\TranslationServiceProvider(), array( |
||
217 | 689 | 'locale' => $this['config']['locale'], |
|
218 | )); |
||
219 | $this['translator'] = $this->share($this->extend('translator', function($translator, \Silex\Application $app) { |
||
220 | $translator->addLoader('yaml', new \Symfony\Component\Translation\Loader\YamlFileLoader()); |
||
221 | |||
222 | $r = new \ReflectionClass('Symfony\Component\Validator\Validator'); |
||
223 | $file = dirname($r->getFilename()).'/Resources/translations/validators.'.$app['locale'].'.xlf'; |
||
224 | if (file_exists($file)) { |
||
225 | $translator->addResource('xliff', $file, $app['locale'], 'validators'); |
||
226 | } |
||
227 | |||
228 | $file = __DIR__.'/Resource/locale/validator.'.$app['locale'].'.yml'; |
||
229 | if (file_exists($file)) { |
||
230 | $translator->addResource('yaml', $file, $app['locale'], 'validators'); |
||
231 | } |
||
232 | |||
233 | $file = __DIR__.'/Resource/locale/message.'.$app['locale'].'.yml'; |
||
234 | if (file_exists($file)) { |
||
235 | $translator->addResource('yaml', $file, $app['locale']); |
||
236 | } |
||
237 | |||
238 | 364 | return $translator; |
|
239 | })); |
||
240 | 689 | } |
|
241 | |||
242 | 689 | public function initSession() |
|
267 | |||
268 | 689 | public function initRendering() |
|
269 | { |
||
270 | $this->register(new \Silex\Provider\TwigServiceProvider(), array( |
||
271 | 'twig.form.templates' => array('Form/form_layout.twig'), |
||
272 | )); |
||
273 | $this['twig'] = $this->share($this->extend('twig', function(\Twig_Environment $twig, \Silex\Application $app) { |
||
274 | $twig->addExtension(new \Eccube\Twig\Extension\EccubeExtension($app)); |
||
275 | $twig->addExtension(new \Twig_Extension_StringLoader()); |
||
276 | |||
277 | 124 | return $twig; |
|
278 | })); |
||
279 | |||
280 | $this->before(function(Request $request, \Silex\Application $app) { |
||
281 | // フロント or 管理画面ごとにtwigの探索パスを切り替える. |
||
282 | $app['twig'] = $app->share($app->extend('twig', function(\Twig_Environment $twig, \Silex\Application $app) { |
||
283 | 95 | $paths = array(); |
|
284 | |||
285 | // 互換性がないのでprofiler とproduction 時のcacheを分離する |
||
286 | |||
287 | if (isset($app['profiler'])) { |
||
288 | $cacheBaseDir = __DIR__.'/../../app/cache/twig/profiler/'; |
||
289 | } else { |
||
290 | 95 | $cacheBaseDir = __DIR__.'/../../app/cache/twig/production/'; |
|
291 | } |
||
292 | if (strpos($app['request']->getPathInfo(), '/'.trim($app['config']['admin_route'], '/')) === 0) { |
||
293 | if (file_exists(__DIR__.'/../../app/template/admin')) { |
||
294 | 55 | $paths[] = __DIR__.'/../../app/template/admin'; |
|
295 | } |
||
296 | $paths[] = $app['config']['template_admin_realdir']; |
||
297 | 55 | $paths[] = __DIR__.'/../../app/Plugin'; |
|
298 | 55 | $cache = $cacheBaseDir.'admin'; |
|
299 | } else { |
||
300 | if (file_exists($app['config']['template_realdir'])) { |
||
301 | $paths[] = $app['config']['template_realdir']; |
||
302 | } |
||
303 | $paths[] = $app['config']['template_default_realdir']; |
||
304 | 40 | $paths[] = __DIR__.'/../../app/Plugin'; |
|
305 | $cache = $cacheBaseDir.$app['config']['template_code']; |
||
306 | 55 | } |
|
307 | $twig->setCache($cache); |
||
308 | $app['twig.loader']->addLoader(new \Twig_Loader_Filesystem($paths)); |
||
309 | |||
310 | 95 | return $twig; |
|
311 | })); |
||
312 | |||
313 | // 管理画面のIP制限チェック. |
||
314 | if (strpos($app['request']->getPathInfo(), '/'.trim($app['config']['admin_route'], '/')) === 0) { |
||
315 | // IP制限チェック |
||
316 | $allowHost = $app['config']['admin_allow_host']; |
||
317 | if (count($allowHost) > 0) { |
||
318 | if (array_search($app['request']->getClientIp(), $allowHost) === false) { |
||
319 | throw new \Exception(); |
||
320 | } |
||
321 | } |
||
322 | } |
||
323 | }, self::EARLY_EVENT); |
||
324 | |||
325 | // twigのグローバル変数を定義. |
||
326 | 689 | $app = $this; |
|
327 | $this->on(\Symfony\Component\HttpKernel\KernelEvents::CONTROLLER, function(\Symfony\Component\HttpKernel\Event\FilterControllerEvent $event) use ($app) { |
||
328 | // ショップ基本情報 |
||
329 | $BaseInfo = $app['eccube.repository.base_info']->get(); |
||
330 | $app['twig']->addGlobal('BaseInfo', $BaseInfo); |
||
331 | |||
332 | if (strpos($app['request']->getPathInfo(), '/'.trim($app['config']['admin_route'], '/')) === 0) { |
||
333 | // 管理画面 |
||
334 | // 管理画面メニュー |
||
335 | 55 | $menus = array('', '', ''); |
|
336 | $app['twig']->addGlobal('menus', $menus); |
||
337 | |||
338 | $Member = $app->user(); |
||
339 | if (is_object($Member)) { |
||
340 | // ログインしていれば管理者のロールを取得 |
||
341 | $AuthorityRoles = $app['eccube.repository.authority_role']->findBy(array('Authority' => $Member->getAuthority())); |
||
342 | |||
343 | 52 | $roles = array(); |
|
344 | foreach ($AuthorityRoles as $AuthorityRole) { |
||
345 | // 管理画面でメニュー制御するため相対パス全てをセット |
||
346 | $roles[] = $app['request']->getBaseUrl() . '/' . $app['config']['admin_route'] . $AuthorityRole->getDenyUrl(); |
||
347 | 52 | } |
|
348 | |||
349 | $app['twig']->addGlobal('AuthorityRoles', $roles); |
||
350 | } |
||
351 | |||
352 | } else { |
||
353 | // フロント画面 |
||
354 | $request = $event->getRequest(); |
||
355 | $route = $request->attributes->get('_route'); |
||
356 | |||
357 | // ユーザ作成画面 |
||
358 | if ($route === trim($app['config']['user_data_route'])) { |
||
359 | $params = $request->attributes->get('_route_params'); |
||
360 | $route = $params['route']; |
||
361 | // プレビュー画面 |
||
362 | } elseif ($request->get('preview')) { |
||
363 | $route = 'preview'; |
||
364 | } |
||
365 | |||
366 | try { |
||
367 | $DeviceType = $app['eccube.repository.master.device_type'] |
||
368 | ->find(\Eccube\Entity\Master\DeviceType::DEVICE_TYPE_PC); |
||
369 | $PageLayout = $app['eccube.repository.page_layout']->getByUrl($DeviceType, $route); |
||
370 | } catch (\Doctrine\ORM\NoResultException $e) { |
||
371 | $PageLayout = $app['eccube.repository.page_layout']->newPageLayout($DeviceType); |
||
372 | 19 | } |
|
373 | |||
374 | $app['twig']->addGlobal('PageLayout', $PageLayout); |
||
375 | $app['twig']->addGlobal('title', $PageLayout->getName()); |
||
376 | 55 | } |
|
377 | }); |
||
378 | 689 | } |
|
379 | |||
380 | 689 | public function initMailer() |
|
409 | |||
410 | 689 | public function initDoctrine() |
|
460 | |||
461 | 689 | public function initSecurity() |
|
561 | |||
562 | public function initializePlugin() |
||
570 | |||
571 | 449 | public function initPluginEventDispatcher() |
|
608 | |||
609 | public function loadPlugin() |
||
694 | } |
||
695 |