Merge remote-tracking branch 'upstream/4.4' into 4.4-master-2014-07-14-13-42-39
[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 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_Template::$smartyPluginDirs = $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 */
68 function main() {
69 if (!empty($this->digestPath) && file_exists($this->digestPath) && $this->hasExpectedFiles()) {
70 if ($this->getDigest() === file_get_contents($this->digestPath)) {
71 echo "GenCode has previously executed. To force execution, please (a) omit CIVICRM_GENCODE_DIGEST\n";
72 echo "or (b) remove {$this->digestPath} or (c) call GenCode with new parameters.\n";
73 exit();
74 }
75 // Once we start GenCode, the old build is invalid
76 unlink($this->digestPath);
77 }
78
79 echo "\ncivicrm_domain.version := ". $this->db_version . "\n\n";
80 if ($this->buildVersion < 1.1) {
81 echo "The Database is not compatible for this version";
82 exit();
83 }
84
85 if (substr(phpversion(), 0, 1) != 5) {
86 echo phpversion() . ', ' . substr(phpversion(), 0, 1) . "\n";
87 echo "
88 CiviCRM requires a PHP Version >= 5
89 Please upgrade your php / webserver configuration
90 Alternatively you can get a version of CiviCRM that matches your PHP version
91 ";
92 exit();
93 }
94
95 $specification = new CRM_Core_CodeGen_Specification();
96 $specification->parse($this->schemaPath, $this->buildVersion);
97 # cheese:
98 $this->database = $specification->database;
99 $this->tables = $specification->tables;
100
101 $this->runAllTasks();
102
103 if (!empty($this->digestPath)) {
104 file_put_contents($this->digestPath, $this->getDigest());
105 }
106 }
107
108 function runAllTasks() {
109 // TODO: This configuration can be manipulated dynamically.
110 $components = $this->getTasks();
111 foreach ($components as $component) {
112 $task = new $component($this);
113
114 if (is_a($task, 'CRM_Core_CodeGen_ITask')) {
115 $task->setConfig($this);
116 $task->run();
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 of class names; each class implements CRM_Core_CodeGen_ITask
126 */
127 public function getTasks() {
128 $components = array(
129 'CRM_Core_CodeGen_Config',
130 'CRM_Core_CodeGen_Reflection',
131 'CRM_Core_CodeGen_Schema',
132 'CRM_Core_CodeGen_DAO',
133 //'CRM_Core_CodeGen_Test',
134 'CRM_Core_CodeGen_I18n',
135 );
136 return $components;
137 }
138
139 /**
140 * Compute a digest based on the inputs to the code-generator (ie the properties
141 * of the codegen and the source files loaded by the codegen).
142 *
143 * @return string
144 */
145 function getDigest() {
146 if ($this->digest === NULL) {
147 $srcDir = CRM_Core_CodeGen_Util_File::findCoreSourceDir();
148 $files = CRM_Core_CodeGen_Util_File::findManyFiles(array(
149 array("$srcDir/CRM/Core/CodeGen", '*.php'),
150 array("$srcDir/xml", "*.php"),
151 array("$srcDir/xml", "*.tpl"),
152 array("$srcDir/xml", "*.xml"),
153 ));
154
155 $properties = var_export(array(
156 CRM_Core_CodeGen_Util_File::digestAll($files),
157 $this->buildVersion,
158 $this->db_version,
159 $this->cms,
160 $this->CoreDAOCodePath,
161 $this->sqlCodePath,
162 $this->phpCodePath,
163 $this->tplCodePath,
164 $this->schemaPath,
165 $this->getTasks(),
166 ), TRUE);
167
168 $this->digest = md5($properties);
169 }
170 return $this->digest;
171 }
172
173 /**
174 * @return array
175 */
176 function getExpectedFiles() {
177 return array(
178 $this->sqlCodePath . '/civicrm.mysql',
179 $this->phpCodePath . '/CRM/Contact/DAO/Contact.php',
180 );
181 }
182
183 /**
184 * @return bool
185 */
186 function hasExpectedFiles() {
187 foreach ($this->getExpectedFiles() as $file) {
188 if (!file_exists($file)) {
189 return FALSE;
190 }
191 }
192 return TRUE;
193 }
194 }