These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Kunstmaan\DashboardBundle\Command; |
||
4 | |||
5 | use Kunstmaan\DashboardBundle\Command\Helper\Analytics\ChartDataCommandHelper; |
||
6 | use Kunstmaan\DashboardBundle\Command\Helper\Analytics\GoalCommandHelper; |
||
7 | use Kunstmaan\DashboardBundle\Command\Helper\Analytics\MetricsCommandHelper; |
||
8 | use Kunstmaan\DashboardBundle\Command\Helper\Analytics\UsersCommandHelper; |
||
9 | use Kunstmaan\DashboardBundle\Entity\AnalyticsOverview; |
||
10 | use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; |
||
11 | use Symfony\Component\Console\Input\InputInterface; |
||
12 | use Symfony\Component\Console\Input\InputOption; |
||
13 | use Symfony\Component\Console\Output\OutputInterface; |
||
14 | use Doctrine\ORM\EntityManagerInterface; |
||
15 | use Kunstmaan\DashboardBundle\Helper\Google\Analytics\ServiceHelper; |
||
16 | |||
17 | /** |
||
18 | * @final since 5.1 |
||
19 | * NEXT_MAJOR extend from `Command` and remove `$this->getContainer` usages |
||
20 | */ |
||
21 | class GoogleAnalyticsDataCollectCommand extends ContainerAwareCommand |
||
22 | { |
||
23 | /** @var EntityManagerInterface $em */ |
||
24 | private $em; |
||
25 | |||
26 | /** @var OutputInterface $output */ |
||
27 | private $output; |
||
28 | |||
29 | /** @var int $errors */ |
||
30 | private $errors = 0; |
||
31 | |||
32 | /** @var ServiceHelper */ |
||
33 | private $serviceHelper; |
||
34 | |||
35 | /** |
||
36 | * @param EntityManagerInterface|null $em |
||
37 | * @param ServiceHelper $serviceHelper |
||
38 | */ |
||
39 | View Code Duplication | public function __construct(/* EntityManagerInterface */ $em = null, ServiceHelper $serviceHelper = null) |
|
0 ignored issues
–
show
|
|||
40 | { |
||
41 | parent::__construct(); |
||
42 | |||
43 | if (!$em instanceof EntityManagerInterface) { |
||
44 | @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version symfony 3.4 and will be removed in symfony 4.0. If the command was registered by convention, make it a service instead. ', __METHOD__), E_USER_DEPRECATED); |
||
45 | |||
46 | $this->setName(null === $em ? 'kuma:dashboard:widget:googleanalytics:data:collect' : $em); |
||
47 | |||
48 | return; |
||
49 | } |
||
50 | |||
51 | $this->em = $em; |
||
52 | $this->serviceHelper = $serviceHelper; |
||
53 | } |
||
54 | |||
55 | /** |
||
56 | * Configures the current command. |
||
57 | */ |
||
58 | protected function configure() |
||
59 | { |
||
60 | $this |
||
61 | ->setName('kuma:dashboard:widget:googleanalytics:data:collect') |
||
62 | ->setDescription('Collect the Google Analytics dashboard widget data') |
||
63 | ->addOption( |
||
64 | 'config', |
||
65 | null, |
||
66 | InputOption::VALUE_OPTIONAL, |
||
67 | 'Specify to only update one config', |
||
68 | false |
||
69 | ) |
||
70 | ->addOption( |
||
71 | 'segment', |
||
72 | null, |
||
73 | InputOption::VALUE_OPTIONAL, |
||
74 | 'Specify to only update one segment', |
||
75 | false |
||
76 | ) |
||
77 | ->addOption( |
||
78 | 'overview', |
||
79 | null, |
||
80 | InputOption::VALUE_OPTIONAL, |
||
81 | 'Specify to only update one overview', |
||
82 | false |
||
83 | ); |
||
84 | } |
||
85 | |||
86 | /** |
||
87 | * @param InputInterface $input |
||
88 | * @param OutputInterface $output |
||
89 | * |
||
90 | * @return int|null|void |
||
91 | */ |
||
92 | protected function execute(InputInterface $input, OutputInterface $output) |
||
93 | { |
||
94 | if (null === $this->em) { |
||
95 | $this->em = $this->getContainer()->get('doctrine.orm.entity_manager'); |
||
96 | } |
||
97 | |||
98 | if (null === $this->serviceHelper) { |
||
99 | $this->serviceHelper = $this->getContainer()->get('kunstmaan_dashboard.helper.google.analytics.service'); |
||
100 | } |
||
101 | |||
102 | $this->output = $output; |
||
103 | |||
104 | // check if token is set |
||
105 | $configHelper = $this->getContainer()->get('kunstmaan_dashboard.helper.google.analytics.config'); |
||
106 | if (!$configHelper->tokenIsSet()) { |
||
107 | $this->output->writeln('You haven\'t configured a Google account yet'); |
||
108 | |||
109 | return; |
||
110 | } |
||
111 | |||
112 | // get params |
||
113 | $configId = false; |
||
114 | $segmentId = false; |
||
115 | $overviewId = false; |
||
116 | |||
117 | try { |
||
118 | $configId = $input->getOption('config'); |
||
119 | $segmentId = $input->getOption('segment'); |
||
120 | $overviewId = $input->getOption('overview'); |
||
121 | } catch (\Exception $e) { |
||
122 | } |
||
123 | |||
124 | // get the overviews |
||
125 | try { |
||
126 | $overviews = []; |
||
127 | |||
128 | if ($overviewId) { |
||
129 | $overviews[] = $this->getSingleOverview($overviewId); |
||
130 | } elseif ($segmentId) { |
||
131 | $overviews = $this->getOverviewsOfSegment($segmentId); |
||
132 | } elseif ($configId) { |
||
133 | $overviews = $this->getOverviewsOfConfig($configId); |
||
134 | } else { |
||
135 | $overviews = $this->getAllOverviews(); |
||
136 | } |
||
137 | |||
138 | // update the overviews |
||
139 | $this->updateData($overviews); |
||
140 | $result = '<fg=green>Google Analytics data updated with <fg=red>'.$this->errors.'</fg=red> error'; |
||
141 | $result .= $this->errors != 1 ? 's</fg=green>' : '</fg=green>'; |
||
142 | $this->output->writeln($result); // done |
||
143 | } catch (\Exception $e) { |
||
144 | $this->output->writeln($e->getMessage()); |
||
145 | } |
||
146 | } |
||
147 | |||
148 | /** |
||
149 | * get a single overview |
||
150 | * |
||
151 | * @param int $overviewId |
||
152 | * |
||
153 | * @return AnalyticsOverview |
||
154 | */ |
||
155 | private function getSingleOverview($overviewId) |
||
156 | { |
||
157 | // get specified overview |
||
158 | $overviewRepository = $this->em->getRepository('KunstmaanDashboardBundle:AnalyticsOverview'); |
||
159 | $overview = $overviewRepository->find($overviewId); |
||
160 | |||
161 | if (!$overview) { |
||
162 | throw new \Exception('Unkown overview ID'); |
||
163 | } |
||
164 | |||
165 | return $overview; |
||
166 | } |
||
167 | |||
168 | /** |
||
169 | * get all overviews of a segment |
||
170 | * |
||
171 | * @param int $segmentId |
||
172 | * |
||
173 | * @return array |
||
174 | */ |
||
175 | View Code Duplication | private function getOverviewsOfSegment($segmentId) |
|
176 | { |
||
177 | // get specified segment |
||
178 | $segmentRepository = $this->em->getRepository('KunstmaanDashboardBundle:AnalyticsSegment'); |
||
179 | $segment = $segmentRepository->find($segmentId); |
||
180 | |||
181 | if (!$segment) { |
||
182 | throw new \Exception('Unkown segment ID'); |
||
183 | } |
||
184 | |||
185 | // init the segment |
||
186 | $segmentRepository->initSegment($segment); |
||
187 | |||
188 | // get the overviews |
||
189 | return $segment->getOverviews(); |
||
190 | } |
||
191 | |||
192 | /** |
||
193 | * get all overviews of a config |
||
194 | * |
||
195 | * @param int $configId |
||
196 | * |
||
197 | * @return array |
||
198 | */ |
||
199 | private function getOverviewsOfConfig($configId) |
||
200 | { |
||
201 | $configRepository = $this->em->getRepository('KunstmaanDashboardBundle:AnalyticsConfig'); |
||
202 | $segmentRepository = $this->em->getRepository('KunstmaanDashboardBundle:AnalyticsSegment'); |
||
203 | $overviewRepository = $this->em->getRepository('KunstmaanDashboardBundle:AnalyticsOverview'); |
||
204 | // get specified config |
||
205 | $config = $configRepository->find($configId); |
||
206 | |||
207 | if (!$config) { |
||
208 | throw new \Exception('Unkown config ID'); |
||
209 | } |
||
210 | |||
211 | // create default overviews for this config if none exist yet |
||
212 | if (!count($config->getOverviews())) { |
||
213 | $overviewRepository->addOverviews($config); |
||
214 | } |
||
215 | |||
216 | // init all the segments for this config |
||
217 | $segments = $config->getSegments(); |
||
218 | foreach ($segments as $segment) { |
||
219 | $segmentRepository->initSegment($segment); |
||
220 | } |
||
221 | |||
222 | // get the overviews |
||
223 | return $config->getOverviews(); |
||
224 | } |
||
225 | |||
226 | /** |
||
227 | * get all overviews |
||
228 | * |
||
229 | * @return array |
||
230 | */ |
||
231 | View Code Duplication | private function getAllOverviews() |
|
232 | { |
||
233 | $configRepository = $this->em->getRepository('KunstmaanDashboardBundle:AnalyticsConfig'); |
||
234 | $overviewRepository = $this->em->getRepository('KunstmaanDashboardBundle:AnalyticsOverview'); |
||
235 | $segmentRepository = $this->em->getRepository('KunstmaanDashboardBundle:AnalyticsSegment'); |
||
236 | $configs = $configRepository->findAll(); |
||
237 | |||
238 | foreach ($configs as $config) { |
||
239 | // add overviews if none exist yet |
||
240 | if (count($config->getOverviews()) == 0) { |
||
241 | $overviewRepository->addOverviews($config); |
||
242 | } |
||
243 | |||
244 | // init all the segments for this config |
||
245 | $segments = $config->getSegments(); |
||
246 | foreach ($segments as $segment) { |
||
247 | $segmentRepository->initSegment($segment); |
||
248 | } |
||
249 | } |
||
250 | |||
251 | // get all overviews |
||
252 | return $overviewRepository->findAll(); |
||
253 | } |
||
254 | |||
255 | /** |
||
256 | * update the overviews |
||
257 | * |
||
258 | * @param array $overviews collection of all overviews which need to be updated |
||
259 | */ |
||
260 | public function updateData($overviews) |
||
261 | { |
||
262 | // helpers |
||
263 | $queryHelper = $this->getContainer()->get('kunstmaan_dashboard.helper.google.analytics.query'); |
||
264 | $configHelper = $this->getContainer()->get('kunstmaan_dashboard.helper.google.analytics.config'); |
||
265 | $metrics = new MetricsCommandHelper($configHelper, $queryHelper, $this->output, $this->em); |
||
266 | $chartData = new ChartDataCommandHelper($configHelper, $queryHelper, $this->output, $this->em); |
||
267 | $goals = new GoalCommandHelper($configHelper, $queryHelper, $this->output, $this->em); |
||
268 | $visitors = new UsersCommandHelper($configHelper, $queryHelper, $this->output, $this->em); |
||
269 | |||
270 | // get data per overview |
||
271 | foreach ($overviews as $overview) { |
||
272 | $configHelper->init($overview->getConfig()->getId()); |
||
273 | /* @var AnalyticsOverview $overview */ |
||
274 | $this->output->writeln('Fetching data for overview "<fg=green>' . $overview->getTitle() . '</fg=green>"'); |
||
275 | |||
276 | try { |
||
277 | // metric data |
||
278 | $metrics->getData($overview); |
||
279 | if ($overview->getSessions()) { // if there are any visits |
||
280 | // day-specific data |
||
281 | $chartData->getData($overview); |
||
282 | |||
283 | // get goals |
||
284 | $goals->getData($overview); |
||
285 | |||
286 | // visitor types |
||
287 | $visitors->getData($overview); |
||
288 | } else { |
||
289 | // reset overview |
||
290 | $this->reset($overview); |
||
291 | $this->output->writeln("\t" . 'No visitors'); |
||
292 | } |
||
293 | // persist entity back to DB |
||
294 | $this->output->writeln("\t" . 'Persisting..'); |
||
295 | $this->em->persist($overview); |
||
296 | $this->em->flush($overview); |
||
297 | |||
298 | $this->em->getRepository('KunstmaanDashboardBundle:AnalyticsConfig')->setUpdated($overview->getConfig()->getId()); |
||
299 | } catch (\Google_ServiceException $e) { |
||
300 | $error = explode(')', $e->getMessage()); |
||
301 | $error = $error[1]; |
||
302 | $this->output->writeln("\t" . '<fg=red>Invalid segment: </fg=red>' .$error); |
||
303 | $this->errors += 1; |
||
304 | } |
||
305 | } |
||
306 | } |
||
307 | |||
308 | /** |
||
309 | * Reset the data for the overview |
||
310 | * |
||
311 | * @param AnalyticsOverview $overview The overview |
||
312 | */ |
||
313 | private function reset(AnalyticsOverview $overview) |
||
314 | { |
||
315 | // reset overview |
||
316 | $overview->setNewUsers(0); |
||
317 | $overview->setReturningUsers(0); |
||
318 | } |
||
319 | } |
||
320 |
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.