Merge pull request #8328 from mlutfy/master-crm18524
[civicrm-core.git] / CRM / Core / CodeGen / Main.php
1 <?php
2
3 /**
4 * Class CRM_Core_CodeGen_Main
5 */
6 class CRM_Core_CodeGen_Main {
7 var $buildVersion;
8 var $db_version;
9 var $cms; // drupal, joomla, wordpress
10
11 var $CoreDAOCodePath;
12 var $sqlCodePath;
13 var $phpCodePath;
14 var $tplCodePath;
15 var $schemaPath; // ex: schema/Schema.xml
16
17 /**
18 * @var string|NULL path in which to store a marker that indicates the last execution of
19 * GenCode. If a matching marker already exists, GenCode doesn't run.
20 */
21 var $digestPath;
22
23 /**
24 * @var string|NULL a digest of the inputs to the code-generator (eg the properties and source files)
25 */
26 var $digest;
27
28 /**
29 * @param $CoreDAOCodePath
30 * @param $sqlCodePath
31 * @param $phpCodePath
32 * @param $tplCodePath
33 * @param $smartyPluginDirs
34 * @param $argCms
35 * @param $argVersion
36 * @param $schemaPath
37 * @param $digestPath
38 */
39 public function __construct($CoreDAOCodePath, $sqlCodePath, $phpCodePath, $tplCodePath, $smartyPluginDirs, $argCms, $argVersion, $schemaPath, $digestPath) {
40 $this->CoreDAOCodePath = $CoreDAOCodePath;
41 $this->sqlCodePath = $sqlCodePath;
42 $this->phpCodePath = $phpCodePath;
43 $this->tplCodePath = $tplCodePath;
44 $this->digestPath = $digestPath;
45 $this->digest = NULL;
46
47 // default cms is 'drupal', if not specified
48 $this->cms = isset($argCms) ? strtolower($argCms) : 'drupal';
49
50 CRM_Core_CodeGen_Util_Smarty::singleton()->setPluginDirs($smartyPluginDirs);
51
52 $versionFile = "version.xml";
53 $versionXML = CRM_Core_CodeGen_Util_Xml::parse($versionFile);
54 $this->db_version = $versionXML->version_no;
55 $this->buildVersion = preg_replace('/^(\d{1,2}\.\d{1,2})\.(\d{1,2}|\w{4,7})$/i', '$1', $this->db_version);
56 if (isset($argVersion)) {
57 // change the version to that explicitly passed, if any
58 $this->db_version = $argVersion;
59 }
60
61 $this->schemaPath = $schemaPath;
62 }
63
64 /**
65 * Automatically generate a variety of files.
66 */
67 public function main() {
68 if (!empty($this->digestPath) && file_exists($this->digestPath) && $this->hasExpectedFiles()) {
69 if ($this->getDigest() === file_get_contents($this->digestPath)) {
70 echo "GenCode has previously executed. To force execution, please (a) omit CIVICRM_GENCODE_DIGEST\n";
71 echo "or (b) remove {$this->digestPath} or (c) call GenCode with new parameters.\n";
72 exit();
73 }
74 // Once we start GenCode, the old build is invalid
75 unlink($this->digestPath);
76 }
77
78 echo "\ncivicrm_domain.version := " . $this->db_version . "\n\n";
79 if ($this->buildVersion < 1.1) {
80 echo "The Database is not compatible for this version";
81 exit();
82 }
83
84 if (substr(phpversion(), 0, 1) != 5) {
85 echo phpversion() . ', ' . substr(phpversion(), 0, 1) . "\n";
86 echo "
87 CiviCRM requires a PHP Version >= 5
88 Please upgrade your php / webserver configuration
89 Alternatively you can get a version of CiviCRM that matches your PHP version
90 ";
91 exit();
92 }
93
94 $specification = new CRM_Core_CodeGen_Specification();
95 $specification->parse($this->schemaPath, $this->buildVersion);
96 # cheese:
97 $this->database = $specification->database;
98 $this->tables = $specification->tables;
99
100 $this->runAllTasks();
101
102 if (!empty($this->digestPath)) {
103 file_put_contents($this->digestPath, $this->getDigest());
104 }
105 }
106
107 public function runAllTasks() {
108 // TODO: This configuration can be manipulated dynamically.
109 $components = $this->getTasks();
110 foreach ($components as $component) {
111 $task = new $component($this);
112
113 if (is_a($task, 'CRM_Core_CodeGen_ITask')) {
114 $task->setConfig($this);
115 $task->run();
116 }
117 else {
118 echo "Bad news: we tried to run a codegen task of an unrecognized type: {$component}\n";
119 exit();
120 }
121 }
122 }
123
124 /**
125 * @return array
126 * Array of class names; each class implements CRM_Core_CodeGen_ITask
127 */
128 public function getTasks() {
129 $components = array(
130 'CRM_Core_CodeGen_Config',
131 'CRM_Core_CodeGen_Reflection',
132 'CRM_Core_CodeGen_Schema',
133 'CRM_Core_CodeGen_DAO',
134 //'CRM_Core_CodeGen_Test',
135 'CRM_Core_CodeGen_I18n',
136 );
137 return $components;
138 }
139
140 /**
141 * Compute a digest based on the inputs to the code-generator (ie the properties
142 * of the codegen and the source files loaded by the codegen).
143 *
144 * @return string
145 */
146 public function getDigest() {
147 if ($this->digest === NULL) {
148 $srcDir = CRM_Core_CodeGen_Util_File::findCoreSourceDir();
149 $files = CRM_Core_CodeGen_Util_File::findManyFiles(array(
150 array("$srcDir/CRM/Core/CodeGen", '*.php'),
151 array("$srcDir/xml", "*.php"),
152 array("$srcDir/xml", "*.tpl"),
153 array("$srcDir/xml", "*.xml"),
154 ));
155
156 $properties = var_export(array(
157 CRM_Core_CodeGen_Util_File::digestAll($files),
158 $this->buildVersion,
159 $this->db_version,
160 $this->cms,
161 $this->CoreDAOCodePath,
162 $this->sqlCodePath,
163 $this->phpCodePath,
164 $this->tplCodePath,
165 $this->schemaPath,
166 $this->getTasks(),
167 ), TRUE);
168
169 $this->digest = md5($properties);
170 }
171 return $this->digest;
172 }
173
174 /**
175 * @return array
176 */
177 public function getExpectedFiles() {
178 return array(
179 $this->sqlCodePath . '/civicrm.mysql',
180 $this->phpCodePath . '/CRM/Contact/DAO/Contact.php',
181 );
182 }
183
184 /**
185 * @return bool
186 */
187 public function hasExpectedFiles() {
188 foreach ($this->getExpectedFiles() as $file) {
189 if (!file_exists($file)) {
190 return FALSE;
191 }
192 }
193 return TRUE;
194 }
195
196 }