PageRenderTime 54ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/src/Command/CacheGenerateCommand.php

https://gitlab.com/snips3/rfpr
PHP | 289 lines | 227 code | 56 blank | 6 comment | 3 complexity | d1892e916629858b19486b9aaf787971 MD5 | raw file
  1. <?php
  2. namespace App\Command;
  3. use App\Domain\Category\Repository\CategoryRepository;
  4. use App\Domain\City\Entity\City;
  5. use App\Domain\City\Repository\CityRepository;
  6. use App\Domain\Product\Entity\Offer;
  7. use App\Domain\Product\Repository\ProductRepository;
  8. use App\Domain\Property\Entity\Property;
  9. use Doctrine\ORM\EntityManagerInterface;
  10. use Symfony\Component\Console\Command\Command;
  11. use Symfony\Component\Console\Helper\ProgressBar;
  12. use Symfony\Component\Console\Input\InputInterface;
  13. use Symfony\Component\Console\Output\ConsoleSectionOutput;
  14. use Symfony\Component\Console\Output\OutputInterface;
  15. use Symfony\Component\Console\Style\SymfonyStyle;
  16. class CacheGenerateCommand extends Command
  17. {
  18. protected static $defaultName = 'cache:generate';
  19. private EntityManagerInterface $entityManager;
  20. private CityRepository $cityRepository;
  21. private CategoryRepository $categoryRepository;
  22. private ProductRepository $productRepository;
  23. private string $path;
  24. private SymfonyStyle $io;
  25. private ProgressBar $memoryBar;
  26. public function __construct(
  27. EntityManagerInterface $entityManager,
  28. CityRepository $cityRepository,
  29. CategoryRepository $categoryRepository,
  30. ProductRepository $productRepository
  31. ) {
  32. parent::__construct();
  33. $this->entityManager = $entityManager;
  34. $this->cityRepository = $cityRepository;
  35. $this->categoryRepository = $categoryRepository;
  36. $this->productRepository = $productRepository;
  37. $this->path = implode('/', [__DIR__, '../..', 'var/cache/json/']);
  38. $this->makeDir($this->path);
  39. chdir($this->path);
  40. }
  41. private function makeDir($path): bool
  42. {
  43. return is_dir($path) || mkdir($path, 0775, true);
  44. }
  45. protected function configure()
  46. {
  47. $this
  48. ->setAliases(['c:g'])
  49. ->setDescription('Generate *.json files');
  50. }
  51. protected function execute(InputInterface $input, OutputInterface $output): int
  52. {
  53. ini_set('memory_limit', '1024M');
  54. $this->io = new SymfonyStyle($input, $output);
  55. /** @var OutputInterface $section */
  56. $section = $output->section('* Memory Usage');
  57. $section->writeln('<info>* Memory Usage</info>');
  58. $this->memoryBar = new ProgressBar($section, 1024);
  59. $this->memoryBar->setEmptyBarCharacter('░');
  60. $this->memoryBar->setProgressCharacter('');
  61. $this->memoryBar->setBarCharacter('▓');
  62. $this->jsonInit($output);
  63. $this->jsonCategoryProducts($output);
  64. $this->jsonCategoryFilters($output);
  65. return Command::SUCCESS;
  66. }
  67. private function jsonInit(OutputInterface $output): self
  68. {
  69. $section = $output->section('Menu');
  70. $section->writeln('<comment>* Menu & Cities</comment>');
  71. $cities = $this->entityManager->getRepository(City::class)->findAll();
  72. $categories = $this->categoryRepository->findBy(['active' => true]);
  73. $progressbar = $this->createProgressBar($section, count($cities));
  74. foreach ($cities as $city) {
  75. $this->trackMemory();
  76. $fileName = implode(
  77. '/',
  78. [
  79. $city->getDomain(),
  80. 'init.json',
  81. ]
  82. );
  83. $this->saveData(
  84. $fileName,
  85. [
  86. 'data' => [
  87. 'cities' => $cities,
  88. 'categories' => $categories
  89. ],
  90. ]
  91. );
  92. $progressbar->advance();
  93. }
  94. $this->entityManager->clear();
  95. $progressbar->finish();
  96. $this->trackMemory();
  97. return $this;
  98. }
  99. private function saveData(string $name, array $data): void
  100. {
  101. $e = explode('/', $name);
  102. if (count($e) > 1) {
  103. array_pop($e);
  104. array_unshift($e, $this->path);
  105. $path = implode('/', $e);
  106. if (!is_dir($path)) {
  107. mkdir($path, 0775, true);
  108. }
  109. }
  110. file_put_contents(
  111. $name,
  112. json_encode(
  113. $data,
  114. (JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT | JSON_UNESCAPED_UNICODE)
  115. )
  116. );
  117. // $this->print(new \SplFileInfo($name));
  118. }
  119. private function jsonCategoryProducts(OutputInterface $output): self
  120. {
  121. $section = $output->section('Categories');
  122. $section->writeln('');
  123. $section->writeln('<comment>* Category Products</comment>');
  124. $categories = $this->categoryRepository->findBy(['active' => true]);
  125. $this->trackMemory();
  126. $this->entityManager->clear();
  127. $this->trackMemory();
  128. $cities = $this->entityManager->getRepository(City::class)->findAll();
  129. $progressbar = $this->createProgressBar($section, (count($categories) * count($cities)));
  130. $offerRepository = $this->entityManager->getRepository(Offer::class);
  131. /** @var City $city */
  132. foreach ($cities as $city) {
  133. foreach ($categories as $category) {
  134. $fileName = implode(
  135. '/',
  136. [
  137. $city->getDomain(),
  138. 'category',
  139. $category->getId(),
  140. 'products.json',
  141. ]
  142. );
  143. $products = $offerRepository->getProductsWithOffersByCityAndCategory($city, $category);
  144. $this->saveData(
  145. $fileName,
  146. [
  147. 'total' => count($products),
  148. 'data' => $products,
  149. //'prices' => $products->getMinMaxPrices(),
  150. ]
  151. );
  152. $progressbar->advance();
  153. $this->trackMemory();
  154. }//end foreach
  155. }//end foreach
  156. $progressbar->finish();
  157. return $this;
  158. }
  159. private function jsonCategoryFilters(OutputInterface $output): self
  160. {
  161. $section = $output->section('Filters');
  162. $section->writeln('');
  163. $section->writeln('<comment>* Category Filters</comment>');
  164. $categories = $this->categoryRepository->findBy(['active' => true]);
  165. $cities = $this->cityRepository->findAll();
  166. $offerRepository = $this->entityManager->getRepository(Property::class);
  167. $total = (count($categories) * count($cities));
  168. $progressbar = $this->createProgressBar($section, $total);
  169. foreach ($cities as $city) {
  170. foreach ($categories as $category) {
  171. $fileName = implode('/', [$city->getDomain(), 'category', $category->getId(), 'filters.json']);
  172. $filters = $offerRepository->getFiltersBy($city, $category);
  173. $this->saveData($fileName, ['data' => $filters]);
  174. $this->trackMemory();
  175. $progressbar->advance();
  176. }
  177. }
  178. $progressbar->finish();
  179. return $this;
  180. }
  181. private function jsonCategorySorting(OutputInterface $output): self
  182. {
  183. $section = $output->section('Sorting');
  184. $section->writeln('');
  185. $section->writeln('<comment>* Category Sorting</comment>');
  186. $categories = $this->categoryRepository->findBy(['active' => true]);
  187. $this->trackMemory();
  188. $this->entityManager->clear();
  189. $this->trackMemory();
  190. $cities = $this->entityManager->getRepository(City::class)->findAll();
  191. $progressbar = $this->createProgressBar($section, (count($categories) * count($cities)));
  192. $offerRepository = $this->entityManager->getRepository(Offer::class);
  193. /** @var City $city */
  194. foreach ($cities as $city) {
  195. foreach ($categories as $category) {
  196. $fileName = implode(
  197. '/',
  198. [
  199. $city->getDomain(),
  200. 'category',
  201. $category->getId(),
  202. 'sorting.json',
  203. ]
  204. );
  205. $products = $offerRepository->getProductsWithOffersByCityAndCategory($city, $category);
  206. $this->saveData(
  207. $fileName,
  208. [
  209. 'total' => count($products),
  210. 'data' => $products,
  211. //'prices' => $products->getMinMaxPrices(),
  212. ]
  213. );
  214. $progressbar->advance();
  215. $this->trackMemory();
  216. }//end foreach
  217. }//end foreach
  218. $progressbar->finish();
  219. return $this;
  220. }
  221. private function trackMemory(): void
  222. {
  223. $this->memoryBar->setProgress(((int) memory_get_peak_usage(true) / 1024 / 1024));
  224. }
  225. private function createProgressBar(ConsoleSectionOutput $sectionOutput, $max = 0)
  226. {
  227. $progressBar = new ProgressBar($sectionOutput, $max);
  228. $progressBar->setEmptyBarCharacter('░');
  229. $progressBar->setProgressCharacter('');
  230. $progressBar->setBarCharacter('▓');
  231. return $progressBar;
  232. }
  233. }