PageRenderTime 42ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/system/cms/modules/widgets/libraries/Widgets.php

https://github.com/marcoscoelho/pyrocms
PHP | 497 lines | 361 code | 111 blank | 25 comment | 26 complexity | ff6de2a9177f3610a50fd1aa63ea4d6e MD5 | raw file
  1. <?php defined('BASEPATH') OR exit('No direct script access allowed');
  2. /**
  3. * @package PyroCMS
  4. * @subpackage Widget module
  5. * @author Phil Sturgeon - PyroCMS Development Team
  6. *
  7. * Widget library takes care of the logic for widgets
  8. */
  9. class Widgets {
  10. private $_widget = NULL;
  11. private $_rendered_areas = array();
  12. private $_widget_locations = array();
  13. function __construct()
  14. {
  15. $this->load->model('widgets/widget_m');
  16. $locations = array(
  17. APPPATH,
  18. ADDONPATH,
  19. SHARED_ADDONPATH,
  20. );
  21. if (defined('ADMIN_THEME'))
  22. {
  23. $locations += array(
  24. SHARED_ADDONPATH.'themes/'.ADMIN_THEME.'/',
  25. APPPATH.'themes/'.ADMIN_THEME.'/',
  26. ADDONPATH.'themes/'.ADMIN_THEME.'/',
  27. );
  28. }
  29. // Map where all widgets are
  30. foreach ($locations as $path)
  31. {
  32. $widgets = glob($path . 'widgets/*', GLOB_ONLYDIR);
  33. if ( ! is_array($widgets))
  34. {
  35. $widgets = array();
  36. }
  37. $module_widgets = glob($path . 'modules/*/widgets/*', GLOB_ONLYDIR);
  38. if ( ! is_array($module_widgets))
  39. {
  40. $module_widgets = array();
  41. }
  42. $widgets = array_merge($widgets, $module_widgets);
  43. foreach ($widgets as $widget_path)
  44. {
  45. $slug = basename($widget_path);
  46. // Set this so we know where it is later
  47. $this->_widget_locations[$slug] = $widget_path . '/';
  48. }
  49. }
  50. }
  51. function list_areas()
  52. {
  53. return $this->widget_m->get_areas();
  54. }
  55. function list_area_instances($slug)
  56. {
  57. return is_array($slug) ? $this->widget_m->get_by_areas($slug) : $this->widget_m->get_by_area($slug);
  58. }
  59. function list_available_widgets()
  60. {
  61. // Firstly, install any uninstalled widgets
  62. $uninstalled_widgets = $this->list_uninstalled_widgets();
  63. foreach ($uninstalled_widgets as $widget)
  64. {
  65. $this->add_widget((array) $widget);
  66. }
  67. // Secondly, uninstall any installed widgets missed
  68. $installed_widgets = $this->widget_m->order_by('slug')->get_all();
  69. $avaliable = array();
  70. foreach ($installed_widgets as $widget)
  71. {
  72. if ( ! isset($this->_widget_locations[$widget->slug]))
  73. {
  74. $this->delete_widget($widget->slug);
  75. continue;
  76. }
  77. // Finally, check if is need and update the widget info
  78. $widget_file = FCPATH . $this->_widget_locations[$widget->slug] . $widget->slug . EXT;
  79. if (file_exists($widget_file) &&
  80. filemtime($widget_file) > $widget->updated_on)
  81. {
  82. $this->reload_widget($widget->slug);
  83. log_message('debug', sprintf('The information of the widget "%s" has been updated', $widget->slug));
  84. }
  85. $avaliable[] = $widget;
  86. }
  87. return $avaliable;
  88. }
  89. function list_uninstalled_widgets()
  90. {
  91. $available = $this->widget_m->order_by('slug')->get_all();
  92. $available_slugs = array();
  93. foreach ($available as $widget)
  94. {
  95. $available_slugs[] = $widget->slug;
  96. }
  97. unset($widget);
  98. $uninstalled = array();
  99. foreach ($this->_widget_locations as $widget_path)
  100. {
  101. $slug = basename($widget_path);
  102. if ( ! in_array($slug, $available_slugs) AND $widget = $this->read_widget($slug))
  103. {
  104. $uninstalled[] = $widget;
  105. }
  106. }
  107. return $uninstalled;
  108. }
  109. function get_instance($instance_id)
  110. {
  111. $widget = $this->widget_m->get_instance($instance_id);
  112. if ($widget)
  113. {
  114. $widget->options = $this->_unserialize_options($widget->options);
  115. return $widget;
  116. }
  117. return FALSE;
  118. }
  119. function get_area($id)
  120. {
  121. return is_numeric($id) ? $this->widget_m->get_area_by('id', $id) : $this->widget_m->get_area_by('slug', $id);
  122. }
  123. function get_widget($id)
  124. {
  125. return is_numeric($id) ? $this->widget_m->get_widget_by('id', $id) : $this->widget_m->get_widget_by('slug', $id);
  126. }
  127. function read_widget($slug)
  128. {
  129. $this->_spawn_widget($slug);
  130. if ($this->_widget === FALSE OR ! is_subclass_of($this->_widget, 'Widgets'))
  131. {
  132. return FALSE;
  133. }
  134. $widget = (object) get_object_vars($this->_widget);
  135. $widget->slug = $slug;
  136. $widget->module = strpos($this->_widget->path, 'modules/') ? basename(dirname($this->_widget->path)) : NULL;
  137. $widget->is_addon = strpos($this->_widget->path, 'addons/') !== FALSE;
  138. return $widget;
  139. }
  140. function render($name, $options = array())
  141. {
  142. $this->_spawn_widget($name);
  143. $data = method_exists($this->_widget, 'run') ? call_user_func(array($this->_widget, 'run'), $options) : array();
  144. // Don't run this widget
  145. if ($data === FALSE)
  146. {
  147. return FALSE;
  148. }
  149. // If we have TRUE, just make an empty array
  150. $data !== TRUE OR $data = array();
  151. // convert to array
  152. is_array($data) OR $data = (array) $data;
  153. $data['options'] = $options;
  154. return $this->load_view('display', $data);
  155. }
  156. function render_backend($name, $saved_data = array())
  157. {
  158. $this->_spawn_widget($name);
  159. // No fields, no backend, no rendering
  160. if (empty($this->_widget->fields))
  161. {
  162. return '';
  163. }
  164. $options = array();
  165. $_arrays = array();
  166. foreach ($this->_widget->fields as $field)
  167. {
  168. $field_name = &$field['field'];
  169. if (($pos = strpos($field_name, '[')) !== FALSE)
  170. {
  171. $key = substr($field_name, 0, $pos);
  172. if ( ! in_array($key, $_arrays))
  173. {
  174. $options[$key] = $this->input->post($key);
  175. $_arrays[] = $key;
  176. }
  177. }
  178. $options[$field_name] = set_value($field_name, isset($saved_data[$field_name]) ? $saved_data[$field_name] : '');
  179. unset($saved_data[$field_name]);
  180. }
  181. // Any extra data? Merge it in, but options wins!
  182. if ( ! empty($saved_data))
  183. {
  184. $options = array_merge($saved_data, $options);
  185. }
  186. // Check for default data if there is any
  187. $data = method_exists($this->_widget, 'form') ? call_user_func(array(&$this->_widget, 'form'), $options) : array();
  188. // Options we'rent changed, lets use the defaults
  189. isset($data['options']) OR $data['options'] = $options;
  190. return $this->load_view('form', $data);
  191. }
  192. function render_area($area)
  193. {
  194. if (isset($this->_rendered_areas[$area]))
  195. {
  196. return $this->_rendered_areas[$area];
  197. }
  198. $widgets = $this->widget_m->get_by_area($area);
  199. $output = '';
  200. $view = 'widget_wrapper';
  201. $path = $this->template->get_views_path() . 'modules/widgets/';
  202. if ( ! file_exists($path . $view . EXT))
  203. {
  204. list($path, $view) = Modules::find($view, 'widgets', 'views/');
  205. }
  206. // save the existing view array so we can restore it
  207. $save_path = $this->load->get_view_paths();
  208. foreach ($widgets as $widget)
  209. {
  210. $widget->options = $this->_unserialize_options($widget->options);
  211. $widget->body = $this->render($widget->slug, $widget->options);
  212. if ($widget->body !== FALSE)
  213. {
  214. // add this view location to the array
  215. $this->load->set_view_path($path);
  216. $output .= $this->load->_ci_load(array('_ci_view' => $view, '_ci_vars' => array('widget' => $widget), '_ci_return' => TRUE)) . "\n";
  217. // Put the old array back
  218. $this->load->set_view_path($save_path);
  219. }
  220. }
  221. $this->_rendered_areas[$area] = $output;
  222. return $output;
  223. }
  224. function reload_widget($slug)
  225. {
  226. if (is_array($slug))
  227. {
  228. foreach ($slug as $_slug)
  229. {
  230. if ( ! $this->reload_widget($_slug))
  231. {
  232. return FALSE;
  233. }
  234. }
  235. return TRUE;
  236. }
  237. $widget = $this->read_widget($slug);
  238. return $this->edit_widget(array(
  239. 'title' => $widget->title,
  240. 'slug' => $widget->slug,
  241. 'description' => $widget->description,
  242. 'author' => $widget->author,
  243. 'website' => $widget->website,
  244. 'version' => $widget->version
  245. ));
  246. }
  247. function add_widget($input)
  248. {
  249. return $this->widget_m->insert_widget($input);
  250. }
  251. function edit_widget($input)
  252. {
  253. return $this->widget_m->update_widget($input);
  254. }
  255. function update_widget_order($id, $position)
  256. {
  257. return $this->widget_m->update_widget_order($id, $position);
  258. }
  259. function delete_widget($slug)
  260. {
  261. return $this->widget_m->delete_widget($slug);
  262. }
  263. function add_area($input)
  264. {
  265. return $this->widget_m->insert_area((array) $input);
  266. }
  267. function edit_area($input)
  268. {
  269. return $this->widget_m->update_area((array) $input);
  270. }
  271. function delete_area($slug)
  272. {
  273. return $this->widget_m->delete_area($slug);
  274. }
  275. function add_instance($title, $widget_id, $widget_area_id, $options = array(), $data = array())
  276. {
  277. $slug = $this->get_widget($widget_id)->slug;
  278. if ($error = $this->validation_errors($slug, $data))
  279. {
  280. return array('status' => 'error', 'error' => $error);
  281. }
  282. // The widget has to do some stuff before it saves
  283. $options = $this->widgets->prepare_options($slug, $options);
  284. $this->widget_m->insert_instance(array(
  285. 'title' => $title,
  286. 'widget_id' => $widget_id,
  287. 'widget_area_id' => $widget_area_id,
  288. 'options' => $this->_serialize_options($options),
  289. 'data' => $data
  290. ));
  291. return array('status' => 'success');
  292. }
  293. function edit_instance($instance_id, $title, $widget_area_id, $options = array(), $data = array())
  294. {
  295. $slug = $this->widget_m->get_instance($instance_id)->slug;
  296. if ($error = $this->validation_errors($slug, $options))
  297. {
  298. return array('status' => 'error', 'error' => $error);
  299. }
  300. // The widget has to do some stuff before it saves
  301. $options = $this->widgets->prepare_options($slug, $options);
  302. $this->widget_m->update_instance($instance_id, array(
  303. 'title' => $title,
  304. 'widget_area_id' => $widget_area_id,
  305. 'options' => $this->_serialize_options($options),
  306. 'data' => $data
  307. ));
  308. return array('status' => 'success');
  309. }
  310. function update_instance_order($id, $position)
  311. {
  312. return $this->widget_m->update_instance_order($id, $position);
  313. }
  314. function delete_instance($id)
  315. {
  316. return $this->widget_m->delete_instance($id);
  317. }
  318. function validation_errors($name, $options)
  319. {
  320. // $_POST = $options;
  321. $this->load->library('form_validation');
  322. $this->form_validation->set_rules('title', lang('title_label'), 'trim|required|max_length[100]');
  323. $this->_widget OR $this->_spawn_widget($name);
  324. if (property_exists($this->_widget, 'fields'))
  325. {
  326. $this->form_validation->set_rules($this->_widget->fields);
  327. }
  328. if ( ! $this->form_validation->run('', FALSE))
  329. {
  330. return validation_errors();
  331. }
  332. }
  333. function prepare_options($name, $options = array())
  334. {
  335. $this->_widget OR $this->_spawn_widget($name);
  336. if (method_exists($this->_widget, 'save'))
  337. {
  338. return (array) call_user_func(array(&$this->_widget, 'save'), $options);
  339. }
  340. return $options;
  341. }
  342. private function _spawn_widget($name)
  343. {
  344. $widget_path = $this->_widget_locations[$name];
  345. $widget_file = FCPATH . $widget_path . $name . EXT;
  346. if (file_exists($widget_file))
  347. {
  348. require_once $widget_file;
  349. $class_name = 'Widget_' . ucfirst($name);
  350. $this->_widget = new $class_name;
  351. $this->_widget->path = $widget_path;
  352. return;
  353. }
  354. $this->_widget = NULL;
  355. }
  356. public function __get($var)
  357. {
  358. if (isset(get_instance()->$var))
  359. {
  360. return get_instance()->$var;
  361. }
  362. }
  363. protected function load_view($view, $data = array())
  364. {
  365. $path = isset($this->_widget->path) ? $this->_widget->path : $this->path;
  366. return $view == 'display'
  367. ? $this->parser->parse_string($this->load->_ci_load(array(
  368. '_ci_path' => $path . 'views/' . $view . EXT,
  369. '_ci_vars' => $data,
  370. '_ci_return' => TRUE
  371. )), array(), TRUE)
  372. : $this->load->_ci_load(array(
  373. '_ci_path' => $path . 'views/' . $view . EXT,
  374. '_ci_vars' => $data,
  375. '_ci_return' => TRUE
  376. ));
  377. }
  378. private function _serialize_options($options)
  379. {
  380. return serialize((array) $options);
  381. }
  382. private function _unserialize_options($options)
  383. {
  384. return (array) unserialize($options);
  385. }
  386. }