test Drupal site working on Koality Theme Builder
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

417 lines
12 KiB

4 years ago
  1. <?php
  2. namespace Drupal\koality_theme\Command;
  3. use Drupal\Console\Command\Shared\ArrayInputTrait;
  4. use Symfony\Component\Console\Input\InputInterface;
  5. use Symfony\Component\Console\Input\InputOption;
  6. use Symfony\Component\Console\Output\OutputInterface;
  7. use Drupal\Console\Command\Shared\ThemeRegionTrait;
  8. use Drupal\Console\Command\Shared\ThemeBreakpointTrait;
  9. use Drupal\Console\Command\Shared\ConfirmationTrait;
  10. use Drupal\Console\Core\Command\Command;
  11. use Drupal\Console\Extension\Manager;
  12. use Drupal\Console\Utils\Site;
  13. use Drupal\Console\Core\Utils\StringConverter;
  14. use Drupal\Console\Utils\Validator;
  15. use Drupal\Core\Extension\ThemeHandler;
  16. use Webmozart\PathUtil\Path;
  17. use Drupal\koality_theme\Generator\KoalityThemeGenerator;
  18. /**
  19. * Class GenerateThemeCommand.
  20. *
  21. * Drupal\Console\Annotations\DrupalCommand (
  22. * extension="koality_theme",
  23. * extensionType="module"
  24. * )
  25. */
  26. class GenerateThemeCommand extends Command {
  27. use ConfirmationTrait;
  28. use ThemeRegionTrait;
  29. use ThemeBreakpointTrait;
  30. use ArrayInputTrait;
  31. /**
  32. * @var Manager
  33. */
  34. protected $extensionManager;
  35. /**
  36. * @var KoalityThemeGenerator
  37. */
  38. protected $generator;
  39. /**
  40. * @var Validator
  41. */
  42. protected $validator;
  43. /**
  44. * @var string
  45. */
  46. protected $appRoot;
  47. /**
  48. * @var ThemeHandler
  49. */
  50. protected $themeHandler;
  51. /**
  52. * @var Site
  53. */
  54. protected $site;
  55. /**
  56. * @var StringConverter
  57. */
  58. protected $stringConverter;
  59. /**
  60. * ThemeCommand constructor.
  61. *
  62. * @param Manager $extensionManager
  63. * @param KoalityThemeGenerator $generator
  64. * @param Validator $validator
  65. * @param $appRoot
  66. * @param ThemeHandler $themeHandler
  67. * @param Site $site
  68. * @param StringConverter $stringConverter
  69. */
  70. public function __construct(
  71. Manager $extensionManager,
  72. KoalityThemeGenerator $generator,
  73. Validator $validator,
  74. $appRoot,
  75. ThemeHandler $themeHandler,
  76. Site $site,
  77. StringConverter $stringConverter
  78. ) {
  79. $this->extensionManager = $extensionManager;
  80. $this->generator = $generator;
  81. $this->validator = $validator;
  82. $this->appRoot = $appRoot;
  83. $this->themeHandler = $themeHandler;
  84. $this->site = $site;
  85. $this->stringConverter = $stringConverter;
  86. parent::__construct();
  87. }
  88. /**
  89. * {@inheritdoc}
  90. */
  91. protected function configure() {
  92. $this
  93. ->setName('koality_theme:generate')
  94. ->setDescription($this->trans('commands.generate.theme.description'))
  95. ->setHelp($this->trans('commands.generate.theme.help'))
  96. ->addOption(
  97. 'theme',
  98. NULL,
  99. InputOption::VALUE_REQUIRED,
  100. $this->trans('commands.generate.theme.options.theme')
  101. )
  102. ->addOption(
  103. 'machine-name',
  104. NULL,
  105. InputOption::VALUE_REQUIRED,
  106. $this->trans('commands.generate.theme.options.machine-name')
  107. )
  108. ->addOption(
  109. 'theme-path',
  110. NULL,
  111. InputOption::VALUE_REQUIRED,
  112. $this->trans('commands.generate.theme.options.theme-path')
  113. )
  114. ->addOption(
  115. 'description',
  116. NULL,
  117. InputOption::VALUE_OPTIONAL,
  118. $this->trans('commands.generate.theme.options.description')
  119. )
  120. ->addOption('core', NULL, InputOption::VALUE_OPTIONAL, $this->trans('commands.generate.theme.options.core'))
  121. ->addOption(
  122. 'package',
  123. NULL,
  124. InputOption::VALUE_OPTIONAL,
  125. $this->trans('commands.generate.theme.options.package')
  126. )
  127. ->addOption(
  128. 'global-library',
  129. NULL,
  130. InputOption::VALUE_OPTIONAL,
  131. $this->trans('commands.generate.theme.options.global-library')
  132. )
  133. ->addOption(
  134. 'libraries',
  135. NULL,
  136. InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
  137. $this->trans('commands.generate.theme.options.libraries')
  138. )
  139. ->addOption(
  140. 'base-theme',
  141. NULL,
  142. InputOption::VALUE_OPTIONAL,
  143. $this->trans('commands.generate.theme.options.base-theme')
  144. )
  145. ->addOption(
  146. 'base-theme-regions',
  147. NULL,
  148. InputOption::VALUE_NONE,
  149. $this->trans('commands.generate.theme.options.base-theme-regions')
  150. )
  151. ->addOption(
  152. 'regions',
  153. NULL,
  154. InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
  155. $this->trans('commands.generate.theme.options.regions')
  156. )
  157. ->addOption(
  158. 'breakpoints',
  159. NULL,
  160. InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
  161. $this->trans('commands.generate.theme.options.breakpoints')
  162. )
  163. ->setAliases(['gt']);
  164. }
  165. /**
  166. * {@inheritdoc}
  167. */
  168. protected function execute(InputInterface $input, OutputInterface $output) {
  169. // @see use Drupal\Console\Command\Shared\ConfirmationTrait::confirmOperation
  170. if (!$this->confirmOperation()) {
  171. return 1;
  172. }
  173. $theme = $this->validator->validateModuleName($input->getOption('theme'));
  174. // Get the profile path and define a profile path if it is null
  175. // Check that it is an absolute path or otherwise create an absolute path using appRoot
  176. $theme_path = $input->getOption('theme-path');
  177. if (is_null($theme_path)) {
  178. $uri = $this->site->getMultisiteName($input);
  179. $defaultThemePath = 'themes/custom';
  180. $theme_path = $this->site->multisiteMode($uri) ? 'sites/' . $this->site->getMultisiteDir($uri) . '/' . $defaultThemePath : $defaultThemePath;
  181. }
  182. $theme_path = Path::isAbsolute($theme_path) ? $theme_path : Path::makeAbsolute($theme_path, $this->appRoot);
  183. $theme_path = $this->validator->validateModulePath($theme_path, TRUE);
  184. $machine_name = $input->getOption('machine-name') ?
  185. $this->validator->validateMachineName($input->getOption('machine-name'))
  186. : $this->stringConverter->createMachineName($theme);
  187. $description = $input->getOption('description');
  188. $core = $input->getOption('core');
  189. $package = $input->getOption('package');
  190. $base_theme = $input->getOption('base-theme');
  191. $base_theme_regions = $input->getOption('base-theme-regions');
  192. $global_library = $input->getOption('global-library');
  193. $libraries = $input->getOption('libraries');
  194. $regions = $input->getOption('regions');
  195. $breakpoints = $input->getOption('breakpoints');
  196. $noInteraction = $input->getOption('no-interaction');
  197. // Parse nested data.
  198. if ($noInteraction) {
  199. $libraries = $this->explodeInlineArray($libraries);
  200. $regions = $this->explodeInlineArray($regions);
  201. $breakpoints = $this->explodeInlineArray($breakpoints);
  202. }
  203. $base_theme_path = $this->extensionManager->getTheme($base_theme);
  204. $this->generator->generate([
  205. 'theme' => $theme,
  206. 'machine_name' => $machine_name,
  207. 'dir' => $theme_path,
  208. 'core' => $core,
  209. 'description' => $description,
  210. 'package' => $package,
  211. 'base_theme' => $base_theme,
  212. 'base_theme_path' => is_null($base_theme_path) ? FALSE : $base_theme_path->getRealPath(),
  213. 'base_theme_regions' => $base_theme_regions,
  214. 'global_library' => $global_library,
  215. 'libraries' => $libraries,
  216. 'regions' => $regions,
  217. 'breakpoints' => $breakpoints,
  218. ]);
  219. return 0;
  220. }
  221. /**
  222. * {@inheritdoc}
  223. */
  224. protected function interact(InputInterface $input, OutputInterface $output) {
  225. try {
  226. $theme = $input->getOption('theme') ? $this->validator->validateModuleName($input->getOption('theme')) : NULL;
  227. } catch (\Exception $error) {
  228. $this->getIo()->error($error->getMessage());
  229. return 1;
  230. }
  231. if (!$theme) {
  232. $theme = $this->getIo()->ask(
  233. $this->trans('commands.generate.theme.questions.theme'),
  234. '',
  235. function ($theme) {
  236. return $this->validator->validateModuleName($theme);
  237. }
  238. );
  239. $input->setOption('theme', $theme);
  240. }
  241. try {
  242. $machine_name = $input->getOption('machine-name') ? $this->validator->validateModuleName($input->getOption('machine-name')) : NULL;
  243. } catch (\Exception $error) {
  244. $this->getIo()->error($error->getMessage());
  245. return 1;
  246. }
  247. if (!$machine_name) {
  248. $machine_name = $this->getIo()->ask(
  249. $this->trans('commands.generate.theme.questions.machine-name'),
  250. $this->stringConverter->createMachineName($theme),
  251. function ($machine_name) {
  252. return $this->validator->validateMachineName($machine_name);
  253. }
  254. );
  255. $input->setOption('machine-name', $machine_name);
  256. }
  257. $theme_path = $input->getOption('theme-path');
  258. if (!$theme_path) {
  259. $uri = $this->site->getMultisiteName($input);
  260. $defaultThemePath = 'themes/custom';
  261. $theme_path = $this->getIo()->ask(
  262. $this->trans('commands.generate.theme.questions.theme-path'),
  263. $this->site->multisiteMode($uri) ? 'sites/' . $this->site->getMultisiteDir($uri) . '/' . $defaultThemePath : $defaultThemePath,
  264. function ($theme_path) use ($machine_name) {
  265. $fullPath = Path::isAbsolute($theme_path) ? $theme_path : Path::makeAbsolute($theme_path, $this->appRoot);
  266. $fullPath = $fullPath . '/' . $machine_name;
  267. if (file_exists($fullPath)) {
  268. throw new \InvalidArgumentException(
  269. sprintf(
  270. $this->trans('commands.generate.theme.errors.directory-exists'),
  271. $fullPath
  272. )
  273. );
  274. }
  275. else {
  276. return $theme_path;
  277. }
  278. }
  279. );
  280. $input->setOption('theme-path', $theme_path);
  281. }
  282. $description = $input->getOption('description');
  283. if (!$description) {
  284. $description = $this->getIo()->ask(
  285. $this->trans('commands.generate.theme.questions.description'),
  286. $this->trans('commands.generate.theme.suggestions.my-awesome-theme')
  287. );
  288. $input->setOption('description', $description);
  289. }
  290. $package = $input->getOption('package');
  291. if (!$package) {
  292. $package = $this->getIo()->ask(
  293. $this->trans('commands.generate.theme.questions.package'),
  294. $this->trans('commands.generate.theme.suggestions.other')
  295. );
  296. $input->setOption('package', $package);
  297. }
  298. $core = $input->getOption('core');
  299. if (!$core) {
  300. $core = $this->getIo()->ask(
  301. $this->trans('commands.generate.theme.questions.core'),
  302. '8.x'
  303. );
  304. $input->setOption('core', $core);
  305. }
  306. $base_theme = $input->getOption('base-theme');
  307. if (!$base_theme) {
  308. $themes = $this->themeHandler->rebuildThemeData();
  309. $themes['false'] = '';
  310. uasort($themes, 'system_sort_modules_by_info_name');
  311. $base_theme = $this->getIo()->choiceNoList(
  312. $this->trans('commands.generate.theme.options.base-theme'),
  313. array_keys($themes)
  314. );
  315. $input->setOption('base-theme', $base_theme);
  316. }
  317. $global_library = $input->getOption('global-library');
  318. if (!$global_library) {
  319. $global_library = $this->getIo()->ask(
  320. $this->trans('commands.generate.theme.questions.global-library'),
  321. 'global-styling'
  322. );
  323. $input->setOption('global-library', $global_library);
  324. }
  325. // --libraries option.
  326. $libraries = $input->getOption('libraries');
  327. if (!$libraries) {
  328. if ($this->getIo()->confirm(
  329. $this->trans('commands.generate.theme.questions.library-add'),
  330. TRUE
  331. )
  332. ) {
  333. // @see \Drupal\Console\Command\Shared\ThemeRegionTrait::libraryQuestion
  334. $libraries = $this->libraryQuestion();
  335. }
  336. }
  337. else {
  338. $libraries = $this->explodeInlineArray($libraries);
  339. }
  340. $input->setOption('libraries', $libraries);
  341. // --regions option.
  342. $regions = $input->getOption('regions');
  343. if (!$regions) {
  344. if ($this->getIo()->confirm(
  345. $this->trans('commands.generate.theme.questions.regions'),
  346. TRUE
  347. )
  348. ) {
  349. // @see \Drupal\Console\Command\Shared\ThemeRegionTrait::regionQuestion
  350. $regions = $this->regionQuestion();
  351. }
  352. }
  353. else {
  354. $regions = $this->explodeInlineArray($regions);
  355. }
  356. $input->setOption('regions', $regions);
  357. // --breakpoints option.
  358. $breakpoints = $input->getOption('breakpoints');
  359. if (!$breakpoints) {
  360. if ($this->getIo()->confirm(
  361. $this->trans('commands.generate.theme.questions.breakpoints'),
  362. TRUE
  363. )
  364. ) {
  365. // @see \Drupal\Console\Command\Shared\ThemeRegionTrait::regionQuestion
  366. $breakpoints = $this->breakpointQuestion();
  367. }
  368. }
  369. else {
  370. $breakpoints = $this->explodeInlineArray($breakpoints);
  371. }
  372. $input->setOption('breakpoints', $breakpoints);
  373. }
  374. }