More phpcbs code cleanups
[civicrm-core.git] / tools / bin / scripts / set-version.php
CommitLineData
545fc9df
TO
1#!/usr/bin/env php
2<?php
3
4// Update the data-files within this repo to reflect a new version number.
5// Example usage:
6// git checkout origin/master -b master-4.7.29
7// ./tools/bin/scripts/set-version.php 4.7.29 --commit
8// git commit -m "Update to version 4.7.29"
9// git push origin master
10
11/* *********************************************************************** */
12/* Boot */
5c5ed6db 13if (!(php_sapi_name() == 'cli' || (is_numeric($_SERVER['argc']) && $_SERVER['argc'] > 0))) {
a9f3bf65
SL
14 header("HTTP/1.0 404 Not Found");
15 return;
16}
545fc9df
TO
17$civicrm_root = dirname(dirname(dirname(__DIR__)));
18chdir($civicrm_root);
19
20/* *********************************************************************** */
21/* Parse inputs -- $oldVersion, $newVersion, $doCommit */
22
23$oldVersion = (string) simplexml_load_file("xml/version.xml")->version_no;
24if (!isVersionValid($oldVersion)) {
25 fatal("failed to read old version from \"xml/version.xml\"\n");
26}
27
28a98d7e
EM
28/**
29 * @var string $newVersion */
30/**
31 * @var bool $doCommit */
32/**
33 * @var bool $doSql */
b43bfb44
TO
34extract(parseArgs($argv));
35
545fc9df
TO
36if (!isVersionValid($newVersion)) {
37 fatal("failed to read new version\n");
38}
39
545fc9df
TO
40/* *********************************************************************** */
41/* Main */
42
337dc87a
TO
43echo "Changing version from $oldVersion to $newVersion...\n";
44
45$verName = makeVerName($newVersion);
3bef53f6 46$phpFile = initFile("CRM/Upgrade/Incremental/php/{$verName}.php", function () use ($verName, $newVersion) {
337dc87a
TO
47 ob_start();
48 global $camelNumber;
3bef53f6 49 global $versionNumber;
337dc87a 50 $camelNumber = $verName;
3bef53f6 51 $versionNumber = $newVersion;
337dc87a 52 require 'CRM/Upgrade/Incremental/php/Template.php';
3bef53f6 53 unset($camelNumber, $versionNumber);
337dc87a
TO
54 return ob_get_clean();
55});
56
bd9556c5
TO
57// It is typical for `*.alpha` to need SQL file -- and for `*.beta1` and `*.0` to NOT need a SQL file.
58if ($doSql === TRUE || ($doSql === 'auto' && preg_match(';alpha;', $newVersion))) {
59 $sqlFile = initFile("CRM/Upgrade/Incremental/sql/{$newVersion}.mysql.tpl", function () use ($newVersion) {
60 return "{* file to handle db changes in $newVersion during upgrade *}\n";
61 });
62}
545fc9df
TO
63
64updateFile("xml/version.xml", function ($content) use ($newVersion, $oldVersion) {
65 return str_replace($oldVersion, $newVersion, $content);
66});
67
653b713e
C
68if (file_exists("civicrm-version.php")) {
69 updateFile("civicrm-version.php", function ($content) use ($newVersion, $oldVersion) {
70 return str_replace($oldVersion, $newVersion, $content);
71 });
72}
4d4f529c 73
545fc9df
TO
74updateFile("sql/civicrm_generated.mysql", function ($content) use ($newVersion, $oldVersion) {
75 return str_replace($oldVersion, $newVersion, $content);
76});
77
d071a643
SL
78updateFile("sql/test_data_second_domain.mysql", function ($content) use ($newVersion, $oldVersion) {
79 return str_replace($oldVersion, $newVersion, $content);
80});
81
a9b847ea
TO
82$infoXmls = findCoreInfoXml();
83foreach ($infoXmls as $infoXml) {
68122019
TO
84 updateXmlFile($infoXml, function (DOMDocument $dom) use ($newVersion) {
85 foreach ($dom->getElementsByTagName('version') as $tag) {
28a98d7e 86 /* @var \DOMNode $tag */
68122019
TO
87 $tag->textContent = $newVersion;
88 }
89 });
90}
91
545fc9df 92if ($doCommit) {
bd9556c5 93 $files = array_filter(
a9b847ea 94 array_merge(['xml/version.xml', 'sql/civicrm_generated.mysql', 'sql/test_data_second_domain.mysql', $phpFile, @$sqlFile], $infoXmls),
bd9556c5
TO
95 'file_exists'
96 );
97 $filesEsc = implode(' ', array_map('escapeshellarg', $files));
98 passthru("git add $filesEsc");
99 passthru("git commit $filesEsc -m " . escapeshellarg("Set version to $newVersion"));
545fc9df
TO
100}
101
102/* *********************************************************************** */
103/* Helper functions */
104
337dc87a
TO
105/**
106 * Update the content of a file.
107 *
108 * @param string $file
109 * @param callable $callback
110 * Function(string $originalContent) => string $newContent.
111 */
545fc9df
TO
112function updateFile($file, $callback) {
113 if (!file_exists($file)) {
114 die("File does not exist: $file\n");
115 }
116 echo "Update \"$file\"\n";
117 $content = file_get_contents($file);
118 $content = $callback($content);
119 file_put_contents($file, $content);
120}
121
68122019
TO
122/**
123 * Update the content of an XML file
124 *
125 * @param string $file
126 * @param callable $callback
127 * Function(DOMDocument $dom)
128 */
129function updateXmlFile($file, $callback) {
130 updateFile($file, function ($content) use ($callback) {
131 $dom = new DomDocument();
132 $dom->loadXML($content);
133 $dom->preserveWhiteSpace = FALSE;
134 $dom->formatOutput = TRUE;
135 $callback($dom);
136 return $dom->saveXML();
137 });
138}
139
337dc87a
TO
140/**
141 * Initialize a file (if it doesn't already exist).
142 * @param string $file
143 * @param callable $callback
144 * Function() => string $newContent.
145 */
146function initFile($file, $callback) {
147 if (file_exists($file)) {
148 echo "File \"$file\" already exists.\n";
149 }
150 else {
151 echo "Initialize \"$file\"\n";
152 $content = $callback();
153 file_put_contents($file, $content);
154 }
155 return $file;
156}
157
158/**
159 * Render a pretty string for a major/minor version number.
160 *
161 * @param string $version
162 * Ex: '5.10.alpha1'
163 * @return string
164 * Ex: 'FiveTen'.
165 */
166function makeVerName($version) {
b43bfb44 167 [$a, $b] = explode('.', $version);
337dc87a
TO
168 require_once 'CRM/Utils/EnglishNumber.php';
169 return CRM_Utils_EnglishNumber::toCamelCase($a) . CRM_Utils_EnglishNumber::toCamelCase($b);
170}
171
545fc9df
TO
172function isVersionValid($v) {
173 return $v && preg_match('/^[0-9a-z\.\-]+$/', $v);
174}
175
176/**
177 * @param $error
178 */
179function fatal($error) {
180 echo $error;
bd9556c5
TO
181 echo "usage: set-version.php <new-version> [--sql|--no-sql] [--commit|--no-commit]\n";
182 echo " --sql A placeholder *.sql file will be created.\n";
183 echo " --no-sql A placeholder *.sql file will not be created.\n";
184 echo " --commit Any changes will be committed automatically the current git branch.\n";
185 echo " --no-commit Any changes will be left uncommitted.\n";
186 echo "\n";
187 echo "If the SQL style is not specified, it will decide automatically. (Alpha versions get SQL files.)\n";
188 echo "\n";
189 echo "You MUST indicate whether to commit.\n";
545fc9df
TO
190 exit(1);
191}
b43bfb44
TO
192
193/**
28a98d7e 194 * @param array $argv
b43bfb44
TO
195 * Ex: ['myscript.php', '--no-commit', '5.6.7']
196 * @return array
28a98d7e 197 * Ex: ['scriptFile' => 'myscript.php', 'doCommit' => FALSE, 'newVersion' => '5.6.7']
b43bfb44
TO
198 */
199function parseArgs($argv) {
200 $parsed = [];
bd9556c5 201 $parsed['doSql'] = 'auto';
b43bfb44
TO
202 $positions = ['scriptFile', 'newVersion'];
203 $positional = [];
204
205 foreach ($argv as $arg) {
206 switch ($arg) {
207 case '--commit':
208 $parsed['doCommit'] = TRUE;
209 break;
210
211 case '--no-commit':
212 $parsed['doCommit'] = FALSE;
213 break;
214
bd9556c5
TO
215 case '--sql':
216 $parsed['doSql'] = TRUE;
217 break;
218
219 case '--no-sql':
220 $parsed['doSql'] = FALSE;
221 break;
222
b43bfb44
TO
223 default:
224 if ($arg[0] !== '-') {
225 $positional[] = $arg;
226 }
227 else {
228 fatal("Unrecognized argument: $arg\n");
229 }
230 break;
231 }
232 }
233
234 foreach ($positional as $offset => $value) {
235 $name = $positions[$offset] ?? "unknown_$offset";
236 $parsed[$name] = $value;
237 }
238
239 if (!isset($parsed['doCommit'])) {
240 fatal("Must specify --commit or --no-commit\n");
241 }
242
243 return $parsed;
244}
68122019
TO
245
246/**
247 * @return array
248 * Ex: ['ext/afform/html/info.xml', 'ext/search_kit/info.xml']
249 */
250function findCoreInfoXml() {
251 $lines = explode("\n", file_get_contents('distmaker/core-ext.txt'));
252 $exts = preg_grep(";^#;", $lines, PREG_GREP_INVERT);
253 $exts = preg_grep(';[a-z-A-Z];', $exts);
254
255 $infoXmls = [];
256 foreach ($exts as $coreExtDir) {
257 $infoXmls = array_merge($infoXmls, (array) glob("ext/$coreExtDir/*/info.xml"));
258 if (file_exists("ext/$coreExtDir/info.xml")) {
259 $infoXmls[] = "ext/$coreExtDir/info.xml";
260 }
261 }
262
263 return $infoXmls;
264}