Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
install.inc
1 <?php
37 function regenerate_configs()
38 {
39  // We need to include this so we can find out whether we should save the context
40  // config (which is stored in a database rather than a config file)
41  require_once SQ_LIB_PATH.'/db_install/db_install.inc';
42 
43  // Re-generate the System Config to make sure that we get any new defines that may have been issued
44  require_once SQ_INCLUDE_PATH.'/system_config.inc';
45  $cfg = new System_Config();
46  if (!$cfg->save(Array(), FALSE)) return FALSE;
47 
48  // Re-generate the External Tools Config to make sure that we get any new defines that may have been issued
49  require_once SQ_INCLUDE_PATH.'/external_tools_config.inc';
50  $cfg = new External_Tools_Config();
51  if (!$cfg->save(Array(), FALSE)) return FALSE;
52 
53  // Re-generate the Server Config to make sure that we get any new defines that may have been issued
54  require_once SQ_SYSTEM_ROOT.'/core/server/squiz_server_config.inc';
55  $squiz_server_cfg = new Squiz_Server_Config();
56  if (!$squiz_server_cfg->save(Array(), FALSE)) {
57  return FALSE;
58  }
59 
60  // Re-generate the Apache Config to make sure that we get any new vars that may have been issued
61  require_once SQ_INCLUDE_PATH.'/apache_config.inc';
62  $apache_cfg = new Apache_Config();
63  if (!$apache_cfg->save(Array(), FALSE)) return FALSE;
64 
65  // Re-generate the HIPO Config to make sure that we get any new defines that may have been issued
66  require_once SQ_SYSTEM_ROOT.'/core/hipo/hipo_config.inc';
67  $hipo_cfg = new HIPO_Config();
68  if (!$hipo_cfg->save(Array(), FALSE)) return FALSE;
69 
70  // Re-generate the Messaging Service Config to make sure that we get any new defines that may have been issued
71  require_once SQ_INCLUDE_PATH.'/messaging_service_config.inc';
72  $ms_cfg = new Messaging_Service_Config();
73  if (!$ms_cfg->save(Array(), FALSE)) return FALSE;
74 
75  // Re-generate the Password Rules Config to make sure that we get any new defines that may have been issued
76  require_once SQ_INCLUDE_PATH.'/password_rules_config.inc';
77  $pwd_cfg = new Password_Rules_Config();
78  if (!$pwd_cfg->save(Array(), FALSE)) return FALSE;
79 
80  // Re-generate the Proxy Authentication Config to make sure that we get any new defines that may have been issued
81  require_once SQ_INCLUDE_PATH.'/proxy_authentication_config.inc';
82  $pa_cfg = new Proxy_Authentication_Config();
83  if (!$pa_cfg->save(Array(), FALSE)) return FALSE;
84 
85  // Re-generate the Context Config to ma.... yeah, yeah, you know the deal by now =)
86  // But this is a special case - saving to a DB table rather than a config file
87  // So need to make sure the table exists before saving to it
88  $db_tables = get_database_tables();
89  $query_found = file_exists(MatrixDAL::getOvenPath().'/core/coreQueries.inc') ? TRUE : FALSE;
90  if ((in_array('sq_ctx_def', $db_tables) === TRUE) && ($query_found === TRUE)) {
91  require_once SQ_INCLUDE_PATH.'/context_config.inc';
92  $context_cfg = new Context_Config();
93  $current = $context_cfg->load();
94  if (!$context_cfg->save(Array('contexts' => $current), FALSE)) {
95  return FALSE;
96  }
97  }
98 
99  return TRUE;
100 
101 }//end regenerate_configs()
102 
103 
110 function uninstall_asset_types()
111 {
112  // always contains the full list of asset type_codes currently registered in the database
113  $all_asset_types = $GLOBALS['SQ_SYSTEM']->am->getTypeList();
114 
115  // contains full list (yes we are getting this twice), but will be diff'd with
116  // $package_asset_types leaving what type_codes can be safely deleted
117  $asset_types = $GLOBALS['SQ_SYSTEM']->am->getTypeList();
118 
119  // type_codes of assets which are being claimed by a package
120  $package_asset_types = Array();
121 
122  // find which packages are installed
123  $packages_installed = $GLOBALS['SQ_SYSTEM']->getInstalledPackages();
124 
125  if (!empty($packages_installed)) {
126  foreach ($packages_installed as $package_array) {
127  $package = $package_array['code_name'];
128 
129  // core package is something else
130  if ($package == '__core__') {
131  require_once SQ_CORE_PACKAGE_PATH.'/package_manager_core.inc';
132  $pm = new Package_Manager_Core();
133  $package_asset_types = array_merge($package_asset_types, array_keys($pm->assets));
134  } else {
135  // only process a package if the PM file exists for it, because we need it
136  $package_path = SQ_PACKAGES_PATH.'/'.$package.'/package_manager_'.$package.'.inc';
137  if (file_exists($package_path)) {
138  require_once $package_path;
139  $class = 'package_manager_'.$package;
140  $pm = new $class();
141  $package_asset_types = array_merge($package_asset_types, array_keys($pm->assets));
142  }
143  }
144  }
145  }
146 
147  // What's left after the diff are assets which no package thinks it owns, and can
148  // safely be deleted
149  $asset_types = array_diff($asset_types, $package_asset_types);
150 
151  // Asset types are deleted when no package manager thinks they have the asset type.
152  // They think they have the asset type when the asset.xml says so
153  if (!empty($asset_types)) {
154  $errors = FALSE;
155 
156  // check those asset types that are still going to be there after uninstall
157  // to see whether it depended on something that is being deleted... if it is then
158  // we have massive problems and should bail
159  foreach (array_diff($all_asset_types,$asset_types) as $asset_type) {
160  $asc = $GLOBALS['SQ_SYSTEM']->am->getTypeAncestors($asset_type, FALSE, TRUE);
161  $deleted_parents = array_intersect($asset_types, $asc);
162 
163  // are our parents going to be binned?
164  if (count($deleted_parents) > 0) {
165  trigger_error('One or more of the parents for the asset type \''.$asset_type.'\' no longer exists in the system. The system may be broken until you restore the necessary files of the parent asset type to their proper location.'."\n".'\''.$asset_type.'\' depends on: '.implode(', ', $deleted_parents), E_USER_WARNING);
166  $errors = TRUE;
167  }
168  }
169 
170  // failed dependency tests => bail
171  if ($errors) {
172  trigger_error('Asset hierarchy would be corrupted, uninstall not committed', E_USER_WARNING);
173  exit(1);
174  }
175 
176  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db2');
177  $GLOBALS['SQ_SYSTEM']->doTransaction('BEGIN');
178  $db = MatrixDAL::getDb();
179 
180  // now actually delete the types
181  foreach ($asset_types as $asset_type) {
182  // delete the types
183  try {
184  $sql = 'DELETE FROM sq_ast_typ WHERE type_code = :type_code';
185  $query = MatrixDAL::preparePdoQuery($sql);
186  MatrixDAL::bindValueToPdo($query, 'type_code', $asset_type);
187  MatrixDAL::execPdoQuery($query);
188  } catch (Exception $e) {
189  throw new Exception('Unable to delete type code '.$asset_type.' due to the following database error:'.$e->getMessage());
190  }//end try catch
191 
192 
193  // remove the inherited types
194  try {
195  $sql = 'DELETE FROM sq_ast_typ_inhd
196  WHERE type_code = :type_code
197  OR inhd_type_code = :inhd_type_code';
198 
199  $query = MatrixDAL::preparePdoQuery($sql);
200  MatrixDAL::bindValueToPdo($query, 'type_code', $asset_type);
201  MatrixDAL::bindValueToPdo($query, 'inhd_type_code', $asset_type);
202  MatrixDAL::execPdoQuery($query);
203  } catch (Exception $e) {
204  throw new Exception('Unable to delete inherited type code '.$asset_type.' due to the following database error:'.$e->getMessage());
205  }//end try catch
206 
207  // remove the attributes
208  try {
209  $sql = 'DELETE FROM sq_ast_attr WHERE type_code = :type_code';
210 
211  $query = MatrixDAL::preparePdoQuery($sql);
212  MatrixDAL::bindValueToPdo($query, 'type_code', $asset_type);
213  MatrixDAL::execPdoQuery($query);
214  } catch (Exception $e) {
215  throw new Exception('Unable to delete attribute with type code '.$asset_type.' due to the following database error:'.$e->getMessage());
216  }//end try catch
217  }
218 
219  $GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
220  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
221 
222  // report if we did uninstall some asset types
223  if (!empty($asset_types)) {
224  $ms = $GLOBALS['SQ_SYSTEM']->getMessagingService();
225  $msg_reps = Array(
226  'type_code_list' => implode("\n", $asset_types),
227  );
228  $message = $ms->newMessage(Array(), 'install.asset_type.uninstall', $msg_reps);
229  $message->send();
230  }
231 
232  }//end if asset types not empty
233 
234  // clear the type cache
235  @unlink(SQ_DATA_PATH.'/private/db/asset_types.inc');
236 
237  return TRUE;
238 
239 }//end uninstall_asset_types()
240 
241 
248 function uninstall_packages()
249 {
250  // If the package manager doesn't exist for a package, it does not exist.
251  // Assumption: packages live in the packages directory (Core never gets uninstalled).
252  $packages_installed = $GLOBALS['SQ_SYSTEM']->getInstalledPackages();
253 
254  if (!empty($packages_installed)) {
255  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db2');
256  $GLOBALS['SQ_SYSTEM']->doTransaction('BEGIN');
257  $db = $GLOBALS['SQ_SYSTEM']->db;
258 
259  foreach ($packages_installed as $package_array) {
260  $package = $package_array['code_name'];
261 
262  // never delete the core package!
263  if ($package == '__core__') continue;
264 
265  // package manager should exist for the package to exist
266  $dir = 'packages/'.$package;
267  $exists = file_exists(SQ_SYSTEM_ROOT.'/'.$dir.'/package_manager_'.$package.'.inc');
268 
269  if (!$exists) {
270  // folder or the package manager does not exist, safe to delete
271  $sql = 'DELETE FROM sq_pkg WHERE code_name = :package_name';
272  $query = MatrixDAL::preparePdoQuery($sql);
273  MatrixDAL::bindValueToPdo($query, 'package_name', $package);
274  MatrixDAL::execPdoQuery($query);
275 
276  // remove its asset map file from the data directory
277  if (file_exists(SQ_DATA_PATH.'/private/asset_map/'.$package.'.xml')) {
278  if (!unlink(SQ_DATA_PATH.'/private/asset_map/'.$package.'.xml')) {
279  trigger_error('Could not delete the asset map file for "'.$package.'"', E_USER_WARNING);
280  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
281  exit(1);
282  }
283  } else {
284  trigger_error('Package file does not exist, it must have been deleted before', E_USER_NOTICE);
285  }
286 
287  $ms = $GLOBALS['SQ_SYSTEM']->getMessagingService();
288  $message_body = 'Uninstalled '.$package;
289  $msg_reps = Array(
290  'package' => $package,
291  );
292  $message = $ms->newMessage(Array(), 'install.package.uninstall', $msg_reps);
293  $message->send();
294 
295  }//end if exists
296 
297  }//end foreach installed package
298 
299  $GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
300  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
301 
302  }//end if installed packages not empty
303 
304  return TRUE;
305 
306 }//end uninstall_packages()
307 
308 
318 function install_core($package_list=Array())
319 {
320  // If there's some packages defined in the array, make sure the Core
321  // is one of them, otherwise break out.
322 
323  $assets = Array();
324 
325  if (count($package_list) > 0) {
326  if (!isset($package_list['core'])) {
327  return TRUE;
328  } else {
329  $assets = $package_list['core'];
330  // If it wasn't an array at the core index, just make it empty
331  if (!is_array($assets)) $assets = Array();
332  }
333  }
334  require_once SQ_CORE_PACKAGE_PATH.'/package_manager_core.inc';
335  $pm = new Package_Manager_Core();
336  $result = $pm->updatePackageDetails($assets);
337 
338  $ms = $GLOBALS['SQ_SYSTEM']->getMessagingService();
339  $msg_reps = Array(
340  'package' => 'Core',
341  );
342  $message = $ms->newMessage(Array(), 'install.package.'.($result ? 'success' : 'fail'), $msg_reps);
343  $message->send();
344 
345  if (!$result) exit(1);
346 
347  $result = $pm->installSystemAssets();
348 
349  // 0 (zero) indicates success, but no system assets were created - suppress in this case
350  if ($result != 0) {
351  $ms = $GLOBALS['SQ_SYSTEM']->getMessagingService();
352  $msg_reps = Array(
353  'package' => 'Core',
354  'num_assets' => $result,
355  );
356  $message = $ms->newMessage(Array(), 'install.system_assets.'.($result != -1 ? 'success' : 'fail'), $msg_reps);
357  $message->send();
358 
359  }
360  if ($result == -1) exit(1);
361 
362  // set the current user object to the root user so we can finish
363  // the install process without permission denied errors
364  $root_user = $GLOBALS['SQ_SYSTEM']->am->getSystemAsset('root_user');
365  $GLOBALS['SQ_SYSTEM']->setCurrentUser($root_user);
366 
367  return TRUE;
368 
369 }//end install_core()
370 
371 
378 function get_package_list()
379 {
380  $packages = Array();
381  $d = dir(SQ_PACKAGES_PATH);
382 
383  while (FALSE !== ($entry = $d->read())) {
384  if ($entry == '.' || $entry == '..') {
385  continue;
386  }
387  // if this is a directory, process it
388  if ($entry != 'CVS' && is_dir(SQ_PACKAGES_PATH.'/'.$entry)) {
389  $packages[] = $entry;
390  }
391  }
392  $d->close();
393 
394  return $packages;
395 
396 }//end get_package_list()
397 
398 
413 function install_packages($package_assets=Array())
414 {
415  // right now that we have sorted all that out we can install the packages
416  $d = dir(SQ_PACKAGES_PATH);
417 
418  $deferred_packages = Array();
419 
420  // Do we only install named packages?
421  $limit_packages = count($package_assets);
422  $packages = get_package_list();
423 
424  foreach ($packages as $package) {
425  $assets = Array();
426  if ($limit_packages) {
427  if (!isset($package_assets[$package])) {
428  echo "\nSkipping package $package \n";
429  continue;
430  }
431  $assets = $package_assets[$package];
432  // If it wasn't an array at the core index, just quit.
433  if (!is_array($assets)) $assets = Array();
434  }
435 
436  $result = install_package($package, $assets);
437  if (is_array($result)) {
438  $deferred_packages[$package] = $result;
439  }
440  }
441 
442  return count($deferred_packages) ? $deferred_packages : TRUE;
443 
444 }//end install_packages()
445 
446 
459 function install_package($package, $package_assets=Array())
460 {
461  require_once SQ_PACKAGES_PATH.'/'.$package.'/package_manager_'.$package.'.inc';
462  require_once SQ_LIB_PATH.'/db_install/db_install.inc';
463  $class = 'package_manager_'.$package;
464  $pm = new $class();
465  $result = $pm->updatePackageDetails($package_assets);
466 
467  $ms = $GLOBALS['SQ_SYSTEM']->getMessagingService();
468 
469  if (is_array($result)) {
470  $msg_reps = Array(
471  'package' => $package,
472  );
473  $message = $ms->newMessage(Array(), 'install.package.deferred', $msg_reps);
474  $message->send();
475  return $result;
476  }
477 
478  $message_body = strtoupper($package).' PACKAGE '.(($result) ? 'DONE SUCCESSFULLY' : 'FAILED');
479  $msg_reps = Array(
480  'package' => $package,
481  );
482  $message = $ms->newMessage(Array(), 'install.package.'.($result ? 'success' : 'fail'), $msg_reps);
483  $message->send();
484 
485  if (!$result) exit(1);
486  $result = $pm->installSystemAssets();
487  if ($result != 0) { // 0 indicates success, but no system assets were created - suppress in this case
488  $msg_reps = Array(
489  'package' => $package,
490  'num_assets' => $result,
491  );
492  $message_body = strtoupper($package).' SYSTEM ASSET CREATION '.(($result == -1) ? 'FAILED' : (': '.$result.' NEW ASSETS CREATED'));
493  $message = $ms->newMessage(Array(), 'install.system_assets.'.($result ? 'success' : 'fail'), $msg_reps);
494  $message->send();
495  }
496 
497  if ($result == -1) exit(1);
498  unset($pm);
499 
500  return TRUE;
501 
502 }//end install_package()
503 
504 
515 function install_deferred($packages)
516 {
517  $deferred = install_packages($packages);
518 
519  if ($deferred === TRUE) return TRUE;
520 
521  // if the arrays are identical, return the array
522  if ($deferred == $packages) return $deferred;
523 
524  // the list should be smaller now...
525  return install_deferred($deferred);
526 
527 }//end install_deferred()
528 
529 
536 function install_authentication_types()
537 {
538  // get all the authentication types that are currently installed
539  $auth_types = $GLOBALS['SQ_SYSTEM']->am->getTypeDescendants('authentication');
540 
541  // get installed authentication systems
542  $auth_folder = $GLOBALS['SQ_SYSTEM']->am->getSystemAsset('authentication_folder');
543  $links = $GLOBALS['SQ_SYSTEM']->am->getLinks($auth_folder->id, SQ_LINK_TYPE_1, 'authentication', FALSE);
544  $installed_auth_types = Array();
545  foreach ($links as $link_data) {
546  $installed_auth_types[] = $link_data['minor_type_code'];
547  }
548 
549  // install all systems that are not currently installed
550  $folder_link = Array(
551  'asset' => &$auth_folder,
552  'link_type' => SQ_LINK_TYPE_1,
553  'is_exclusive' => 1,
554  );
555  foreach ($auth_types as $type_code) {
556  if (in_array($type_code, $installed_auth_types)) {
557  continue;
558  }
559  $GLOBALS['SQ_SYSTEM']->am->includeAsset($type_code);
560  $auth = new $type_code();
561 
562  if (!$auth->create($folder_link)) {
563  trigger_error('AUTHENTICATION TYPE "'.strtoupper($type_code).'" NOT CREATED', E_USER_WARNING);
564  } else {
565  $ms = $GLOBALS['SQ_SYSTEM']->getMessagingService();
566  $msg_reps = Array(
567  'auth_type_name' => strtoupper($type_code),
568  'assetid' => $auth->id,
569  );
570  $message = $ms->newMessage(Array(), 'install.authentication', $msg_reps);
571  $message->send();
572 
573  }
574  }
575 
576  return TRUE;
577 
578 }//end install_authentication_types()
579 
580 
587 function generate_global_preferences()
588 {
589  // we need to install any event listeners here, now that we have installed all the asset types.
590  $packages = $GLOBALS['SQ_SYSTEM']->getInstalledPackages();
591 
592  $preferences = Array();
593  if (is_file(SQ_DATA_PATH.'/private/conf/preferences.inc')) {
594  include SQ_DATA_PATH.'/private/conf/preferences.inc';
595  }
596 
597  foreach ($packages as $package) {
598  // slight change for the core package
599  if ($package['code_name'] == '__core__') {
600  require_once SQ_CORE_PACKAGE_PATH.'/package_manager_core.inc';
601  $class = 'package_manager_core';
602  } else {
603  require_once SQ_PACKAGES_PATH.'/'.$package['code_name'].'/package_manager_'.$package['code_name'].'.inc';
604  $class = 'package_manager_'.$package['code_name'];
605  }
606 
607  $pm = new $class();
608  $pm->installUserPreferences($preferences);
609  unset($pm);
610  }
611  $str = '<'.'?php $preferences = '.var_export($preferences, TRUE).'; ?'.'>';
612  if (!string_to_file($str, SQ_DATA_PATH.'/private/conf/preferences.inc')) {
613  return FALSE;
614  }
615 
616  $ms = $GLOBALS['SQ_SYSTEM']->getMessagingService();
617  $message = $ms->newMessage(Array(), 'install.prefs', Array());
618  $message->send();
619 
620  return TRUE;
621 
622 }//end generate_global_preferences()
623 
624 
631 function generate_lang_char_map()
632 {
633  $lang_char_map = Array(
634  'pl' => Array(
635  'ą' => 'a',
636  'ć' => 'c',
637  'ę' => 'e',
638  'ł' => 'l',
639  'ń' => 'n',
640  'ó' => 'o',
641  'ś' => 's',
642  'ż' => 'z',
643  'ź' => 'z',
644  'Ą' => 'a',
645  'Ć' => 'c',
646  'Ę' => 'e',
647  'Ł' => 'l',
648  'Ń' => 'n',
649  'Ó' => 'o',
650  'Ś' => 's',
651  'Ż' => 'z',
652  'Ź' => 'z',
653  ),
654  'en' => Array (
655  'ā' => 'a',
656  'ē' => 'e',
657  'ī' => 'i',
658  'ō' => 'o',
659  'ū' => 'u',
660  'Ā' => 'A',
661  'Ē' => 'E',
662  'Ī' => 'I',
663  'Ō' => 'O',
664  'Ū' => 'U',
665  'á' => 'a',
666  'é' => 'e',
667  'í' => 'i',
668  'ó' => 'o',
669  'ú' => 'u',
670  'ü' => 'u',
671  'ñ' => 'n',
672  'Á' => 'A',
673  'É' => 'E',
674  'Í' => 'I',
675  'Ó' => 'O',
676  'Ú' => 'U',
677  'Ü' => 'U',
678  'Ñ' => 'N',
679  ),
680  );
681 
682  $str = '<'.'?php $lang_char_map = '.var_export($lang_char_map, TRUE).'; ?'.'>';
683  if (!string_to_file($str, SQ_DATA_PATH.'/private/conf/lang_char_map.inc')) {
684  return FALSE;
685  }
686 
687  return TRUE;
688 
689 }//end generate_lang_char_map()
690 
691 
698 function cache_asset_types()
699 {
700  $asset_types = $GLOBALS['SQ_SYSTEM']->am->getAssetTypes();
701  foreach ($asset_types as $type_code => $details) {
702  $asset_types[$type_code]['ancestor_types'] = $GLOBALS['SQ_SYSTEM']->am->getTypeAncestors($type_code, FALSE, TRUE);
703  }
704  $output = '<'.'?php'."\n".' $asset_types = ';
705  $output .= var_export($asset_types, TRUE);
706  $output .= "\n?".'>';
707 
708  if (!string_to_file($output, SQ_DATA_PATH.'/private/db/asset_types.inc')) {
709  trigger_error('Could not cache the asset types', E_USER_ERROR);
710  }
711 
712  pre_echo('ASSET TYPES CACHED');
713 
714 }//end cache_asset_types()
715 
716 
723 function install_event_listeners()
724 {
725  // we need to install any event listeners here, now that we have installed all the asset types
726  $packages = $GLOBALS['SQ_SYSTEM']->getInstalledPackages();
727 
728  $em = $GLOBALS['SQ_SYSTEM']->getEventManager();
729  $em->writeStaticEventsCacheFile();
730 
731  $ms = $GLOBALS['SQ_SYSTEM']->getMessagingService();
732  $message = $ms->newMessage(Array(), 'install.event_listeners', Array());
733  $message->send();
734 
735  return TRUE;
736 
737 }//end install_event_listeners()
738 
739 
746 function generate_performance_config()
747 {
748  $str = "<?php\n";
749  $str .= "#Constants for performance timeline chart\n";
750  $str .= "define('PERFORMANCE_TIME_PRINT_PRECISION', 2);\n";
751  $str .= "define('PERFORMANCE_PERCENTAGE_PRINT_PRECISION', 8);\n";
752 
753  $performance_config = Array(
754  'page_asset_listing' => Array(
755  'report' => 'http://www.squizlabs.com/squiz-matrix/matrix-performance-report-asset-listing-page',
756  )
757  );
758 
759  $str .= '$performance_config = '.var_export($performance_config, TRUE).";\n";
760  $str .= "?>";
761  if (!string_to_file($str, SQ_DATA_PATH.'/private/conf/performance_config.inc')) {
762  return FALSE;
763  }
764 
765  return TRUE;
766 
767 }//end generate_performance_config()
768 
769 
776 function generate_file_bridge_config()
777 {
778  if(is_file(SQ_DATA_PATH.'/private/conf/file_bridge.inc')) return TRUE;
779 
780  $str = "<?php\n";
781  $str .= "#path of file bridge\n";
782  $str .= "define('FILE_BRIDGE_PATH', SQ_DATA_PATH.'/public');\n";
783  $str .= "?>";
784  if (!string_to_file($str, SQ_DATA_PATH.'/private/conf/file_bridge.inc')) {
785  return FALSE;
786  }
787 
788  return TRUE;
789 
790 }//end generate_file_bridge_config()
791 
792 
793 
800 function generate_import_tools_manager_config()
801 {
802  if(is_file(SQ_DATA_PATH.'/private/conf/import_tools_manager.inc')) return TRUE;
803  $structured_import_dir = '';
804  $bulk_file_import_dir = '';
805  if( $GLOBALS['SQ_SYSTEM']->am->installed('import_tools_manager')) {
806  $itm = $GLOBALS['SQ_SYSTEM']->am->getSystemAsset('import_tools_manager');
807  $structured_import_dir = $itm->attr('import_dir');
808  $bulk_file_import_dir = $itm->attr('bulk_file_import_dir');
809  }
810 
811 
812  $str = "<?php\n";
813 
814  $str .= "#path of structured file import directory \n";
815  $str .= "define('STRUCTURED_FILE_IMPORT_DIR', '$structured_import_dir');\n";
816 
817  $str .= "#path of bulk file import directory \n";
818  $str .= "define('BULK_FILE_IMPORT_DIR', '$bulk_file_import_dir');\n";
819 
820  $str .= "?>";
821  if (!string_to_file($str, SQ_DATA_PATH.'/private/conf/import_tools_manager.inc')) {
822  return FALSE;
823  }
824 
825  return TRUE;
826 
827 }//end generate_import_tools_manager_config()
828 
829 
830 
837 function minify_css_files()
838 {
839  pre_echo('Minify JS Files');
840 
841  require_once SQ_SYSTEM_ROOT.'/scripts/ees_minify/jsmin.php';
842 
843  $file = SQ_SYSTEM_ROOT.'/core/lib/js/matrix.min.js';
844 
845  $source_files = Array (
846  SQ_SYSTEM_ROOT.'/fudge/var_serialise/var_serialise.js',
847  SQ_SYSTEM_ROOT.'/core/lib/js/general.js',
848  SQ_SYSTEM_ROOT.'/core/lib/js/debug.js',
849  SQ_SYSTEM_ROOT.'/core/lib/js/layer_handler.js',
850  SQ_SYSTEM_ROOT.'/core/lib/html_form/html_form.js',
851  SQ_SYSTEM_ROOT.'/core/lib/js/detect.js',
852  SQ_SYSTEM_ROOT.'/core/assets/bodycopy/bodycopy/js/bodycopy_edit_divs.js',
853  SQ_SYSTEM_ROOT.'/core/assets/metadata/metadata_fields/metadata_field_select/js/metadata_field_select.js',
854  SQ_SYSTEM_ROOT.'/core/assets/metadata/metadata_fields/metadata_field_multiple_text/js/metadata_field_multiple_text.js',
855  SQ_SYSTEM_ROOT.'/core/assets/metadata/metadata_fields/metadata_field_hierarchy/js/metadata_field_hierarchy.js',
856  );
857 
858  // Output a minified version
859  $string = '';
860  foreach ($source_files as $source) {
861  echo 'processing '.$source."\n";
862  $string .= JSMin::minify(file_get_contents($source));
863  }
864  $result = file_put_contents($file, $string);
865 
866  if($result === FALSE) {
867  trigger_error ("FAILED TO GENREATE MINIFIED JS FILES FOR EES");
868  return FALSE;
869  }
870 
871  echo $file." is completed.\n";
872 
873  return TRUE;
874 }
875 
876 
885 function format_deferred_packages($packages)
886 {
887  $out = '';
888  foreach ($packages as $package => $types) {
889  $out .= "\n".$package.":\n";
890  foreach ($types as $type) {
891  $out .= "\t".$type."\n";
892  }
893  }
894 
895  return $out;
896 
897 }//end format_deferred_packages()
898 
899 
909 function find_asset_type_dirs($asset_type)
910 {
911  if ($asset_type != 'asset') {
912  $asset_dir = SQ_SYSTEM_ROOT.'/'.$GLOBALS['SQ_SYSTEM']->am->getTypeInfo($asset_type, 'dir');
913 
914  $asset_dirs = Array($asset_dir);
915  $parent_type = $asset_type;
916  while (($parent_type = $GLOBALS['SQ_SYSTEM']->am->getTypeInfo($parent_type, 'parent_type')) != 'asset') {
917  $asset_dirs[] = SQ_SYSTEM_ROOT.'/'.$GLOBALS['SQ_SYSTEM']->am->getTypeInfo($parent_type, 'dir');
918  }
919  } else {
920  $asset_dirs = Array();
921  }
922 
923  return $asset_dirs;
924 
925 }//end find_asset_type_dirs()
926 
927 
938 function find_edit_interface_file($asset_type, $file_name)
939 {
940  $file_name = 'edit_interface_'.$file_name.'.xml';
941 
942  $file = '';
943  $asset_dirs = find_asset_type_dirs($asset_type);
944  array_push($asset_dirs, SQ_INCLUDE_PATH.'/asset_edit');
945  for ($i = 0; $i < count($asset_dirs); $i++) {
946  if (file_exists($asset_dirs[$i].'/'.$file_name)) {
947  $file = $asset_dirs[$i].'/'.$file_name;
948  break;
949  }
950  }
951 
952  if (!$file) {
953  trigger_error($file_name.' not found for Asset Type "'.$asset_type.'"', E_USER_WARNING);
954  return FALSE;
955  }
956 
957  return $file;
958 
959 }//end find_edit_interface_file()
960 
961 
976 function find_edit_interface_language_files($asset_type, $file_name, $locale)
977 {
978  $file_name = 'lang_'.$file_name.'.xml';
979 
980  $files = Array();
981  $asset_dirs = find_asset_type_dirs($asset_type);
982  array_push($asset_dirs, SQ_INCLUDE_PATH.'/asset_edit');
983 
984  list($lang, $country, $variant) = $GLOBALS['SQ_SYSTEM']->lm->getLocaleParts($locale);
985 
986  $lang_dirs = Array(strtolower($lang));
987  if (!empty($country)) {
988  array_unshift($lang_dirs, strtolower($lang).'/'.strtoupper($country));
989 
990  if (!empty($variant)) {
991  array_unshift($lang_dirs, strtolower($lang).'/'.strtoupper($country).'/'.$variant);
992  }
993  }
994 
995  for ($i = 0; $i < count($lang_dirs); $i++) {
996  for ($j = 0; $j < count($asset_dirs); $j++) {
997  if (file_exists($asset_dirs[$j].'/locale/'.$lang_dirs[$i].'/'.$file_name)) {
998  $files[] = $asset_dirs[$j].'/locale/'.$lang_dirs[$i].'/'.$file_name;
999  }
1000  }
1001  }
1002 
1003  return $files;
1004 
1005 }//end find_edit_interface_language_files()
1006 
1007 
1018 function build_localised_screen($asset_type, $screen, $locale)
1019 {// TODO: TOF test this function
1020  $ei_file = find_edit_interface_file($asset_type, $screen);
1021 
1022  // get the XML for the edit interface file
1023  try {
1024  $to_cache = new SimpleXMLElement($ei_file, LIBXML_NOCDATA, TRUE);
1025  } catch (Exception $e) {
1026  throw new Exception('Could not open edit interface file "'.$ei_file.'": '.$e->getMessage());
1027  }
1028 
1029  if (count($to_cache->section) <= 0) {
1030  return serialize($to_cache);
1031  }
1032 
1033  $lang_files = find_edit_interface_language_files($asset_type, $screen, $locale);
1034 
1035  foreach ($lang_files as $lang_file) {
1036 
1037  try {
1038  $lang_root = new SimpleXMLElement($lang_file, LIBXML_NOCDATA, TRUE);
1039  } catch (Exception $e) {
1040  throw new Exception('Could not open edit interface localisation file "'.$lang_file.'": '.$e->getMessage());
1041  }
1042 
1043  // work through all the sections
1044  $section_found = FALSE;
1045 
1046  foreach ($lang_root->section as $xml_section) {
1047 
1048  foreach ($to_cache->section as $this_section) {
1049  if (strcmp(((string)$this_section->attributes()->name), ((string)$xml_section->attributes()->name)) === 0) {
1050  $section_found = TRUE;
1051  break;
1052  }
1053  }//end foreach inner
1054 
1055  // not found
1056  if (!$section_found) continue;
1057  // now work through all the fields
1058  foreach ($xml_section->children() as $xml_field) {
1059  switch ($xml_field->getName()) {
1060  case 'display_name':
1061  // is a display name already set?
1062  if (!isset($this_section->attributes()->{'display_name'})) {
1063  $this_section->attributes()->{'display_name'} = (string)$xml_field;
1064  }
1065  break;
1066 
1067  case 'note':
1068  // is a section note already set?
1069  if (!isset($this_section->attributes()->note)) {
1070  $this_section->addChild($xml_field->getName(), (string)$xml_field);
1071  }
1072  break;
1073 
1074  case 'field':
1075  // TODO TOF: write unit tests
1076  // as in the current painting of the interface,
1077  // the existence of an attribute name means we are
1078  // accessing an attribute, otherwise we are accessing
1079  // a function call
1080  if (!isset($xml_field->attributes()->attribute)) {
1081  // first, look for the function call tag in the language file
1082  foreach ($xml_field->children() as $child_field) {
1083  if ($child_field->getName() == 'function_call') {
1084  $xml_paint_field = $child_field;
1085  break;
1086  }
1087  }
1088 
1089  // now, look to see if any of the structure fields match
1090  $field_found = FALSE;
1091  foreach ($this_section->children() as $this_field) {
1092  if (isset($this_field->{'function_call'}->{'paint_function'})) {
1093  $paint_field = $this_field->{'function_call'}->{'paint_function'};
1094  if (strcmp((string)$paint_field->attributes()->name, (string)$xml_paint_field->paint_function->attributes()->name) == 0) {
1095  $field_found = TRUE;
1096  break;
1097  }
1098  }
1099  }
1100 
1101  // not found
1102  if (!$field_found) continue;
1103  // check to see whether we already have a display
1104  // name or note, because we don't want to double
1105  // them up
1106  $has_display_name = FALSE;
1107  $has_note = FALSE;
1108 
1109  foreach ($this_field->children() as $sub_field) {
1110  if ($sub_field->getName() == 'display_name') {
1111  $has_display_name = TRUE;
1112  }
1113 
1114  if ($sub_field->getName() == 'note') $has_note = TRUE;
1115  }
1116 
1117  foreach ($xml_field->children() as $xml_sub_field) {
1118  // in the previous implementation of matrix
1119  // "display_name" element should be added at the first position
1120  // and "note" element should be added to the second last position
1121  // that might cause some problem when reading the xml from other functions
1122  switch ($xml_sub_field->getName()) {
1123  case 'display_name':
1124  case 'note':
1125  $this_field->addChild($xml_sub_field->getName(), (string)$xml_sub_field);
1126  break;
1127 
1128  }
1129 
1130  }
1131 
1132  } else {
1133 
1134  $attr_name = $xml_field->attributes()->attribute;
1135 
1136  $field_found = FALSE;
1137  foreach ($this_section->children() as $this_field) {
1138  if ((string)$this_field->attributes()->attribute === (string)$attr_name) {
1139  $field_found = TRUE;
1140  break;
1141  }
1142  }
1143 
1144  // not found
1145  if (!$field_found) continue;
1146 
1147  // check to see whether we already have a display
1148  // name or note, because we don't want to double
1149  // them up
1150  $has_display_name = FALSE;
1151  $has_note = FALSE;
1152 
1153  foreach ($this_field->children() as $sub_field) {
1154  if ($sub_field->getName() == 'display_name') {
1155  $has_display_name = TRUE;
1156  }
1157 
1158  if ($sub_field->getName() == 'note') $has_note = TRUE;
1159  }
1160 
1161  foreach ($xml_field->children() as $xml_sub_field) {
1162  switch ($xml_sub_field->getName()) {
1163  case 'display_name':
1164  if (!$has_display_name) {
1165  $this_field->addChild($xml_sub_field->getName(), (string)$xml_sub_field);
1166  }
1167  break;
1168 
1169  case 'note':
1170  if (!$has_note) {
1171  $note_value = (string)$xml_sub_field;
1172  // if we got html entities convert them else simple xml might complain when parsing the xml again
1173  if ((stripos($note_value, "<li>") !== FALSE)
1174  || (stripos($note_value, "</li>") !== FALSE)
1175  || (stripos($note_value, "<ul>") !== FALSE)
1176  || (stripos($note_value, "</ul>") !== FALSE)
1177  || (stripos($note_value, "<br />") !== FALSE)) {
1178  $note_value = htmlentities($note_value);
1179  }
1180 
1181  $this_field->addChild($xml_sub_field->getName(), $note_value);
1182  }
1183  break;
1184 
1185  }
1186  }
1187 
1188  }//end else
1189 
1190  break;
1191 
1192  }//end switch
1193 
1194  }//end for
1195 
1196  }//end for
1197 
1198  }//end foreach
1199 
1200  return $to_cache;
1201 
1202 }//end build_localised_screen()
1203 
1204 
1215 function build_localised_static_screen($asset_type, $screen, $locale)
1216 {
1217  $ei_file = find_edit_interface_file($asset_type, $screen);
1218  // get the XML for the edit interface file
1219  try {
1220  $to_cache = new SimpleXMLElement($ei_file, LIBXML_NOCDATA, TRUE);
1221  } catch (Exception $e) {
1222  throw new Exception('Could not open edit interface file "'.$ei_file.'": '.$e->getMessage());
1223  }
1224 
1225  if (count($to_cache->section) <= 0) {
1226  return $to_cache;
1227  }
1228 
1229  $lang_files = find_edit_interface_language_files($asset_type, $screen, $locale);
1230 
1231  foreach ($lang_files as $lang_file) {
1232 
1233  // get the XML for the edit interface file
1234  try {
1235  $lang_root = new SimpleXMLElement($lang_file, LIBXML_NOCDATA, TRUE);
1236  } catch (Exception $e) {
1237  throw new Exception('Could not open edit interface localisation file "'.$lang_file.'": '.$e->getMessage());
1238  }
1239 
1240  // work through all the sections
1241  foreach ($lang_root->children() as $xml_section) {
1242 
1243  $section_found = FALSE;
1244  foreach ($to_cache->children() as $this_section) {
1245 
1246  if ((string)$this_section->attributes()->name === (string)$xml_section->attributes()->name) {
1247  $section_found = TRUE;
1248  break;
1249  }
1250  }
1251 
1252  // not found
1253  if (!$section_found) continue;
1254 
1255  // now work through all the fields
1256  foreach ($xml_section->children() as $xml_field) {
1257 
1258  switch ($xml_field->getName()) {
1259  case 'display_name':
1260  // is a display name already set?
1261  if (is_null($this_section->attributes()->{'display_name'})) {
1262  $this_section->attributes()->{'display_name'} = (string)$xml_field;
1263  }
1264  break;
1265 
1266  case 'note':
1267  // is a section note already set?
1268  if (is_null($this_section->attributes()->note)) {
1269  $this_section->addChild($xml_field->getName(), (string)$xml_field);
1270  }
1271  break;
1272 
1273  case 'field':
1274  // as in the current painting of the interface,
1275  // the existence of an attribute name means we are
1276  // accessing an attribute, otherwise we are accessing
1277  // a function call
1278 
1279  if (is_null($xml_field->attributes()->code)) {
1280  throw new Exception('Failed to parse static localised screen file "'.$lang_file.'": static screen sections need a code for each field.');
1281  } else {
1282 
1283  $code_name = $xml_field->attributes()->code;
1284 
1285  $field_found = FALSE;
1286  foreach ($this_section->children() as $this_field) {
1287  if ((string)$this_field->attributes()->code === (string)$code_name) {
1288  $field_found = TRUE;
1289  break;
1290  }
1291  }
1292 
1293  // not found
1294  if (!$field_found) continue;
1295 
1296  // check to see whether we already have a display
1297  // name or note, because we don't want to double
1298  // them up
1299  $has_display_name = FALSE;
1300  $has_note = FALSE;
1301 
1302  foreach ($this_field->children() as $sub_field) {
1303  if ($sub_field->getName() == 'display_name') {
1304  $has_display_name = TRUE;
1305  }
1306 
1307  if ($sub_field->getName() == 'note') $has_note = TRUE;
1308  }
1309 
1310  foreach ($xml_field->children() as $xml_sub_field) {
1311  switch ($xml_sub_field->getName()) {
1312  case 'display_name':
1313  if (!$has_display_name) {
1314  $this_field->addChild($xml_sub_field->getName(), (string)$xml_sub_field);
1315  }
1316  break;
1317 
1318  case 'note':
1319  // want to insert this as last
1320  if (!$has_note) {
1321  $this_field->addChild($xml_sub_field->getName(), (string)$xml_sub_field);
1322  }
1323  break;
1324 
1325  }
1326  }
1327 
1328  }//end else
1329 
1330  break;
1331 
1332  }//end switch
1333 
1334  }//end for
1335 
1336  }//end for
1337 
1338  }//end foreach
1339 
1340  return $to_cache;
1341 
1342 }//end build_localised_static_screen()
1343 
1344 
1356 function find_string_language_files($asset_dirs, $locale, $file='strings')
1357 {
1358  $file_name = 'lang_'.$file.'.xml';
1359 
1360  $files = Array();
1361 
1362  list($lang, $country, $variant) = $GLOBALS['SQ_SYSTEM']->lm->getLocaleParts($locale);
1363 
1364  $lang_dirs = Array(strtolower($lang));
1365  if (!empty($country)) {
1366  array_unshift($lang_dirs, strtolower($lang).'/'.strtoupper($country));
1367 
1368  if (!empty($variant)) {
1369  array_unshift($lang_dirs, strtolower($lang).'/'.strtoupper($country).'/'.$variant);
1370  }
1371  }
1372 
1373  for ($i = 0; $i < count($lang_dirs); $i++) {
1374  for ($j = 0; $j < count($asset_dirs); $j++) {
1375  if (file_exists($asset_dirs[$j].'/locale/'.$lang_dirs[$i].'/'.$file_name)) {
1376  $files[] = $asset_dirs[$j].'/locale/'.$lang_dirs[$i].'/'.$file_name;
1377  }
1378  }
1379  }
1380 
1381  return $files;
1382 
1383 }//end find_string_language_files()
1384 
1385 
1394 function build_locale_string_file($locale)
1395 {
1396  $asset_types = $GLOBALS['SQ_SYSTEM']->am->getAssetTypes();
1397  $packages = $GLOBALS['SQ_SYSTEM']->getInstalledPackages();
1398 
1399  $files_to_parse = Array(
1400  'core' => Array(),
1401  'packages' => Array(),
1402  'assets' => Array(),
1403  );
1404 
1405  $strings = Array();
1406 
1407  // run through the core
1408  $asset_dirs = Array(SQ_SYSTEM_ROOT.'/core');
1409  $files_to_parse['core'] = find_string_language_files($asset_dirs, $locale);
1410 
1411 
1412  // run through each installed package
1413  foreach ($packages as $package) {
1414  $package_name = $package['code_name'];
1415 
1416  if ($package_name == '__core__') {
1417  $asset_dirs = Array(SQ_CORE_PACKAGE_PATH);
1418  } else {
1419  $asset_dirs = Array(SQ_PACKAGES_PATH.'/'.$package_name);
1420  }
1421 
1422  $files_to_parse['packages'][$package_name] = find_string_language_files($asset_dirs, $locale);
1423  }
1424 
1425  // run through each installed asset
1426  foreach ($asset_types as $asset_type) {
1427  $type_code = $asset_type['type_code'];
1428  $asset_dirs = find_asset_type_dirs($type_code);
1429 
1430  $files_to_parse['assets'][$type_code] = find_string_language_files($asset_dirs, $locale);
1431  }
1432 
1433  $strings = Array();
1434  $js_strings = Array();
1435  $java_strings = Array();
1436 
1437  foreach ($files_to_parse['core'] as $file) {
1438  // grab the strings
1439  list($ex_strings, $ex_js_strings, $ex_java_strings) = extract_strings_from_xml($file, 'strings', 'string', 'source');
1440  $strings = array_merge($strings, $ex_strings);
1441  $js_strings = array_merge($js_strings, $ex_js_strings);
1442  $java_strings = array_merge($java_strings, $ex_java_strings);
1443  }
1444 
1445  if (!empty($strings)) {
1446  create_directory(SQ_DATA_PATH.'/private/system/core');
1447  string_to_file(serialize($strings), SQ_DATA_PATH.'/private/system/core/strings.'.$locale);
1448  }
1449 
1450  foreach ($files_to_parse['packages'] as $package_name => $files) {
1451  $strings = Array();
1452  foreach ($files as $file) {
1453  list($ex_strings, $ex_js_strings, $ex_java_strings) = extract_strings_from_xml($file, 'strings', 'string', 'source');
1454  $strings = array_merge($strings, $ex_strings);
1455  $js_strings = array_merge($js_strings, $ex_js_strings);
1456  $java_strings = array_merge($java_strings, $ex_java_strings);
1457  }
1458 
1459  if ($package_name == '__core__') {
1460  $package_dir = Array(SQ_CORE_PACKAGE_PATH);
1461  } else {
1462  $package_dir = Array(SQ_PACKAGES_PATH.'/'.$package_name);
1463  }
1464  if (!empty($strings)) {
1465  create_directory(SQ_DATA_PATH.'/private/packages/'.$package_name);
1466  string_to_file(serialize($strings), SQ_DATA_PATH.'/private/packages/'.$package_name.'/strings.'.$locale);
1467  }
1468  }
1469 
1470  foreach ($files_to_parse['assets'] as $type_code => $files) {
1471  $strings = Array();
1472  foreach ($files as $file) {
1473  list($ex_strings, $ex_js_strings, $ex_java_strings) = extract_strings_from_xml($file, 'strings', 'string', 'source');
1474  $strings = array_merge($strings, $ex_strings);
1475  $js_strings = array_merge($js_strings, $ex_js_strings);
1476  $java_strings = array_merge($java_strings, $ex_java_strings);
1477  }
1478 
1479  $asset_dir = $asset_types[$type_code]['dir'];
1480  if (!empty($strings)) {
1481  create_directory(SQ_DATA_PATH.'/private/asset_types/'.$type_code);
1482  string_to_file(serialize($strings), SQ_DATA_PATH.'/private/asset_types/'.$type_code.'/strings.'.$locale);
1483  }
1484  }
1485 
1486  // only one JavaScript and one Java file will be kept, in Core
1487  if (!empty($js_strings)) {
1488  create_directory(SQ_DATA_PATH.'/public/system/core');
1489 
1490  $js_file = 'SQ_CURRENT_LOCALE = "'.$locale.'";'."\n".
1491  'translated_strings["'.$locale.'"] = new Array();'."\n";
1492 
1493  foreach ($js_strings as $string_code => $string) {
1494  $string = str_replace("\n", '\\n', $string);
1495  $string = str_replace('"', '\\"', $string);
1496  $js_file .= 'translated_strings["'.$locale.'"]["'.$string_code.'"] = "'.$string.'";'."\n";
1497  }
1498 
1499  string_to_file($js_file, SQ_DATA_PATH.'/public/system/core/js_strings.'.$locale.'.js');
1500  }
1501 
1502  // Similar for Java file, BUT to take advantage of i18n stuff in Java, we
1503  // need to change the replacements to Java 'MessageFormat' format
1504  // eg. '%1$s' => '{0}', '%2$s' => '{1}', etc.
1505  if (!empty($java_strings)) {
1506  create_directory(SQ_DATA_PATH.'/private/system/core');
1507 
1508  $java_file = '';
1509  foreach ($java_strings as $string_code => $string) {
1510  // replace single parameters with {0}
1511  $string = preg_replace('|%s|', '{0}', $string);
1512 
1513  // iterate through the string until there's no more replacements
1514  while (preg_match('|%(\d*)\\$s|', $string, $match, PREG_OFFSET_CAPTURE)) {
1515  // build the Java-style argument and shove it into the string
1516  $new_arg = '{'.((int)$match[1][0]-1).'}';
1517  $string = substr_replace($string, $new_arg, $match[0][1], strlen($match[1][0]) + 3);
1518  }
1519 
1520  $java_file .= $string_code.' = '.$string."\n";
1521  }
1522 
1523  string_to_file($java_file, SQ_DATA_PATH.'/private/system/core/java_strings_'.$locale.'.properties');
1524  }
1525 
1526 }//end build_locale_string_file()
1527 
1528 
1540 function build_locale_error_file($locale)
1541 {
1542  $packages = $GLOBALS['SQ_SYSTEM']->getInstalledPackages();
1543 
1544  $files_to_parse = Array(
1545  'core' => Array(),
1546  'packages' => Array(),
1547  );
1548 
1549  $strings = Array();
1550 
1551  // run through the core
1552  $asset_dirs = Array(SQ_SYSTEM_ROOT.'/core');
1553  $files_to_parse['core'] = find_string_language_files($asset_dirs, $locale, 'errors');
1554 
1555  // run through each installed package
1556  foreach ($packages as $package) {
1557  $package_name = $package['code_name'];
1558 
1559  if ($package_name == '__core__') {
1560  $asset_dirs = Array(SQ_CORE_PACKAGE_PATH);
1561  } else {
1562  $asset_dirs = Array(SQ_PACKAGES_PATH.'/'.$package_name);
1563  }
1564 
1565  $files_to_parse['packages'][$package_name] = find_string_language_files($asset_dirs, $locale, 'errors');
1566  }
1567 
1568  $strings = Array();
1569 
1570  foreach ($files_to_parse['core'] as $file) {
1571  $strings = array_merge(array_get_index($strings, 'core', Array()), extract_errors_from_xml($file, 'errors', 'error', 'code'));
1572  }
1573 
1574  if (!empty($strings)) {
1575  create_directory(SQ_DATA_PATH.'/private/system/core');
1576  string_to_file(serialize($strings), SQ_DATA_PATH.'/private/system/core/errors.'.$locale);
1577  }
1578 
1579  foreach ($files_to_parse['packages'] as $package_name => $files) {
1580  $strings = Array();
1581  foreach ($files as $file) {
1582  $strings = array_merge($strings, extract_errors_from_xml($file, 'errors', 'error', 'code'));
1583  }
1584 
1585  if ($package_name == '__core__') {
1586  $package_dir = Array(SQ_CORE_PACKAGE_PATH);
1587  } else {
1588  $package_dir = Array(SQ_PACKAGES_PATH.'/'.$package_name);
1589  }
1590  if (!empty($strings)) {
1591  create_directory(SQ_DATA_PATH.'/private/packages/'.$package_name);
1592  string_to_file(serialize($strings), SQ_DATA_PATH.'/private/packages/'.$package_name.'/errors.'.$locale);
1593  }
1594  }
1595 
1596 }//end build_locale_error_file()
1597 
1598 
1607 function build_locale_internal_messages_file($locale)
1608 {
1609  $packages = $GLOBALS['SQ_SYSTEM']->getInstalledPackages();
1610 
1611  $files_to_parse = Array(
1612  'core' => Array(),
1613  'packages' => Array(),
1614  );
1615 
1616  $strings = Array();
1617 
1618  // run through the core
1619  $asset_dirs = Array(SQ_SYSTEM_ROOT.'/core');
1620  $files_to_parse['core'] = find_string_language_files($asset_dirs, $locale, 'messages');
1621 
1622  // run through each installed package
1623  foreach ($packages as $package) {
1624  $package_name = $package['code_name'];
1625 
1626  if ($package_name == '__core__') {
1627  $asset_dirs = Array(SQ_CORE_PACKAGE_PATH);
1628  } else {
1629  $asset_dirs = Array(SQ_PACKAGES_PATH.'/'.$package_name);
1630  }
1631 
1632  $files_to_parse['packages'][$package_name] = find_string_language_files($asset_dirs, $locale, 'messages');
1633  }
1634 
1635  $strings = Array();
1636 
1637  $message_types = array();
1638 
1639  foreach ($files_to_parse['core'] as $file) {
1640  $msgs = extract_internal_messages($file);
1641  $message_types = array_merge($message_types, array_keys($msgs));
1642  $strings = array_merge(array_get_index($strings, 'core', Array()), $msgs);
1643 
1644  if (!empty($strings)) {
1645  create_directory(SQ_DATA_PATH.'/private/system/core');
1646  string_to_file(serialize($strings), SQ_DATA_PATH.'/private/system/core/internal_messages.'.$locale);
1647  }
1648  }
1649 
1650  foreach ($files_to_parse['packages'] as $package_name => $files) {
1651  $strings = Array();
1652  foreach ($files as $file) {
1653  $msgs = extract_internal_messages($file);
1654  $message_types = array_merge($message_types, array_keys($msgs));
1655  $strings = array_merge($strings, $msgs);
1656  }
1657 
1658  if ($package_name == '__core__') {
1659  $package_dir = Array(SQ_CORE_PACKAGE_PATH);
1660  } else {
1661  $package_dir = Array(SQ_PACKAGES_PATH.'/'.$package_name);
1662  }
1663  if (!empty($strings)) {
1664  create_directory(SQ_DATA_PATH.'/private/packages/'.$package_name);
1665  string_to_file(serialize($strings), SQ_DATA_PATH.'/private/packages/'.$package_name.'/internal_messages.'.$locale);
1666  }
1667  }
1668 
1669  sort($message_types);
1670  $message_type_string = "<?php\n";
1671  $message_type_string .= '$message_types = '.var_export($message_types, true).";\n";
1672  $message_type_string .= 'return $message_types;'."\n";
1673  // So we don't break syntax highlighting - break up the end of php tag.
1674  $message_type_string .= "?".">";
1675  string_to_file($message_type_string, SQ_DATA_PATH.'/private/system/core/internal_message_types.inc');
1676 
1677 }//end build_locale_internal_messages_file()
1678 
1679 
1691 function extract_child_nodes_from_xml($file, $root_element, $child_element, $key_attribute)
1692 {
1693  $extracted_strings = Array();
1694 
1695  try {
1696  $doc = new DOMDocument();
1697  $doc->load($file);
1698  $xpath = new DOMXPath($doc);
1699  } catch (Exception $e) {
1700  throw new Exception('Could not open XML file "'.$file.'": '.$e->getMessage());
1701  }
1702 
1703  $root_nodes = $xpath->query('/'.$root_element);
1704 
1705  if ((count($root_nodes) !== 1) && $root_nodes->item(0)->nodeName !== $root_element) {
1706  throw new Exception('XML file "'.$file.'" does not appear to be valid - expecting "'.$root_element.'" as document element, found "'.$root->nodeName.'"');
1707  return Array();
1708  } else {
1709  $root = $root_nodes->item(0);
1710  unset($root_nodes);
1711  }
1712 
1713  // Find any non-conforming elements - ie. either not of the type we wanted,
1714  // or containing the attribute that we require.
1715  $non_child_elements = $xpath->evaluate('count(./*[name() != "'.$child_element.'"])', $root);
1716  $missing_attributes = $xpath->evaluate('count(./*[name() = "'.$child_element.'" and not(@'.$key_attribute.')])', $root);
1717 
1718  if (($non_child_elements > 0) || ($missing_attributes > 0)) {
1719  // Failure: construct the message based on exactly what was wrong with it.
1720  $msg = 'XML file "'.$file.'" does not appear to be valid.';
1721  if ($non_child_elements > 0) {
1722  $msg .= ' Found '.$non_child_elements.' element(s) not of the expected type "'.$child_element.'".';
1723  }
1724  if ($missing_attributes > 0) {
1725  $msg .= ' Found '.$missing_attributes.' element(s) of type "'.$child_element.'" that do not contain the required attribute "'.$key_attribute.'".';
1726  }
1727  throw new Exception($msg);
1728  return Array();
1729  }
1730 
1731  // File seems okay, so return the child nodes
1732  $child_nodes = $xpath->query('./'.$child_element, $root);
1733  return $child_nodes;
1734 
1735 }//end extract_child_nodes_from_xml()
1736 
1737 
1753 function extract_strings_from_xml($file, $root_element, $child_element, $key_attribute)
1754 {
1755  $extracted_strings = Array();
1756  $js_strings = Array();
1757  $java_strings = Array();
1758 
1759  $children = extract_child_nodes_from_xml($file, $root_element, $child_element, $key_attribute);
1760 
1761  foreach ($children as $string_node) {
1762  if ($string_node->nodeName !== $child_element) {
1763  throw new Exception('XML file "'.$file.'" does not appear to be valid - expecting node "'.$child_element.'", found "'.$string_node->nodeName.'"');
1764  return Array();
1765  }
1766 
1767  if (!$string_node->hasAttribute($key_attribute)) {
1768  throw new Exception('XML file "'.$file.'" does not appear to be valid - missing attribute "'.$key_attribute.'" in string node');
1769  return Array();
1770  }
1771 
1772  $source_code = $string_node->getAttribute($key_attribute);
1773  $translation = $string_node->nodeValue;
1774 
1775  // have it already been set in this file?
1776  if (isset($extracted_strings[$source_code])) {
1777  throw new Exception('XML file "'.$file.'" does not appear to be valid - detected duplicate code "'.$source_code.'"');
1778  return Array(Array(), Array(), Array());
1779  } else if (empty($translation)) {
1780  throw new Exception('Skipping translation for code "'.$source_code.'" as the translation appears to be empty');
1781  } else if (preg_match_all('|[^%]%s|', $translation, $matches) > 1) {
1782  throw new Exception('Skipping translation for code "'.$source_code.'"; it has multiple occurrences of unpositioned "%s" - use positioned replacements (eg. "%1$s") when you have more than one');
1783  } else {
1784 
1785  $extracted_strings[$source_code] = $translation;
1786 
1787  if ($string_node->hasAttribute('js') && ($string_node->getAttribute('js') == 1)) {
1788  $js_strings[$source_code] = $extracted_strings[$source_code];
1789  }
1790  if ($string_node->hasAttribute('java') && ($string_node->getAttribute('java') == 1)) {
1791  $java_strings[$source_code] = $extracted_strings[$source_code];
1792  }
1793  }
1794 
1795  }//end foreach string_node
1796 
1797  return Array($extracted_strings, $js_strings, $java_strings);
1798 
1799 }//end extract_strings_from_xml()
1800 
1801 
1817 function extract_errors_from_xml($file, $root_element, $child_element, $key_attribute)
1818 {
1819  $extracted_strings = Array();
1820 
1821  $children = extract_child_nodes_from_xml($file, $root_element, $child_element, $key_attribute);
1822 
1823  foreach ($children as $string_node) {
1824  if ($string_node->nodeName != $child_element) {
1825  throw new Exception('XML file "'.$file.'" does not appear to be valid - expecting node "'.$child_element.'", found "'.$string_node->nodeName.'"');
1826  return Array();
1827  }
1828 
1829  if (!$string_node->hasAttribute($key_attribute)) {
1830  throw new Exception('XML file "'.$file.'" does not appear to be valid - missing attribute "'.$key_attribute.'" in string node');
1831  return Array();
1832  }
1833 
1834  $source_code = $string_node->getAttribute($key_attribute);
1835  $translation = html_entity_decode($string_node->nodeValue);
1836 
1837  // have it already been set in this file?
1838  if (isset($extracted_strings[$source_code])) {
1839  throw new Exception('XML file "'.$file.'" does not appear to be valid - detected duplicate code "'.$source_code.'"');
1840  return Array(Array(), Array(), Array());
1841  } else if (empty($translation)) {
1842  throw new Exception('Skipping translation for code "'.$source_code.'" as the translation appears to be empty');
1843  } else if (preg_match_all('|%s|', $translation, $matches) > 1) {
1844  throw new Exception('Skipping translation for code "'.$source_code.'"; it has multiple occurrences of unpositioned "%s" - use positioned replacements (eg. "%1$s") when you have more than one');
1845  } else {
1846  $extracted_strings[$source_code] = $translation;
1847  }
1848 
1849  }//end foreach string_node
1850 
1851  return $extracted_strings;
1852 
1853 }//end extract_errors_from_xml()
1854 
1855 
1869 function extract_internal_messages($file)
1870 {
1871  $root_element = 'messages';
1872  $child_element = 'message';
1873  $key_attribute = 'type';
1874  $extracted_messages = Array();
1875 
1876  $children = extract_child_nodes_from_xml($file, $root_element, $child_element, $key_attribute);
1877 
1878  foreach ($children as $string_node) {
1879  if ($string_node->nodeName != $child_element) {
1880  throw new Exception('XML file "'.$file.'" does not appear to be valid - expecting node "'.$child_element.'", found "'.$string_node->nodeName.'"');
1881  return Array();
1882  }
1883 
1884  if (!$string_node->hasAttribute($key_attribute)) {
1885  throw new Exception('XML file "'.$file.'" does not appear to be valid - missing attribute "'.$key_attribute.'" in string node');
1886  return Array();
1887  }
1888 
1889  $source_code = $string_node->getAttribute($key_attribute);
1890  $translation = Array();
1891 
1892  foreach ($string_node->childNodes as $sub_node) {
1893  $sub_node_name = $sub_node->nodeName;
1894  if (($sub_node_name == 'subject') || ($sub_node_name == 'body')) {
1895  $translation[$sub_node_name] = html_entity_decode($sub_node->nodeValue);
1896  }
1897  }
1898 
1899  if (!isset($translation['subject']) || !isset($translation['body'])) {
1900  // we don't have enough stuff?
1901  throw new Exception('XML file "'.$file.'" does not appear to be valid - internal message type "'.$source_code.'" does not seem to have a subject and body');
1902  } else if (isset($extracted_messages[$source_code])) {
1903  // have it already been set in this file?
1904  throw new Exception('XML file "'.$file.'" does not appear to be valid - detected duplicate message type "'.$source_code.'"');
1905  return Array();
1906  } else if (empty($translation)) {
1907  throw new Exception('Skipping translation for code "'.$source_code.'" as the translation appears to be empty');
1908  } else {
1909  $extracted_messages[$source_code]['subject'] = $translation['subject'];
1910  $extracted_messages[$source_code]['body'] = $translation['body'];
1911  }
1912 
1913  }//end foreach string_node
1914 
1915  return $extracted_messages;
1916 
1917 }//end extract_internal_messages()
1918 
1919 
1935 function generate_install_key($create_key_file=FALSE)
1936 {
1937  $host = php_uname('n');
1938  $ip = gethostbyname($host);
1939  $install_key = md5($host.'-'.$ip.'-'.SQ_SYSTEM_ROOT);
1940 
1941  if ($create_key_file) {
1942  require_once SQ_INCLUDE_PATH.'/system_config.inc';
1943  $cfg = new System_Config();
1944  ob_start();
1945  if (!$cfg->save(Array('SQ_LICENCE_INSTALL_KEY' => $install_key), FALSE, FALSE)) {
1946  ob_end_clean();
1947  return NULL;
1948  }
1949  ob_end_clean();
1950  }
1951 
1952  return $install_key;
1953 
1954 }//end generate_install_key()
1955 
1956 
1963 function install_dal_core_queries()
1964 {
1965  $old_path = ini_get('include_path');
1966  ini_set('include_path', SQ_LIB_PATH);
1967  require_once SQ_LIB_PATH.'/MatrixDAL/MatrixDALBaker.inc';
1970  ini_set('include_path', $old_path);
1971 
1972 }//end install_dal_core_queries()
1973 
1982 function install_dal_package_queries($name)
1983 {
1984  $old_path = ini_get('include_path');
1985  ini_set('include_path', SQ_LIB_PATH);
1986  require_once SQ_LIB_PATH.'/MatrixDAL/MatrixDALBaker.inc';
1987  $queries_found = MatrixDALBaker::addPackageQueries($name);
1988  if ($queries_found) {
1989  MatrixDALBaker::bakeQueriesFile($name.'_package');
1990  }
1991  ini_set('include_path', $old_path);
1992 
1993 }//end install_dal_core_queries()
1994 
1995 ?>