1 <?php
defined('SYSPATH') OR die('No direct access allowed.');
8 protected $editable = TRUE; /**< An editable widget has settings that can be changed */
9 protected $movable = TRUE; /**< A movable widget can be dragged around */
10 protected $collapsable = TRUE; /**< A collapsable widget can be collapsed, so only the title bar is visible */
11 protected $removable = TRUE; /**< A removable widget can be deleted */
12 protected $closeconfirm = TRUE; /**< Whether to ask the user to confirm widget deletion */
13 protected $duplicatable = FALSE; /**< Whether the widget can be copied. Setting this to true requires testing, so default to the more backwards compatible mode */
15 public $result = false; /**< widget content result */
16 public $js = false; /**< required js resources? */
17 public $css = false; /**< additional css? */
18 public $inline_js = false; /**< additional inline javascript, as a string */
19 public $widget_base_path = false; /**< path to widget main directory */
20 public $widget_full_path = false; /**< path to this widget's directory */
21 public $model = false; /**< The widget model instance this widget represents */
22 public $extra_data_attributes = array(); /**< array Key-value to attach to widget-container (for example ["hello"] => "bye" which renders as <div data-hello="bye" />, good for javascript-hooks */
23 private static $loaded_widgets = array();
25 public $arguments = array(); /**< The arguments for this instance, constructed from the option objects */
28 * Create new widget instance from a given widget model.
30 public function __construct($widget_model)
32 $this->widget_base_path
= Kohana
::config('widget.path').Kohana
::config('widget.dirname');
33 $this->auto_render
= FALSE;
35 $path = Kohana
::find_file(Kohana
::config('widget.custom_dirname').$widget_model->name
, $widget_model->name
, false);
36 if ($path === false) {
37 $path = Kohana
::find_file(Kohana
::config('widget.dirname').$widget_model->name
, $widget_model->name
, false);
39 if (strstr($path, Kohana
::config('widget.custom_dirname')) !== false) {
40 $this->widget_base_path
= Kohana
::config('widget.path').Kohana
::config('widget.custom_dirname');
42 $this->widget_full_path
= $this->widget_base_path
.$widget_model->name
;
44 $this->model
= $widget_model;
48 * DEPRECATED: Do not use
50 * For legacy reasons, this provides a shortcut to a populated Current_status_Model instance.
51 * There once were significant performance advantages to use this wrapper, but there isn't anymore.
52 * Just call Current_status_Model::instance() instead.
54 public static function get_current_status() {
55 $current_status = Current_status_Model
::instance();
56 $current_status->analyze_status_data();
57 return $current_status;
61 * Returns the populated argument array
63 public function get_arguments() {
65 foreach ($this->options() as $option) {
66 if (!is_string($option))
67 $arguments[$option->name
] = $option->value($this->model
->setting
);
69 if (is_array($this->model
->setting
)) {
70 foreach ($this->model
->setting
as $opt => $val) {
71 if (!isset($arguments[$opt]))
72 $arguments[$opt] = $val;
79 * Find path of widget viewer
80 * @param $view Template object
81 * @return str path to viewer
83 public function view_path($view=false)
89 $widget = $this->model
->name
;
90 # first try custom path
92 $path = Kohana
::find_file(Kohana
::config('widget.custom_dirname').$this->model
->name
, $view, false);
93 if ($path === false) {
94 # try core path if not found in custom
95 $path = Kohana
::find_file(Kohana
::config('widget.dirname').$this->model
->name
, $view, false);
102 * Return the list of options to use in this widget. This should be an array of
103 * option instances, or - if you want to do more manual work - strings.
105 * Actual widgets typically want to extend this method.
107 public function options()
109 $refresh = new option($this->model
->name
, 'refresh_interval', 'Refresh (sec)', 'input', array('size'=>3, 'type'=>'text'), 60);
110 $refresh->should_render_js(false);
113 '<div class="refresh_slider"></div>'
118 * Hook to force additional CSS classes to the rendering
120 public function add_css_class ($class)
122 if (!isset($this->added_classes
))
123 $this->added_classes
= array();
124 $this->added_classes
[] = $class;
128 * Method to render a widget
130 * @param $method Name of method
131 * @param $with_chrome True to generate widget with the menus and everything, false otherwise
132 * @return The rendered widget as a string
134 public function render($method='index', $with_chrome=true)
137 $widget_id = $this->model
->name
.'-'.$this->model
->instance_id
;
139 $options = $this->options();
140 $widget_legal_classes = array('editable', 'movable', 'collapsable', 'removable', 'closeconfirm', 'duplicatable');
141 $widget_classes = array();
143 foreach ($widget_legal_classes as $class) {
145 $widget_classes[] = $class;
149 if (isset($this->added_classes
)) {
150 for($i = 0; $i < count($this->added_classes
); $i++
) {
151 $widget_classes[] = $this->added_classes
[$i];
154 $data_attributes = "";
155 foreach($this->extra_data_attributes
as $key => $value) {
156 $data_attributes .= " data-$key='$value'";
159 $content .= '<div class="widget '.implode(' ', $widget_classes).'" id="widget-'.$widget_id.'" data-name="'.$this->model
->name
.'" '.$data_attributes.' data-instance_id="'.$this->model
->instance_id
.'">';
160 $content .= '<div class="widget-header"><span class="'.$widget_id.'_editable" id="'.$widget_id.'_title">'.$this->model
->friendly_name
.'</span></div>';
161 if (!empty($options) && $this->editable
) {
162 $content .= '<div class="clear"></div><div class="widget-editbox">';
163 $content .= form
::open('widget/save_widget_setting', array('id' => $widget_id.'_form', 'onsubmit' => 'return false;'));
164 $content .= '<fieldset>';
165 if (!isset(self
::$loaded_widgets[$this->model
->name
]))
166 $this->inline_js
.= "widget.register_widget_load('".$this->model
->name
."', function() {";
167 foreach ($options as $option) {
168 if (is_string($option)) {
172 $content .= '<div class="widget-editbox-label"><div>'.$option->render_label($this->model
->instance_id
).'</div></div>';
173 $content .= '<div class="widget-editbox-field"><div>'.$option->render_widget($this->model
->instance_id
, $this->model
->setting
).'</div></div>';
174 $js = $option->render_js();
175 if (!empty($js) && !isset(self
::$loaded_widgets[$this->model
->name
]))
176 $this->inline_js
.= "($js)(this);\n";
180 if (!isset(self
::$loaded_widgets[$this->model
->name
]))
181 $this->inline_js
.= "});\n";
182 $content .= '</fieldset>';
183 $content .= form
::close();
184 $content .= '</div>';
187 $content .= '<div class="%%WIDGET_CLASS%%" style="overflow: auto;">'; // Clear and end widget header and start widget content
192 if (gettype($this->widget_base_path
) === 'boolean') {
193 $content .= '<h2>Widget Error</h2><br />';
194 $content = str_replace('%%WIDGET_CLASS%%', 'widget-content-error', $content);
196 $content = str_replace('%%WIDGET_CLASS%%', 'widget-content', $content);
199 $content .= ob_get_contents();
202 $content .= '</div>';
203 $content .= '</div>';
205 self
::$loaded_widgets[$this->model
->name
] = 1;
210 * Print the widget contents here
212 * Concrete widgets typically want to override this.
214 public function index()
216 echo "<p>(empty widget)</p>";
220 * Weird little method that returns all the resources referenced in this instance
222 public function resources($in_files=false, $type='js')
224 if (empty($in_files) ||
empty($type))
226 $type = strtolower($type);
228 foreach ($in_files as $file) {
229 if (file_exists($this->widget_base_path
.$this->model
->name
.'/'.$file.'.'.$type))
230 $files[] = $this->widget_base_path
.$this->model
->name
.'/'.$file.'.'.$type;
232 $files[] = $file.'.'.$type;
246 * @param $rel_path string: Relative path
247 * @return false on errors, "full relative" path on success.
249 public function add_path($rel_path)
251 $rel_path = trim($rel_path);
252 if (empty($rel_path)) {
257 # assume rel_path is relative to views directory
258 $path = 'application/views/'.$rel_path;
259 # make sure we didn't mix up start/end slashes
260 $path = str_replace('//', '/', $path);