| Commit | Line | Data |
|---|---|---|
| 9f3609c9 EM |
1 | <?php |
| 2 | // $Id$ | |
| 3 | ||
| 4 | /** | |
| f2e5a0c5 EM |
5 | * Returns the API version of Panels. This didn't exist in 1. |
| 6 | * | |
| 7 | * @return An array with the major and minor versions | |
| 9f3609c9 | 8 | */ |
| f2e5a0c5 EM |
9 | function panels_api_version() { |
| 10 | return array(2, 0); | |
| 11 | } | |
| 12 | ||
| 13 | function panels_theme() { | |
| 14 | $theme = array(); | |
| 15 | $theme['panels_layout_link'] = array( | |
| 16 | 'arguments' => array('title', 'id', 'image', 'link'), | |
| 17 | ); | |
| 18 | $theme['panels_layout_icon'] = array( | |
| 19 | 'arguments' => array('id', 'image', 'title' => NULL), | |
| 20 | ); | |
| 21 | $theme['panels_imagebutton'] = array( | |
| 22 | 'arguments' => array('element'), | |
| 23 | ); | |
| 24 | $theme['panels_edit_display_form'] = array( | |
| 25 | 'arguments' => array('form'), | |
| 26 | 'file' => 'includes/display-edit.inc', | |
| 27 | ); | |
| 28 | $theme['panels_edit_layout_form_choose'] = array( | |
| 29 | 'arguments' => array('form'), | |
| 30 | 'file' => 'includes/display-edit.inc', | |
| 31 | ); | |
| f2e5a0c5 EM |
32 | $theme['panels_pane'] = array( |
| 33 | 'arguments' => array('content', 'pane', 'display'), | |
| 6d7f8ba7 | 34 | 'file' => 'includes/display-render.inc', |
| f2e5a0c5 EM |
35 | ); |
| 36 | $theme['panels_common_content_list'] = array( | |
| 37 | 'arguments' => array('display'), | |
| 38 | 'file' => 'includes/common.inc', | |
| 39 | ); | |
| 40 | $theme['panels_common_context_list'] = array( | |
| 41 | 'arguments' => array('object'), | |
| 42 | 'file' => 'includes/common.inc', | |
| 43 | ); | |
| 44 | $theme['panels_common_context_item_form'] = array( | |
| 45 | 'arguments' => array('form'), | |
| 46 | 'file' => 'includes/common.inc', | |
| 47 | ); | |
| dcc5ebb8 | 48 | $theme['panels_common_context_item_row'] = array( |
| f2e5a0c5 EM |
49 | 'arguments' => array('type', 'form', 'position', 'count', 'with_tr' => TRUE), |
| 50 | 'file' => 'includes/common.inc', | |
| 51 | ); | |
| 52 | $theme['panels_dnd'] = array( | |
| 53 | 'arguments' => array('content'), | |
| 54 | 'file' => 'includes/display-edit.inc', | |
| 55 | 'function' => 'theme_panels_dnd', | |
| 56 | ); | |
| 57 | $theme['panels_panel_dnd'] = array( | |
| 58 | 'arguments' => array('content', 'area', 'label', 'footer'), | |
| 59 | 'file' => 'includes/display-edit.inc', | |
| 60 | 'function' => 'theme_panels_panel_dnd', | |
| 61 | ); | |
| 62 | $theme['panels_pane_dnd'] = array( | |
| 63 | 'arguments' => array('block', 'id', 'label', 'left_buttons' => NULL, 'buttons' => NULL), | |
| 64 | 'file' => 'includes/display-edit.inc', | |
| 65 | ); | |
| 66 | $theme['panels_pane_collapsible'] = array( | |
| 67 | 'arguments' => array('block'), | |
| 68 | 'file' => 'includes/display-edit.inc', | |
| 69 | ); | |
| 70 | ||
| 71 | // Register layout and style themes on behalf of all of these items. | |
| 72 | panels_load_include('plugins'); | |
| 73 | ||
| 74 | // No need to worry about files; the plugin has to already be loaded for us | |
| 75 | // to even know what the theme function is, so files will be auto included. | |
| 76 | $layouts = panels_get_layouts(); | |
| 77 | foreach ($layouts as $name => $data) { | |
| 78 | if (!empty($data['theme'])) { | |
| 79 | $theme[$data['theme']] = array( | |
| aa3e4818 | 80 | 'arguments' => array('css_id' => NULL, 'content' => NULL, 'settings' => NULL), |
| fc8f8fa8 | 81 | 'path' => $data['path'], |
| f2e5a0c5 | 82 | ); |
| fc8f8fa8 EM |
83 | |
| 84 | // if no theme function exists, assume template. | |
| 85 | if (!function_exists("theme_$data[theme]")) { | |
| 86 | $theme[$data['theme']]['template'] = str_replace('_', '-', $data['theme']); | |
| 87 | } | |
| f2e5a0c5 | 88 | } |
| 9f3609c9 | 89 | } |
| f2e5a0c5 EM |
90 | |
| 91 | $styles = panels_get_styles(); | |
| 92 | foreach ($styles as $name => $data) { | |
| 93 | if (!empty($data['render pane'])) { | |
| 94 | $theme[$data['render pane']] = array( | |
| 95 | 'arguments' => array('content' => NULL, 'pane' => NULL, 'display' => NULL), | |
| 96 | ); | |
| 97 | } | |
| 98 | if (!empty($data['render panel'])) { | |
| 99 | $theme[$data['render panel']] = array( | |
| 100 | 'arguments' => array('display' => NULL, 'panel_id' => NULL, 'panes' => NULL, 'settings' => NULL), | |
| 101 | ); | |
| 102 | } | |
| 103 | ||
| 104 | } | |
| 105 | ||
| 106 | return $theme; | |
| 9f3609c9 EM |
107 | } |
| 108 | ||
| 109 | /** | |
| f2e5a0c5 | 110 | * Implementation of hook_menu |
| 9f3609c9 | 111 | */ |
| f2e5a0c5 EM |
112 | function panels_menu() { |
| 113 | $items = array(); | |
| 114 | ||
| 115 | // Provide some common options to reduce code repetition. | |
| 116 | // By using array addition and making sure these are the rightmost | |
| 117 | // value, they won't override anything already set. | |
| 118 | $base = array( | |
| 119 | 'access arguments' => array('access content'), | |
| 120 | 'type' => MENU_CALLBACK, | |
| 121 | 'file' => 'includes/display-edit.inc', | |
| 122 | ); | |
| 123 | ||
| 124 | $items['panels/ajax/add-pane'] = array( | |
| 125 | 'page callback' => 'panels_ajax_add_pane_choose', | |
| 126 | ) + $base; | |
| 127 | $items['panels/ajax/add-pane-config'] = array( | |
| 128 | 'page callback' => 'panels_ajax_add_pane_config', | |
| 129 | ) + $base; | |
| 130 | $items['panels/ajax/configure'] = array( | |
| 131 | 'page callback' => 'panels_ajax_configure_pane', | |
| 132 | ) + $base; | |
| 133 | $items['panels/ajax/show'] = array( | |
| 134 | 'page callback' => 'panels_ajax_toggle_shown', | |
| 135 | 'page arguments' => array('show'), | |
| 136 | ) + $base; | |
| 137 | $items['panels/ajax/hide'] = array( | |
| 138 | 'page callback' => 'panels_ajax_toggle_shown', | |
| 139 | 'page arguments' => array('hide'), | |
| 140 | ) + $base; | |
| 141 | $items['panels/ajax/cache-method'] = array( | |
| 142 | 'page callback' => 'panels_ajax_cache_method', | |
| 143 | ) + $base; | |
| 144 | $items['panels/ajax/cache-settings'] = array( | |
| 145 | 'page callback' => 'panels_ajax_cache_settings', | |
| 146 | ) + $base; | |
| 147 | ||
| 148 | // For panel settings on the edit layout settings page | |
| 149 | $items['panels/ajax/style-settings'] = array( | |
| 150 | 'page callback' => 'panels_ajax_style_settings', | |
| 151 | 'file' => 'includes/display-layout-settings.inc', | |
| 152 | ) + $base; | |
| 153 | ||
| 154 | // Non-display editor callbacks | |
| 155 | $items['panels/node/autocomplete'] = array( | |
| 156 | 'title' => t('Autocomplete node'), | |
| 157 | 'page callback' => 'panels_node_autocomplete', | |
| 158 | 'file' => 'includes/callbacks.inc', | |
| 159 | ) + $base; | |
| 160 | ||
| 04894a03 EM |
161 | // For context add/configure calls in common-context.inc |
| 162 | $items['panels/ajax/context-add'] = array( | |
| 163 | 'page callback' => 'panels_ajax_context_item_add', | |
| 164 | 'file' => 'includes/common-context.inc', | |
| f2e5a0c5 | 165 | ) + $base; |
| dcc5ebb8 EM |
166 | $items['panels/ajax/context-configure'] = array( |
| 167 | 'page callback' => 'panels_ajax_context_item_edit', | |
| 168 | 'file' => 'includes/common-context.inc', | |
| 169 | ) + $base; | |
| c8af7bc8 EM |
170 | $items['panels/ajax/context-delete'] = array( |
| 171 | 'page callback' => 'panels_ajax_context_item_delete', | |
| 172 | 'file' => 'includes/common-context.inc', | |
| 173 | ) + $base; | |
| f2e5a0c5 EM |
174 | |
| 175 | // Provide a nice location for a panels admin panel. | |
| f2e5a0c5 EM |
176 | $items['admin/panels'] = array( |
| 177 | 'title' => t('Panels'), | |
| 178 | 'access arguments' => array('access administration pages'), | |
| ade117f2 EM |
179 | 'page callback' => 'panels_admin_page', |
| 180 | 'file' => 'includes/callbacks.inc', | |
| f2e5a0c5 EM |
181 | 'description' => t('Administer items related to the Panels module.'), |
| 182 | ); | |
| 183 | ||
| 184 | return $items; | |
| 9f3609c9 EM |
185 | } |
| 186 | ||
| 187 | /** | |
| f2e5a0c5 | 188 | * Implementation of hook_init() |
| 9f3609c9 | 189 | */ |
| f2e5a0c5 EM |
190 | function panels_init() { |
| 191 | drupal_add_css(panels_get_path('css/panels.css')); | |
| 192 | drupal_add_js(panels_get_path('js/panels.js')); | |
| 9f3609c9 EM |
193 | } |
| 194 | ||
| 195 | /** | |
| f2e5a0c5 | 196 | * Load a panels include file. |
| 9f3609c9 | 197 | */ |
| f2e5a0c5 EM |
198 | function panels_load_include($include, $path = 'includes/') { |
| 199 | require_once './' . panels_get_path("$path$include.inc"); | |
| 9f3609c9 EM |
200 | } |
| 201 | ||
| 202 | /** | |
| 203 | * panels path helper function | |
| 204 | */ | |
| f2e5a0c5 EM |
205 | function panels_get_path($file, $base_path = FALSE, $module = 'panels') { |
| 206 | $output = $base_path ? base_path() : ''; | |
| 9f3609c9 EM |
207 | return $output . drupal_get_path('module', $module) . '/' . $file; |
| 208 | } | |
| 209 | ||
| f2e5a0c5 EM |
210 | /** |
| 211 | * Implementation of hook_perm | |
| 212 | */ | |
| 213 | function panels_perm() { | |
| 214 | return array( | |
| 215 | 'view all panes', | |
| 216 | 'view pane admin links', | |
| 217 | 'administer pane visibility', | |
| 218 | 'administer pane access', | |
| 219 | 'administer advanced pane settings', | |
| 220 | 'use panels caching features' | |
| 221 | ); | |
| 222 | } | |
| 9f3609c9 EM |
223 | |
| 224 | /** | |
| f2e5a0c5 | 225 | * Get an object from cache. |
| 9f3609c9 | 226 | */ |
| f2e5a0c5 EM |
227 | function panels_cache_get($obj, $did, $skip_cache = FALSE) { |
| 228 | static $cache = array(); | |
| 229 | $key = "$obj:$did"; | |
| 230 | if ($skip_cache) { | |
| 231 | unset($cache[$key]); | |
| 232 | } | |
| 233 | ||
| 234 | if (!array_key_exists($key, $cache)) { | |
| 235 | $data = db_fetch_object(db_query("SELECT * FROM {panels_object_cache} WHERE sid = '%s' AND obj = '%s' AND did = %d", session_id(), $obj, $did)); | |
| 236 | if ($data) { | |
| 237 | $cache[$key] = unserialize($data->data); | |
| 238 | } | |
| 239 | } | |
| 240 | return isset($cache[$key]) ? $cache[$key] : NULL; | |
| 9f3609c9 EM |
241 | } |
| 242 | ||
| 243 | /** | |
| f2e5a0c5 | 244 | * Save the edited object into the cache. |
| 9f3609c9 | 245 | */ |
| f2e5a0c5 EM |
246 | function panels_cache_set($obj, $did, $cache) { |
| 247 | panels_cache_clear($obj, $did); | |
| 248 | db_query("INSERT INTO {panels_object_cache} (sid, obj, did, data, timestamp) VALUES ('%s', '%s', %d, '%s', %d)", session_id(), $obj, $did, serialize($cache), time()); | |
| 9f3609c9 EM |
249 | } |
| 250 | ||
| f2e5a0c5 EM |
251 | /** |
| 252 | * Clear a object from the cache; used if the editing is aborted. | |
| 253 | */ | |
| 254 | function panels_cache_clear($obj, $did) { | |
| 255 | db_query("DELETE FROM {panels_object_cache} WHERE sid = '%s' AND obj = '%s' AND did = %d", session_id(), $obj, $did); | |
| 9f3609c9 EM |
256 | } |
| 257 | ||
| 258 | /** | |
| f2e5a0c5 | 259 | * Implementation of hook_cron. Clean up old caches. |
| 9f3609c9 | 260 | */ |
| f2e5a0c5 EM |
261 | function panels_cron() { |
| 262 | // delete anything 7 days old or more. | |
| 263 | db_query("DELETE FROM {panels_object_cache} WHERE timestamp < %d", time() - (86400 * 7)); | |
| 264 | } | |
| 9f3609c9 | 265 | |
| 9f3609c9 | 266 | // --------------------------------------------------------------------------- |
| f2e5a0c5 | 267 | // panels display editing |
| 9f3609c9 EM |
268 | |
| 269 | /** | |
| f2e5a0c5 EM |
270 | * @defgroup mainapi Functions comprising the main panels API |
| 271 | * @{ | |
| 9f3609c9 | 272 | */ |
| 9f3609c9 | 273 | |
| f2e5a0c5 EM |
274 | /** |
| 275 | * Main API entry point to edit a panel display. | |
| 276 | * | |
| 277 | * Sample implementations utiltizing the the complex $destination behavior can be found | |
| 278 | * in panels_page_edit_content() and, in a separate contrib module, OG Blueprints | |
| 279 | * (http://drupal.org/project/og_blueprints), og_blueprints_blueprint_edit(). | |
| 280 | * | |
| 281 | * @ingroup mainapi | |
| 282 | * | |
| 283 | * @param object $display instanceof panels_display \n | |
| 284 | * A fully loaded panels $display object, as returned from panels_load_display(). | |
| 285 | * Merely passing a did is NOT sufficient. \n | |
| 286 | * Note that 'fully loaded' means the $display must already be loaded with any contexts | |
| 287 | * the caller wishes to have set for the display. | |
| 288 | * @param mixed $destination \n | |
| 289 | * The redirect destination that the user should be taken to on form submission or | |
| 290 | * cancellation. With panels_edit, $destination has complex effects on the return | |
| 291 | * values of panels_edit() once the form has been submitted. See the explanation of | |
| 292 | * the return value below to understand the different types of values returned by panels_edit() | |
| 293 | * at different stages of FAPI. Under most circumstances, simply passing in | |
| 294 | * drupal_get_destination() is all that's necessary. | |
| 295 | * @param array $content_types \n | |
| 296 | * An associative array of allowed content types, typically as returned from | |
| 297 | * panels_common_get_allowed_types(). Note that context partially governs available content types, | |
| 298 | * so you will want to create any relevant contexts using panels_create_context() or | |
| 299 | * panels_create_context_empty() to make sure all the appropriate content types are available. | |
| 300 | * | |
| 301 | * @return | |
| 302 | * Because the functions called by panels_edit() invoke the form API, this function | |
| 303 | * returns different values depending on the stage of form submission we're at. In Drupal 5, | |
| 304 | * the phase of form submission is indicated by the contents of $_POST['op']. Here's what you'll | |
| 305 | * get at different stages: | |
| 306 | * -# If !$_POST['op']: then we're on on the initial passthrough and the form is being | |
| 307 | * rendered, so it's the $form itself that's being returned. Because negative margins, | |
| 308 | * a common CSS technique, bork the display editor's ajax drag-and-drop, it's important | |
| 309 | * that the $output be printed, not returned. Use this syntax in the caller function: \n | |
| 310 | * print theme('page', panels_edit($display, $destination, $content_types), FALSE); \n | |
| 311 | * -# If $_POST['op'] == t('Cancel'): form submission has been cancelled. If empty($destination) == FALSE, | |
| 312 | * then there is no return value and the panels API takes care of redirecting to $destination. | |
| 313 | * If empty($destination) == TRUE, then there's still no return value, but the caller function | |
| 314 | * has to take care of form redirection. | |
| 315 | * -# If $_POST['op'] == ('Save'): the form has been submitted successfully and has run through | |
| 316 | * panels_edit_display_submit(). $output depends on the value of $destination: | |
| 317 | * - If empty($destination) == TRUE: $output contains the modified $display | |
| 318 | * object, and no redirection will occur. This option is useful if the caller | |
| 319 | * needs to perform additional operations on or with the modified $display before | |
| 320 | * the page request is complete. Using hook_form_alter() to add an additional submit | |
| 321 | * handler is typically the preferred method for something like this, but there | |
| 322 | * are certain use cases where that is infeasible and $destination = NULL should | |
| 323 | * be used instead. If this method is employed, the caller will need to handle form | |
| 324 | * redirection. Note that having $_REQUEST['destination'] set, whether via | |
| 325 | * drupal_get_destination() or some other method, will NOT interfere with this | |
| 326 | * functionality; consequently, you can use drupal_get_destination() to safely store | |
| 327 | * your desired redirect in the caller function, then simply use drupal_goto() once | |
| 328 | * panels_edit() has done its business. | |
| 329 | * - If empty($destination) == FALSE: the form will redirect to the URL string | |
| 330 | * given in $destination and NO value will be returned. | |
| 9f3609c9 | 331 | */ |
| f2e5a0c5 EM |
332 | function panels_edit($display, $destination = NULL, $content_types = NULL) { |
| 333 | panels_load_include('display-edit'); | |
| 334 | panels_load_include('ajax'); | |
| 335 | panels_load_include('plugins'); | |
| 336 | return _panels_edit($display, $destination, $content_types); | |
| 337 | } | |
| 9f3609c9 | 338 | |
| f2e5a0c5 EM |
339 | /** |
| 340 | * API entry point for selecting a layout for a given display. | |
| 341 | * | |
| 342 | * Layout selection is nothing more than a list of radio items encompassing the available | |
| 343 | * layouts for this display, as defined by .inc files in the panels/layouts subdirectory. | |
| 344 | * The only real complexity occurs when a user attempts to change the layout of a display | |
| 345 | * that has some content in it. | |
| 346 | * | |
| 347 | * @param object $display instanceof panels_display \n | |
| 348 | * A fully loaded panels $display object, as returned from panels_load_display(). | |
| 349 | * Merely passing a did is NOT sufficient. | |
| 350 | * @param string $finish | |
| 351 | * A string that will be used for the text of the form submission button. If no value is provided, | |
| 352 | * then the form submission button will default to t('Save'). | |
| 353 | * @param mixed $destination | |
| 354 | * Basic usage is a string containing the URL that the form should redirect to upon submission. | |
| 355 | * For a discussion of advanced usages, see panels_edit(). | |
| 356 | * @param mixed $allowed_layouts | |
| 357 | * Allowed layouts has three different behaviors that depend on which of three value types | |
| 358 | * are passed in by the caller: | |
| 359 | * #- if $allowed_layouts instanceof panels_allowed_layouts (includes subclasses): the most | |
| 360 | * complex use of the API. The caller is passing in a loaded panels_allowed_layouts object | |
| 361 | * that the client module previously created and stored somewhere using a custom storage | |
| 362 | * mechanism. | |
| 363 | * #- if is_string($allowed_layouts): the string will be used in a call to variable_get() which | |
| 364 | * will call the $allowed_layouts . '_allowed_layouts' var. If the data was stored properly | |
| 365 | * in the system var, the $allowed_layouts object will be unserialized and recreated. | |
| 366 | * @see panels_common_set_allowed_layouts() | |
| 367 | * #- if is_null($allowed_layouts): the default behavior, which also provides backwards | |
| 368 | * compatibility for implementations of the Panels2 API written before beta4. In this case, | |
| 369 | * a dummy panels_allowed_layouts object is created which does not restrict any layouts. | |
| 370 | * Subsequent behavior is indistinguishable from pre-beta4 behavior. | |
| 371 | * | |
| 372 | * @return | |
| 373 | * Can return nothing, or a modified $display object, or a redirection string; return values for the | |
| 374 | * panels_edit* family of functions are quite complex. See panels_edit() for detailed discussion. | |
| 375 | * @see panels_edit() | |
| 376 | */ | |
| 377 | function panels_edit_layout($display, $finish, $destination = NULL, $allowed_layouts = NULL) { | |
| 378 | panels_load_include('display-layout'); | |
| 379 | panels_load_include('plugins'); | |
| 380 | return _panels_edit_layout($display, $finish, $destination, $allowed_layouts); | |
| 9f3609c9 EM |
381 | } |
| 382 | ||
| f2e5a0c5 EM |
383 | /** |
| 384 | * API entry point for configuring the layout settings for a given display. | |
| 385 | * | |
| 386 | * For all layouts except Flexible, the layout settings form allows the user to select styles, | |
| 387 | * as defined by .inc files in the panels/styles subdirectory, for the panels in their display. | |
| 388 | * For the Flexible layout, the layout settings form allows the user to provide dimensions | |
| 389 | * for their flexible layout in addition to applying styles to panels. | |
| 390 | * | |
| 391 | * @param object $display instanceof panels_display \n | |
| 392 | * A fully loaded panels $display object, as returned from panels_load_display(). | |
| 393 | * Merely passing a did is NOT sufficient. | |
| 394 | * @param string $finish | |
| 395 | * A string that will be used for the text of (one of) the form submission button(s). Note that | |
| 396 | * panels will NOT wrap $finish in t() for you, so your caller should make sure to do so. \n | |
| 397 | * The submit behavior of the form is primarily governed by the value of $destination (see | |
| 398 | * below), but is secondarily governed by $finish as follows: | |
| 399 | * -# If $finish != t('Save'), then two #submit buttons will be present: one with the button | |
| 400 | * text t('Save'), and the other with the button text $finish. . | |
| 401 | * - Clicking the 'Save' button will save any changes on the form to the $display object and | |
| 402 | * keep the user on the same editing page. | |
| 403 | * - Clicking the $finish button will also save the $display object, but the user will be | |
| 404 | * redirected to the URL specified in $destination. | |
| 405 | * -# If $finish == t('Save'), then there is only one button, still called t('Save'), but it | |
| 406 | * mimics the behavior of the $finish button above by redirecting the user away from the form. | |
| 407 | * @param mixed $destination | |
| 408 | * Basic usage is a string containing the URL that the form should redirect to upon submission. | |
| 409 | * For a discussion of advanced usages that rely on NULL values for $destination, see the | |
| 410 | * panels_edit() documentation. | |
| 411 | * @param mixed $title | |
| 412 | * The $title variable has three modes of operation: | |
| 413 | * -# If $title == FALSE (the default), then no widget will appear on the panels_edit_layout_settings form | |
| 414 | * allowing the user to select a title, and other means for setting page titles will take precedent. If | |
| 415 | * no other means are used to provide a title, then the title will be hidden when rendering the $display. | |
| 416 | * -# If $title == TRUE, then two widgets will appear on the panels_edit_layout_settings form allowing the | |
| 417 | * user to input a title specific to this $display, as well as a checkbox enabling the user to disable | |
| 418 | * page titles entirely for this $display object. | |
| 419 | * -# If $title == (string), then the behavior is very similar to mode 2, but the widget description | |
| 420 | * on the title textfield will indicate that the $title string will be used as the default page title | |
| 421 | * if none is provided on this form. When utilizing this option, note that the panels API can only | |
| 422 | * provide the data for these values; you must implement the appropriate conditionals to make it true. | |
| 423 | * | |
| 424 | * @return | |
| 425 | * Can return nothing, or a modified $display object, or a redirection string; return values for the | |
| 426 | * panels_edit* family of functions are quite complex. See panels_edit() for detailed discussion. | |
| 427 | * @see panels_edit() | |
| 9f3609c9 | 428 | */ |
| f2e5a0c5 EM |
429 | function panels_edit_layout_settings($display, $finish, $destination = NULL, $title = FALSE) { |
| 430 | panels_load_include('display-layout-settings'); | |
| 431 | panels_load_include('ajax'); | |
| 432 | panels_load_include('plugins'); | |
| 433 | return _panels_edit_layout_settings($display, $finish, $destination, $title); | |
| 9f3609c9 EM |
434 | } |
| 435 | ||
| f2e5a0c5 EM |
436 | |
| 437 | // --------------------------------------------------------------------------- | |
| 438 | // panels database functions | |
| 439 | ||
| 9f3609c9 | 440 | /** |
| f2e5a0c5 EM |
441 | * Forms the basis of a panel display |
| 442 | * | |
| 9f3609c9 | 443 | */ |
| f2e5a0c5 EM |
444 | class panels_display { |
| 445 | var $args = array(); | |
| 446 | var $content = array(); | |
| 447 | var $panels = array(); | |
| 448 | var $incoming_content = NULL; | |
| 449 | var $css_id = NULL; | |
| 450 | var $context = array(); | |
| 451 | var $layout_settings = array(); | |
| 452 | var $panel_settings = array(); | |
| 453 | var $cache = array(); | |
| 454 | var $title = ''; | |
| 455 | var $hide_title = 0; | |
| 456 | ||
| 457 | function add_pane($pane, $location = FALSE) { | |
| 458 | $pane->pid = $this->next_new_pid(); | |
| 459 | if (!$location || !isset($this->panels[$location])) { | |
| 460 | foreach ($this->panels as $panel_name => $panel) { | |
| 461 | if (array_key_exists($pane->pid, $panel)) { | |
| 462 | $this->panels[$panel_name][] = $pane->pid; | |
| 463 | } | |
| 9f3609c9 | 464 | } |
| 9f3609c9 | 465 | } |
| f2e5a0c5 EM |
466 | else { |
| 467 | $this->panels[$location][] = $pane->pid; | |
| 468 | } | |
| 9f3609c9 EM |
469 | } |
| 470 | ||
| f2e5a0c5 EM |
471 | function duplicate_pane($pid, $location = FALSE) { |
| 472 | $pane = $this->clone_pane($pid); | |
| 473 | $this->add_pane($pane, $location); | |
| 9f3609c9 EM |
474 | } |
| 475 | ||
| f2e5a0c5 EM |
476 | function clone_pane($pid) { |
| 477 | $pane = drupal_clone($this->content[$pid]); | |
| 478 | foreach (array_keys($this->content) as $pidcheck) { | |
| 479 | // necessary? | |
| 480 | unset($pane->position); | |
| 481 | } | |
| 482 | return $pane; | |
| 483 | } | |
| 9f3609c9 | 484 | |
| f2e5a0c5 EM |
485 | function next_new_pid() { |
| 486 | // necessary if/until we use this method and ONLY this method for adding temporary pids. | |
| 487 | // then we can do it with a nice static var. | |
| 488 | $id = array(0); | |
| 489 | foreach (array_keys($this->content) as $pid) { | |
| 490 | if (!is_numeric($pid)) { | |
| 491 | $id[] = substr($pid, 4); | |
| 492 | } | |
| 493 | } | |
| 494 | $next_id = end($id); | |
| 495 | return ++$next_id; | |
| 9f3609c9 | 496 | } |
| 9f3609c9 EM |
497 | } |
| 498 | ||
| 499 | /** | |
| f2e5a0c5 | 500 | * }@ End of 'defgroup mainapi', although other functions are specifically added later |
| 9f3609c9 | 501 | */ |
| f2e5a0c5 EM |
502 | |
| 503 | function panels_export_pane_across_displays($source_display, &$target_display, $pid, $location = FALSE) { | |
| 504 | $pane = $source_display->clone_pane($pid); | |
| 505 | $target_display->add_pane($pane, $location); | |
| 9f3609c9 EM |
506 | } |
| 507 | ||
| 508 | /** | |
| f2e5a0c5 EM |
509 | * Clean up a display object and add some required information, if missing. |
| 510 | * | |
| 511 | * Currently a display object needs 'args', 'incoming content', 'context' | |
| 512 | * and a 'css_id'. | |
| 513 | * | |
| 514 | * @param &$display | |
| 515 | * The display object to be sanitized. | |
| 516 | * @return | |
| 517 | * The sanitized display object. | |
| 9f3609c9 | 518 | */ |
| f2e5a0c5 EM |
519 | function panels_sanitize_display(&$display) { |
| 520 | if (!isset($display->args)) { | |
| 521 | $display->args = array(); | |
| 522 | } | |
| 9f3609c9 | 523 | |
| f2e5a0c5 EM |
524 | if (!isset($display->incoming_content)) { |
| 525 | $display->incoming_content = NULL; | |
| 526 | } | |
| 9f3609c9 | 527 | |
| f2e5a0c5 EM |
528 | if (!isset($display->context)) { |
| 529 | $display->context = array(); | |
| 530 | } | |
| 9f3609c9 | 531 | |
| f2e5a0c5 EM |
532 | if (!isset($display->css_id)) { |
| 533 | $display->css_id = NULL; | |
| 9f3609c9 | 534 | } |
| f2e5a0c5 | 535 | } |
| 9f3609c9 | 536 | |
| f2e5a0c5 EM |
537 | /** |
| 538 | * Creates a new display, setting the ID to our magic new id. | |
| 539 | */ | |
| 540 | function panels_new_display() { | |
| 541 | $display = new panels_display(); | |
| 542 | $display->did = 'new'; | |
| 543 | return $display; | |
| 544 | } | |
| 9f3609c9 | 545 | |
| f2e5a0c5 EM |
546 | function panels_new_pane($type, $subtype) { |
| 547 | $pane = new stdClass(); | |
| 548 | $pane->pid = 'new'; | |
| 549 | $pane->type = $type; | |
| 550 | $pane->subtype = $subtype; | |
| 551 | $pane->configuration = array(); | |
| 552 | $pane->access = array(); | |
| 553 | $pane->shown = TRUE; | |
| 554 | return $pane; | |
| 555 | } | |
| 9f3609c9 | 556 | |
| f2e5a0c5 EM |
557 | /** |
| 558 | * Load and fill the requested $display object(s). | |
| 559 | * | |
| 560 | * Helper function primarily for for panels_load_display(). | |
| 561 | * | |
| 562 | * @param array $dids | |
| 563 | * An indexed array of dids to be loaded from the database. | |
| 564 | * | |
| 565 | * @return $displays | |
| 566 | * An array of displays, keyed by their display dids. | |
| 567 | */ | |
| 568 | function panels_load_displays($dids) { | |
| 569 | $displays = array(); | |
| 570 | if (empty($dids) || !is_array($dids)) { | |
| 571 | return $displays; | |
| 572 | } | |
| 9f3609c9 | 573 | |
| f2e5a0c5 | 574 | $subs = implode(', ', array_fill(0, count($dids), '%d')); |
| 9f3609c9 | 575 | |
| f2e5a0c5 | 576 | $result = db_query("SELECT * FROM {panels_display} WHERE did IN ($subs)", $dids); |
| 9f3609c9 | 577 | |
| f2e5a0c5 EM |
578 | while ($obj = db_fetch_array($result)) { |
| 579 | $display = new panels_display(); | |
| 9f3609c9 | 580 | |
| f2e5a0c5 EM |
581 | foreach ($obj as $key => $value) { |
| 582 | $display->$key = $value; | |
| 583 | // unserialize important bits | |
| 584 | if (in_array($key, array('layout_settings', 'panel_settings', 'cache'))) { | |
| 585 | $display->$key = empty($display->$key) ? array() : unserialize($display->$key); | |
| 9f3609c9 | 586 | } |
| 9f3609c9 EM |
587 | } |
| 588 | ||
| f2e5a0c5 EM |
589 | $display->panels = $display->content = array(); |
| 590 | ||
| 591 | $displays[$display->did] = $display; | |
| 592 | } | |
| 593 | ||
| 594 | foreach (module_implements('panels_layout_content_alter') as $module) { | |
| 595 | $function = $module . '_panels_layout_content_alter'; | |
| 596 | $function($content, $layout, $settings); | |
| 9f3609c9 EM |
597 | } |
| 598 | ||
| f2e5a0c5 | 599 | $result = db_query("SELECT * FROM {panels_pane} WHERE did IN ($subs) ORDER BY did, panel, position", $dids); |
| 9f3609c9 | 600 | |
| f2e5a0c5 EM |
601 | while ($pane = db_fetch_object($result)) { |
| 602 | $pane->configuration = unserialize($pane->configuration); | |
| 603 | $pane->cache = empty($pane->cache) ? array() : unserialize($pane->cache); | |
| 604 | $pane->access = ($pane->access ? explode(', ', $pane->access) : array()); | |
| 605 | // Old panels may not have shown property, so enable by default when loading. | |
| 606 | $pane->shown = isset($pane->shown) ? $pane->shown : TRUE; | |
| 607 | ||
| 608 | $displays[$pane->did]->panels[$pane->panel][] = $pane->pid; | |
| 609 | $displays[$pane->did]->content[$pane->pid] = $pane; | |
| 610 | } | |
| 611 | return $displays; | |
| 9f3609c9 EM |
612 | } |
| 613 | ||
| 614 | /** | |
| f2e5a0c5 EM |
615 | * Load a single display. |
| 616 | * | |
| 617 | * @ingroup mainapi | |
| 618 | * | |
| 619 | * @param int $did | |
| 620 | * The display id (did) of the display to be loaded. | |
| 621 | * | |
| 622 | * @return object $display instanceof panels_display \n | |
| 623 | * Returns a partially-loaded panels_display object. $display objects returned from | |
| 624 | * from this function have only the following data: | |
| 625 | * - $display->did (the display id) | |
| 626 | * - $display->name (the 'name' of the display, where applicable - it often isn't) | |
| 627 | * - $display->layout (a string with the system name of the display's layout) | |
| 628 | * - $display->panel_settings (custom layout style settings contained in an associative array; NULL if none) | |
| 629 | * - $display->layout_settings (panel size and configuration settings for Flexible layouts; NULL if none) | |
| 630 | * - $display->css_id (the special css_id that has been assigned to this display, if any; NULL if none) | |
| 631 | * - $display->content (an array of pane objects, keyed by pane id (pid)) | |
| 632 | * - $display->panels (an associative array of panel regions, each an indexed array of pids in the order they appear in that region) | |
| 633 | * - $display->cache (any relevant data from panels_simple_cache) | |
| 634 | * - $display->args | |
| 635 | * - $display->incoming_content | |
| 636 | * | |
| 637 | * While all of these members are defined, $display->context is NEVER defined in the returned $display; | |
| 638 | * it must be set using one of the panels_context_create() functions. | |
| 9f3609c9 | 639 | */ |
| f2e5a0c5 EM |
640 | function panels_load_display($did) { |
| 641 | $displays = panels_load_displays(array($did)); | |
| 642 | if (!empty($displays)) { | |
| 643 | return array_shift($displays); | |
| 644 | } | |
| 645 | } | |
| 9f3609c9 | 646 | |
| f2e5a0c5 EM |
647 | /** |
| 648 | * Save a display object. | |
| 649 | * | |
| 650 | * @ingroup mainapi | |
| 651 | * | |
| 652 | * Note a new $display only receives a real did once it is run through this function. | |
| 653 | * Until then, it uses a string placeholder, 'new', in place of a real did. The same | |
| 654 | * applies to all new panes (whether on a new $display or not); in addition, | |
| 655 | * panes have sequential numbers appended, of the form 'new-1', 'new-2', etc. | |
| 656 | * | |
| 657 | * @param object $display instanceof panels_display \n | |
| 658 | * The display object to be saved. Passed by reference so the caller need not use | |
| 659 | * the return value for any reason except convenience. | |
| 660 | * | |
| 661 | * @return object $display instanceof panels_display \n | |
| 662 | */ | |
| 663 | function panels_save_display(&$display) { | |
| 664 | // @todo -- update all this to just use drupal_write_record or something like it. | |
| 665 | if (!empty($display->did) && $display->did != 'new') { | |
| 666 | db_query("UPDATE {panels_display} SET layout = '%s', layout_settings = '%s', panel_settings = '%s', cache = '%s', title = '%s', hide_title = %d WHERE did = %d", $display->layout, serialize($display->layout_settings), serialize($display->panel_settings), serialize($display->cache), $display->title, $display->hide_title, $display->did); | |
| 667 | // Get a list of all panes currently in the database for this display so we can know if there | |
| 668 | // are panes that need to be deleted. (i.e, aren't currently in our list of panes). | |
| 669 | $result = db_query("SELECT pid FROM {panels_pane} WHERE did = %d", $display->did); | |
| 670 | while ($pane = db_fetch_object($result)) { | |
| 671 | $pids[$pane->pid] = $pane->pid; | |
| 9f3609c9 | 672 | } |
| f2e5a0c5 EM |
673 | } |
| 674 | else { | |
| 675 | db_query("INSERT INTO {panels_display} (layout, layout_settings, panel_settings, cache, title, hide_title) VALUES ('%s', '%s', '%s', '%s', '%s', %d)", $display->layout, serialize($display->layout_settings), serialize($display->panel_settings), serialize($display->cache), $display->title, $display->hide_title); | |
| 676 | $display->did = db_last_insert_id('panels_display', 'did'); | |
| 677 | $pids = array(); | |
| 9f3609c9 EM |
678 | } |
| 679 | ||
| f2e5a0c5 EM |
680 | // update all the panes |
| 681 | panels_load_include('plugins'); | |
| 9f3609c9 | 682 | |
| f2e5a0c5 EM |
683 | foreach ((array) $display->panels as $id => $panes) { |
| 684 | $position = 0; | |
| 685 | $new_panes = array(); | |
| 686 | foreach ((array) $panes as $pid) { | |
| 687 | $pane = $display->content[$pid]; | |
| 688 | $pane->position = $position++; | |
| 9f3609c9 | 689 | |
| f2e5a0c5 EM |
690 | // make variables right. |
| 691 | $type = panels_get_content_type($pane->type); | |
| 692 | $access = isset($pane->access) ? implode(', ', $pane->access) : ''; | |
| 693 | $visibility = $type['visibility serialize'] ? serialize($pane->visibility) : $pane->visibility; | |
| 694 | $pane->shown = isset($pane->shown) ? $pane->shown : TRUE; | |
| 695 | ||
| 696 | if (empty($pane->cache)) { | |
| 697 | $pane->cache = array(); | |
| 9f3609c9 | 698 | } |
| 9f3609c9 | 699 | |
| f2e5a0c5 EM |
700 | $v = array($display->did, $pane->panel, $pane->type, $pane->subtype, serialize($pane->configuration), serialize($pane->cache), $pane->shown, $access, $visibility, $pane->position); |
| 701 | ||
| 702 | if (!is_numeric($pid)) { | |
| 703 | unset($display->content[$pid]); | |
| 704 | // doin it this way for readability | |
| 705 | $f = 'did, panel, type, subtype, configuration, cache, shown, access, visibility, position'; | |
| 706 | $q = "%d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d"; | |
| 707 | ||
| 708 | db_query("INSERT INTO {panels_pane} ($f) VALUES ($q)", $v); | |
| 709 | $pane->pid = db_last_insert_id('panels_pane', 'pid'); | |
| 710 | } | |
| 711 | else { | |
| 712 | $v[] = $pane->pid; | |
| 713 | $f = "did = %d, panel = '%s', type = '%s', subtype = '%s', configuration = '%s', cache = '%s', shown = '%s', access = '%s', visibility = '%s', position = '%d'"; | |
| 714 | db_query("UPDATE {panels_pane} SET $f WHERE pid = %d", $v); | |
| 715 | } | |
| 716 | // and put it back so our pids and positions can be used | |
| 717 | $display->content[$pane->pid] = $pane; | |
| 718 | $new_panes[] = $pane->pid; | |
| 719 | if (isset($pids[$pane->pid])) { | |
| 720 | unset($pids[$pane->pid]); | |
| 9f3609c9 EM |
721 | } |
| 722 | } | |
| 9f3609c9 | 723 | |
| f2e5a0c5 EM |
724 | $display->panels[$id] = $new_panes; |
| 725 | } | |
| 726 | if ($pids) { | |
| 727 | db_query("DELETE FROM {panels_pane} WHERE pid IN (" . db_placeholders($pids) . ")", $pids); | |
| 9f3609c9 | 728 | } |
| 9f3609c9 | 729 | |
| f2e5a0c5 EM |
730 | // Clear any cached content for this display. |
| 731 | panels_clear_cached_content($display); | |
| 9f3609c9 | 732 | |
| f2e5a0c5 EM |
733 | // to be nice, even tho we have a reference. |
| 734 | return $display; | |
| 9f3609c9 EM |
735 | } |
| 736 | ||
| 737 | /** | |
| f2e5a0c5 | 738 | * Delete a display. |
| 9f3609c9 | 739 | */ |
| f2e5a0c5 EM |
740 | function panels_delete_display($display) { |
| 741 | if (is_object($display)) { | |
| 742 | $did = $display->did; | |
| 743 | } | |
| 744 | else { | |
| 745 | $did = $display; | |
| 746 | } | |
| 747 | db_query("DELETE FROM {panels_display} WHERE did = %d", $did); | |
| 748 | db_query("DELETE FROM {panels_pane} WHERE did = %d", $did); | |
| 9f3609c9 EM |
749 | } |
| 750 | ||
| 751 | /** | |
| f2e5a0c5 EM |
752 | * Exports the provided display into portable code. |
| 753 | * | |
| 754 | * This function is primarily intended as a mechanism for cloning displays. | |
| 755 | * It generates an exact replica (in code) of the provided $display, with | |
| 756 | * the exception that it replaces all ids (dids and pids) with 'new-*' values. | |
| 757 | * Only once panels_save_display() is called on the code version of $display will | |
| 758 | * the exported display written to the database and permanently saved. | |
| 759 | * | |
| 760 | * @see panels_page_export() or _panels_page_fetch_display() for sample implementations. | |
| 761 | * | |
| 762 | * @ingroup mainapi | |
| 763 | * | |
| 764 | * @param object $display instanceof panels_display \n | |
| 765 | * This export function does no loading of additional data about the provided | |
| 766 | * display. Consequently, the caller should make sure that all the desired data | |
| 767 | * has been loaded into the $display before calling this function. | |
| 768 | * @param string $prefix | |
| 769 | * A string prefix that is prepended to each line of exported code. This is primarily | |
| 770 | * used for prepending a double space when exporting so that the code indents and lines up nicely. | |
| 771 | * | |
| 772 | * @return string $output | |
| 773 | * The passed-in $display expressed as code, ready to be imported. Import by running | |
| 774 | * eval($output) in the caller function; doing so will create a new $display variable | |
| 775 | * with all the exported values. Note that if you have already defined a $display variable in | |
| 776 | * the same scope as where you eval(), your existing $display variable WILL be overwritten. | |
| 9f3609c9 | 777 | */ |
| f2e5a0c5 EM |
778 | function panels_export_display($display, $prefix = '') { |
| 779 | $output = ''; | |
| 780 | $output .= $prefix . '$display = new panels_display()' . ";\n"; | |
| 781 | $output .= $prefix . '$display->did = \'new\'' . ";\n"; | |
| 782 | $fields = array('name', 'layout', 'layout_settings', 'panel_settings'); | |
| 783 | foreach ($fields as $field) { | |
| 784 | $output .= $prefix . '$display->' . $field . ' = ' . panels_var_export($display->$field, $prefix) . ";\n"; | |
| 9f3609c9 | 785 | } |
| 9f3609c9 | 786 | |
| f2e5a0c5 EM |
787 | $output .= $prefix . '$display->content = array()' . ";\n"; |
| 788 | $output .= $prefix . '$display->panels = array()' . ";\n"; | |
| 789 | $panels = array(); | |
| 790 | ||
| 791 | if (!empty($display->content)) { | |
| 792 | $pid_counter = 0; | |
| 793 | $region_counters = array(); | |
| 794 | foreach ($display->content as $pane) { | |
| 795 | $pane->pid = 'new-' . ++$pid_counter; | |
| 796 | $output .= panels_export_pane($pane, $prefix . ' '); | |
| 797 | $output .= "$prefix " . '$display->content[\'' . $pane->pid . '\'] = $pane' . ";\n"; | |
| 798 | if (!isset($region_counters[$pane->panel])) { | |
| 799 | $region_counters[$pane->panel] = 0; | |
| 9f3609c9 | 800 | } |
| f2e5a0c5 | 801 | $output .= "$prefix " . '$display->panels[\'' . $pane->panel . '\'][' . $region_counters[$pane->panel]++ .'] = \'' . $pane->pid . "';\n"; |
| 9f3609c9 EM |
802 | } |
| 803 | } | |
| f2e5a0c5 | 804 | return $output; |
| 9f3609c9 EM |
805 | } |
| 806 | ||
| f2e5a0c5 EM |
807 | function panels_export_pane($pane, $prefix = '') { |
| 808 | $output = ''; | |
| 809 | $output = $prefix . '$pane = new stdClass()' . ";\n"; | |
| 810 | $fields = array('pid', 'panel', 'type', 'subtype', 'access', 'configuration'); | |
| 811 | foreach ($fields as $field) { | |
| 812 | $output .= "$prefix " . '$pane->' . $field . ' = ' . panels_var_export($pane->$field, "$prefix ") . ";\n"; | |
| 813 | } | |
| 814 | return $output; | |
| 9f3609c9 | 815 | } |
| 9f3609c9 | 816 | |
| f2e5a0c5 EM |
817 | function panels_var_export($object, $prefix = '') { |
| 818 | if (is_array($object) && empty($object)) { | |
| 819 | $output = 'array()'; | |
| 9f3609c9 | 820 | } |
| f2e5a0c5 EM |
821 | else { |
| 822 | $output = var_export($object, TRUE); | |
| 9f3609c9 EM |
823 | } |
| 824 | ||
| f2e5a0c5 EM |
825 | if ($prefix) { |
| 826 | $output = str_replace("\n", "\n$prefix", $output); | |
| 9f3609c9 | 827 | } |
| 9f3609c9 EM |
828 | return $output; |
| 829 | } | |
| 830 | ||
| f2e5a0c5 EM |
831 | /** |
| 832 | * Render a display by loading the content into an appropriate | |
| 833 | * array and then passing through to panels_render_layout. | |
| 834 | * | |
| 835 | * if $incoming_content is NULL, default content will be applied. Use | |
| 836 | * an empty string to indicate no content. | |
| 837 | * @render | |
| 838 | * @ingroup hook_invocations | |
| 839 | */ | |
| 840 | function panels_render_display(&$display) { | |
| 841 | panels_load_include('display-render'); | |
| 842 | panels_load_include('plugins'); | |
| 843 | return _panels_render_display($display); | |
| 9f3609c9 EM |
844 | } |
| 845 | ||
| 846 | /** | |
| 847 | * For external use: Given a layout ID and a $content array, return the | |
| f2e5a0c5 EM |
848 | * panel display. The content array is filled in based upon the content |
| 849 | * available in the layout. If it's a two column with a content | |
| 850 | * array defined like array('left' => t('Left side'), 'right' => | |
| 851 | * t('Right side')), then the $content array should be array('left' => | |
| 852 | * $output_left, 'right' => $output_right) | |
| 853 | * @render | |
| 9f3609c9 EM |
854 | */ |
| 855 | function panels_print_layout($id, $content) { | |
| f2e5a0c5 EM |
856 | panels_load_include('plugins'); |
| 857 | return _panels_print_layout($id, $content); | |
| 9f3609c9 EM |
858 | } |
| 859 | ||
| f2e5a0c5 EM |
860 | // @layout |
| 861 | function panels_print_layout_icon($id, $layout, $title = NULL) { | |
| 862 | drupal_add_css(panels_get_path('css/panels_admin.css')); | |
| fc8f8fa8 | 863 | $file = $layout['path'] . '/' . $layout['icon']; |
| f2e5a0c5 | 864 | return theme('panels_layout_icon', $id, theme('image', $file), $title); |
| 9f3609c9 EM |
865 | } |
| 866 | ||
| f2e5a0c5 EM |
867 | /** |
| 868 | * Theme the layout icon image | |
| 869 | * @layout | |
| 870 | * @todo move to theme.inc | |
| 871 | */ | |
| 872 | function theme_panels_layout_icon($id, $image, $title = NULL) { | |
| 14996ee1 | 873 | $output = '<div class="layout-icon">'; |
| f2e5a0c5 EM |
874 | $output .= $image; |
| 875 | if ($title) { | |
| 876 | $output .= '<div class="caption">' . $title . '</div>'; | |
| 9f3609c9 | 877 | } |
| f2e5a0c5 EM |
878 | $output .= '</div>'; |
| 879 | return $output; | |
| 9f3609c9 EM |
880 | } |
| 881 | ||
| 882 | /** | |
| f2e5a0c5 EM |
883 | * Theme the layout link image |
| 884 | * @layout | |
| 9f3609c9 | 885 | */ |
| f2e5a0c5 | 886 | function theme_panels_layout_link($title, $id, $image, $link) { |
| 14996ee1 | 887 | $output = '<div class="layout-link">'; |
| f2e5a0c5 EM |
888 | $output .= $image; |
| 889 | $output .= '<div>' . $title . '</div>'; | |
| 890 | $output .= '</div>'; | |
| 891 | return $output; | |
| 9f3609c9 | 892 | } |
| aa3e4818 EM |
893 | |
| 894 | /** | |
| 895 | * Print the layout link. Sends out to a theme function. | |
| 896 | * @layout | |
| 897 | */ | |
| 898 | function panels_print_layout_link($id, $layout, $link) { | |
| 899 | drupal_add_css(panels_get_path('css/panels_admin.css')); | |
| 900 | $file = $layout['path'] . '/' . $layout['icon']; | |
| 901 | $image = l(theme('image', $file), $link, array('html' => true)); | |
| 902 | $title = l($layout['title'], $link); | |
| 903 | return theme('panels_layout_link', $title, $id, $image, $link); | |
| 904 | } | |
| 905 |