PageRenderTime 49ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/php/lib/content_object_installer.class.php

https://bitbucket.org/chamilo/chamilo-repository-dev/
PHP | 432 lines | 390 code | 26 blank | 16 comment | 11 complexity | 3fb4b6e970bf3c3774a17747429e5bfb MD5 | raw file
  1. <?php
  2. namespace repository;
  3. use admin\AdminDataManager;
  4. use home\HomeBlockRegistration;
  5. use common\libraries\Translation;
  6. use common\libraries\Path;
  7. use common\libraries\Configuration;
  8. use common\libraries\Utilities;
  9. use common\libraries\EqualityCondition;
  10. use common\libraries\Filesystem;
  11. use common\libraries\FileProperties;
  12. use user\UserDataManager;
  13. use user\User;
  14. use admin\Registration;
  15. use admin\PackageInfo;
  16. use admin\Setting;
  17. use DOMDocument;
  18. /**
  19. * $Id: installer.class.php 198 2009-11-13 12:20:22Z vanpouckesven $
  20. * @package common
  21. * @todo Some more common install-functions can be added here. Example: A
  22. * function which returns the list of xml-files from a given directory.
  23. */
  24. abstract class ContentObjectInstaller
  25. {
  26. const TYPE_NORMAL = '1';
  27. const TYPE_CONFIRM = '2';
  28. const TYPE_WARNING = '3';
  29. const TYPE_ERROR = '4';
  30. const INSTALL_SUCCESS = 'success';
  31. const INSTALL_MESSAGE = 'message';
  32. /**
  33. * The datamanager which can be used by the installer of the application
  34. */
  35. private $data_manager;
  36. /**
  37. * Message to be displayed upon completion of the installation procedure
  38. */
  39. private $message;
  40. /**
  41. * Constructor
  42. */
  43. function __construct()
  44. {
  45. $this->data_manager = RepositoryDataManager :: get_instance();
  46. $this->message = array();
  47. }
  48. function install()
  49. {
  50. if (! $this->register_content_object())
  51. {
  52. return false;
  53. }
  54. $dir = $this->get_path();
  55. $files = Filesystem :: get_directory_content($dir, Filesystem :: LIST_FILES);
  56. foreach ($files as $file)
  57. {
  58. if ((substr($file, - 3) == 'xml'))
  59. {
  60. if (! $this->create_storage_unit($file))
  61. {
  62. return false;
  63. }
  64. }
  65. }
  66. if (! $this->configure_content_object())
  67. {
  68. return false;
  69. }
  70. if (! $this->register_home_blocks())
  71. {
  72. return false;
  73. }
  74. if (method_exists($this, 'install_extra'))
  75. {
  76. if (! $this->install_extra())
  77. {
  78. return false;
  79. }
  80. }
  81. if (! $this->import_content_object())
  82. {
  83. return false;
  84. }
  85. return $this->installation_successful();
  86. }
  87. public function import_content_object()
  88. {
  89. $type = $this->get_content_object();
  90. $file = Path :: get_repository_content_object_path() . $type . '/php/install/example.cpo';
  91. if (file_exists($file))
  92. {
  93. // We need to do this to make sure that the latest registration is also cached.
  94. AdminDataManager :: init_registrations();
  95. $condition = new EqualityCondition(User :: PROPERTY_PLATFORMADMIN, 1);
  96. $user = UserDataManager :: get_instance()->retrieve_users($condition)->next_result();
  97. $category = RepositoryDataManager :: get_instance();
  98. $import = ContentObjectImportController :: factory('cpo', FileProperties :: from_path($file));
  99. if (! $import->run())
  100. {
  101. $message = Translation :: get('ContentObjectImportFailed');
  102. $this->installation_failed($message);
  103. return false;
  104. }
  105. else
  106. {
  107. $this->add_message(self :: TYPE_NORMAL, Translation :: get('ImportSuccessfull'));
  108. }
  109. }
  110. return true;
  111. }
  112. function get_content_object()
  113. {
  114. $content_object_class = $this->get_content_object_name();
  115. $content_object = Utilities :: camelcase_to_underscores($content_object_class);
  116. return $content_object;
  117. }
  118. function get_content_object_name()
  119. {
  120. $classname_parts = explode('\\', get_class($this));
  121. array_pop($classname_parts);
  122. $content_object_class = array_pop($classname_parts);
  123. return Utilities :: underscores_to_camelcase($content_object_class);
  124. }
  125. /**
  126. * Parses an XML file describing a storage unit.
  127. * For defining the 'type' of the field, the same definition is used as the
  128. * PEAR::MDB2 package. See http://pear.php.net/manual/en/package.database.
  129. * mdb2.datatypes.php
  130. * @param string $file The complete path to the XML-file from which the
  131. * storage unit definition should be read.
  132. * @return array An with values for the keys 'name','properties' and
  133. * 'indexes'
  134. */
  135. public static function parse_xml_file($file)
  136. {
  137. $name = '';
  138. $properties = array();
  139. $indexes = array();
  140. $doc = new DOMDocument();
  141. $doc->load($file);
  142. $object = $doc->getElementsByTagname('object')->item(0);
  143. $name = $object->getAttribute('name');
  144. $xml_properties = $doc->getElementsByTagname('property');
  145. $attributes = array('type', 'length', 'unsigned', 'notnull', 'default', 'autoincrement', 'fixed');
  146. foreach ($xml_properties as $index => $property)
  147. {
  148. $property_info = array();
  149. foreach ($attributes as $index => $attribute)
  150. {
  151. if ($property->hasAttribute($attribute))
  152. {
  153. $property_info[$attribute] = $property->getAttribute($attribute);
  154. }
  155. }
  156. $properties[$property->getAttribute('name')] = $property_info;
  157. }
  158. $xml_indexes = $doc->getElementsByTagname('index');
  159. foreach ($xml_indexes as $key => $index)
  160. {
  161. $index_info = array();
  162. $index_info['type'] = $index->getAttribute('type');
  163. $index_properties = $index->getElementsByTagname('indexproperty');
  164. foreach ($index_properties as $subkey => $index_property)
  165. {
  166. $index_info['fields'][$index_property->getAttribute('name')] = array(
  167. 'length' => $index_property->getAttribute('length'));
  168. }
  169. $indexes[$index->getAttribute('name')] = $index_info;
  170. }
  171. $result = array();
  172. $result['name'] = $name;
  173. $result['properties'] = $properties;
  174. $result['indexes'] = $indexes;
  175. return $result;
  176. }
  177. function add_message($type = self :: TYPE_NORMAL, $message)
  178. {
  179. switch ($type)
  180. {
  181. case self :: TYPE_NORMAL :
  182. $this->message[] = $message;
  183. break;
  184. case self :: TYPE_CONFIRM :
  185. $this->message[] = '<span style="color: green; font-weight: bold;">' . $message . '</span>';
  186. break;
  187. case self :: TYPE_WARNING :
  188. $this->message[] = '<span style="color: orange; font-weight: bold;">' . $message . '</span>';
  189. break;
  190. case self :: TYPE_ERROR :
  191. $this->message[] = '<span style="color: red; font-weight: bold;">' . $message . '</span>';
  192. break;
  193. default :
  194. $this->message[] = $message;
  195. break;
  196. }
  197. }
  198. function set_message($message)
  199. {
  200. $this->message = $message;
  201. }
  202. function get_message()
  203. {
  204. return $this->message;
  205. }
  206. function get_data_manager()
  207. {
  208. return $this->data_manager;
  209. }
  210. function retrieve_message()
  211. {
  212. return implode('<br />' . "\n", $this->get_message());
  213. }
  214. /**
  215. * Parses an XML file and sends the request to the database manager
  216. * @param String $path
  217. */
  218. function create_storage_unit($path)
  219. { //print_r($path);
  220. $storage_unit_info = self :: parse_xml_file($path);
  221. $this->add_message(self :: TYPE_NORMAL, Translation :: get('StorageUnitCreation') . ': <em>' . $storage_unit_info['name'] . '</em>');
  222. if (! $this->data_manager->create_storage_unit($storage_unit_info['name'], $storage_unit_info['properties'], $storage_unit_info['indexes']))
  223. {
  224. return $this->installation_failed(Translation :: get('StorageUnitCreationFailed') . ': <em>' . $storage_unit_info['name'] . '</em>');
  225. }
  226. else
  227. {
  228. return true;
  229. }
  230. }
  231. function parse_content_object_settings($file)
  232. {
  233. $doc = new DOMDocument();
  234. $doc->load($file);
  235. $object = $doc->getElementsByTagname('application')->item(0);
  236. // Get events
  237. $events = $doc->getElementsByTagname('setting');
  238. $settings = array();
  239. foreach ($events as $index => $event)
  240. {
  241. $settings[$event->getAttribute('name')] = array('default' => $event->getAttribute('default'),
  242. 'default' => $event->getAttribute('default'), 'user_setting' => $event->getAttribute('user_setting'));
  243. }
  244. return $settings;
  245. }
  246. function configure_content_object()
  247. {
  248. $content_object = $this->get_content_object();
  249. $base_path = Path :: get_repository_content_object_path() . $content_object;
  250. $settings_file = $base_path . '/php/settings/settings_' . $content_object . '.xml';
  251. if (file_exists($settings_file))
  252. {
  253. $xml = $this->parse_content_object_settings($settings_file);
  254. foreach ($xml as $name => $parameters)
  255. {
  256. $setting = new Setting();
  257. $setting->set_context(ContentObject :: get_content_object_type_namespace($content_object));
  258. $setting->set_variable($name);
  259. $setting->set_value($parameters['default']);
  260. $user_setting = $parameters['user_setting'];
  261. if ($user_setting)
  262. $setting->set_user_setting($user_setting);
  263. else
  264. $setting->set_user_setting(0);
  265. if (! $setting->create())
  266. {
  267. $message = Translation :: get('ContentObjectConfigurationFailed');
  268. $this->installation_failed($message);
  269. }
  270. }
  271. $this->add_message(self :: TYPE_NORMAL, Translation :: get('SettingsAdded'));
  272. }
  273. return true;
  274. }
  275. function register_content_object()
  276. {
  277. $this->add_message(self :: TYPE_NORMAL, Translation :: get('ContentObjectRegistration'));
  278. $content_object_registration = new Registration();
  279. $content_object_registration->set_type(Registration :: TYPE_CONTENT_OBJECT);
  280. $content_object_registration->set_name($this->get_content_object());
  281. $content_object_registration->set_status(Registration :: STATUS_ACTIVE);
  282. $package_info = PackageInfo :: factory(Registration :: TYPE_CONTENT_OBJECT, $this->get_content_object());
  283. $package_info = $package_info->get_package();
  284. if ($package_info)
  285. {
  286. $content_object_registration->set_version($package_info->get_version());
  287. $content_object_registration->set_category($package_info->get_category());
  288. }
  289. if (! $content_object_registration->create())
  290. {
  291. return $this->installation_failed(Translation :: get('ContentObjectRegistrationFailed'));
  292. }
  293. $succes = RepositoryRights :: get_instance()->create_location_in_content_objects_subtree($this->get_content_object(), $content_object_registration->get_id(), RepositoryRights :: get_instance()->get_content_objects_subtree_root_id());
  294. if (! $succes)
  295. {
  296. return $this->installation_failed(Translation :: get('ContentObjectLocationRegistrationFailed'));
  297. }
  298. return true;
  299. }
  300. function register_home_blocks()
  301. {
  302. $content_object = $this->get_content_object();
  303. $base_path = Path :: get_repository_content_object_path() . $content_object . '/';
  304. $namespace = ContentObject :: get_content_object_type_namespace($content_object);
  305. $dirblock = $base_path . 'php/blocks/type';
  306. if (is_dir($dirblock))
  307. {
  308. $files = Filesystem :: get_directory_content($dirblock, Filesystem :: LIST_FILES);
  309. if (count($files) > 0)
  310. {
  311. foreach ($files as $file)
  312. {
  313. $file_path_info = pathinfo($file);
  314. if ($file_path_info['extension'] === 'php')
  315. {
  316. $file_info = pathinfo($file_path_info['filename']);
  317. $block_name = $file_info['filename'];
  318. $home_block_registration = new HomeBlockRegistration();
  319. $home_block_registration->set_context($namespace);
  320. $home_block_registration->set_block($block_name);
  321. if (! $home_block_registration->create())
  322. {
  323. return $this->installation_failed(Translation :: get('HomeBlockRegistrationFailed'));
  324. }
  325. }
  326. }
  327. }
  328. }
  329. $this->add_message(self :: TYPE_NORMAL, Translation :: get('HomeBlocksRegistered'));
  330. return true;
  331. }
  332. function installation_failed($error_message)
  333. {
  334. $this->add_message(self :: TYPE_ERROR, $error_message);
  335. $this->add_message(self :: TYPE_ERROR, Translation :: get('ContentObjectInstallFailed'));
  336. $this->add_message(self :: TYPE_ERROR, Translation :: get('PlatformInstallFailed'));
  337. return false;
  338. }
  339. function installation_successful()
  340. {
  341. $this->add_message(self :: TYPE_CONFIRM, Translation :: get('InstallSuccess'));
  342. return true;
  343. }
  344. /**
  345. * Creates an application-specific installer.
  346. * @param string $application The application for which we want to start the installer.
  347. * @param string $values The form values passed on by the wizard.
  348. */
  349. static function factory($type)
  350. {
  351. $class = ContentObject :: type_to_class($type) . 'ContentObjectInstaller';
  352. $file = Path :: get_repository_content_object_path() . $type . '/php/install/' . $type . '_installer.class.php';
  353. if (file_exists($file))
  354. {
  355. require_once $file;
  356. return new $class();
  357. }
  358. else
  359. {
  360. return false;
  361. }
  362. }
  363. abstract function get_path();
  364. }
  365. ?>