');
39 |
40 | // Boot CiviCRM to use api4
41 | Civix::boot(['output' => $output]);
42 |
43 | $gen = \Civix::generator();
44 | $gen->addMixins(['mgd-php@1.0']);
45 | if ($entityName === 'Afform') {
46 | $gen->exportAfform($entityId);
47 | }
48 | else {
49 | $gen->exportMgd($entityName, $entityId);
50 | }
51 |
52 | return 0;
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Command/AddPageCommand.php:
--------------------------------------------------------------------------------
1 | setName('generate:page')
12 | ->setDescription('Add a basic web page to a CiviCRM Module-Extension');
13 | }
14 |
15 | protected function getPhpTemplate(InputInterface $input) {
16 | return 'page.php.php';
17 | }
18 |
19 | protected function getTplTemplate(InputInterface $input) {
20 | return 'page.tpl.php';
21 | }
22 |
23 | protected function createClassName(InputInterface $input, $ctx) {
24 | $namespace = str_replace('/', '_', $ctx['namespace']);
25 | return $namespace . '_Page_' . $ctx['shortClassName'];
26 | }
27 |
28 | protected function createTplName(InputInterface $input, $ctx) {
29 | return $ctx['namespace'] . '/Page/' . $ctx['shortClassName'] . '.tpl';
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Command/AddServiceCommand.php:
--------------------------------------------------------------------------------
1 | setName('generate:service')
18 | ->setDescription('Create a new service')
19 | ->addArgument('name', InputArgument::OPTIONAL, 'Machine-name for the service')
20 | ->addOption('naming', NULL, InputOption::VALUE_OPTIONAL, 'Force the service-class to use CRM- or Civi-style naming', 'auto')
21 | ->setHelp('');
22 | parent::configure();
23 | }
24 |
25 | protected function execute(InputInterface $input, OutputInterface $output): int {
26 | $gen = \Civix::generator();
27 | $gen->addMixins(['scan-classes@1.0']);
28 |
29 | $servicePrefix = $gen->infoXml->getFile();
30 | $namespace = Naming::coerceNamespace($gen->infoXml->getNamespace(), $input->getOption('naming'));
31 |
32 | if ($input->isInteractive()) {
33 | $defaultName = $input->getArgument('name') ?? Naming::createServiceName($servicePrefix, 'myService');
34 | Civix::io()->note([
35 | 'The service name is a short machine name. It may appear in contexts like:',
36 | sprintf('Civi::service("%s")->doSomething()', $defaultName),
37 | sprintf('It is recommended to always have a naming prefix (such as "%s").', $servicePrefix),
38 | ]);
39 | $serviceName = Civix::io()->ask('Service name', $defaultName, function ($answer) {
40 | if ('' === trim($answer)) {
41 | throw new \Exception('Service name cannot be empty');
42 | }
43 | return $answer;
44 | });
45 | }
46 | else {
47 | $serviceName = $input->getArgument('name');
48 | if ('' === trim($serviceName)) {
49 | throw new \Exception('Service name cannot be empty');
50 | }
51 | }
52 |
53 | $baseName = Naming::removeServicePrefix($servicePrefix, $serviceName);
54 | $baseNameParts = array_map('ucfirst', explode('.', $baseName));
55 | $className = Naming::createClassName($namespace, ...$baseNameParts);
56 |
57 | $gen->addClass($className, 'service.php.php', [
58 | 'service' => $serviceName,
59 | ], 'ask');
60 |
61 | return 0;
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Command/AddUpgraderCommand.php:
--------------------------------------------------------------------------------
1 | setName('generate:upgrader')
14 | ->setDescription('Add an example upgrader class to a CiviCRM Module-Extension');
15 | }
16 |
17 | protected function execute(InputInterface $input, OutputInterface $output): int {
18 | $this->assertCurrentFormat();
19 | Civix::generator()->addUpgrader('if-forced');
20 | return 0;
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Command/BuildCommand.php:
--------------------------------------------------------------------------------
1 | setName('build:zip')
16 | ->setDescription('Build a zip file for a CiviCRM Extension');
17 | }
18 |
19 | protected function execute(InputInterface $input, OutputInterface $output): int {
20 | $this->assertCurrentFormat();
21 |
22 | $ctx = [];
23 | $ctx['type'] = 'module';
24 | $ctx['basedir'] = \CRM\CivixBundle\Application::findExtDir();
25 | $basedir = new Path($ctx['basedir']);
26 |
27 | $info = new Info($basedir->string('info.xml'));
28 | $info->load($ctx);
29 |
30 | $ctx['zipFile'] = $basedir->string('build', $ctx['fullName'] . '.zip');
31 | $cmdArgs = [
32 | '-r',
33 | $ctx['zipFile'],
34 | $ctx['fullName'],
35 | '--exclude',
36 | 'build/*',
37 | '*~',
38 | '*.bak',
39 | '*.git*',
40 | ];
41 | $cmd = 'zip ' . implode(' ', array_map('escapeshellarg', $cmdArgs));
42 |
43 | chdir($basedir->string('..'));
44 | $process = new Process($cmd);
45 | $process->run(function ($type, $buffer) use ($output) {
46 | $output->writeln($buffer);
47 | });
48 | if (!$process->isSuccessful()) {
49 | throw new \RuntimeException('Failed to create zip');
50 | }
51 | print $process->getOutput();
52 | return 0;
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Command/ConfigGetCommand.php:
--------------------------------------------------------------------------------
1 | setName('config:get')
15 | ->setDescription('Get configuration values')
16 | ->addArgument('parameter', InputArgument::OPTIONAL, 'Parameter name');
17 | }
18 |
19 | protected function execute(InputInterface $input, OutputInterface $output): int {
20 | $config = Civix::config();
21 | foreach ($this->getInterestingParameters() as $key) {
22 | printf("%-40s \"%s\"\n", $key, @$config['parameters'][$key]);
23 | }
24 | return 0;
25 | }
26 |
27 | protected function getInterestingParameters() {
28 | return [
29 | 'author',
30 | 'email',
31 | 'license',
32 | ];
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Command/ConfigSetCommand.php:
--------------------------------------------------------------------------------
1 | setName('config:set')
17 | ->setDescription('Set configuration value')
18 | ->addArgument('key', InputArgument::REQUIRED, 'Parameter name')
19 | ->addArgument('value', InputArgument::REQUIRED, 'Parameter value');
20 | }
21 |
22 | protected function execute(InputInterface $input, OutputInterface $output): int {
23 | $ctx = [];
24 | $ext = new Collection();
25 |
26 | $output->writeln("");
27 | $configDir = Civix::configDir();
28 | $configDir->mkdir();
29 | $ext->builders['ini'] = new Ini($configDir->string('civix.ini'));
30 |
31 | $ext->loadInit($ctx);
32 | $data = $ext->builders['ini']->get();
33 | if (!is_array($data)) {
34 | $data = ['parameters' => []];
35 | }
36 | $data['parameters'][$input->getArgument('key')] = $input->getArgument('value');
37 | $ext->builders['ini']->set($data);
38 | $ext->save($ctx, $output);
39 | return 0;
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Command/InfoGetCommand.php:
--------------------------------------------------------------------------------
1 | setName('info:get')
32 | ->setDescription('Read a field from the info.xml file')
33 | ->addOption('xpath', 'x', InputOption::VALUE_REQUIRED, '(REQUIRED) The XPath expression of the field')
34 | ->setHelp("Read a single field from the info.xml file.
35 |
36 | Examples:
37 | civix info:get -x version
38 | civix info:get -x maintainer/author
39 | civix info:get -x maintainer/email
40 |
41 | Common fields:\n * " . implode("\n * ", $fields) . "\n");
42 | }
43 |
44 | protected function execute(InputInterface $input, OutputInterface $output): int {
45 | $basedir = new Path(\CRM\CivixBundle\Application::findExtDir());
46 | $info = new Info($basedir->string('info.xml'));
47 | $ctx = [];
48 | $info->load($ctx);
49 | $info->get();
50 |
51 | $xpath = $input->getOption('xpath');
52 | if (is_null($xpath)) {
53 | // missing xpath value so provide help
54 | $help = $this->getApplication()->get('help');
55 | // tell help to provide specific help for this function
56 | $help->setCommand($this);
57 | return $help->run($input, $output);
58 | }
59 | foreach ($info->get()->xpath($xpath) as $node) {
60 | $output->writeln((string) $node, OutputInterface::OUTPUT_RAW);
61 | }
62 |
63 | return 0;
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Command/InfoSetCommand.php:
--------------------------------------------------------------------------------
1 | setName('info:set')
32 | ->setDescription('Set a field in the info.xml file')
33 | ->addOption('xpath', 'x', InputOption::VALUE_REQUIRED, 'The XPath expression to search on')
34 | ->addOption('to', 't', InputOption::VALUE_REQUIRED, 'The value of the field')
35 | ->setHelp("Set a single field in the info.xml file.
36 |
37 | Examples:
38 | civix info:set -x version --to 2.0.0
39 | civix info:set -x maintainer/author --to 'Frank Lloyd Wright'
40 | civix info:set -x maintainer/email --to 'flloyd@example.com'
41 |
42 | Common fields:
43 | * " . implode("\n * ", $fields) . "\n");
44 | }
45 |
46 | protected function execute(InputInterface $input, OutputInterface $output): int {
47 | $basedir = new Path(\CRM\CivixBundle\Application::findExtDir());
48 | $info = new Info($basedir->string('info.xml'));
49 | $ctx = [];
50 | $info->load($ctx);
51 | $info->get();
52 |
53 | $elements = $info->get()->xpath($input->getOption('xpath'));
54 | if (empty($elements)) {
55 | $output->writeln("Error: Path (" . $input->getOption('xpath') . ") did not match any elements.");
56 | return 1;
57 | }
58 | foreach ($elements as $element) {
59 | $element[0] = $input->getOption('to');
60 | }
61 |
62 | $info->save($ctx, $output);
63 | return 0;
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Command/Mgd.php:
--------------------------------------------------------------------------------
1 | ['module', 'name', 'id'],
13 | 'where' => [
14 | ['entity_type', '=', $entityName],
15 | ['entity_id', '=', $id],
16 | ],
17 | 'checkPermissions' => FALSE,
18 | ])->first();
19 | if ($existingMgd) {
20 | if ($existingMgd['module'] !== $extKey || $existingMgd['name'] !== $managedName) {
21 | $io->warning([
22 | sprintf("Requested entity (%s) is already managed by \"%s\" (#%s). Adding new entity \"%s\" would create conflict.",
23 | "$entityName $id",
24 | $existingMgd['module'] . ':' . $existingMgd['name'],
25 | $existingMgd['id'],
26 | "$extKey:$managedName"
27 | ),
28 | ]);
29 | }
30 | if (!file_exists($managedFileName)) {
31 | $io->warning([
32 | sprintf('The managed entity (%s) already exists in the database, but the expected file (%s) does not exist.',
33 | "$extKey:$managedName",
34 | Files::relativize($managedFileName, \CRM\CivixBundle\Application::findExtDir())
35 | ),
36 | 'The new file will be created, but you may have a conflict within this extension.',
37 | ]);
38 | }
39 | }
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Command/PingCommand.php:
--------------------------------------------------------------------------------
1 | setName('civicrm:ping')
14 | ->setDescription('Test whether the CiviCRM client is properly configured');
15 | }
16 |
17 | protected function execute(InputInterface $input, OutputInterface $output): int {
18 | Civix::boot(['output' => $output]);
19 | $civicrm_api3 = Civix::api3();
20 | if ($civicrm_api3->Contact->Get(['option.limit' => 1])) {
21 | if (empty($civicrm_api3->result->values[0]->contact_type)) {
22 | $output->writeln('Ping failed: Site reported that it found no contacts');
23 | }
24 | else {
25 | $output->writeln('Ping successful');
26 | }
27 | }
28 | else {
29 | $output->writeln('Ping failed: API Error: ' . $civicrm_api3->errorMsg() . '');
30 | }
31 | return 0;
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/ComposerCompile.php:
--------------------------------------------------------------------------------
1 | $mixin) {
24 | $checksum = file_exists($mixin['local']) ? hash('sha256', file_get_contents($mixin['local'])) : '';
25 |
26 | if (!file_exists($mixin['local']) || $checksum !== $mixin['sha256']) {
27 | printf(" - Download %s\n", $mixin['local']);
28 | $content = file_get_contents($mixin['remote']);
29 | $contentChecksum = hash('sha256', $content);
30 | if ($contentChecksum !== $mixin['sha256']) {
31 | throw new \RuntimeException("Download from {$mixin['remote']} has wrong checksum. (expect={$mixin['sha256']}, actual=$contentChecksum)");
32 | }
33 |
34 | static::putFile($mixin['local'], $content);
35 | }
36 | }
37 | }
38 |
39 | protected static function putFile(string $path, string $content): void {
40 | $outDir = dirname($path);
41 | if (!is_dir($outDir)) {
42 | if (!mkdir($outDir, 0777, TRUE)) {
43 | throw new \RuntimeException("Failed to make dir: $outDir");
44 | }
45 | }
46 | if (FALSE === file_put_contents($path, $content)) {
47 | throw new \RuntimeException("Failed to write file: $path");
48 | }
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Parse/ParseException.php:
--------------------------------------------------------------------------------
1 | typeId = $typeId;
30 | $this->value = $value;
31 | }
32 |
33 | protected $typeId;
34 | protected $value;
35 |
36 | /**
37 | * Get ID code of the token type.
38 | *
39 | * @return int
40 | * Ex: T_FUNCTION, T_WHITESPACE, TX_RAW
41 | */
42 | public function typeId(): int {
43 | return $this->typeId;
44 | }
45 |
46 | /**
47 | * Get symbolic name of the token type.
48 | *
49 | * @return string
50 | * Ex: 'T_FUNCTION', 'T_WHITESPACE_', 'TX_RAW'
51 | */
52 | public function name(): string {
53 | if ($this->typeId === TX_RAW) {
54 | return 'TX_RAW';
55 | }
56 | else {
57 | return token_name($this->typeId);
58 | }
59 | }
60 |
61 | /**
62 | * Get literal value of token.
63 | *
64 | * @return string
65 | */
66 | public function value(): string {
67 | return $this->value;
68 | }
69 |
70 | /**
71 | * Check if the token matches an expectation
72 | *
73 | * @param $expect
74 | * One of:
75 | * - Integer: The token-type ID
76 | * - String: The raw value of the token
77 | * - Array: List of strings or integers; any one to match
78 | * @return bool
79 | */
80 | public function is($expect): bool {
81 | if ($expect === NULL) {
82 | return TRUE; /* wildcard */
83 | }
84 | if (is_array($expect)) {
85 | foreach ($expect as $expectOption) {
86 | if ($this->is($expectOption)) {
87 | return TRUE;
88 | }
89 | }
90 | return FALSE;
91 | }
92 | if (is_int($expect)) {
93 | return $this->typeId === $expect;
94 | }
95 | if (is_string($expect)) {
96 | return $this->value === $expect;
97 | }
98 | throw new ParseException("Token::is() expects type ID or literal value");
99 | }
100 |
101 | public function assert($expect): void {
102 | if ($this->is($expect)) {
103 | return;
104 | }
105 |
106 | if ($expect === TX_RAW) {
107 | $expectPretty = 'TX_RAW';
108 | }
109 | elseif (is_int($expect)) {
110 | $expectPretty = token_name($expect);
111 | }
112 | else {
113 | $expectPretty = json_encode($expect, JSON_UNESCAPED_SLASHES);
114 | }
115 |
116 | throw new ParseException(sprintf('Token %s does not match expectation %s', $this->__toString(), $expectPretty));
117 | }
118 |
119 | public function __toString(): string {
120 | return sprintf("%s [%s] %s", $this->name(), $this->typeId, json_encode($this->value(), JSON_UNESCAPED_SLASHES));
121 | }
122 |
123 | }
124 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/doc/index.rst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/src/CRM/CivixBundle/Resources/doc/index.rst
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/translations/messages.fr.xlf:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Symfony2 is great
7 | J'aime Symfony2
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/angular-dir.html.php:
--------------------------------------------------------------------------------
1 |
2 |
{{ts('Example directive ()')}}
3 |
Options: {{myOptions|json}}
4 |
5 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/angular-dir.js.php:
--------------------------------------------------------------------------------
1 | (function(angular, $, _) {
2 | // "" is a basic skeletal directive.
3 | // Example usage: ="{foo: 1, bar: 2}">
4 | angular.module('').directive('', function() {
5 | return {
6 | restrict: 'AE',
7 | templateUrl: '',
8 | scope: {
9 | : '='
10 | },
11 | link: function($scope, $el, $attr) {
12 | var ts = $scope.ts = CRM.ts('');
13 | $scope.$watch('', function(newValue){
14 | $scope.myOptions = newValue;
15 | });
16 | }
17 | };
18 | });
19 | })(angular, CRM.$, CRM._);
20 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/angular-module.css.php:
--------------------------------------------------------------------------------
1 | /* Add any CSS rules for Angular module "" */
2 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/angular-module.js.php:
--------------------------------------------------------------------------------
1 | (function(angular, $, _) {
2 | // Declare a list of dependencies.
3 | angular.module('', CRM.angRequires(''));
4 | })(angular, CRM.$, CRM._);
5 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/angular-page.hlp.php:
--------------------------------------------------------------------------------
1 | {htxt id="full_name"}
2 | {ts}The contact name should be divided in two parts, the first name and last name.{/ts}
3 | {/htxt}
4 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/angular-page.html.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{ts('About %1', {1: $ctrl.myContact.first_name + ' ' + $ctrl.myContact.last_name})}}
5 |
6 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/angular-page.js.php:
--------------------------------------------------------------------------------
1 | (function(angular, $, _) {
2 |
3 | angular.module('').config(function($routeProvider) {
4 | $routeProvider.when('/', {
5 | controller: '',
6 | controllerAs: '$ctrl',
7 | templateUrl: '',
8 |
9 | // If you need to look up data when opening the page, list it out
10 | // under "resolve".
11 | resolve: {
12 | myContact: function(crmApi) {
13 | return crmApi('Contact', 'getsingle', {
14 | id: 'user_contact_id',
15 | return: ['first_name', 'last_name']
16 | });
17 | }
18 | }
19 | });
20 | }
21 | );
22 |
23 | // The controller uses *injection*. This default injects a few things:
24 | // $scope -- This is the set of variables shared between JS and HTML.
25 | // crmApi, crmStatus, crmUiHelp -- These are services provided by civicrm-core.
26 | // myContact -- The current contact, defined above in config().
27 | angular.module('').controller('', function($scope, crmApi, crmStatus, crmUiHelp, myContact) {
28 | // The ts() and hs() functions help load strings for this module.
29 | var ts = $scope.ts = CRM.ts('');
30 | var hs = $scope.hs = crmUiHelp({file: ''}); // See: templates/.hlp
31 | // Local variable for this controller (needed when inside a callback fn where `this` is not available).
32 | var ctrl = this;
33 |
34 | // We have myContact available in JS. We also want to reference it in HTML.
35 | this.myContact = myContact;
36 |
37 | this.save = function() {
38 | return crmStatus(
39 | // Status messages. For defaults, just use "{}"
40 | {start: ts('Saving...'), success: ts('Saved')},
41 | // The save action. Note that crmApi() returns a promise.
42 | crmApi('Contact', 'create', {
43 | id: ctrl.myContact.id,
44 | first_name: ctrl.myContact.first_name,
45 | last_name: ctrl.myContact.last_name
46 | })
47 | );
48 | };
49 | });
50 |
51 | })(angular, CRM.$, CRM._);
52 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/api.php.php:
--------------------------------------------------------------------------------
1 |
5 | use _ExtensionUtil as E;
6 |
7 | /**
8 | * . API specification (optional)
9 | * This is used for documentation and validation.
10 | *
11 | * @param array $spec description of fields supported by this API call
12 | *
13 | * @see https://docs.civicrm.org/dev/en/latest/framework/api-architecture/
14 | */
15 | function __spec(&$spec) {
16 | $spec['magicword']['api.required'] = 1;
17 | }
18 |
19 | /**
20 | * . API
21 | *
22 | * @param array $params
23 | *
24 | * @return array
25 | * API result descriptor
26 | *
27 | * @see civicrm_api3_create_success
28 | *
29 | * @throws CRM_Core_Exception
30 | */
31 | function ($params) {
32 | if (array_key_exists('magicword', $params) && $params['magicword'] == 'sesame') {
33 | $returnValues = array(
34 | // OK, return several data rows
35 | 12 => ['id' => 12, 'name' => 'Twelve'],
36 | 34 => ['id' => 34, 'name' => 'Thirty four'],
37 | 56 => ['id' => 56, 'name' => 'Fifty six'],
38 | );
39 | // ALTERNATIVE: $returnValues = []; // OK, success
40 | // ALTERNATIVE: $returnValues = ["Some value"]; // OK, return a single value
41 |
42 | // Spec: civicrm_api3_create_success($values = 1, $params = [], $entity = NULL, $action = NULL)
43 | return civicrm_api3_create_success($returnValues, $params, '', '');
44 | }
45 | else {
46 | throw new CRM_Core_Exception(/*error_message*/ 'Everyone knows that the magicword is "sesame"', /*error_code*/ 'magicword_incorrect');
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/bootstrap.css.php:
--------------------------------------------------------------------------------
1 | /**
2 | * This is a placeholder for bootstrap.css in the '' theme.
3 | * Here are a few ideas on what to do about it:
4 | * - Make a real CSS file (e.g. by hand-coding or setting up a SASS/SCSS build process).
5 | * - Inherit the stock Greenwich file:
6 | * - Edit the file '.theme.php'
7 | * and add 'greenwich' to the 'search_order'
8 | * - Delete this copy of 'bootstrap.css'
9 | * - Disable this file completely:
10 | * - Edit the file '.theme.php'
11 | * and add 'css/bootstrap.css' to the 'excludes' list
12 | * - Delete this copy of 'bootstrap.css'
13 | */
14 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/case-type.xml.php:
--------------------------------------------------------------------------------
1 | '; ?>
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Open Case
11 | 1
12 |
13 |
14 | Follow up
15 |
16 |
17 | Change Case Type
18 |
19 |
20 | Change Case Status
21 |
22 |
23 | Change Case Start Date
24 |
25 |
26 | Link Cases
27 |
28 |
29 |
30 |
31 | Email
32 |
33 |
34 | Meeting
35 |
36 |
37 | Phone Call
38 |
39 |
40 |
41 |
42 |
43 |
44 | standard_timeline
45 |
46 | true
47 |
48 |
49 | Open Case
50 | Completed
51 |
52 |
53 | Phone Call
54 | 1
55 | newest
56 |
57 |
58 | Follow up
59 | 7
60 | newest
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | Case Coordinator
69 | 1
70 | 1
71 |
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/civicrm.css.php:
--------------------------------------------------------------------------------
1 | /**
2 | * This is a placeholder for civicrm.css in the '' theme.
3 | * Here are a few ideas on what to do about it:
4 | * - Make a real CSS file (e.g. by hand-coding or setting up a SASS/SCSS build process).
5 | * - Inherit the stock Greenwich file:
6 | * - Edit the file '.theme.php'
7 | * and add 'greenwich' to the 'search_order'
8 | * - Delete this copy of 'civicrm.css'
9 | * - Disable this file completely:
10 | * - Edit the file '.theme.php'
11 | * and add 'css/civicrm.css' to the 'excludes' list
12 | * - Delete this copy of 'civicrm.css'
13 | */
14 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/entity-api.php.php:
--------------------------------------------------------------------------------
1 |
5 | use _ExtensionUtil as E;
6 |
7 | /**
8 | * .create API specification (optional).
9 | * This is used for documentation and validation.
10 | *
11 | * @param array $spec description of fields supported by this API call
12 | *
13 | * @see https://docs.civicrm.org/dev/en/latest/framework/api-architecture/
14 | */
15 | function _create_spec(&$spec) {
16 | // $spec['some_parameter']['api.required'] = 1;
17 | }
18 |
19 | /**
20 | * .create API.
21 | *
22 | * @param array $params
23 | *
24 | * @return array
25 | * API result descriptor
26 | *
27 | * @throws CRM_Core_Exception
28 | */
29 | function create($params) {
30 | return _civicrm_api3_basic_create(_civicrm_api3_get_BAO(__FUNCTION__), $params, );
31 | }
32 |
33 | /**
34 | * .delete API.
35 | *
36 | * @param array $params
37 | *
38 | * @return array
39 | * API result descriptor
40 | *
41 | * @throws CRM_Core_Exception
42 | */
43 | function delete($params) {
44 | return _civicrm_api3_basic_delete(_civicrm_api3_get_BAO(__FUNCTION__), $params);
45 | }
46 |
47 | /**
48 | * .get API.
49 | *
50 | * @param array $params
51 | *
52 | * @return array
53 | * API result descriptor
54 | *
55 | * @throws CRM_Core_Exception
56 | */
57 | function get($params) {
58 | return _civicrm_api3_basic_get(_civicrm_api3_get_BAO(__FUNCTION__), $params, TRUE, );
59 | }
60 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/entity-api3-test.php.php:
--------------------------------------------------------------------------------
1 |
4 |
5 | use Civi\Test\CiviEnvBuilder;
6 | use Civi\Test\HeadlessInterface;
7 | use Civi\Test\HookInterface;
8 | use Civi\Test\TransactionalInterface;
9 |
10 | /**
11 | * API Test Case
12 | * @group headless
13 | */
14 | class extends \PHPUnit\Framework\TestCase implements HeadlessInterface, HookInterface, TransactionalInterface {
15 | use \Civi\Test\Api3TestTrait;
16 |
17 | /**
18 | * Set up for headless tests.
19 | *
20 | * Civi\Test has many helpers, like install(), uninstall(), sql(), and sqlFile().
21 | *
22 | * See: https://docs.civicrm.org/dev/en/latest/testing/phpunit/#civitest
23 | */
24 | public function setUpHeadless(): CiviEnvBuilder {
25 | return \Civi\Test::headless()
26 | ->installMe(__DIR__)
27 | ->apply();
28 | }
29 |
30 | /**
31 | * The setup() method is executed before the test is executed (optional).
32 | */
33 | public function setUp(): void {
34 | $table = CRM_Core_DAO_AllCoreTables::getTableForEntityName();
35 | $this->assertTrue($table && CRM_Core_DAO::checkTableExists($table), 'There was a problem with extension installation. Table for ' . . ' not found.');
36 | parent::setUp();
37 | }
38 |
39 | /**
40 | * The tearDown() method is executed after the test was executed (optional)
41 | * This can be used for cleanup.
42 | */
43 | public function tearDown(): void {
44 | parent::tearDown();
45 | }
46 |
47 | /**
48 | * Simple example test case.
49 | *
50 | * Note how the function name begins with the word "test".
51 | */
52 | public function testCreateGetDelete(): void {
53 | // Boilerplate entity has one data field -- 'contact_id'.
54 | // Put some data in, read it back out, and delete it.
55 |
56 | $created = $this->callAPISuccess(, 'create', [
57 | 'contact_id' => 1,
58 | ]);
59 | $this->assertTrue(is_numeric($created['id']));
60 |
61 | $get = $this->callAPISuccess(, 'get', []);
62 | $this->assertEquals(1, $get['count']);
63 | $this->assertEquals(1, $get['values'][$created['id']]['contact_id']);
64 |
65 | $this->callAPISuccess(, 'delete', [
66 | 'id' => $created['id'],
67 | ]);
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/entity-api4.php.php:
--------------------------------------------------------------------------------
1 |
2 | namespace Civi\Api4;
3 |
4 | /**
5 | * entity.
6 | *
7 | * Provided by the extension.
8 | *
9 | * @package Civi\Api4
10 | */
11 | class extends Generic\DAOEntity {
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/entity-bao.php.php:
--------------------------------------------------------------------------------
1 |
5 |
6 | use _ExtensionUtil as E;
7 |
8 | class extends {
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/entity-dao.php.php:
--------------------------------------------------------------------------------
1 |
7 |
8 | /**
9 | * DAOs provide an OOP-style facade for reading and writing database records.
10 | *
11 | * DAOs are a primary source for metadata in older versions of CiviCRM (<5.74)
12 | * and are required for some subsystems (such as APIv3).
13 | *
14 | * This stub provides compatibility. It is not intended to be modified in a
15 | * substantive way. Property annotations may be added, but are not required.
16 | $propType) {
18 | echo " * @property $propType \$$propName\n";
19 | }
20 | ?> */
21 | class extends {
22 |
23 | /**
24 | * Required by older versions of CiviCRM (<5.74).
25 | * @var string
26 | */
27 | public static $_tableName = ;
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/form.php.php:
--------------------------------------------------------------------------------
1 |
5 |
6 | use _ExtensionUtil as E;
7 |
8 | /**
9 | * Form controller class
10 | *
11 | * @see https://docs.civicrm.org/dev/en/latest/framework/quickform/
12 | */
13 | class extends CRM_Core_Form {
14 |
15 | /**
16 | * @throws \CRM_Core_Exception
17 | */
18 | public function buildQuickForm(): void {
19 |
20 | // add form elements
21 | $this->add(
22 | 'select', // field type
23 | 'favorite_color', // field name
24 | 'Favorite Color', // field label
25 | $this->getColorOptions(), // list of options
26 | TRUE // is required
27 | );
28 | $this->addButtons([
29 | [
30 | 'type' => 'submit',
31 | 'name' => E::ts('Submit'),
32 | 'isDefault' => TRUE,
33 | ],
34 | ]);
35 |
36 | // export form elements
37 | $this->assign('elementNames', $this->getRenderableElementNames());
38 | parent::buildQuickForm();
39 | }
40 |
41 | public function postProcess(): void {
42 | $values = $this->exportValues();
43 | $options = $this->getColorOptions();
44 | CRM_Core_Session::setStatus(E::ts('You picked color "%1"', [
45 | 1 => $options[$values['favorite_color']],
46 | ]));
47 | parent::postProcess();
48 | }
49 |
50 | public function getColorOptions(): array {
51 | $options = [
52 | '' => E::ts('- select -'),
53 | '#f00' => E::ts('Red'),
54 | '#0f0' => E::ts('Green'),
55 | '#00f' => E::ts('Blue'),
56 | '#f0f' => E::ts('Purple'),
57 | ];
58 | foreach (['1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e'] as $f) {
59 | $options["#{$f}{$f}{$f}"] = E::ts('Grey (%1)', [1 => $f]);
60 | }
61 | return $options;
62 | }
63 |
64 | /**
65 | * Get the fields/elements defined in this form.
66 | *
67 | * @return array (string)
68 | */
69 | public function getRenderableElementNames(): array {
70 | // The _elements list includes some items which should not be
71 | // auto-rendered in the loop -- such as "qfKey" and "buttons". These
72 | // items don't have labels. We'll identify renderable by filtering on
73 | // the 'label'.
74 | $elementNames = [];
75 | foreach ($this->_elements as $element) {
76 | /** @var HTML_QuickForm_Element $element */
77 | $label = $element->getLabel();
78 | if (!empty($label)) {
79 | $elementNames[] = $element->getName();
80 | }
81 | }
82 | return $elementNames;
83 | }
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/form.tpl.php:
--------------------------------------------------------------------------------
1 | {* HEADER *}
2 |
3 |
4 | {include file="CRM/common/formButtons.tpl" location="top"}
5 |
6 |
7 | {* FIELD EXAMPLE: OPTION 1 (AUTOMATIC LAYOUT) *}
8 |
9 | {foreach from=$elementNames item=elementName}
10 |
11 |
{$form.$elementName.label}
12 |
{$form.$elementName.html}
13 |
14 |
15 | {/foreach}
16 |
17 | {* FIELD EXAMPLE: OPTION 2 (MANUAL LAYOUT)
18 |
19 |
20 | {$form.favorite_color.label}
21 | {$form.favorite_color.html}
22 |
23 |
24 | {* FOOTER *}
25 |
26 | {include file="CRM/common/formButtons.tpl" location="bottom"}
27 |
28 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/module.php.php:
--------------------------------------------------------------------------------
1 |
5 |
6 | require_once '.civix.php';
7 |
8 | use _ExtensionUtil as E;
9 |
10 | /**
11 | * Implements hook_civicrm_config().
12 | *
13 | * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_config/
14 | */
15 | function _civicrm_config(&$config): void {
16 | __civix_civicrm_config($config);
17 | }
18 |
19 | /**
20 | * Implements hook_civicrm_install().
21 | *
22 | * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_install
23 | */
24 | function _civicrm_install(): void {
25 | __civix_civicrm_install();
26 | }
27 |
28 | /**
29 | * Implements hook_civicrm_enable().
30 | *
31 | * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_enable
32 | */
33 | function _civicrm_enable(): void {
34 | __civix_civicrm_enable();
35 | }
36 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/page.php.php:
--------------------------------------------------------------------------------
1 |
5 | use _ExtensionUtil as E;
6 |
7 | class extends CRM_Core_Page {
8 |
9 | public function run() {
10 | // Example: Set the page-title dynamically; alternatively, declare a static title in xml/Menu/*.xml
11 | CRM_Utils_System::setTitle(E::ts(''));
12 |
13 | // Example: Assign a variable for use in a template
14 | $this->assign('currentTime', date('Y-m-d H:i:s'));
15 |
16 | parent::run();
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/page.tpl.php:
--------------------------------------------------------------------------------
1 | This new page is generated by /Page/.php
2 |
3 | {* Example: Display a variable directly *}
4 | The current time is {$currentTime}
5 |
6 | {* Example: Display a translated string -- which happens to include a variable *}
7 | {ts 1=$currentTime}(In your native language) The current time is %1.{/ts}
8 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/phpunit-boot-cv.php.php:
--------------------------------------------------------------------------------
1 |
4 |
5 | ini_set('memory_limit', '2G');
6 |
7 | // phpcs:disable
8 | eval(cv('php:boot --level=classloader', 'phpcode'));
9 | // phpcs:enable
10 | // Allow autoloading of PHPUnit helper classes in this extension.
11 | $loader = new \Composer\Autoload\ClassLoader();
12 | $loader->add('CRM_', [__DIR__ . '/../..', __DIR__]);
13 | $loader->addPsr4('Civi\\', [__DIR__ . '/../../Civi', __DIR__ . '/Civi']);
14 | $loader->add('api_', [__DIR__ . '/../..', __DIR__]);
15 | $loader->addPsr4('api\\', [__DIR__ . '/../../api', __DIR__ . '/api']);
16 |
17 | $loader->register();
18 |
19 | /**
20 | * Call the "cv" command.
21 | *
22 | * @param string $cmd
23 | * The rest of the command to send.
24 | * @param string $decode
25 | * Ex: 'json' or 'phpcode'.
26 | * @return mixed
27 | * Response output (if the command executed normally).
28 | * For 'raw' or 'phpcode', this will be a string. For 'json', it could be any JSON value.
29 | * @throws \RuntimeException
30 | * If the command terminates abnormally.
31 | */
32 | function cv(string $cmd, string $decode = 'json') {
33 | $cmd = 'cv ' . $cmd;
34 | $descriptorSpec = [0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => STDERR];
35 | $oldOutput = getenv('CV_OUTPUT');
36 | putenv('CV_OUTPUT=json');
37 |
38 | // Execute `cv` in the original folder. This is a work-around for
39 | // phpunit/codeception, which seem to manipulate PWD.
40 | $cmd = sprintf('cd %s; %s', escapeshellarg(getenv('PWD')), $cmd);
41 |
42 | $process = proc_open($cmd, $descriptorSpec, $pipes, __DIR__);
43 | putenv("CV_OUTPUT=$oldOutput");
44 | fclose($pipes[0]);
45 | $result = stream_get_contents($pipes[1]);
46 | fclose($pipes[1]);
47 | if (proc_close($process) !== 0) {
48 | throw new RuntimeException("Command failed ($cmd):\n$result");
49 | }
50 | switch ($decode) {
51 | case 'raw':
52 | return $result;
53 |
54 | case 'phpcode':
55 | // If the last output is /*PHPCODE*/, then we managed to complete execution.
56 | if (substr(trim($result), 0, 12) !== '/*BEGINPHP*/' || substr(trim($result), -10) !== '/*ENDPHP*/') {
57 | throw new \RuntimeException("Command failed ($cmd):\n$result");
58 | }
59 | return $result;
60 |
61 | case 'json':
62 | return json_decode($result, 1);
63 |
64 | default:
65 | throw new RuntimeException("Bad decoder format ($decode)");
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/phpunit-boot.php.php:
--------------------------------------------------------------------------------
1 |
4 |
5 | // Note: $b overrides $a
6 | function _civix_phpunit_settings_merge($a, $b) {
7 | $result = $a;
8 | $b = (array) $b;
9 | foreach ($b as $k1 => $v1) {
10 | foreach ($v1 as $k2 => $v2) {
11 | $result[$k1][$k2] = $v2;
12 | }
13 | }
14 | return $result;
15 | }
16 |
17 | /**
18 | * Install extensions on test database
19 | */
20 | function _civix_phpunit_setUp() {
21 | static $init = FALSE;
22 | if ($init) {
23 | return;
24 | }
25 | $init = TRUE;
26 |
27 | global $civicrm_setting;
28 | //print_r(array('install' => $civicrm_setting['Test']['test_extensions']));
29 | $apiResult = civicrm_api('Extension', 'install', array(
30 | 'version' => 3,
31 | 'keys' => $civicrm_setting['Test']['test_extensions'],
32 | ));
33 | register_shutdown_function('_civix_phpunit_tearDown');
34 | if ($apiResult['is_error'] != 0) {
35 | throw new Exception("Failed to pre-install extensions: " . $apiResult['error_message']);
36 | }
37 | }
38 |
39 | /**
40 | * Uninstall extensions on test database
41 | */
42 | function _civix_phpunit_tearDown() {
43 | global $civicrm_setting;
44 | //print_r(array('disable' => $civicrm_setting['Test']['test_extensions']));
45 | $result = civicrm_api('Extension', 'disable', array(
46 | 'version' => 3,
47 | 'keys' => $civicrm_setting['Test']['test_extensions'],
48 | ));
49 | //print_r(array('uninstall' => $civicrm_setting['Test']['test_extensions']));
50 | $result = civicrm_api('Extension', 'uninstall', array(
51 | 'version' => 3,
52 | 'keys' => $civicrm_setting['Test']['test_extensions'],
53 | 'removeFiles' => FALSE,
54 | ));
55 | }
56 |
57 | global $civicrm_setting;
58 | $civix_civicrm_setting = ;
59 | $civicrm_setting = _civix_phpunit_settings_merge($civix_civicrm_setting, $civicrm_setting);
60 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/readme.md.php:
--------------------------------------------------------------------------------
1 | #
2 |
3 | (*FIXME: In one or two paragraphs, describe what the extension does and why one would download it. *)
4 |
5 | This is an [extension for CiviCRM](https://docs.civicrm.org/sysadmin/en/latest/customize/extensions/), licensed under [](LICENSE.txt).
6 |
7 | ## Getting Started
8 |
9 | (* FIXME: Where would a new user navigate to get started? What changes would they see? *)
10 |
11 | ## Known Issues
12 |
13 | (* FIXME *)
14 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/report.tpl.php:
--------------------------------------------------------------------------------
1 | {* Use the default layout *}
2 | {include file="CRM/Report/Form.tpl"}
3 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/service.php.php:
--------------------------------------------------------------------------------
1 |
8 | use Civi\Core\Service\AutoService;
9 | use Symfony\Component\EventDispatcher\EventSubscriberInterface;
10 |
11 | /**
12 | * @service
13 | */
14 | class extends AutoService implements EventSubscriberInterface {
15 |
16 | // TIP: Many services implement `EventSubscriberInterface`. However, this can be omitted if you don't need it.
17 |
18 | public static function getSubscribedEvents(): array {
19 | return [
20 | // '&hook_civicrm_alterContent' => ['onAlterContent', 0],
21 | // '&hook_civicrm_postCommit::Contribution' => ['onContribute', 0],
22 | // TIP: For hooks based on GenericHookEvent, the "&" will expand arguments.
23 | ];
24 | }
25 |
26 | // /**
27 | // * @see \CRM_Utils_Hook::alterContent()
28 | // */
29 | // public function onAlterContent(&$content, $context, $tplName, &$object) { ... }
30 |
31 | // /**
32 | // * @see \CRM_Utils_Hook::postCommit()
33 | // */
34 | // public function onContribute($op, $objectName, $objectId, $objectRef = NULL) { ... }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/test-api.php.php:
--------------------------------------------------------------------------------
1 |
4 |
5 | use Civi\Test\CiviEnvBuilder;
6 | use Civi\Test\HeadlessInterface;
7 | use Civi\Test\HookInterface;
8 | use Civi\Test\TransactionalInterface;
9 |
10 | /**
11 | * . API Test Case
12 | * This is a generic test class implemented with PHPUnit.
13 | * @group headless
14 | */
15 | class extends \PHPUnit\Framework\TestCase implements HeadlessInterface, HookInterface, TransactionalInterface {
16 | use \Civi\Test\Api3TestTrait;
17 |
18 | /**
19 | * Set up for headless tests.
20 | *
21 | * Civi\Test has many helpers, like install(), uninstall(), sql(), and sqlFile().
22 | *
23 | * See: https://docs.civicrm.org/dev/en/latest/testing/phpunit/#civitest
24 | */
25 | public function setUpHeadless(): CiviEnvBuilder {
26 | return \Civi\Test::headless()
27 | ->installMe(__DIR__)
28 | ->apply();
29 | }
30 |
31 | /**
32 | * The setup() method is executed before the test is executed (optional).
33 | */
34 | public function setUp(): void {
35 | parent::setUp();
36 | }
37 |
38 | /**
39 | * The tearDown() method is executed after the test was executed (optional)
40 | * This can be used for cleanup.
41 | */
42 | public function tearDown(): void {
43 | parent::tearDown();
44 | }
45 |
46 | /**
47 | * Simple example test case.
48 | *
49 | * Note how the function name begins with the word "test".
50 | */
51 | public function testApiExample() {
52 | $result = civicrm_api3('', '', array('magicword' => 'sesame'));
53 | $this->assertEquals('Twelve', $result['values'][12]['name']);
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/test-e2e.php.php:
--------------------------------------------------------------------------------
1 |
9 |
10 | use _ExtensionUtil as E;
11 | use Civi\Test\EndToEndInterface;
12 |
13 | /**
14 | * FIXME - Add test description.
15 | *
16 | * Tips:
17 | * - The global variable $_CV has some properties which may be useful, such as:
18 | * CMS_URL, ADMIN_USER, ADMIN_PASS, ADMIN_EMAIL, DEMO_USER, DEMO_PASS, DEMO_EMAIL.
19 | * - To spawn a new CiviCRM thread and execute an API call or PHP code, use cv(), e.g.
20 | * cv('api system.flush');
21 | * $data = cv('eval "return Civi::settings()->get(\'foobar\')"');
22 | * $dashboardUrl = cv('url civicrm/dashboard');
23 | * - This template uses the most generic base-class, but you may want to use a more
24 | * powerful base class, such as \PHPUnit_Extensions_SeleniumTestCase or
25 | * \PHPUnit_Extensions_Selenium2TestCase.
26 | * See also: https://phpunit.de/manual/4.8/en/selenium.html
27 | *
28 | * @group e2e
29 | * @see cv
30 | */
31 | class extends \PHPUnit\Framework\TestCase implements EndToEndInterface {
32 |
33 | public static function setUpBeforeClass(): void {
34 | // See: https://docs.civicrm.org/dev/en/latest/testing/phpunit/#civitest
35 |
36 | // Example: Install this extension. Don't care about anything else.
37 | \Civi\Test::e2e()->installMe(__DIR__)->apply();
38 |
39 | // Example: Uninstall all extensions except this one.
40 | // \Civi\Test::e2e()->uninstall('*')->installMe(__DIR__)->apply();
41 |
42 | // Example: Install only core civicrm extensions.
43 | // \Civi\Test::e2e()->uninstall('*')->install('org.civicrm.*')->apply();
44 | }
45 |
46 | public function setUp(): void {
47 | parent::setUp();
48 | }
49 |
50 | public function tearDown(): void {
51 | parent::tearDown();
52 | }
53 |
54 | /**
55 | * Example: Test that a version is returned.
56 | */
57 | public function testWellFormedVersion(): void {
58 | $this->assertNotEmpty(E::SHORT_NAME);
59 | $this->assertMatchesRegularExpression('/^([0-9\.]|alpha|beta)*$/', \CRM_Utils_System::version());
60 | }
61 |
62 | /**
63 | * Example: Test that we're using a real CMS (Drupal, WordPress, etc).
64 | */
65 | public function testWellFormedUF(): void {
66 | $this->assertMatchesRegularExpression('/^(Drupal|Backdrop|WordPress|Joomla)/', CIVICRM_UF);
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/test-headless.php.php:
--------------------------------------------------------------------------------
1 |
9 |
10 | use _ExtensionUtil as E;
11 | use Civi\Test\CiviEnvBuilder;
12 | use Civi\Test\HeadlessInterface;
13 | use Civi\Test\HookInterface;
14 | use Civi\Test\TransactionalInterface;
15 |
16 | /**
17 | * FIXME - Add test description.
18 | *
19 | * Tips:
20 | * - With HookInterface, you may implement CiviCRM hooks directly in the test class.
21 | * Simply create corresponding functions (e.g. "hook_civicrm_post(...)" or similar).
22 | * - With TransactionalInterface, any data changes made by setUp() or test****() functions will
23 | * rollback automatically -- as long as you don't manipulate schema or truncate tables.
24 | * If this test needs to manipulate schema or truncate tables, then either:
25 | * a. Do all that using setupHeadless() and Civi\Test.
26 | * b. Disable TransactionalInterface, and handle all setup/teardown yourself.
27 | *
28 | * @group headless
29 | */
30 | class extends \PHPUnit\Framework\TestCase implements HeadlessInterface, HookInterface, TransactionalInterface {
31 |
32 | /**
33 | * Setup used when HeadlessInterface is implemented.
34 | *
35 | * Civi\Test has many helpers, like install(), uninstall(), sql(), and sqlFile().
36 | *
37 | * @link https://github.com/civicrm/org.civicrm.testapalooza/blob/master/civi-test.md
38 | *
39 | * @return \Civi\Test\CiviEnvBuilder
40 | *
41 | * @throws \CRM_Extension_Exception_ParseException
42 | */
43 | public function setUpHeadless(): CiviEnvBuilder {
44 | return \Civi\Test::headless()
45 | ->installMe(__DIR__)
46 | ->apply();
47 | }
48 |
49 | public function setUp():void {
50 | parent::setUp();
51 | }
52 |
53 | public function tearDown():void {
54 | parent::tearDown();
55 | }
56 |
57 | /**
58 | * Example: Test that a version is returned.
59 | */
60 | public function testWellFormedVersion():void {
61 | $this->assertNotEmpty(E::SHORT_NAME);
62 | $this->assertMatchesRegularExpression('/^([0-9\.]|alpha|beta)*$/', \CRM_Utils_System::version());
63 | }
64 |
65 | /**
66 | * Example: Test that we're using a fake CMS.
67 | */
68 | public function testWellFormedUF():void {
69 | $this->assertEquals('UnitTests', CIVICRM_UF);
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/test-legacy.php.php:
--------------------------------------------------------------------------------
1 |
9 |
10 | use _ExtensionUtil as E;
11 | use Civi\Test\HeadlessInterface;
12 |
13 | /**
14 | * FIXME - Add test description.
15 | *
16 | * Note: Legacy test cases are based on CiviUnitTestCase. These should work about
17 | * as well (or as poorly) as before. This generator is provided primarily as a way
18 | * test backward compatibility.
19 | *
20 | * @group headless
21 | * @group legacy
22 | */
23 | class extends \CiviUnitTestCase implements HeadlessInterface {
24 |
25 | /**
26 | * Setup for when Headless interface is implemented.
27 | *
28 | * `CiviTestListener`+`HeadlessInterface` has some clever tricks for
29 | * bootstrapping which make it easier to use phpunit CLI.
30 | * However, there's not much point in using setupHeadless() with CiviUnitTestCase
31 | * because CiviUnitTestCase performs its own special setup/teardown logic.
32 | */
33 | public function setUpHeadless(): void {}
34 |
35 | /**
36 | * Setup any fixtures required for the tests in this class.
37 | */
38 | public function setUp(): void {
39 | parent::setUp();
40 | }
41 |
42 | /**
43 | * Return the database to the original state..
44 | */
45 | public function tearDown(): void {
46 | parent::tearDown();
47 | }
48 |
49 | /**
50 | * Example: Test that a version is returned.
51 | */
52 | public function testWellFormedVersion(): void {
53 | $this->assertNotEmpty(E::SHORT_NAME);
54 | $this->assertMatchesRegularExpression('/^([0-9\.]|alpha|beta)*$/', \CRM_Utils_System::version());
55 | }
56 |
57 | /**
58 | * Example: Test that we're using a fake CMS.
59 | */
60 | public function testWellFormedUF(): void {
61 | $this->assertEquals('UnitTests', CIVICRM_UF);
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Resources/views/Code/test-phpunit.php.php:
--------------------------------------------------------------------------------
1 |
4 |
5 | /**
6 | * This is a generic test class for the extension (implemented with PHPUnit).
7 | */
8 | class extends \PHPUnit\Framework\TestCase {
9 |
10 | /**
11 | * The setup() method is executed before the test is executed (optional).
12 | */
13 | public function setUp():void {
14 | parent::setUp();
15 | }
16 |
17 | /**
18 | * The tearDown() method is executed after the test was executed (optional).
19 | *
20 | * This can be used for cleanup.
21 | */
22 | public function tearDown():void {
23 | parent::tearDown();
24 | }
25 |
26 | /**
27 | * Simple example test case.
28 | *
29 | * Note how the function name begins with the word "test".
30 | */
31 | public function testExample():void {
32 | self::assertTrue(TRUE, "The argument must be true to pass the test");
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/RunMethodsTrait.php:
--------------------------------------------------------------------------------
1 | runMethods('/^checkRequirements_/');
16 | * }
17 | * protected function checkRequirements_foo() { ... }
18 | * protected function checkRequirements_bar() { ... }
19 | */
20 | trait RunMethodsTrait {
21 |
22 | /**
23 | *
24 | * Ex: [$results] = $this->runMethods(';foo.*;');
25 | * Ex: [$results, $skipped] = $this->runMethods(';foo.*;', ['val1', 'val2']);
26 | *
27 | * @param string $methodRegex
28 | * @param array $params
29 | * A list of parameters to pass down to each method.
30 | * @return array
31 | * Results of calling the methods.
32 | * Some methods have opted-out of execution.
33 | * Formally, the results are a tuple of `[$executed, $skipped]`.
34 | * @throws \ReflectionException
35 | */
36 | protected function runMethods(string $methodRegex, array $params = []): array {
37 | $executed = [];
38 | $skipped = [];
39 |
40 | $class = new \ReflectionClass($this);
41 | foreach ($class->getMethods() as $method) {
42 | /** @var \ReflectionMethod $method */
43 |
44 | if (preg_match($methodRegex, $method->getName())) {
45 | try {
46 | $result = $method->invoke($this, ...$params);
47 | $executed[$method->getName()] = $result;
48 | }
49 | catch (SkippedMethodException $e) {
50 | $skipped[$method->getName()] = $method->getName();
51 | }
52 | }
53 | }
54 |
55 | return [$executed, $skipped];
56 | }
57 |
58 | /**
59 | * Assert that the current method is (or is not) applicable.
60 | *
61 | * @param bool $bool
62 | * If TRUE, then proceed with normal execution.
63 | *
64 | * If FALSE, raise an exception that will propagate back to the main `testSnapshot()` method.
65 | * The next check will run.
66 | */
67 | protected function runsIf(bool $bool) {
68 | if (!$bool) {
69 | throw new SkippedMethodException();
70 | }
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/SkippedMethodException.php:
--------------------------------------------------------------------------------
1 | baseCommand = $baseCommand;
34 | }
35 |
36 | /**
37 | * Executes the command.
38 | *
39 | * @param array $input An array of command arguments and options
40 | * @param array $options An array of execution options
41 | * Ignored
42 | * @return int The command exit code
43 | */
44 | public function execute(array $input, array $options = []) {
45 | if (!empty($options)) {
46 | throw new \LogicException(__CLASS__ . " does not implement support for execute() options");
47 | }
48 |
49 | $command = $this->baseCommand;
50 | foreach ($input as $key => $value) {
51 | if (substr($key, 0, 2) === '--') {
52 | if ($value === TRUE) {
53 | $command[] = $key;
54 | }
55 | else {
56 | $command[] = "$key=$value";
57 | }
58 | }
59 | else {
60 | $command[] = $value;
61 | }
62 | }
63 |
64 | $buffer = fopen('php://memory', 'w+');
65 |
66 | $p = new Process($command);
67 | $this->commandLine = $p->getCommandLine();
68 |
69 | $p->run(function ($type, $data) use ($buffer) {
70 | // Default policy - combine STDOUT and STDIN into one continuous stream.
71 | fwrite($buffer, $data);
72 | });
73 | $this->statusCode = $p->getExitCode();
74 |
75 | rewind($buffer);
76 | $this->display = stream_get_contents($buffer);
77 | fclose($buffer);
78 |
79 | return $this->statusCode;
80 | }
81 |
82 | public function getDisplay(bool $normalize = FALSE) {
83 | if ($normalize) {
84 | return str_replace(\PHP_EOL, "\n", $this->display);
85 | }
86 | else {
87 | return $this->display;
88 | }
89 | }
90 |
91 | public function getStatusCode(): int {
92 | return $this->statusCode;
93 | }
94 |
95 | public function getCommandLine(): string {
96 | return $this->commandLine;
97 | }
98 |
99 | }
100 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/UpgradeList.php:
--------------------------------------------------------------------------------
1 | getUpgrades());
18 | }
19 |
20 | /**
21 | * @return array
22 | * array(string $version => string $filePath)
23 | */
24 | public function getUpgrades(): array {
25 | if ($this->upgrades === NULL) {
26 | $this->upgrades = $this->scan();
27 | }
28 | return $this->upgrades;
29 | }
30 |
31 | /**
32 | * Get a list of upgrades appropriate to a particular codebase.
33 | *
34 | * @param string $startVersion
35 | * The initial/start version of the codebase.
36 | * @return array
37 | * array(string $version => string $filePath)
38 | */
39 | public function findUpgrades(string $startVersion): array {
40 | return array_filter($this->getUpgrades(),
41 | function($upgradeVersion) use ($startVersion) {
42 | return (bool) version_compare($upgradeVersion, $startVersion, '>');
43 | },
44 | ARRAY_FILTER_USE_KEY
45 | );
46 | }
47 |
48 | /**
49 | * Scan for upgrade files.
50 | *
51 | * @return array
52 | * array(string $version => string $filePath)
53 | */
54 | protected function scan(): array {
55 | $parseVer = function($file) {
56 | return basename($file, '.up.php');
57 | };
58 |
59 | $upgrades = [];
60 | $iter = new \DirectoryIterator(Application::findCivixDir() . '/upgrades');
61 | foreach ($iter as $file) {
62 | /** @var \SplFileInfo $file */
63 | if (preg_match(';\.up\.php$;', $file->getBasename())) {
64 | $upgrades[$parseVer($file->getBasename())] = $file->getPathname();
65 | }
66 | }
67 |
68 | uksort($upgrades, 'version_compare');
69 | return $upgrades;
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Utils/AutoCleanup.php:
--------------------------------------------------------------------------------
1 | callback = $callback;
26 | }
27 |
28 | public function __destruct() {
29 | call_user_func($this->callback);
30 | }
31 |
32 | /**
33 | * Prohibit (de)serialization of AutoCleanup.
34 | *
35 | * The generic nature of AutoClean makes it a potential target for escalating
36 | * serialization vulnerabilities, and there's no good reason for serializing it.
37 | */
38 | public function __sleep() {
39 | throw new \RuntimeException("AutoCleanup is a runtime helper. It is not intended for serialization.");
40 | }
41 |
42 | /**
43 | * Prohibit (de)serialization of AutoCleanup.
44 | *
45 | * The generic nature of AutoClean makes it a potential target for escalating
46 | * serialization vulnerabilities, and there's no good reason for deserializing it.
47 | */
48 | public function __wakeup() {
49 | throw new \RuntimeException("AutoCleanup is a runtime helper. It is not intended for deserialization.");
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Utils/CivixStyle.php:
--------------------------------------------------------------------------------
1 | find()) {
42 | throw new \RuntimeException('The php executable could not be found, add it to your PATH environment variable and try again');
43 | }
44 | return $phpPath;
45 | }
46 |
47 | /**
48 | * Determine the full path to an executable
49 | *
50 | * @param $name
51 | * @return string|FALSE
52 | */
53 | public static function findExecutable($name) {
54 | $paths = explode(PATH_SEPARATOR, getenv('PATH'));
55 | foreach ($paths as $path) {
56 | if (file_exists("$path/$name")) {
57 | return "$path/$name";
58 | }
59 | }
60 | return FALSE;
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Utils/EvilEx.php:
--------------------------------------------------------------------------------
1 | = count($expectLines)) {
67 | $endOffset = $actualLineNum;
68 | break 2;
69 | }
70 | }
71 | }
72 |
73 | if ($endOffset === NULL) {
74 | return $body;
75 | }
76 |
77 | $rawActualLines = array_column($actualLines, 'raw');
78 | $matchLines = array_slice($rawActualLines, $startOffset, $endOffset - $startOffset + 1, TRUE);
79 | $newLines = $filterChunk($matchLines);
80 | array_splice($rawActualLines, $startOffset, $endOffset - $startOffset + 1, $newLines);
81 | return implode("\n", $rawActualLines);
82 | }
83 |
84 | public static function digestLine(string $line): string {
85 | return mb_strtolower(preg_replace('/\s+/', '', $line));
86 | }
87 |
88 | public static function digestLines($lines): array {
89 | $result = [];
90 | foreach ($lines as $line) {
91 | $result[] = ['raw' => $line, 'dig' => static::digestLine($line)];
92 | }
93 | return $result;
94 | }
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Utils/Formatting.php:
--------------------------------------------------------------------------------
1 | $item) {
24 | $item = (array) $item;
25 | $line = sprintf($itemFormat, ...$item);
26 | $buf .= ((1 + $int) . ". " . $line);
27 | }
28 | return rtrim($buf);
29 | }
30 |
31 | /**
32 | * Format an unordered list.
33 | *
34 | * @param string $itemFormat
35 | * Ex: "Hello %s.\n"
36 | * Ex: "Hello %s from %s.\n"
37 | * Ex: "Everyone in %2$s says hello to %1$s."
38 | * @param iterable $list
39 | * Ex: ['Alice', 'Bob']
40 | * Ex: [['Alice','Argentina'], ['Bob','Britain']]
41 | * @return string
42 | * Ex: "Hello Alice.\nHello Bob.\n"
43 | * Ex: "Hello alice from Argentina!\nHello Bob from Britain!"
44 | */
45 | public static function ul(string $itemFormat, iterable $list) {
46 | $buf = '';
47 | foreach ($list as $int => $item) {
48 | $item = (array) $item;
49 | $line = sprintf($itemFormat, ...$item);
50 | $buf .= "- " . $line;
51 | }
52 | return rtrim($buf);
53 | }
54 |
55 | /**
56 | * @param array $headers
57 | * @param array $rows
58 | * @return string
59 | */
60 | public static function table(array $headers, array $rows) {
61 | $buffer = new \Symfony\Component\Console\Output\BufferedOutput();
62 | $table = new \Symfony\Component\Console\Helper\Table($buffer);
63 | $table->setHeaders($headers);
64 | $table->setRows($rows);
65 | $table->render();
66 | return $buffer->fetch();
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Utils/Functions.php:
--------------------------------------------------------------------------------
1 | stack, [
11 | 'input' => $input,
12 | 'output' => $output,
13 | 'io' => new CivixStyle($input, $output),
14 | ]);
15 | }
16 |
17 | public function pop(): array {
18 | return array_shift($this->stack);
19 | }
20 |
21 | public function current(string $property) {
22 | return $this->stack[0][$property];
23 | }
24 |
25 | public function reset() {
26 | $this->stack = [];
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Utils/Path.php:
--------------------------------------------------------------------------------
1 | path(...$args);
24 | }
25 | return $result;
26 | }
27 |
28 | /**
29 | * @param string|Path $basedir
30 | */
31 | public function __construct($basedir) {
32 | if ($basedir instanceof Path) {
33 | $this->basedir = $basedir->basedir;
34 | }
35 | else {
36 | $this->basedir = static::normalize($basedir);
37 | }
38 | }
39 |
40 | public function __toString(): string {
41 | return $this->basedir;
42 | }
43 |
44 | /**
45 | * Determine the full path to a file underneath this path
46 | *
47 | * ex: $basepath = $path->string()
48 | * ex: $item = $this->string('subdir', 'file.xml');
49 | *
50 | * @return string
51 | */
52 | public function string() {
53 | $args = func_get_args();
54 | array_unshift($args, $this->basedir);
55 | return static::normalize(implode('/', $args));
56 | }
57 |
58 | /**
59 | * Construct the full path to a file underneath this path
60 | *
61 | * ex: $item = $this->path('subdir', 'file.xml');
62 | *
63 | * @return Path
64 | */
65 | public function path() {
66 | $args = func_get_args();
67 | array_unshift($args, $this->basedir);
68 | return new Path(implode('/', $args));
69 | }
70 |
71 | /**
72 | * Make a folder for this path (if necessary).
73 | *
74 | * @param int $mode
75 | */
76 | public function mkdir($mode = 0777): void {
77 | $args = func_get_args();
78 | $dir = call_user_func_array([$this, 'string'], $args);
79 | if (!is_dir($dir)) {
80 | if (!mkdir($dir, $mode, TRUE)) {
81 | throw new \RuntimeException("Failed to make directory: $path");
82 | }
83 | }
84 | }
85 |
86 | /**
87 | * Recursively search for files matching $pattern.
88 | *
89 | * @param string $pattern
90 | * Ex: 'glob:foobar/*.xml' (non-recursive search)
91 | * Ex: 'find:*.whizbang.php' (recursive search, under .)
92 | * Ex: 'find:meta/*.whizbang.php' (recursive search, under ./meta)
93 | * @return array
94 | */
95 | public function search($pattern): array {
96 | [$patternType, $patternValue] = explode(':', $pattern, 2);
97 | switch ($patternType) {
98 | case 'glob':
99 | return Glob::glob($this->string($patternValue));
100 |
101 | case 'find':
102 | $relDir = dirname($patternValue);
103 | $filePat = basename($patternValue);
104 | return Files::findFiles($this->string($relDir), $filePat);
105 |
106 | default:
107 | throw new \RuntimeException("Unrecognized file pattern: $pattern");
108 | }
109 | }
110 |
111 | protected static function normalize(string $path) {
112 | return str_replace('\\', '/', $path);
113 | }
114 |
115 | }
116 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Utils/PathTest.php:
--------------------------------------------------------------------------------
1 | assertEquals('/var/www', Path::for('/var/www'));
12 | $this->assertEquals('e:/project/web', Path::for('e:\\project\\web'));
13 | $this->assertEquals('e:/project/web/ab/cd/ef', Path::for('e:\\project\\web', 'ab', 'cd\\ef'));
14 | $this->assertEquals('/var/www/foo/bar', Path::for('/var/www', 'foo/bar'));
15 | $this->assertEquals('/var/www/foo/bar', Path::for('/var/www', 'foo\bar'));
16 | $this->assertEquals('/var/www/foobar/whizbang', Path::for('/var/www', 'foobar', 'whizbang'));
17 | }
18 |
19 | public function testPathString() {
20 | $base = Path::for('/var/www');
21 | $this->assertEquals('/var/www', $base->string());
22 | $this->assertEquals('/var/www/foo', $base->string('foo'));
23 | $this->assertEquals('/var/www/foo/bar', $base->string('foo', 'bar'));
24 | $this->assertEquals('/var/www/foo/bar', $base->string('foo/bar'));
25 | $this->assertEquals('/var/www/foo/bar', $base->string('foo\\bar'));
26 | }
27 |
28 | public function testPathChild() {
29 | $this->assertEquals('/var/www/foo', (string) Path::for('/var')->path('www')->path('foo'));
30 | $this->assertEquals('/var/www/foo/whiz/bang', (string) Path::for('/var')->path('www', 'foo')->path('whiz/bang'));
31 | $this->assertEquals('e:/work/www/foo/whiz/bang', (string) Path::for('e:\\work')->path('www', 'foo')->path('whiz\\bang'));
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Utils/PathloadPackage.php:
--------------------------------------------------------------------------------
1 | majorName, $self->name, $self->version] = static::parseExpr($base);
53 | $self->file = $file;
54 | $self->type = $type;
55 | return $self;
56 | }
57 |
58 | /**
59 | * @var string
60 | * Ex: '/var/www/app-1/lib/cloud-file-io@1.2.3.phar'
61 | */
62 | public $file;
63 |
64 | /**
65 | * @var string
66 | * Ex: 'cloud-file-io'
67 | */
68 | public $name;
69 |
70 | /**
71 | * @var string
72 | * Ex: 'cloud-file-io@1'
73 | */
74 | public $majorName;
75 |
76 | /**
77 | * @var string
78 | * Ex: '1.2.3'
79 | */
80 | public $version;
81 |
82 | /**
83 | * @var string
84 | * Ex: 'php' or 'phar' or 'dir'
85 | */
86 | public $type;
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/src/CRM/CivixBundle/Utils/Versioning.php:
--------------------------------------------------------------------------------
1 | addPsr4('E2E\\', __DIR__ . '/e2e');
20 |
--------------------------------------------------------------------------------
/tests/e2e/AddManagedEntityTest.php:
--------------------------------------------------------------------------------
1 | civixGenerateModule(static::getKey());
17 | chdir(static::getKey());
18 |
19 | $this->assertFileGlobs([
20 | 'info.xml' => 1,
21 | 'civix_exportmgd.php' => 1,
22 | 'civix_exportmgd.civix.php' => 1,
23 | ]);
24 | $this->civixMixin(['--disable-all' => TRUE]);
25 | }
26 |
27 | public function testAddMgd(): void {
28 | $this->assertMixinStatuses(['mgd-php@1' => 'off']);
29 | $this->assertFileGlobs(['managed/OptionGroup_preferred_communication_method.mgd.php' => 0]);
30 |
31 | $tester = static::civix('export');
32 | $tester->execute(['' => 'OptionGroup', '' => 1]);
33 | if ($tester->getStatusCode() !== 0) {
34 | throw new \RuntimeException(sprintf("Failed to generate mgd (%s)", static::getKey()));
35 | }
36 |
37 | $this->assertMixinStatuses(['mgd-php@1' => 'on']);
38 | $this->assertFileGlobs(['managed/OptionGroup_preferred_communication_method.mgd.php' => 1]);
39 |
40 | ProcessHelper::runOk('php -l managed/OptionGroup_preferred_communication_method.mgd.php');
41 | $expectPhrases = [
42 | "use CRM_CivixExportmgd_ExtensionUtil as E;",
43 | "'title' => E::ts('Preferred Communication Method')",
44 | "'option_group_id.name' => 'preferred_communication_method'",
45 | "'label' => E::ts('Phone')",
46 | "'value' => '1'",
47 | "'label' => E::ts('Email')",
48 | "'value' => '2'",
49 | ];
50 | $this->assertStringSequence($expectPhrases, file_get_contents('managed/OptionGroup_preferred_communication_method.mgd.php'));
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/tests/e2e/AddPageTest.php:
--------------------------------------------------------------------------------
1 | civixGenerateModule(static::getKey());
15 | chdir(static::getKey());
16 |
17 | $this->assertFileGlobs([
18 | 'info.xml' => 1,
19 | 'civix_addpage.php' => 1,
20 | 'civix_addpage.civix.php' => 1,
21 | ]);
22 | }
23 |
24 | public function testAddPage(): void {
25 | $this->assertFileGlobs([
26 | 'CRM/CivixAddpage/Page/MyPage.php' => 0,
27 | 'templates/CRM/CivixAddpage/Page/MyPage.tpl' => 0,
28 | 'xml/Menu/civix_addpage.xml' => 0,
29 | ]);
30 |
31 | $this->civixGeneratePage('MyPage', 'civicrm/thirty');
32 |
33 | $this->assertFileGlobs([
34 | 'CRM/CivixAddpage/Page/MyPage.php' => 1,
35 | 'templates/CRM/CivixAddpage/Page/MyPage.tpl' => 1,
36 | 'xml/Menu/civix_addpage.xml' => 1,
37 | ]);
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/tests/e2e/AddServiceTest.php:
--------------------------------------------------------------------------------
1 | civixGenerateModule(static::getKey());
15 | chdir(static::getKey());
16 |
17 | $this->assertFileGlobs([
18 | 'info.xml' => 1,
19 | 'civix_addsvc.php' => 1,
20 | 'civix_addsvc.civix.php' => 1,
21 | ]);
22 | }
23 |
24 | public function testAddService(): void {
25 | $this->assertFileGlobs([
26 | 'CRM/CivixAddsvc/Whiz/Bang.php' => 0,
27 | ]);
28 |
29 | $this->civixGenerateService('civix_addsvc.whiz.bang');
30 |
31 | $this->assertFileGlobs([
32 | 'CRM/CivixAddsvc/Whiz/Bang.php' => 1,
33 | ]);
34 |
35 | $code = file_get_contents('CRM/CivixAddsvc/Whiz/Bang.php');
36 | $expect = [
37 | 'use CRM_CivixAddsvc_ExtensionUtil as E',
38 | 'use Civi\Core\Service\AutoService',
39 | 'use Symfony\Component\EventDispatcher\EventSubscriberInterface',
40 | '@service civix_addsvc.whiz.bang',
41 | 'class CRM_CivixAddsvc_Whiz_Bang extends AutoService implements EventSubscriberInterface',
42 | 'function getSubscribedEvents',
43 | ];
44 | $this->assertStringSequence($expect, $code);
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/tests/e2e/CRMNamingTest.php:
--------------------------------------------------------------------------------
1 | civixGenerateModule(static::getKey());
22 | chdir(static::getKey());
23 |
24 | $this->assertFileGlobs([
25 | 'info.xml' => 1,
26 | 'civix_crmnaming.php' => 1,
27 | 'civix_crmnaming.civix.php' => 1,
28 | ]);
29 |
30 | \Civix::ioStack()->push(...$this->createInputOutput());
31 | $this->upgrader = \Civix::generator(static::getExtPath());
32 | $this->upgrader->updateInfo(function(Info $info) {
33 | // FIXME: Allow "_" instead of "/"
34 | $info->get()->civix->namespace = 'CRM/NamingTest';
35 | });
36 | }
37 |
38 | protected function tearDown(): void {
39 | parent::tearDown();
40 | \Civix::ioStack()->reset();
41 | }
42 |
43 | public function testNaming_OnePart(): void {
44 | $vars = $this->upgrader->createClassVars('CRM_NamingTest_Widget');
45 | $this->assertTrue(is_string($vars['extBaseDir']) && is_dir($vars['extBaseDir']));
46 | $this->assertEquals('civix_crmnaming', $vars['extMainFile']);
47 | $this->assertEquals('civix_crmnaming', $vars['extKey']);
48 | $this->assertEquals('CRM/NamingTest/Widget.php', $vars['classFile']);
49 | $this->assertEquals('CRM_NamingTest_Widget', $vars['className']);
50 | $this->assertEquals('CRM_NamingTest_Widget', $vars['classNameFull']);
51 | $this->assertEquals('', $vars['classNamespace']);
52 | $this->assertEquals('', $vars['classNamespaceDecl']);
53 | $this->assertEquals('use CRM_NamingTest_ExtensionUtil as E;', $vars['useE']);
54 | }
55 |
56 | public function testNaming_TwoParts(): void {
57 | $vars = $this->upgrader->createClassVars('CRM_NamingTest_Widget_Gizmo');
58 | $this->assertTrue(is_string($vars['extBaseDir']) && is_dir($vars['extBaseDir']));
59 | $this->assertEquals('civix_crmnaming', $vars['extMainFile']);
60 | $this->assertEquals('civix_crmnaming', $vars['extKey']);
61 | $this->assertEquals('CRM/NamingTest/Widget/Gizmo.php', $vars['classFile']);
62 | $this->assertEquals('CRM_NamingTest_Widget_Gizmo', $vars['className']);
63 | $this->assertEquals('CRM_NamingTest_Widget_Gizmo', $vars['classNameFull']);
64 | $this->assertEquals('', $vars['classNamespace']);
65 | $this->assertEquals('', $vars['classNamespaceDecl']);
66 | $this->assertEquals('use CRM_NamingTest_ExtensionUtil as E;', $vars['useE']);
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/tests/e2e/CiviNamingTest.php:
--------------------------------------------------------------------------------
1 | civixGenerateModule(static::getKey());
22 | chdir(static::getKey());
23 |
24 | $this->assertFileGlobs([
25 | 'info.xml' => 1,
26 | 'civix_civinaming.php' => 1,
27 | 'civix_civinaming.civix.php' => 1,
28 | ]);
29 |
30 | \Civix::ioStack()->push(...$this->createInputOutput());
31 | $this->upgrader = \Civix::generator(static::getExtPath());
32 | $this->upgrader->updateInfo(function(Info $info) {
33 | // FIXME: Allow "\" instead of "/"
34 | $info->get()->civix->namespace = 'Civi/NamingTest';
35 | });
36 | }
37 |
38 | protected function tearDown(): void {
39 | parent::tearDown();
40 | \Civix::ioStack()->reset();
41 | }
42 |
43 | public function testNaming_OnePart(): void {
44 | $vars = $this->upgrader->createClassVars('Civi\\NamingTest\\Widget');
45 | $this->assertTrue(is_string($vars['extBaseDir']) && is_dir($vars['extBaseDir']));
46 | $this->assertEquals('civix_civinaming', $vars['extMainFile']);
47 | $this->assertEquals('civix_civinaming', $vars['extKey']);
48 | $this->assertEquals('Civi/NamingTest/Widget.php', $vars['classFile']);
49 | $this->assertEquals('Widget', $vars['className']);
50 | $this->assertEquals('Civi\\NamingTest\\Widget', $vars['classNameFull']);
51 | $this->assertEquals('Civi\\NamingTest', $vars['classNamespace']);
52 | $this->assertEquals('namespace Civi\\NamingTest;', $vars['classNamespaceDecl']);
53 | $this->assertEquals('use CRM_NamingTest_ExtensionUtil as E;', $vars['useE']);
54 | }
55 |
56 | public function testNaming_TwoParts(): void {
57 | $vars = $this->upgrader->createClassVars('Civi\\NamingTest\\Widget\\Gizmo');
58 | $this->assertTrue(is_string($vars['extBaseDir']) && is_dir($vars['extBaseDir']));
59 | $this->assertEquals('civix_civinaming', $vars['extMainFile']);
60 | $this->assertEquals('civix_civinaming', $vars['extKey']);
61 | $this->assertEquals('Civi/NamingTest/Widget/Gizmo.php', $vars['classFile']);
62 | $this->assertEquals('Gizmo', $vars['className']);
63 | $this->assertEquals('Civi\\NamingTest\\Widget\\Gizmo', $vars['classNameFull']);
64 | $this->assertEquals('Civi\\NamingTest\\Widget', $vars['classNamespace']);
65 | $this->assertEquals('namespace Civi\\NamingTest\\Widget;', $vars['classNamespaceDecl']);
66 | $this->assertEquals('use CRM_NamingTest_ExtensionUtil as E;', $vars['useE']);
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/tests/e2e/CleanEmptyTest.in.txt:
--------------------------------------------------------------------------------
1 | civixGenerateModule(static::getKey());
15 | chdir(static::getKey());
16 |
17 | $this->assertFileExists('info.xml');
18 | }
19 |
20 | public function testCleanup(): void {
21 | $mainPhp = static::getKey() . '.php';
22 | copy(__DIR__ . '/CleanEmptyTest.in.txt', $mainPhp);
23 | $this->assertEquals(0, $this->civix('upgrade')->execute([]));
24 | $this->assertFileEquals(__DIR__ . '/CleanEmptyTest.out.txt', $mainPhp);
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/tests/e2e/IdempotentUpgradeTest.php:
--------------------------------------------------------------------------------
1 | civixGenerateModule(static::getKey(), ['--compatibility' => '5.0']);
19 | chdir(static::getKey());
20 | }
21 |
22 | /**
23 | * Do the upgrade a full replay (`civix upgrade --start=0`).
24 | */
25 | public function testBasicUpgrade(): void {
26 | // Make an example
27 | $this->civixGeneratePage('MyPage', 'civicrm/thirty');
28 | $this->civixGenerateUpgrader(); /* TODO: Make this implicit with generate:entity */
29 | $this->civixGenerateEntity('MyEntity');
30 | $start = $this->getExtSnapshot();
31 |
32 | // Do the upgrade
33 | $result = $this->civixUpgrade()->getDisplay(TRUE);
34 | $expectLines = [
35 | 'Incremental upgrades',
36 | 'General upgrade',
37 | ];
38 | $this->assertStringSequence($expectLines, $result);
39 | $this->assertDoesNotMatchRegularExpression(';Upgrade v([\d\.]+) => v([\d\.]+);', $result);
40 |
41 | // Compare before+after
42 | $end = $this->getExtSnapshot();
43 | $this->assertEquals($start, $end);
44 | }
45 |
46 | /**
47 | * Do the upgrade a full replay (`civix upgrade --start=0`).
48 | */
49 | public function testResetVersion0(): void {
50 | // Make an example
51 | $this->civixGeneratePage('MyPage', 'civicrm/thirty');
52 | $this->civixGenerateUpgrader(); /* TODO: Make this implicit with generate:entity */
53 | $this->civixGenerateEntity('MyEntity');
54 | $start = $this->getExtSnapshot();
55 |
56 | // Do the upgrade
57 | $result = $this->civixUpgrade(['--start' => '0'])->getDisplay(TRUE);
58 | $expectLines = [
59 | 'Incremental upgrades',
60 | 'Upgrade v13.10.0 => v16.10.0',
61 | 'Upgrade v22.05.0 => v22.05.2',
62 | 'General upgrade',
63 | ];
64 | $this->assertStringSequence($expectLines, $result);
65 |
66 | // Compare before+after
67 | $end = $this->getExtSnapshot();
68 | $this->assertEquals($start, $end);
69 | }
70 |
71 | /**
72 | * Do the upgrade a full replay (`civix upgrade --start=22.01.0`).
73 | */
74 | public function testResetVersion2201(): void {
75 | // Make an example
76 | $this->civixGeneratePage('MyPage', 'civicrm/thirty');
77 | $this->civixGenerateUpgrader(); /* TODO: Make this implicit with generate:entity */
78 | $this->civixGenerateEntity('MyEntity');
79 | $start = $this->getExtSnapshot();
80 |
81 | // Do the upgrade
82 | $result = $this->civixUpgrade(['--start' => '22.01.0'])->getDisplay(TRUE);
83 | $expectLines = [
84 | 'Incremental upgrades',
85 | 'Upgrade v22.05.0 => v22.05.2',
86 | 'General upgrade',
87 | ];
88 | $this->assertStringSequence($expectLines, $result);
89 | $this->assertStringNotContainsString('Upgrade v13.10.0 => v16.10.0', $result);
90 |
91 | // Compare before+after
92 | $end = $this->getExtSnapshot();
93 | $this->assertEquals($start, $end);
94 | }
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/tests/e2e/MultiExtensionTest.php:
--------------------------------------------------------------------------------
1 | civixGenerateModule($key);
26 | }
27 |
28 | foreach ($this->visitExts() as $name) {
29 | $this->assertFileGlobs([
30 | 'info.xml' => 1,
31 | "$name.php" => 1,
32 | "$name.civix.php" => 1,
33 | ]);
34 | }
35 | }
36 |
37 | protected function tearDown(): void {
38 | chdir(static::getWorkspacePath());
39 | PH::runOk('civibuild restore');
40 | \Civix::ioStack()->reset();
41 | }
42 |
43 | public function testAddPage(): void {
44 | foreach ($this->visitExts() as $name) {
45 | $camel = ucfirst($name);
46 | $this->assertFileGlobs(["CRM/$camel/Page/My$camel.php" => 0]);
47 | $this->civixGeneratePage("My$camel", "civicrm/example/$name");
48 | $this->assertFileGlobs(["CRM/$camel/Page/My$camel.php" => 1]);
49 |
50 | PH::runOK('cv en ' . escapeshellarg($name));
51 | }
52 |
53 | foreach ($this->visitExts() as $name) {
54 | $camel = ucfirst($name);
55 | $getPage = PH::runOK("cv api4 Route.get +w path=civicrm/example/$name +s page_callback");
56 | $this->assertTrue((bool) preg_match("/CRM_{$camel}_Page_My{$camel}/", $getPage->getOutput()), "Route 'civicrm/example/$name' should be registered");
57 | }
58 | }
59 |
60 | protected function visitExts(): \Generator {
61 | foreach (static::$keys as $key) {
62 | static::$key = $key;
63 | chdir(static::getWorkspacePath());
64 | chdir($key);
65 | yield $key;
66 | }
67 | chdir(static::getWorkspacePath());
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/tests/scenarios/README.md:
--------------------------------------------------------------------------------
1 | Define extra tests to supplement the `make-snapshots.sh` process.
2 |
3 | When running `make-snapshots.sh`, you can give a list of scenarios like `qf`
4 | and `entity4`. Each corresponds to a subfolder. For example, the `entity4`
5 | scenario would have a structure like this
6 |
7 | * `./tests/scenarios/entity4/`
8 | * `make.sh` (generate a new extension; mandatory)
9 | * `phpunit.xml.dist` (phpunit config; recommended)
10 | * `bootstrap.php` (phpunit bootstrap; recommended)
11 | * `MyTest.php` (phpunit test-case; recommended)
12 |
--------------------------------------------------------------------------------
/tests/scenarios/empty/make.sh:
--------------------------------------------------------------------------------
1 | echo "Nothing to add"
--------------------------------------------------------------------------------
/tests/scenarios/entity4/Entity4Test.php:
--------------------------------------------------------------------------------
1 | getMapper();
13 | $this->assertTrue($mapper->isActiveModule('civixsnapshot'), 'Extension civixsnapshot should already be active.');
14 | }
15 |
16 | public function testSchemaExists() {
17 | $table = 'civicrm_my_entity_four';
18 | $exists = \CRM_Core_DAO::checkTableExists($table);
19 | $this->assertTrue($exists, "Table $table should exist");
20 | }
21 |
22 | public function testAlterSchemaField() {
23 | $this->assertEquals(FALSE, CRM_Core_BAO_SchemaHandler::checkIfFieldExists('civicrm_my_entity_four', 'extra_string'), 'extra_string should not yet exist');
24 | E::schema()->alterSchemaField('MyEntityFour', 'extra_string', [
25 | 'title' => ts('Example'),
26 | 'sql_type' => 'varchar(64)',
27 | 'input_type' => 'Text',
28 | 'required' => FALSE,
29 | ]);
30 | $this->assertEquals(TRUE, CRM_Core_BAO_SchemaHandler::checkIfFieldExists('civicrm_my_entity_four', 'extra_string'), 'extra_string should exist');
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/tests/scenarios/entity4/bootstrap.php:
--------------------------------------------------------------------------------
1 | ["pipe", "r"], 1 => ["pipe", "w"], 2 => STDERR];
24 | $oldOutput = getenv('CV_OUTPUT');
25 | putenv("CV_OUTPUT=json");
26 | printf("pwd=%s\n", getcwd());
27 | $process = proc_open($cmd, $descriptorSpec, $pipes, __DIR__);
28 | putenv("CV_OUTPUT=$oldOutput");
29 | fclose($pipes[0]);
30 | $result = stream_get_contents($pipes[1]);
31 | fclose($pipes[1]);
32 | if (proc_close($process) !== 0) {
33 | throw new RuntimeException("Command failed ($cmd):\n$result");
34 | }
35 | switch ($decode) {
36 | case 'raw':
37 | return $result;
38 |
39 | case 'phpcode':
40 | // If the last output is /*PHPCODE*/, then we managed to complete execution.
41 | if (substr(trim($result), 0, 12) !== "/*BEGINPHP*/" || substr(trim($result), -10) !== "/*ENDPHP*/") {
42 | throw new \RuntimeException("Command failed ($cmd):\n$result");
43 | }
44 | return $result;
45 |
46 | case 'json':
47 | return json_decode($result, 1);
48 |
49 | default:
50 | throw new RuntimeException("Bad decoder format ($decode)");
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/tests/scenarios/entity4/make.sh:
--------------------------------------------------------------------------------
1 | $CIVIX $VERBOSITY generate:upgrader
2 | $CIVIX $VERBOSITY generate:entity MyEntityFour
--------------------------------------------------------------------------------
/tests/scenarios/entity4/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
16 | ./src
17 |
18 |
19 |
20 |
21 | ./
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/tests/scenarios/kitchensink/make.sh:
--------------------------------------------------------------------------------
1 | $CIVIX $VERBOSITY generate:api MyEntity Myaction
2 | $CIVIX $VERBOSITY generate:api MyEntity myaction2
3 | $CIVIX $VERBOSITY generate:case-type MyLabel MyName
4 | # $CIVIX $VERBOSITY generate:custom-xml -f --data="FIXME" --uf="FIXME"
5 | $CIVIX $VERBOSITY generate:entity MyEntityFour
6 | $CIVIX $VERBOSITY generate:form MyForm civicrm/my-form
7 | $CIVIX $VERBOSITY generate:form My_StuffyForm civicrm/my-stuffy-form
8 | $CIVIX $VERBOSITY generate:page MyPage civicrm/my-page
9 | $CIVIX $VERBOSITY generate:report MyReport CiviContribute
10 | $CIVIX $VERBOSITY generate:search MySearch
11 | $CIVIX $VERBOSITY generate:test --template=headless 'Civi\Civiexample\BarTest'
12 | $CIVIX $VERBOSITY generate:test --template=e2e 'Civi\Civiexample\EndTest'
13 | $CIVIX $VERBOSITY generate:test --template=phpunit 'Civi\CiviExample\PHPUnitTest'
14 | $CIVIX $VERBOSITY generate:upgrader
15 | $CIVIX $VERBOSITY generate:angular-module
16 | $CIVIX $VERBOSITY generate:angular-page FooCtrl foo
17 | $CIVIX $VERBOSITY generate:angular-directive foo-bar
18 | $CIVIX $VERBOSITY generate:theme
19 | $CIVIX $VERBOSITY generate:theme extratheme
--------------------------------------------------------------------------------
/tests/scenarios/qf/make.sh:
--------------------------------------------------------------------------------
1 | $CIVIX $VERBOSITY generate:page MyPage civicrm/my-page
2 | $CIVIX $VERBOSITY generate:form MyForm civicrm/my-form
--------------------------------------------------------------------------------
/tests/scenarios/svc/make.sh:
--------------------------------------------------------------------------------
1 | $CIVIX $VERBOSITY generate:service some.thing --naming=Civi --no-interaction
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v16.02.0-empty/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v16.02.0-empty/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v16.02.0-kitchensink/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v16.02.0-kitchensink/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v16.02.0-qf/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v16.02.0-qf/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v17.10.5-empty/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v17.10.5-empty/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v17.10.5-kitchensink/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v17.10.5-kitchensink/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v17.10.5-qf/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v17.10.5-qf/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v18.12.0-empty/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v18.12.0-empty/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v18.12.0-entity3/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v18.12.0-entity3/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v18.12.0-kitchensink/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v18.12.0-kitchensink/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v18.12.0-qf/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v18.12.0-qf/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v19.11.0-empty/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v19.11.0-empty/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v19.11.0-entity3/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v19.11.0-entity3/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v19.11.0-kitchensink/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v19.11.0-kitchensink/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v19.11.0-qf/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v19.11.0-qf/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v20.09.0-empty/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v20.09.0-empty/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v20.09.0-entity3/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v20.09.0-entity3/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v20.09.0-kitchensink/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v20.09.0-kitchensink/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v20.09.0-qf/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v20.09.0-qf/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v22.02.0-empty/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v22.02.0-empty/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v22.02.0-entity3/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v22.02.0-entity3/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v22.02.0-entity34/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v22.02.0-entity34/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v22.02.0-kitchensink/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v22.02.0-kitchensink/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v22.02.0-qf/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v22.02.0-qf/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v22.06.0-empty/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v22.06.0-empty/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v22.06.0-entity3/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v22.06.0-entity3/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v22.06.0-entity34/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v22.06.0-entity34/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v22.06.0-kitchensink/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v22.06.0-kitchensink/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v22.06.0-qf/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v22.06.0-qf/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v22.10.2-empty/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v22.10.2-empty/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v22.10.2-entity3/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v22.10.2-entity3/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v22.10.2-entity34/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v22.10.2-entity34/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v22.10.2-kitchensink/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v22.10.2-kitchensink/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v22.10.2-qf/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v22.10.2-qf/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v23.12.1-svc/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v23.12.1-svc/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v23.12.2-entity34/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v23.12.2-entity34/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v23.12.2-entity4/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v23.12.2-entity4/original.zip
--------------------------------------------------------------------------------
/tests/snapshots/org.example.civixsnapshot-v24.09.1-entity4/original.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totten/civix/b4c7e5fe832cb88a91b503a6f7ea436e7637f749/tests/snapshots/org.example.civixsnapshot-v24.09.1-entity4/original.zip
--------------------------------------------------------------------------------
/upgrades/16.10.0.up.php:
--------------------------------------------------------------------------------
1 | ` option.
7 | */
8 | return function (\CRM\CivixBundle\Generator $gen) {
9 | $io = \Civix::io();
10 |
11 | if (!empty($gen->infoXml->get()->upgrader)) {
12 | $io->note("Found tag. Skip hook_postInstall.");
13 | return;
14 | }
15 |
16 | // Give a notice if the new `CRM/*/Upgrader/Base` has a substantive change.
17 | // Note: The change is actually done in the generic regen. This is just a notice.
18 | $phpBaseClass = \CRM\CivixBundle\Utils\Naming::createClassName($gen->infoXml->getNamespace(), 'Upgrader', 'Base');
19 | $phpBaseFile = \CRM\CivixBundle\Utils\Naming::createClassFile($gen->infoXml->getNamespace(), 'Upgrader', 'Base');
20 | if (file_exists($phpBaseFile)) {
21 | $content = file_get_contents($phpBaseFile);
22 | if (preg_match('|CRM_Core_BAO_Setting::setItem\(.revision, *.Extension.|', $content)) {
23 | $io->note([
24 | "$phpBaseClass is based on a very old template.",
25 | "When $phpBaseClass is regenerated, it will transition an important data element from \"civicrm_setting\" to \"civicrm_extension\".",
26 | "Several extensions have made this transition, and there are no known issues.",
27 | "See also: https://issues.civicrm.org/jira/browse/CRM-19252",
28 | ]);
29 | if (!$io->confirm('Continue with upgrade?')) {
30 | throw new \RuntimeException('User stopped upgrade');
31 | }
32 | }
33 |
34 | $gen->addHookDelegation('civicrm_postInstall', '',
35 | "This hook is important for supporting the new version of $phpBaseClass.");
36 | }
37 | else {
38 | $gen->addHookDelegation('civicrm_postInstall', '',
39 | 'If you use civix to facilitate database upgrades ("civix generate:upgrader"), then you should enable this stub. Otherwise, it is not needed.');
40 | }
41 |
42 | };
43 |
--------------------------------------------------------------------------------
/upgrades/19.06.2.up.php:
--------------------------------------------------------------------------------
1 | baseDir->string('tests'), '*.php');
24 | $gen->updateTextFiles($testFiles, function(string $file, string $content) use ($io, $gen) {
25 | $old = 'PHPUnit_Framework_TestCase';
26 | $new = 'PHPUnit\Framework\TestCase';
27 | $relFile = \CRM\CivixBundle\Utils\Files::relativize($file, $gen->baseDir->string() . '/');
28 |
29 | if (strpos($content, $old) === FALSE) {
30 | return $content;
31 | }
32 |
33 | $io->writeln("PHPUnit 6.x+ changed the name of the standard base-class ($old => $new).");
34 | $io->writeln("The file $relFile contains at least one reference to the old name.");
35 | $io->writeln("The upgrader can do an automatic search-replace on this file.");
36 | if ($io->confirm("Perform search/replace?")) {
37 | $content = str_replace($old, $new, $content);
38 | }
39 | return $content;
40 | });
41 |
42 | };
43 |
--------------------------------------------------------------------------------
/upgrades/20.06.0.up.php:
--------------------------------------------------------------------------------
1 | baseDir->string('phpunit.xml'),
13 | $gen->baseDir->string('phpunit.xml.dist'),
14 | ], 'file_exists');
15 | $gen->updateTextFiles($files, function(string $file, string $oldContent) use ($io, $gen) {
16 | $relFile = \CRM\CivixBundle\Utils\Files::relativize($file, $gen->baseDir->string() . '/');
17 |
18 | $content = $oldContent;
19 | $content = preg_replace(';(\s+)syntaxCheck="[^\"]+">;', '>', $content);
20 | $content = preg_replace(';(\s+)syntaxCheck=\'[^\']+\'>;', '>', $content);
21 | $content = preg_replace(';(\s+)syntaxCheck="[^\"]+"(\s+);', '\1', $content);
22 | $content = preg_replace(';(\s+)syntaxCheck=\'[^\']+\'(\s+);', '\1', $content);
23 | if ($content !== $oldContent) {
24 | $io->writeln("$relFile includes obsolete option syntaxCheck=\"...\". Removing it. ");
25 | }
26 | return $content;
27 | });
28 |
29 | };
30 |
--------------------------------------------------------------------------------
/upgrades/22.05.0.up.php:
--------------------------------------------------------------------------------
1 | infoXml->getFile();
7 |
8 | $io->note([
9 | "Civix v22.05 converts several functions to mixins. This reduces code-duplication and will enable easier updates in the future.",
10 | "The upgrader will examine your extension, remove old functions, and enable mixins (if needed).",
11 | "The following functions+mixins may be affected:\n\n" . implode("\n", [
12 | "1. _*_civix_civicrm_angularModules() => ang-php@1.0.0",
13 | "2. _*_civix_civicrm_managed() => mgd-php@1.0.0",
14 | "3. _*_civix_civicrm_alterSettingsFolders() => setting-php@1.0.0",
15 | "4. _*_civix_civicrm_caseTypes() => case-xml@1.0.0",
16 | "5. _*_civix_civicrm_xmlMenu() => menu-xml@1.0.0",
17 | "6. _*_civix_civicrm_themes() => theme-php@1.0.0",
18 | ]),
19 | ]);
20 |
21 | if (!$io->confirm('Continue with upgrade?')) {
22 | throw new \RuntimeException('User stopped upgrade');
23 | }
24 |
25 | // Do we need a mixin like `ang-php`? Maybe... check whether we have files like `*.ang.php`.
26 | $filePatterns = [
27 | 'glob:ang/*.ang.php' => 'ang-php@1.0.0',
28 | 'find:*.mgd.php' => 'mgd-php@1.0.0',
29 | 'glob:settings/*.setting.php' => 'setting-php@1.0.0',
30 | 'glob:xml/case/*.xml' => 'case-xml@1.0.0',
31 | 'glob:xml/Menu/*.xml' => 'menu-xml@1.0.0',
32 | 'glob:*.theme.php' => 'theme-php@1.0.0',
33 | ];
34 | $mixins = array_filter($filePatterns,
35 | function (string $mixin, string $pattern) use ($gen, $io) {
36 | $flagFiles = $gen->baseDir->search($pattern);
37 | $io->note($flagFiles
38 | ? "Enable \"$mixin\". There are files matching pattern \"$pattern\"."
39 | : "Skip \"$mixin\". There are no files matching pattern \"$pattern\"."
40 | );
41 | return (bool) $flagFiles;
42 | },
43 | ARRAY_FILTER_USE_BOTH
44 | );
45 | $gen->addMixins($mixins);
46 |
47 | $gen->removeHookDelegation([
48 | "_{$prefix}_civix_civicrm_angularModules",
49 | "_{$prefix}_civix_civicrm_managed",
50 | "_{$prefix}_civix_civicrm_alterSettingsFolders",
51 | "_{$prefix}_civix_civicrm_caseTypes",
52 | "_{$prefix}_civix_civicrm_xmlMenu",
53 | "_{$prefix}_civix_civicrm_themes",
54 | ]);
55 |
56 | };
57 |
--------------------------------------------------------------------------------
/upgrades/22.05.2.up.php:
--------------------------------------------------------------------------------
1 | infoXml, $gen->baseDir->string('mixin'));
8 | $declared = $mixins->getDeclaredMixinConstraints();
9 | $hasSettingMixin = (bool) preg_grep('/^setting-php@/', $declared);
10 | $action = NULL;
11 |
12 | $gen->updateModulePhp(function (\CRM\CivixBundle\Builder\Info $info, string $content) use ($gen, $hasSettingMixin, &$action) {
13 | $prefix = $gen->infoXml->getFile();
14 | $hookFunc = "{$prefix}_civicrm_alterSettingsFolders";
15 | $hookBody = [
16 | 'static $configured = FALSE;',
17 | 'if ($configured) return;',
18 | '$configured = TRUE;',
19 | '$extRoot = dirname( __FILE__ ) . DIRECTORY_SEPARATOR;',
20 | '$extDir = $extRoot . \'settings\';',
21 | 'if(!in_array($extDir, $metaDataFolders)){',
22 | ' $metaDataFolders[] = $extDir;',
23 | '}',
24 | ];
25 |
26 | $newContent = EvilEx::rewriteMultilineChunk($content, $hookBody, function(array $matchLines) use ($hookFunc, $content, $gen, $hasSettingMixin, &$action) {
27 | /* @var \Symfony\Component\Console\Style\OutputStyle $io */
28 | $io = \Civix::io();
29 | $matchLineKeys = array_keys($matchLines);
30 | $allLines = explode("\n", $content);
31 | $focusStart = min($matchLineKeys);
32 | $focusEnd = max($matchLineKeys);
33 |
34 | $io->note("The following chunk resembles an older template for \"{$hookFunc}()\".");
35 | $gen->showCode($allLines, $focusStart - 4, $focusEnd + 4, $focusStart, $focusEnd);
36 |
37 | if ($hasSettingMixin) {
38 | $io->note([
39 | "Similar functionality is now provided by the \"setting-php\" mixin, which is already enabled.",
40 | ]);
41 | }
42 | else {
43 | $io->note([
44 | "Similar functionality is now available in the \"setting-php\" mixin, which is currently disabled.",
45 | ]);
46 | }
47 |
48 | $actions = [
49 | 'm' => 'Use the mixin ("setting-php") and remove this boilerplate.',
50 | 'b' => 'Use the boilerplate and disable the mixin ("setting-php").',
51 | 'n' => 'Do nothing. Keep as-is. (You may manually change it later.)',
52 | ];
53 | $action = $io->choice("What should we do?", $actions, 'm');
54 | return ($action == 'm') ? [] : $matchLines;
55 | });
56 |
57 | if ($action === 'm' && !$hasSettingMixin) {
58 | $gen->updateMixins(function (Mixins $mixins) {
59 | $mixins->addMixin('setting-php@1.0.0');
60 | });
61 | }
62 | elseif ($action === 'b' && $hasSettingMixin) {
63 | $gen->updateMixins(function (Mixins $mixins) {
64 | $mixins->removeMixin('setting-php');
65 | });
66 | }
67 |
68 | return $newContent;
69 | });
70 |
71 | };
72 |
--------------------------------------------------------------------------------
/upgrades/22.10.0.up.php:
--------------------------------------------------------------------------------
1 | ` for `CRM_`
7 | *
8 | * Just add the '` bit to everything.
9 | */
10 | return function (\CRM\CivixBundle\Generator $gen) {
11 |
12 | $gen->updateInfo(function (\CRM\CivixBundle\Builder\Info $info) use ($gen) {
13 | /* @var \Symfony\Component\Console\Style\OutputStyle $io */
14 | $io = \Civix::io();
15 |
16 | $loaders = $info->getClassloaders();
17 | $prefixes = array_column($loaders, 'prefix');
18 | if (file_exists($gen->baseDir->string('CRM')) && !in_array('CRM_', $prefixes)) {
19 | $io->section('"CRM" Class-loader');
20 | $io->note([
21 | 'Older templates enabled class-loading via "hook_config" and "include_path".',
22 | 'Newer templates enable class-loading via "info.xml" (""). This fixes some edge-case issues and allows more configuration.',
23 | 'It is generally safe for these loaders to coexist. The upgrade will add "" for the "CRM" folder.',
24 | ]);
25 | $io->warning([
26 | 'If you use the rare (and ill-advised/unsupported) practice of class-overrides, then you may need extra diligence with any changes to class-loading.',
27 | ]);
28 |
29 | if (!$io->confirm('Continue with upgrade?')) {
30 | throw new \RuntimeException('User stopped upgrade');
31 | }
32 | $loaders[] = ['type' => 'psr0', 'prefix' => 'CRM_', 'path' => '.'];
33 | $info->setClassLoaders($loaders);
34 | }
35 |
36 | });
37 |
38 | };
39 |
--------------------------------------------------------------------------------
/upgrades/23.01.0.up.php:
--------------------------------------------------------------------------------
1 | 'smarty-v2@1.0.0',
14 | ];
15 | $mixins = array_filter($filePatterns,
16 | function (string $mixin, string $pattern) use ($gen, $io, &$previewChanges) {
17 | $flagFiles = $gen->baseDir->search($pattern);
18 | $previewChanges[] = [
19 | 'info.xml',
20 | $flagFiles ? "Enable $mixin" : "Skip $mixin. (No files match \"$pattern\")",
21 | ];
22 | return (bool) $flagFiles;
23 | },
24 | ARRAY_FILTER_USE_BOTH
25 | );
26 |
27 | $io->note([
28 | "Civix v23.01 simplifies the boilerplate used for Smarty registration.",
29 | "The following may be affected:",
30 | Formatting::ol("%-31s %s\n", $previewChanges),
31 | ]);
32 |
33 | if (!empty($mixins)) {
34 | $io->warning([
35 | "If Smarty templates are used by any lifecycle hooks (install,enable,disable,uninstall,upgrade,managed), then please re-test them.",
36 | ]);
37 | }
38 |
39 | if (!$io->confirm('Continue with upgrade?')) {
40 | throw new \RuntimeException('User stopped upgrade');
41 | }
42 |
43 | $gen->addMixins($mixins);
44 |
45 | };
46 |
--------------------------------------------------------------------------------
/upgrades/23.02.0.up.php:
--------------------------------------------------------------------------------
1 | infoXml->getFile();
9 |
10 | if (is_dir($gen->baseDir->string('xml/schema/CRM'))) {
11 | \Civix::io()->note([
12 | 'Civix 23.02 removes `*_civix_civicrm_entityTypes` in favor of a mixin `entity-types-php@1.0`.',
13 | 'This reduces code-duplication and will enable easier updates in the future.',
14 | 'This may raise the minimum requirements to CiviCRM v5.45.',
15 | ]);
16 | if (!\Civix::io()->confirm('Continue with upgrade?')) {
17 | throw new \RuntimeException('User stopped upgrade');
18 | }
19 |
20 | $gen->addMixins(['entity-types-php@1.0']);
21 | }
22 |
23 | $gen->removeHookDelegation([
24 | "_{$prefix}_civix_civicrm_entityTypes",
25 | ]);
26 |
27 | };
28 |
--------------------------------------------------------------------------------
/upgrades/23.02.1.up.php:
--------------------------------------------------------------------------------
1 | updateInfo(function (\CRM\CivixBundle\Builder\Info $info) use ($gen) {
11 | /* @var \Symfony\Component\Console\Style\OutputStyle $io */
12 | $io = \Civix::io();
13 |
14 | $loaders = $info->getClassloaders();
15 | $prefixes = array_column($loaders, 'prefix');
16 | if (!in_array('Civi\\', $prefixes)) {
17 | $io->section('"Civi" Class-loader');
18 | $io->note([
19 | 'Technologies like APIv4 may require you to use the "Civi" namespace, which is not enabled on this extension.',
20 | 'You can automatically add the "Civi" namespace now to get prepared, or you can skip this.',
21 | '(If you change your mind later, then simply edit "info.xml" to add or remove "" rules.)',
22 | ]);
23 |
24 | if ($io->confirm('Add the "Civi" namespace?')) {
25 | $loaders[] = ['type' => 'psr4', 'prefix' => 'Civi\\', 'path' => 'Civi'];
26 | $info->setClassLoaders($loaders);
27 | }
28 | }
29 |
30 | });
31 |
32 | };
33 |
--------------------------------------------------------------------------------
/upgrades/24.09.0.up.php:
--------------------------------------------------------------------------------
1 | coreHasPathload()) {
13 | $steps[] = 'Create mixin/lib/pathload-0.php';
14 | }
15 | if (!Civix::checker()->coreProvidesLibrary('civimix-schema@5')) {
16 | $steps[] = 'Create mixin/lib/' . basename($gen->mixinLibraries->available['civimix-schema@5']->file);
17 | }
18 |
19 | if (\Civix::checker()->hasUpgrader() && $steps) {
20 | \Civix::io()->note([
21 | "This update adds a new helper, E::schema(), which requires the library civimix-schema@5. To enable support for older versions of CiviCRM (<5.73), the update will:\n\n" . Formatting::ol("%s\n", $steps),
22 | ]);
23 | }
24 |
25 | };
26 |
--------------------------------------------------------------------------------
/upgrades/25.01.0.up.php:
--------------------------------------------------------------------------------
1 | hasSchemaPhp() && !\Civix::checker()->hasMixin('/^entity-types-php@2/')) {
20 | // OK, not our problem.
21 | return;
22 | }
23 |
24 | $gen->updateModulePhp(function (\CRM\CivixBundle\Builder\Info $infoXml, string $body) {
25 | $hookFunc = $infoXml->getFile() . '_civicrm_entityTypes';
26 | $hookDelegate = '_' . $infoXml->getFile() . '_civix_civicrm_entityTypes';
27 |
28 | /**
29 | * @param string $func
30 | * Ex: 'myfile_civicrm_fooBar'
31 | * @param string $sig
32 | * Ex: 'array &$arg1, string $arg2'
33 | * @param string $code
34 | * Ex: 'echo "Hello";\necho "World";'
35 | */
36 | return PrimitiveFunctionVisitor::visit($body, function (string &$func, string &$sig, string &$code) use ($infoXml, $hookFunc, $hookDelegate) {
37 | if ($func !== $hookFunc || empty($code)) {
38 | return NULL;
39 | }
40 |
41 | $lines = preg_split(';\n\w*;', $code);
42 | $lines = array_map('trim', $lines);
43 | $lines = array_filter($lines, function ($line) {
44 | return !empty($line) && !preg_match(';^(#|//);', $line);
45 | });
46 | $delegateRE = '/' . preg_quote($hookDelegate, '/') . '/i';
47 |
48 | // $hasDelegate = !empty(preg_grep($delegateRE, $lines));
49 | $hasBespokeLogic = !empty(preg_grep($delegateRE, $lines, PREG_GREP_INVERT));
50 |
51 | if (!$hasBespokeLogic) {
52 | return NULL;
53 | }
54 |
55 | $io = Civix::io();
56 | $io->title("Suspicious Entity Hook");
57 |
58 | $fullCode = sprintf("function %s(%s) {%s}", $func, $sig, $code);
59 | Civix::generator()->showCode(explode("\n", $fullCode));
60 |
61 | $io->note([
62 | "In Entity Framework v2, conventions for metadata have changed.",
63 | "Metadata is usually loaded from schema/*.entityType.php.",
64 | "This implementation of hook_entityTypes contains special declarations. Consider whether this is needed.",
65 | "For example:\n - This function might duplicate the content of schema/*.entityType.php. Remove it to avoid conflicts.\n - This function might define special, dynamic entities. Keep it ensure continued operation.",
66 | ]);
67 |
68 | $actionLabels = [
69 | 'c' => 'Comment-out this function',
70 | 'k' => 'Keep this function',
71 | 'd' => 'Delete this function',
72 | ];
73 | $action = $io->choice("What should we do with {$func}()?", $actionLabels, 'c');
74 | $results = ['k' => NULL, 'c' => 'COMMENT', 'd' => 'DELETE'];
75 | return $results[$action] ?? NULL;
76 | });
77 | });
78 |
79 | };
80 |
--------------------------------------------------------------------------------
/upgrades/25.01.1.up.php:
--------------------------------------------------------------------------------
1 | baseDir->search('glob:mixin/lib/civimix-schema@5.*.phar')) {
13 | $io = Civix::io();
14 | $io->title("Convert civimix-schema@5");
15 |
16 | $gen->updateMixinLibraries(function (MixinLibraries $mixinLibraries): void {
17 | $mixinLibraries->remove('civimix-schema@5');
18 | $mixinLibraries->add('civimix-schema@5');
19 | });
20 | }
21 |
22 | };
23 |
--------------------------------------------------------------------------------