protected function execute(InputInterface $input, OutputInterface $output) { $ctx = array(); $ctx['type'] = 'module'; $ctx['basedir'] = rtrim(getcwd(), '/'); $basedir = new Path($ctx['basedir']); $info = new Info($basedir->string('info.xml')); $info->load($ctx); $attrs = $info->get()->attributes(); if ($attrs['type'] != 'module') { $output->writeln('<error>Wrong extension type: ' . $attrs['type'] . '</error>'); return; } if (!preg_match('/^[A-Za-z0-9_]+$/', $input->getArgument('<CRM_Full_ClassName>'))) { throw new Exception("Class name must be alphanumeric (with underscores)"); } if (!preg_match('/Test$/', $input->getArgument('<CRM_Full_ClassName>'))) { throw new Exception("Class name must end with the word \"Test\""); } $ctx['testClass'] = $input->getArgument('<CRM_Full_ClassName>'); $ctx['testFile'] = strtr($ctx['testClass'], '_', '/') . '.php'; $ctx['testPath'] = $basedir->string('tests', 'phpunit', $ctx['testFile']); $dirs = new Dirs(array(dirname($ctx['testPath']))); $dirs->save($ctx, $output); if (!file_exists($ctx['testPath'])) { $output->writeln(sprintf('<info>Write %s</info>', $ctx['testPath'])); file_put_contents($ctx['testPath'], $this->getContainer()->get('templating')->render('CRMCivixBundle:Code:test.php.php', $ctx)); } else { $output->writeln(sprintf('<error>Skip %s: file already exists</error>', $ctx['testPath'])); } }
protected function execute(InputInterface $input, OutputInterface $output) { //// Figure out template data //// $ctx = array(); $ctx['type'] = 'module'; $ctx['basedir'] = rtrim(getcwd(), '/'); $basedir = new Path($ctx['basedir']); $info = new Info($basedir->string('info.xml')); $info->load($ctx); $attrs = $info->get()->attributes(); if ($attrs['type'] != 'module') { $output->writeln('<error>Wrong extension type: ' . $attrs['type'] . '</error>'); return; } $ctx['angularModuleName'] = $input->getOption('am') ? $input->getOption('am') : $ctx['mainFile']; $ctx['angularModulePhp'] = $basedir->string('ang', $ctx['angularModuleName'] . '.ang.php'); $ctx['angularModuleJs'] = $basedir->string('ang', $ctx['angularModuleName'] . '.js'); $ctx['angularModuleCss'] = $basedir->string('ang', $ctx['angularModuleName'] . '.css'); //// Construct files //// $output->writeln("<info>Initialize Angular module \"" . $ctx['angularModuleName'] . "\"</info>"); $ext = new Collection(); $ext->builders['dirs'] = new Dirs(array(dirname($ctx['angularModulePhp']), dirname($ctx['angularModuleJs']))); if (!file_exists($ctx['angularModulePhp'])) { $angModMeta = array('js' => array('ang/' . $ctx['angularModuleName'] . '.js', 'ang/' . $ctx['angularModuleName'] . '/*.js', 'ang/' . $ctx['angularModuleName'] . '/*/*.js'), 'css' => array('ang/' . $ctx['angularModuleName'] . '.css'), 'partials' => array('ang/' . $ctx['angularModuleName']), 'settings' => array()); $header = "// This file declares an Angular module which can be autoloaded\n" . "// in CiviCRM. See also:\n" . "// http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_angularModules\n"; $ext->builders['mgd.php'] = new PhpData($ctx['angularModulePhp'], $header); $ext->builders['mgd.php']->set($angModMeta); } $ext->builders['js'] = new Template('CRMCivixBundle:Code:angular-module.js.php', $ctx['angularModuleJs'], FALSE, $this->getContainer()->get('templating')); $ext->builders['css'] = new Template('CRMCivixBundle:Code:angular-module.css.php', $ctx['angularModuleCss'], FALSE, $this->getContainer()->get('templating')); $ext->init($ctx); $ext->save($ctx, $output); }
protected function execute(InputInterface $input, OutputInterface $output) { $ctx = array(); $ctx['type'] = 'module'; $ctx['basedir'] = rtrim(getcwd(), '/'); $basedir = new Path($ctx['basedir']); $info = new Info($basedir->string('info.xml')); $info->load($ctx); $attrs = $info->get()->attributes(); if ($attrs['type'] != 'module') { $output->writeln('<error>Wrong extension type: ' . $attrs['type'] . '</error>'); return; } $ctx['zipFile'] = $basedir->string('build', $ctx['fullName'] . '.zip'); $cmdArgs = array('-r', $ctx['zipFile'], $ctx['fullName'], '--exclude', 'build/*', '*~', '*.bak'); $cmd = 'zip ' . implode(' ', array_map('escapeshellarg', $cmdArgs)); chdir($basedir->string('..')); $process = new Process($cmd); $process->run(function ($type, $buffer) use($output) { $output->writeln($buffer); }); if (!$process->isSuccessful()) { throw new \RuntimeException('Failed to create zip'); } print $process->getOutput(); }
protected function execute(InputInterface $input, OutputInterface $output) { //// Figure out template data //// $ctx = array(); $ctx['type'] = 'module'; $ctx['basedir'] = rtrim(getcwd(), '/'); $basedir = new Path($ctx['basedir']); $info = new Info($basedir->string('info.xml')); $info->load($ctx); $attrs = $info->get()->attributes(); if ($attrs['type'] != 'module') { $output->writeln('<error>Wrong extension type: ' . $attrs['type'] . '</error>'); return; } $ctx['tsDomain'] = $ctx['mainFile']; $ctx['angularModuleName'] = $input->getOption('am') ? $input->getOption('am') : $ctx['mainFile']; $ctx['ctrlSuffix'] = $input->getArgument('<Ctrl>'); $ctx['ctrlRelPath'] = $input->getArgument('<RelPath>'); $ctx['ctrlName'] = ucwords($ctx['angularModuleName']) . $ctx['ctrlSuffix']; $ctx['jsPath'] = $basedir->string('ang', $ctx['angularModuleName'], $ctx['ctrlSuffix'] . '.js'); $ctx['htmlName'] = implode('/', array('~', $ctx['angularModuleName'], $ctx['ctrlSuffix'] . '.html')); $ctx['htmlPath'] = $basedir->string('ang', $ctx['angularModuleName'], $ctx['ctrlSuffix'] . '.html'); $ctx['hlpName'] = 'CRM' . '/' . $ctx['angularModuleName'] . '/' . $ctx['ctrlSuffix']; $ctx['hlpPath'] = $basedir->string('templates', $ctx['hlpName'] . '.hlp'); //// Construct files //// $output->writeln("<info>Initialize Angular page \"" . $ctx['ctrlName'] . "\" (civicrm/a/#/" . $ctx['ctrlRelPath'] . ")</info>"); $ext = new Collection(); $ext->builders['dirs'] = new Dirs(array(dirname($ctx['jsPath']), dirname($ctx['htmlPath']), dirname($ctx['hlpPath']))); $ext->builders['ctrl.js'] = new Template('CRMCivixBundle:Code:angular-page.js.php', $ctx['jsPath'], FALSE, $this->getContainer()->get('templating')); $ext->builders['html'] = new Template('CRMCivixBundle:Code:angular-page.html.php', $ctx['htmlPath'], FALSE, $this->getContainer()->get('templating')); $ext->builders['hlp'] = new Template('CRMCivixBundle:Code:angular-page.hlp.php', $ctx['hlpPath'], FALSE, $this->getContainer()->get('templating')); $ext->init($ctx); $ext->save($ctx, $output); }
protected function execute(InputInterface $input, OutputInterface $output) { //// Figure out template data and put it in $ctx //// $ctx = array(); $ctx['type'] = 'module'; $ctx['basedir'] = rtrim(getcwd(), '/'); $basedir = new Path($ctx['basedir']); $info = new Info($basedir->string('info.xml')); $info->load($ctx); $attrs = $info->get()->attributes(); if ($attrs['type'] != 'module') { $output->writeln('<error>Wrong extension type: ' . $attrs['type'] . '</error>'); return; } if (!in_array($input->getArgument('<CiviComponent>'), $this->getReportComponents())) { throw new \Exception("Component must be one of: " . implode(', ', $this->getReportComponents())); } $ctx['reportClassName'] = strtr($ctx['namespace'], '/', '_') . '_Form_Report_' . $input->getArgument('<ClassName>'); $ctx['reportClassFile'] = $basedir->string(strtr($ctx['reportClassName'], '_', '/') . '.php'); $ctx['reportMgdFile'] = $basedir->string(strtr($ctx['reportClassName'], '_', '/') . '.mgd.php'); $ctx['reportTplFile'] = $basedir->string('templates', strtr($ctx['reportClassName'], '_', '/') . '.tpl'); $webPath = $input->getOption('webPath'); if (!empty($webPath)) { if (preg_match('/^civicrm\\/report\\/(.+)$/', $webPath, $matches)) { $ctx['reportUrl'] = strtolower($matches[1]); } else { throw new \Exception("webPath must begin with \"civicrm/report/\""); } } else { $ctx['reportUrl'] = strtolower($ctx['fullName'] . '/' . $input->getArgument('<ClassName>')); } //// Construct files //// $output->writeln("<info>Initialize report " . $ctx['reportClassName'] . "</info>"); $ext = new Collection(); $ext->builders['dirs'] = new Dirs(array(dirname($ctx['reportClassFile']), dirname($ctx['reportMgdFile']), dirname($ctx['reportTplFile']))); // Register the report in the DB using api/v3/ReportTemplate and hook_civicrm_managed if (!file_exists($ctx['reportMgdFile'])) { $mgdEntities = array(array('name' => $ctx['reportClassName'], 'entity' => 'ReportTemplate', 'params' => array('version' => 3, 'label' => $input->getArgument('<ClassName>'), 'description' => sprintf("%s (%s)", $input->getArgument('<ClassName>'), $ctx['fullName']), 'class_name' => $ctx['reportClassName'], 'report_url' => $ctx['reportUrl'], 'component' => $input->getArgument('<CiviComponent>') == 'null' ? '' : $input->getArgument('<CiviComponent>')))); $header = "// This file declares a managed database record of type \"ReportTemplate\".\n" . "// The record will be automatically inserted, updated, or deleted from the\n" . "// database as appropriate. For more details, see \"hook_civicrm_managed\" at:\n" . "// http://wiki.civicrm.org/confluence/display/CRMDOC42/Hook+Reference"; $ext->builders['mgd.php'] = new PhpData($ctx['reportMgdFile'], $header); $ext->builders['mgd.php']->set($mgdEntities); } // Create .php & .tpl by either copying from core source tree or using a civix template if ($srcClassName = $input->getOption('copy')) { // To locate the original file, we need to bootstrap Civi and search the include path $civicrm_api3 = $this->getContainer()->get('civicrm_api3'); if (!$civicrm_api3 || !$civicrm_api3->local) { $output->writeln("<error>--copy requires access to local CiviCRM source tree. Configure civicrm_api3_conf_path.</error>"); return; } $origTplFile = 'templates/' . preg_replace('/_/', '/', $srcClassName) . '.tpl'; $ext->builders['report.php'] = new CopyClass($srcClassName, $ctx['reportClassName'], $ctx['reportClassFile'], FALSE); $ext->builders['page.tpl.php'] = new CopyFile($origTplFile, $ctx['reportTplFile'], FALSE); } else { $ext->builders['report.php'] = new Template('CRMCivixBundle:Code:report.php.php', $ctx['reportClassFile'], FALSE, $this->getContainer()->get('templating')); $ext->builders['page.tpl.php'] = new Template('CRMCivixBundle:Code:report.tpl.php', $ctx['reportTplFile'], FALSE, $this->getContainer()->get('templating')); } $ext->init($ctx); $ext->save($ctx, $output); }
function save(&$ctx, OutputInterface $output) { $basedir = new Path($ctx['basedir']); $module = new Template('CRMCivixBundle:Code:module.php.php', $basedir->string($ctx['mainFile'] . '.php'), 'ignore', $this->templateEngine); $module->save($ctx, $output); $moduleCivix = new Template('CRMCivixBundle:Code:module.civix.php.php', $basedir->string($ctx['mainFile'] . '.civix.php'), TRUE, $this->templateEngine); $moduleCivix->save($ctx, $output); }
protected function execute(InputInterface $input, OutputInterface $output) { //// Figure out template data //// $ctx = array(); $ctx['type'] = 'module'; $ctx['basedir'] = rtrim(getcwd(), '/'); $basedir = new Path($ctx['basedir']); $info = new Info($basedir->string('info.xml')); $info->load($ctx); $attrs = $info->get()->attributes(); if ($attrs['type'] != 'module') { $output->writeln('<error>Wrong extension type: ' . $attrs['type'] . '</error>'); return; } $ctx['searchClassName'] = strtr($ctx['namespace'], '/', '_') . '_Form_Search_' . $input->getArgument('<ClassName>'); $ctx['searchClassFile'] = $basedir->string(strtr($ctx['searchClassName'], '_', '/') . '.php'); $ctx['searchMgdFile'] = $basedir->string(strtr($ctx['searchClassName'], '_', '/') . '.mgd.php'); $ctx['searchTplRelFile'] = strtr($ctx['searchClassName'], '_', '/') . '.tpl'; $ctx['searchTplFile'] = $basedir->string('templates', $ctx['searchTplRelFile']); //// Construct files //// $output->writeln("<info>Initialize search " . $ctx['searchClassName'] . "</info>"); $ext = new Collection(); $ext->builders['dirs'] = new Dirs(array(dirname($ctx['searchClassFile']), dirname($ctx['searchMgdFile']))); if (!file_exists($ctx['searchMgdFile'])) { $mgdEntities = array(array('name' => $ctx['searchClassName'], 'entity' => 'CustomSearch', 'params' => array('version' => 3, 'label' => $input->getArgument('<ClassName>'), 'description' => sprintf("%s (%s)", $input->getArgument('<ClassName>'), $ctx['fullName']), 'class_name' => $ctx['searchClassName']))); $header = "// This file declares a managed database record of type \"CustomSearch\".\n" . "// The record will be automatically inserted, updated, or deleted from the\n" . "// database as appropriate. For more details, see \"hook_civicrm_managed\" at:\n" . "// http://wiki.civicrm.org/confluence/display/CRMDOC42/Hook+Reference"; $ext->builders['mgd.php'] = new PhpData($ctx['searchMgdFile'], $header); $ext->builders['mgd.php']->set($mgdEntities); } if ($srcClassName = $input->getOption('copy')) { // we need bootstrap to set up include path to locate file -- but that's it $civicrm_api3 = $this->getContainer()->get('civicrm_api3'); if (!$civicrm_api3 || !$civicrm_api3->local) { $output->writeln("<error>--copy requires access to local CiviCRM source tree. Configure civicrm_api3_conf_path.</error>"); return; } if (self::findTpl($srcClassName) == self::GENERIC_SEARCH_TEMPLATE) { $ext->builders['search.php'] = new CopyClass($srcClassName, $ctx['searchClassName'], $ctx['searchClassFile'], FALSE); } else { $ext->builders['dirs']->paths[] = dirname($ctx['searchTplFile']); $origTplFile = self::findTpl($srcClassName); $ext->builders['search.php'] = new CopyClass($srcClassName, $ctx['searchClassName'], $ctx['searchClassFile'], FALSE, function ($phpSrc) use($origTplFile, $ctx) { // i could wile away the hours // conferring with the flowers // consulting with the rain // if i only had a parser return strtr($phpSrc, array($origTplFile => $ctx['searchTplRelFile'])); }); $ext->builders['page.tpl.php'] = new CopyFile('templates/' . $origTplFile, $ctx['searchTplFile'], FALSE); } } else { $ext->builders['search.php'] = new Template('CRMCivixBundle:Code:search.php.php', $ctx['searchClassFile'], FALSE, $this->getContainer()->get('templating')); // $ext->builders['page.tpl.php'] = new Template('CRMCivixBundle:Code:search.tpl.php', $ctx['searchTplFile'], FALSE, $this->getContainer()->get('templating')); } $ext->init($ctx); $ext->save($ctx, $output); }
protected function execute(InputInterface $input, OutputInterface $output) { // TODO validate that hook_civicrm_upgrade has been implemented $ctx = array(); $ctx['type'] = 'module'; $ctx['basedir'] = rtrim(getcwd(), '/'); $basedir = new Path($ctx['basedir']); $info = new Info($basedir->string('info.xml')); $info->load($ctx); $attrs = $info->get()->attributes(); if ($attrs['type'] != 'module') { $output->writeln('<error>Wrong extension type: ' . $attrs['type'] . '</error>'); return; } $dirs = new Dirs(array($basedir->string('sql'), $basedir->string($ctx['namespace']), $basedir->string($ctx['namespace'], 'Upgrader'))); $dirs->save($ctx, $output); $phpFile = $basedir->string($ctx['namespace'], 'Upgrader.php'); if (!file_exists($phpFile)) { $output->writeln(sprintf('<info>Write %s</info>', $phpFile)); file_put_contents($phpFile, $this->getContainer()->get('templating')->render('CRMCivixBundle:Code:upgrader.php.php', $ctx)); } else { $output->writeln(sprintf('<error>Skip %s: file already exists, defer to customized version</error>', $phpFile)); } $phpFile = $basedir->string($ctx['namespace'], 'Upgrader', 'Base.php'); $output->writeln(sprintf('<info>Write %s</info>', $phpFile)); file_put_contents($phpFile, $this->getContainer()->get('templating')->render('CRMCivixBundle:Code:upgrader-base.php.php', $ctx)); $module = new Module($this->getContainer()->get('templating')); $module->loadInit($ctx); $module->save($ctx, $output); }
protected function execute(InputInterface $input, OutputInterface $output) { // load Civi to get access to civicrm_api_get_function_name $civicrm_api3 = $this->getContainer()->get('civicrm_api3'); if (!$civicrm_api3 || !$civicrm_api3->local) { $output->writeln("Requires access to local CiviCRM source tree. Configure civicrm_api3_conf_path.</error>"); return; } if (!preg_match('/^[A-Z][A-Za-z0-9_ \\.\\-]*$/', $input->getArgument('<Label>'))) { throw new Exception("Label should be valid"); } if (!$input->getArgument('<Name>')) { // $input->setArgument('<Name>', \CRM_Utils_String::munge(ucwords(str_replace('_', ' ', $input->getArgument('<Label>'))), '', 0)); $input->setArgument('<Name>', \CRM_Case_XMLProcessor::mungeCasetype($input->getArgument('<Label>'))); } if (!preg_match('/^[A-Z][A-Za-z0-9]*$/', $input->getArgument('<Name>'))) { throw new Exception("Name should be valid (alphanumeric beginning with uppercase)"); } $ctx = array(); $ctx['type'] = 'module'; $ctx['basedir'] = rtrim(getcwd(), '/'); $ctx['caseTypeLabel'] = $input->getArgument('<Label>'); $ctx['caseTypeName'] = $input->getArgument('<Name>'); $basedir = new Path($ctx['basedir']); $info = new Info($basedir->string('info.xml')); $info->load($ctx); $attrs = $info->get()->attributes(); if ($attrs['type'] != 'module') { $output->writeln('<error>Wrong extension type: ' . $attrs['type'] . '</error>'); return; } $dirs = new Dirs(array($basedir->string('xml', 'case'))); $dirs->save($ctx, $output); $xmlFile = $basedir->string('xml', 'case', $ctx['caseTypeName'] . '.xml'); if (!file_exists($xmlFile)) { $output->writeln(sprintf('<info>Write %s</info>', $xmlFile)); file_put_contents($xmlFile, $this->getContainer()->get('templating')->render('CRMCivixBundle:Code:case-type.xml.php', $ctx)); } else { $output->writeln(sprintf('<error>Skip %s: file already exists</error>', $xmlFile)); } $module = new Module($this->getContainer()->get('templating')); $module->loadInit($ctx); $module->save($ctx, $output); }
protected function execute(InputInterface $input, OutputInterface $output) { $ctx = array(); $ext = new Collection(); $output->writeln("<info></info>"); $basedir = new Path(getenv('HOME')); $ext->builders['dirs'] = new Dirs(array($basedir->string('.civix'))); $ext->builders['ini'] = new Ini($basedir->string('.civix', 'civix.ini')); $ext->loadInit($ctx); $data = $ext->builders['ini']->get(); if (!is_array($data)) { $data = array('parameters' => array()); } $data['parameters'][$input->getArgument('key')] = $input->getArgument('value'); $ext->builders['ini']->set($data); $ext->save($ctx, $output); \CRM\CivixBundle\Utils\Commands::createProcess('cache:clear --no-warmup')->run(function ($type, $buffer) { echo $buffer; }); }
protected function execute(InputInterface $input, OutputInterface $output) { // load Civi to get access to civicrm_api_get_function_name $civicrm_api3 = $this->getContainer()->get('civicrm_api3'); if (!$civicrm_api3 || !$civicrm_api3->local) { $output->writeln("<error>generate:custom-xml requires access to local CiviCRM instance. Configure civicrm_api3_conf_path.</error>"); return; } $ctx = array(); $ctx['type'] = 'module'; $ctx['basedir'] = rtrim(getcwd(), '/'); $basedir = new Path($ctx['basedir']); $info = new Info($basedir->string('info.xml')); $info->load($ctx); $attrs = $info->get()->attributes(); if ($attrs['type'] != 'module') { $output->writeln('<error>Wrong extension type: ' . $attrs['type'] . '</error>'); return; } $dirs = new Dirs(array($basedir->string('xml'))); $dirs->save($ctx, $output); if ($input->getArgument('<CustomDataFile.xml>')) { $customDataXMLFile = $basedir->string($input->getArgument('<CustomDataFile.xml>')); } else { $customDataXMLFile = $basedir->string('xml', 'auto_install.xml'); } if (!$input->getOption('data') && !$input->getOption('uf')) { $output->writeln("<error>generate:custom-xml requires --data and/or --uf</error>"); return; } $customDataXML = new CustomDataXML($input->getOption('data') ? explode(',', $input->getOption('data')) : array(), $input->getOption('uf') ? explode(',', $input->getOption('uf')) : array(), $customDataXMLFile, $input->getOption('force')); $customDataXML->save($ctx, $output); if (preg_match('/\\/xml\\/.*_install.xml$/', $customDataXMLFile)) { $output->writeln(" * NOTE: This filename ends with \"_install.xml\". If you would like to load it automatically on new sites, then make sure there is an install/upgrade class (i.e. run \"civix generate:upgrader\")"); } else { $output->writeln(" * NOTE: By default, this file will not be loaded automatically -- you must define installation or upgrade logic to load the file."); } }
protected function execute(InputInterface $input, OutputInterface $output) { // load Civi to get access to civicrm_api_get_function_name $civicrm_api3 = $this->getContainer()->get('civicrm_api3'); if (!$civicrm_api3 || !$civicrm_api3->local) { $output->writeln("<error>Require access to local CiviCRM source tree. Configure civicrm_api3_conf_path.</error>"); return; } $ctx = array(); $ctx['type'] = 'module'; $ctx['basedir'] = rtrim(getcwd(), '/'); $basedir = new Path($ctx['basedir']); $info = new Info($basedir->string('info.xml')); $info->load($ctx); $attrs = $info->get()->attributes(); if ($attrs['type'] != 'module') { $output->writeln('<error>Wrong extension type: ' . $attrs['type'] . '</error>'); return; } if (!preg_match('/^[A-Za-z0-9]+$/', $input->getArgument('<EntityName>'))) { throw new Exception("Entity name must be alphanumeric camel-case"); } $ctx['entityNameCamel'] = ucfirst($input->getArgument('<EntityName>')); $ctx['tableName'] = 'civicrm_' . strtolower($input->getArgument('<EntityName>')); if (function_exists('civicrm_api_get_function_name')) { $ctx['apiFunctionPrefix'] = strtolower(civicrm_api_get_function_name($ctx['entityNameCamel'], '', self::API_VERSION)); } elseif (function_exists('_civicrm_api_get_entity_name_from_camel')) { $ctx['apiFunctionPrefix'] = 'civicrm_api' . self::API_VERSION . '_' . _civicrm_api_get_entity_name_from_camel($ctx['entityNameCamel']) . '_' . $ctx['actionNameCamel']; } else { throw new Exception("Failed to determine proper API function name. Perhaps the API internals have changed?"); } $ctx['apiFile'] = $basedir->string('api', 'v3', $ctx['entityNameCamel'] . '.php'); $ctx['daoClassName'] = strtr($ctx['namespace'], '/', '_') . '_DAO_' . $input->getArgument('<EntityName>'); $ctx['daoClassFile'] = $basedir->string(strtr($ctx['daoClassName'], '_', '/') . '.php'); $ctx['baoClassName'] = strtr($ctx['namespace'], '/', '_') . '_BAO_' . $input->getArgument('<EntityName>'); $ctx['baoClassFile'] = $basedir->string(strtr($ctx['baoClassName'], '_', '/') . '.php'); $ctx['schemaFile'] = $basedir->string('xml', 'schema', $ctx['namespace'], $input->getArgument('<EntityName>') . '.xml'); $ctx['entityTypeFile'] = $basedir->string('xml', 'schema', $ctx['namespace'], $input->getArgument('<EntityName>') . '.entityType.php'); $ext = new Collection(); $ext->builders['dirs'] = new Dirs(array(dirname($ctx['apiFile']), dirname($ctx['daoClassFile']), dirname($ctx['baoClassFile']), dirname($ctx['schemaFile']))); $ext->builders['dirs']->save($ctx, $output); $ext->builders['api.php'] = new Template('CRMCivixBundle:Code:entity-api.php.php', $ctx['apiFile'], FALSE, $this->getContainer()->get('templating')); $ext->builders['bao.php'] = new Template('CRMCivixBundle:Code:entity-bao.php.php', $ctx['baoClassFile'], FALSE, $this->getContainer()->get('templating')); $ext->builders['entity.xml'] = new Template('CRMCivixBundle:Code:entity-schema.xml.php', $ctx['schemaFile'], FALSE, $this->getContainer()->get('templating')); if (!file_exists($ctx['entityTypeFile'])) { $mgdEntities = array(array('name' => $ctx['entityNameCamel'], 'class' => $ctx['daoClassName'], 'table' => $ctx['tableName'])); $header = "// This file declares a new entity type. For more details, see \"hook_civicrm_entityTypes\" at:\n" . "// http://wiki.civicrm.org/confluence/display/CRMDOC/Hook+Reference"; $ext->builders['entityType.php'] = new PhpData($ctx['entityTypeFile'], $header); $ext->builders['entityType.php']->set($mgdEntities); } $ext->init($ctx); $ext->save($ctx, $output); }
protected function execute(InputInterface $input, OutputInterface $output) { if (!preg_match('/^civicrm\\//', $input->getArgument('<web/path>'))) { throw new Exception("Web path must begin with 'civicrm/'"); } if (!preg_match('/^[A-Z][A-Za-z0-9_]*$/', $input->getArgument('<ClassName>'))) { throw new Exception("Class name should be valid (alphanumeric beginning with uppercase)"); } $ctx = array(); $ctx['type'] = 'module'; $ctx['basedir'] = rtrim(getcwd(), '/'); $ctx['shortClassName'] = $input->getArgument('<ClassName>'); $basedir = new Path($ctx['basedir']); $info = new Info($basedir->string('info.xml')); $info->load($ctx); $attrs = $info->get()->attributes(); if ($attrs['type'] != 'module') { $output->writeln('<error>Wrong extension type: ' . $attrs['type'] . '</error>'); return; } $ctx['fullClassName'] = $this->createClassName($input, $ctx); $phpFile = $basedir->string(str_replace('_', '/', $ctx['fullClassName']) . '.php'); $tplFile = $basedir->string('templates', $this->createTplName($input, $ctx)); if (preg_match('/^CRM_/', $input->getArgument('<ClassName>'))) { throw new Exception("Class name looks suspicious. Please note the final class would be \"{$ctx['fullClassName']}\""); } $dirs = new Dirs(array($basedir->string('xml', 'Menu'), dirname($phpFile), dirname($tplFile))); $dirs->save($ctx, $output); $menu = new Menu($basedir->string('xml', 'Menu', $ctx['mainFile'] . '.xml')); $menu->loadInit($ctx); if (!$menu->hasPath($input->getArgument('<web/path>'))) { $menu->addItem($ctx, $input->getArgument('<ClassName>'), $ctx['fullClassName'], $input->getArgument('<web/path>')); $menu->save($ctx, $output); } else { $output->writeln(sprintf('<error>Failed to bind %s to class %s; %s is already bound</error>', $input->getArgument('<web/path>'), $input->getArgument('<ClassName>'), $input->getArgument('<web/path>'))); } if (!file_exists($phpFile)) { $output->writeln(sprintf('<info>Write %s</info>', $phpFile)); file_put_contents($phpFile, $this->getContainer()->get('templating')->render($this->getPhpTemplate($input), $ctx)); } else { $output->writeln(sprintf('<error>Skip %s: file already exists</error>', $phpFile)); } if (!file_exists($tplFile)) { $output->writeln(sprintf('<info>Write %s</info>', $tplFile)); file_put_contents($tplFile, $this->getContainer()->get('templating')->render($this->getTplTemplate($input), $ctx)); } else { $output->writeln(sprintf('<error>Skip %s: file already exists</error>', $tplFile)); } $module = new Module($this->getContainer()->get('templating')); $module->loadInit($ctx); $module->save($ctx, $output); }
protected function execute(InputInterface $input, OutputInterface $output) { $ctx = array(); $ctx['type'] = 'report'; $ctx['typeInfo'] = array(); $ctx['fullName'] = $input->getArgument('<full.ext.name>'); $ctx['basedir'] = $ctx['fullName']; $ctx['reportClassName'] = preg_replace(':\\.:', '_', $ctx['fullName']); if (preg_match('/^[a-z0-9\\.]+\\.([a-z0-9]+)$/', $ctx['fullName'], $matches)) { $ctx['mainFile'] = $matches[1]; } else { $output->writeln('<error>Malformed package name</error>'); return; } if (in_array($input->getArgument('<CiviComponent>'), $this->getReportComponents())) { $ctx['typeInfo']['component'] = $input->getArgument('<CiviComponent>'); } else { throw new \Exception("Component must be one of: " . implode(', ', $this->getReportComponents())); } if (preg_match('/^civicrm\\/report\\/(.*)$/', $input->getOption('webPath'), $matches)) { $ctx['typeInfo']['reportUrl'] = $matches[1]; } else { $ctx['typeInfo']['reportUrl'] = $ctx['fullName']; } $ext = new Collection(); $output->writeln("<info>Initialize report " . $ctx['fullName'] . "</info>"); $basedir = new Path($ctx['basedir']); $ext->builders['dirs'] = new Dirs(array($basedir->string('build'), $basedir->string('templates'))); $ext->builders['info'] = new Info($basedir->string('info.xml')); $phpFile = $basedir->string($ctx['mainFile'] . '.php'); $tplFile = $basedir->string('templates', $ctx['mainFile'] . '.tpl'); if ($srcClassName = $input->getOption('copy')) { // we need bootstrap to set up include path to locate file -- but that's it $civicrm_api3 = $this->getContainer()->get('civicrm_api3'); if (!$civicrm_api3 || !$civicrm_api3->local) { $output->writeln("<error>--copy requires access to local CiviCRM source tree. Configure civicrm_api3_conf_path.</error>"); return; } $origTplFile = 'templates/' . preg_replace('/_/', '/', $srcClassName) . '.tpl'; $ext->builders['report.php'] = new CopyClass($srcClassName, $ctx['reportClassName'], $phpFile, FALSE); $ext->builders['page.tpl.php'] = new CopyFile($origTplFile, $tplFile, FALSE); } else { $ext->builders['report.php'] = new Template('CRMCivixBundle:Code:report.php.php', $phpFile, FALSE, $this->getContainer()->get('templating')); $ext->builders['page.tpl.php'] = new Template('CRMCivixBundle:Code:report.tpl.php', $tplFile, FALSE, $this->getContainer()->get('templating')); } $ext->init($ctx); $ext->save($ctx, $output); }
protected function execute(InputInterface $input, OutputInterface $output) { $licenses = new \LicenseData\Repository(); $ctx = array(); $ctx['type'] = 'module'; $ctx['fullName'] = $input->getArgument('<full.ext.name>'); $ctx['basedir'] = $ctx['fullName']; if (preg_match('/^[a-z0-9\\.]+\\.([a-z0-9]+)$/', $ctx['fullName'], $matches)) { $ctx['mainFile'] = $matches[1]; $ctx['namespace'] = 'CRM/' . strtoupper($ctx['mainFile'][0]) . substr($ctx['mainFile'], 1); } else { $output->writeln('<error>Malformed package name</error>'); return; } if ($input->getOption('author') && $input->getOption('email')) { $ctx['author'] = $input->getOption('author'); $ctx['email'] = $input->getOption('email'); } else { $output->writeln("<error>Missing author name or email address</error>"); $output->writeln("<error>Please pass --author and --email, or set defaults in ~/.gitconfig</error>"); return; } $ctx['license'] = $input->getOption('license'); if ($licenses->get($ctx['license'])) { $output->writeln(sprintf('<comment>License set to %s (authored by %s \\<%s>)</comment>', $ctx['license'], $ctx['author'], $ctx['email'])); $output->writeln('<comment>If this is in error, please correct info.xml and LICENSE.txt</comment>'); } else { $output->writeln('<error>Unrecognized license (' . $ctx['license'] . ')</error>'); return; } $ext = new Collection(); $output->writeln("<info>Initalize module " . $ctx['fullName'] . "</info>"); $basedir = new Path($ctx['basedir']); $ext->builders['dirs'] = new Dirs(array($basedir->string('build'), $basedir->string('templates'), $basedir->string('xml'), $basedir->string($ctx['namespace']))); $ext->builders['info'] = new Info($basedir->string('info.xml')); $ext->builders['module'] = new Module($this->getContainer()->get('templating')); $ext->builders['license'] = new License($licenses->get($ctx['license']), $basedir->string('LICENSE.txt'), FALSE); $ext->loadInit($ctx); $ext->save($ctx, $output); $this->tryEnable($input, $output, $ctx['fullName']); }
protected function execute(InputInterface $input, OutputInterface $output) { $basedir = new Path(getcwd()); // Find extension metadata $info = new Info($basedir->string('info.xml')); $info->load($ctx); if ($info->getType() != 'module') { $output->writeln('<error>Wrong extension type: ' . $attrs['type'] . '</error>'); return; } // Find the main phpunit $civicrm_api3 = $this->getContainer()->get('civicrm_api3'); if (!$civicrm_api3 || !$civicrm_api3->local) { $output->writeln("<error>'test' requires access to local CiviCRM source tree. Configure civicrm_api3_conf_path.</error>"); return; } global $civicrm_root; if (empty($civicrm_root) || !is_dir($civicrm_root)) { $output->writeln("<error>Failed to locate CiviCRM root path: {$civicrm_root}</error>"); return; } $phpunit_bin = "{$civicrm_root}/tools/scripts/phpunit"; if (!file_exists($phpunit_bin)) { $output->writeln("<error>Failed to locate PHPUnit:\n {$phpunit_bin}</error>"); $output->writeln("<error>Have you configured CiviCRM for testing? See also:\n http://wiki.civicrm.org/confluence/display/CRM/Setting+up+your+personal+testing+sandbox+HOWTO</error>"); return; } $test_settings_path = "{$civicrm_root}/tests/phpunit/CiviTest/civicrm.settings.php"; $test_settings_dist_path = "{$civicrm_root}/tests/phpunit/CiviTest/civicrm.settings.dist.php"; if (!file_exists($test_settings_path) && !file_exists($test_settings_dist_path)) { $output->writeln("<error>Failed to locate test settings:\n {$test_settings_path}</error>"); $output->writeln("<error>Have you configured CiviCRM for testing? See also:\n http://wiki.civicrm.org/confluence/display/CRM/Setting+up+your+personal+testing+sandbox+HOWTO</error>"); return; } if (file_exists($test_settings_path) && self::checkLegacyExtensionSettings($test_settings_path)) { $output->writeln("<comment>Warning: Possible conflicts in {$test_settings_path}</comment>"); $output->writeln("<comment>The following options may conflict with civix-based testing: 'ext_repo_url', 'extensionsDir', and/or 'extensionsURL'.</comment>"); } $phpunit_boot = $this->getBootstrapFile($info->getKey(), $input->getOption('clear')); if (empty($phpunit_boot) || !file_exists($phpunit_boot)) { $output->writeln("<error>Failed to create PHPUnit bootstrap file</error>"); return; } $tests_dir = implode(DIRECTORY_SEPARATOR, array(getcwd(), 'tests', 'phpunit')); // Prepare the command $command = array(); $command[] = $phpunit_bin; $command[] = '--include-path'; $command[] = $tests_dir; $command[] = '--bootstrap'; $command[] = $phpunit_boot; $command[] = '--colors'; if ($input->getOption('filter')) { $command[] = '--filter'; $command[] = $input->getOption('filter'); } if ($input->getOption('configuration')) { $command[] = '--configuration'; $command[] = $basedir->string('phpunit.xml'); } if ($input->getOption('debug')) { $command[] = '--debug'; } $command[] = $input->getArgument('<TestClass>'); // Run phpunit with our "tests" directory chdir("{$civicrm_root}/tools"); $process = new Process(call_user_func_array(array('\\CRM\\CivixBundle\\Command\\TestRunCommand', 'createPhpShellCommand'), $command), NULL, NULL, NULL, self::TIMEOUT); $process->run(function ($type, $buffer) use($output) { $output->write($buffer); }); $output->write("\n"); }
protected function execute(InputInterface $input, OutputInterface $output) { // load Civi to get access to civicrm_api_get_function_name $civicrm_api3 = $this->getContainer()->get('civicrm_api3'); if (!$civicrm_api3 || !$civicrm_api3->local) { $output->writeln("<error>--copy requires access to local CiviCRM source tree. Configure civicrm_api3_conf_path.</error>"); return; } $ctx = array(); $ctx['type'] = 'module'; $ctx['basedir'] = rtrim(getcwd(), '/'); $basedir = new Path($ctx['basedir']); $info = new Info($basedir->string('info.xml')); $info->load($ctx); $attrs = $info->get()->attributes(); if ($attrs['type'] != 'module') { $output->writeln('<error>Wrong extension type: ' . $attrs['type'] . '</error>'); return; } if (!preg_match('/^[A-Za-z0-9]+$/', $input->getArgument('<EntityName>'))) { throw new Exception("Entity name must be alphanumeric camel-case"); } if (!preg_match('/^[A-Za-z0-9]+$/', $input->getArgument('<ActionName>'))) { throw new Exception("Action name must be alphanumeric camel-case"); } if ($input->getOption('schedule') && !in_array($input->getOption('schedule'), self::getSchedules())) { throw new Exception("Schedule must be one of: " . implode(', ', self::getSchedules())); } $ctx['entityNameCamel'] = ucfirst($input->getArgument('<EntityName>')); $ctx['actionNameCamel'] = ucfirst($input->getArgument('<ActionName>')); if (function_exists('civicrm_api_get_function_name')) { $ctx['apiFunction'] = strtolower(civicrm_api_get_function_name($ctx['entityNameCamel'], $ctx['actionNameCamel'], self::API_VERSION)); } elseif (function_exists('_civicrm_api_get_entity_name_from_camel')) { $ctx['apiFunction'] = 'civicrm_api' . self::API_VERSION . '_' . _civicrm_api_get_entity_name_from_camel($ctx['entityNameCamel']) . '_' . $ctx['actionNameCamel']; } else { throw new Exception("Failed to determine proper API function name. Perhaps the API internals have changed?"); } $ctx['apiFile'] = $basedir->string('api', 'v3', $ctx['entityNameCamel'], $ctx['actionNameCamel'] . '.php'); $ctx['apiCronFile'] = $basedir->string('api', 'v3', $ctx['entityNameCamel'], $ctx['actionNameCamel'] . '.mgd.php'); $dirs = new Dirs(array(dirname($ctx['apiFile']))); $dirs->save($ctx, $output); if (!file_exists($ctx['apiFile'])) { $output->writeln(sprintf('<info>Write %s</info>', $ctx['apiFile'])); file_put_contents($ctx['apiFile'], $this->getContainer()->get('templating')->render('CRMCivixBundle:Code:api.php.php', $ctx)); } else { $output->writeln(sprintf('<error>Skip %s: file already exists</error>', $ctx['apiFile'])); } if ($input->getOption('schedule')) { if (!file_exists($ctx['apiCronFile'])) { $mgdEntities = array(array('name' => 'Cron:' . $ctx['entityNameCamel'] . '.' . $ctx['actionNameCamel'], 'entity' => 'Job', 'params' => array('version' => 3, 'name' => sprintf('Call %s.%s API', $ctx['entityNameCamel'], $ctx['actionNameCamel']), 'description' => sprintf('Call %s.%s API', $ctx['entityNameCamel'], $ctx['actionNameCamel']), 'run_frequency' => $input->getOption('schedule'), 'api_entity' => $ctx['entityNameCamel'], 'api_action' => $ctx['actionNameCamel'], 'parameters' => ''))); $header = "// This file declares a managed database record of type \"Job\".\n" . "// The record will be automatically inserted, updated, or deleted from the\n" . "// database as appropriate. For more details, see \"hook_civicrm_managed\" at:\n" . "// http://wiki.civicrm.org/confluence/display/CRMDOC42/Hook+Reference"; $mgdBuilder = new PhpData($ctx['apiCronFile'], $header); $mgdBuilder->set($mgdEntities); $mgdBuilder->save($ctx, $output); } else { $output->writeln(sprintf('<error>Skip %s: file already exists</error>', $ctx['apiCronFile'])); } } $module = new Module($this->getContainer()->get('templating')); $module->loadInit($ctx); $module->save($ctx, $output); }