SproutCMS

This is the code documentation for the SproutCMS project

source of /sprout/Helpers/MultiEdit.php

  1. <?php
  2. /*
  3.  * Copyright (C) 2017 Karmabunny Pty Ltd.
  4.  *
  5.  * This file is a part of SproutCMS.
  6.  *
  7.  * SproutCMS is free software: you can redistribute it and/or modify it under the terms
  8.  * of the GNU General Public License as published by the Free Software Foundation, either
  9.  * version 2 of the License, or (at your option) any later version.
  10.  *
  11.  * For more information, visit <http://getsproutcms.com>.
  12.  */
  13.  
  14. namespace Sprout\Helpers;
  15.  
  16.  
  17. /**
  18.  * UI system for rapid adding/editing of any number of (sub-)records
  19.  *
  20.  * @example
  21.  * $images = MultiEdit::load('gallery_images', ['gallery_id' => $gallery_id], 'record_order');
  22.  * MultiEdit::itemName('Image');
  23.  * MultiEdit::reorder();
  24.  * MultiEdit::setPostAddJavaScriptFunc('load_thumbnails');
  25.  * MultiEdit::display('images', $images, @$_SESSION['gallery']['field_errors']['multiedit_images']);
  26.  */
  27. class MultiEdit
  28. {
  29. private static $post_add_func = null;
  30. private static $reorder = false;
  31. private static $item_name = null;
  32.  
  33.  
  34. /**
  35.   * Returns an array of data, which should be put into a view, and passed into MultiEdit::display.
  36.   * @param string $table Table to load data from
  37.   * @param array $where Conditions for WHERE clause, as per {@see Pdb::buildClause}
  38.   * @param string|array $order Column(s) to order records by
  39.   * @return array Each element is a row
  40.   */
  41. public static function load($table, array $where = [], $order = 'id')
  42. {
  43. Pdb::validateIdentifier($table);
  44. if (is_string($order)) {
  45. $order = preg_split('/,\s*/', $order);
  46. }
  47. foreach ($order as $col) {
  48. Pdb::validateIdentifier($col);
  49. }
  50.  
  51. if (count($where) == 0) $where = [1];
  52.  
  53. $vals = [];
  54. $where = Pdb::buildClause($where, $vals);
  55. $q = "SELECT * FROM ~{$table}
  56. WHERE {$where}
  57. ORDER BY " . implode(', ', $order);
  58. return Pdb::q($q, $vals, 'arr');
  59. }
  60.  
  61.  
  62. /**
  63.   * Set the name of a javascript function to call after each multiedit item is added
  64.   *
  65.   * The JavaScript function is called with the following arguments:
  66.   * $div jQuery element for the outer div
  67.   * data Array of field data OR null for a new record
  68.   * idx The record index
  69.   *
  70.   * @example
  71.   * // You can use bare functions
  72.   * MultiEdit::setPostAddJavaScriptFunc('alert')
  73.   * @example
  74.   * // Or object functions (this is good for testing)
  75.   * MultiEdit::setPostAddJavaScriptFunc('console.log')
  76.   * @example
  77.   * // If you're insane, you can put a whole blob of JS in there
  78.   * MultiEdit::setPostAddJavaScriptFunc('(function($div,data,idx){ console.log($div); })')
  79.   * @param string $function_name
  80.   */
  81. public static function setPostAddJavaScriptFunc($function_name) {
  82. self::$post_add_func = $function_name;
  83. }
  84.  
  85.  
  86. /**
  87.   * Enable multiedit reordering
  88.   **/
  89. public static function reorder()
  90. {
  91. self::$reorder = true;
  92. }
  93.  
  94.  
  95. /**
  96.   * Set the item name for a multiedit.
  97.   * e.g. 'image'
  98.   **/
  99. public static function itemName($item_name)
  100. {
  101. self::$item_name = $item_name;
  102. }
  103.  
  104.  
  105. /**
  106.   * Displays a multiedit field
  107.   * @param string $key Key to group records for this multiedit
  108.   * @param array|null $data Records from DB or session
  109.   * @param array $errors Error messages, in the format [ index => [field => msg] ]
  110.   */
  111. public static function display($key, $data, array $errors = [])
  112. {
  113. if ($key == '') return;
  114.  
  115. Needs::fileGroup('multiedit');
  116. Needs::fileGroup('fb');
  117. Lnk::editformNeeds();
  118.  
  119. // Get input as an array, and get field keys
  120. if (@count($data)) {
  121. $field_names = array_keys(Sprout::iterableFirstValue($data));
  122.  
  123. } else {
  124. $field_names = array();
  125. $data = array();
  126. }
  127.  
  128. // Transpose error messages
  129. foreach ($errors as $idx => $errs) {
  130. foreach ($errs as $field => $error) {
  131. $data[$idx]['error'][$field] = $error;
  132. }
  133. }
  134.  
  135. $opts = array();
  136. $opts['key'] = $key;
  137. $opts['item_name'] = self::$item_name ? self::$item_name : 'item';
  138. $opts['field_names'] = $field_names;
  139. $opts['reorder'] = self::$reorder;
  140.  
  141. // Do output
  142. echo "<script type=\"text/javascript\">\n";
  143. echo "$(document).ready(function() {\n";
  144. echo " $('#multiedit-{$key}').multiedit(\n";
  145. echo ' ', (self::$post_add_func ?: 'null'), ",\n";
  146. echo ' ', json_encode($data), ",\n";
  147. echo ' ', json_encode($opts), "\n";
  148. echo " );\n";
  149. echo "});\n";
  150. echo "</script>\n";
  151.  
  152. self::$post_add_func = null;
  153. self::$reorder = false;
  154. self::$item_name = null;
  155. }
  156.  
  157. /**
  158.   * Returns true if the multiedit record is empty, false otherwise
  159.   *
  160.   * @param array $record Collated [field => value] pairs which are to be saved with a multiedit record
  161.   * @param array $defaults Default values as [field => value] pairs; any field which is set to its default value
  162.   * isn't counted as non-empty; i.e. if all fields are left as their default values, the record is considered
  163.   * empty.
  164.   * @return boolean
  165.   */
  166. public static function recordEmpty($record, array $defaults = [])
  167. {
  168. foreach ($record as $field => $val) {
  169. if ($val == '') continue;
  170. if ($val == @$defaults[$field]) continue;
  171. return false;
  172. }
  173. return true;
  174. }
  175. }
  176.  
  177.  
  178.