PageRenderTime 90ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/adi_matrix/adi_matrix.php

https://bitbucket.org/mrdale/txp-plugins
PHP | 3752 lines | 2817 code | 366 blank | 569 comment | 603 complexity | 0cde546f0fead1d7451d5decc8cffe9c MD5 | raw file
  1. <?php
  2. // This is a PLUGIN TEMPLATE for Textpattern CMS.
  3. // Copy this file to a new name like abc_myplugin.php. Edit the code, then
  4. // run this file at the command line to produce a plugin for distribution:
  5. // $ php abc_myplugin.php > abc_myplugin-0.1.txt
  6. // Plugin name is optional. If unset, it will be extracted from the current
  7. // file name. Plugin names should start with a three letter prefix which is
  8. // unique and reserved for each plugin author ("abc" is just an example).
  9. // Uncomment and edit this line to override:
  10. $plugin['name'] = 'adi_matrix';
  11. // Allow raw HTML help, as opposed to Textile.
  12. // 0 = Plugin help is in Textile format, no raw HTML allowed (default).
  13. // 1 = Plugin help is in raw HTML. Not recommended.
  14. # $plugin['allow_html_help'] = 1;
  15. $plugin['version'] = '2.1beta2';
  16. $plugin['author'] = 'Adi Gilbert';
  17. $plugin['author_uri'] = 'http://www.greatoceanmedia.com.au/';
  18. $plugin['description'] = 'Multi-article update tabs';
  19. // Plugin load order:
  20. // The default value of 5 would fit most plugins, while for instance comment
  21. // spam evaluators or URL redirectors would probably want to run earlier
  22. // (1...4) to prepare the environment for everything else that follows.
  23. // Values 6...9 should be considered for plugins which would work late.
  24. // This order is user-overrideable.
  25. $plugin['order'] = '5';
  26. // Plugin 'type' defines where the plugin is loaded
  27. // 0 = public : only on the public side of the website (default)
  28. // 1 = public+admin : on both the public and admin side
  29. // 2 = library : only when include_plugin() or require_plugin() is called
  30. // 3 = admin : only on the admin side (no AJAX)
  31. // 4 = admin+ajax : only on the admin side (AJAX supported)
  32. // 5 = public+admin+ajax : on both the public and admin side (AJAX supported)
  33. $plugin['type'] = '1';
  34. // Plugin "flags" signal the presence of optional capabilities to the core plugin loader.
  35. // Use an appropriately OR-ed combination of these flags.
  36. // The four high-order bits 0xf000 are available for this plugin's private use
  37. if (!defined('PLUGIN_HAS_PREFS')) define('PLUGIN_HAS_PREFS', 0x0001); // This plugin wants to receive "plugin_prefs.{$plugin['name']}" events
  38. if (!defined('PLUGIN_LIFECYCLE_NOTIFY')) define('PLUGIN_LIFECYCLE_NOTIFY', 0x0002); // This plugin wants to receive "plugin_lifecycle.{$plugin['name']}" events
  39. $plugin['flags'] = '3';
  40. // Plugin 'textpack' is optional. It provides i18n strings to be used in conjunction with gTxt().
  41. // Syntax:
  42. // ## arbitrary comment
  43. // #@event
  44. // #@language ISO-LANGUAGE-CODE
  45. // abc_string_name => Localized String
  46. /** Uncomment me, if you need a textpack
  47. $plugin['textpack'] = <<<EOT
  48. #@admin
  49. #@language en-gb
  50. abc_sample_string => Sample String
  51. abc_one_more => One more
  52. #@language de-de
  53. abc_sample_string => Beispieltext
  54. abc_one_more => Noch einer
  55. EOT;
  56. **/
  57. // End of textpack
  58. if (!defined('txpinterface'))
  59. @include_once('zem_tpl.php');
  60. # --- BEGIN PLUGIN CODE ---
  61. // NOTE
  62. /*
  63. adi_matrix - Multi-article update tabs
  64. Written by Adi Gilbert
  65. Released under the GNU General Public License
  66. Version history:
  67. 2.1 - further updates for TXP 4.6
  68. - de-colon-isation
  69. 2.0.1beta - fix: enforce unique IDs on glz_cfs checkbox input fields, so that the <input>/<for> tags match up
  70. 2.0 - enhancements:
  71. - publish & delete articles (for mrdale)
  72. - extra article data options: title, section
  73. - show sections
  74. - added section & author to article title tooltip
  75. - matrix under Content or Home tab
  76. - improved validation error messages
  77. - custom WHERE clause conditions
  78. - article list paging
  79. - requires TXP 4.5+
  80. - tested on TXP 4.6
  81. - fix: matrix privileges
  82. - improved validation message (URL-only titles)
  83. - article edit link styling
  84. - and as Apple says "Includes general performance and stability improvements", as well as code "sanity" improvements for my sake
  85. 1.2 - TXP 4.5-ified
  86. - French colon-isation
  87. - lifecycle "upgrade" pseudo-event
  88. 1.1 - code tidy up (thanks gocom)
  89. - enhancement: matrix tab optional footer
  90. - enhancement: matrix tab column sorting
  91. - enhancement: "Any parent" & "Any child" category wildcards
  92. - enhancement: posted timestamp (& reset)
  93. - enhancement: expires timestamp
  94. - enhancement: multi-section select (for maniqui & mrdale)
  95. - enhancement: input field tooltips (for masa)
  96. - for mrdale:
  97. - <body class="adi_matrix"> on all matrix tabs
  98. - another attempt at horizontal scrolling, this time with a fixed article title column
  99. - more sorting options
  100. - TinyMCE support for glz_custom_field textareas
  101. - option to include descendent categories
  102. - fixed: checkboxes again! (thanks redbot)
  103. - changed: "Nothing to do" message changed to "No articles modified"
  104. - changed: admin tab name/title now "Article Matrix"/"Article Matrix Admin"
  105. 1.0.1 - not officially released
  106. - fixed: completely unticked checkboxes not updated (thanks redbot)
  107. - fixed: detect glz_custom_fields in plugin cache (thanks gocom)
  108. 1.0 - enhancement: glz_custom_fields compatibility
  109. - enhancement: force numeric sort (for jpdupont)
  110. - enhancement: sort by Expires timestamp
  111. - enhancement: article catagories (for maniqui)
  112. - enhancement: option to switch on horizontal scroll (for mrdale)
  113. - fixed: MySQL 4.1 compatibility (thanks colak)
  114. - fixed: error if custom field contains single quote (thanks maniqui)
  115. - fixed: superfluous "Logged in user" wildcard option in matrix appearance
  116. - now uses lifecycle events
  117. 0.3 - enhancement: "One category", "Two categories" wildcards
  118. - enhancement: timestamp (for CeBe)
  119. - enhancement: expiry (for CeBe)
  120. - enhancement: future/expired articles highlighted & preference (for CeBe)
  121. - enhancement: article title tooltip, & preference
  122. - admin: install/uninstall/textpack moved to plugin options
  123. 0.2 - fixed: missing child categories (thanks Zanza)
  124. - enhancement: "No category", "Any category" wildcards
  125. - enhancement: "Logged in user" wildcard
  126. - enhancement: article image field (for Zanza)
  127. - enhancement: article limit preference (for milosevic)
  128. 0.1 - initial release
  129. Custom fields
  130. - "standard" TXP custom fields: custom_1 ...custom_10, always present
  131. - with glz_custom_fields, standard CFs can disappear (on "reset"), or additional ones added: custom_11 ...
  132. Upgrade notes (1.0 - 1.1+)
  133. - due to bug in 1.0, expires sort option will get changed to modified
  134. Downgrade (from 2.0 to 1.1/1.2 only)
  135. - go to adi_matrix plugin options tab
  136. - add "&step=downgrade" to end of URL & hit return
  137. - then immediately install previous version of adi_matrix
  138. - BEWARE: multiple sections won't translate very well
  139. - adi_matrix_article_limit pref will be reset to 100
  140. */
  141. /* TODO
  142. - fix up proper ui-icon/ui-icon-pencil for edit link
  143. */
  144. if (txpinterface === 'admin') {
  145. global $adi_matrix_debug,$adi_matrix_dump,$adi_matrix_txp460;
  146. $adi_matrix_debug = 0; // general debuggy info
  147. $adi_matrix_dump = 0; // dump of article data
  148. // using article_validate & new default section pref (4.5.0), so decamp sharpish if need be
  149. if (!version_compare(txp_version,'4.5.0','>=')) return;
  150. $adi_matrix_txp460 = (version_compare(txp_version,'4.6-dev','>='));
  151. adi_matrix_init();
  152. }
  153. function adi_matrix_init() {
  154. // general setup
  155. global $event,$step,$prefs,$txp_groups,$txp_user,$txp_permissions,$theme,$textarray,$adi_matrix_url,$adi_matrix_glz_cfs,$adi_matrix_privs,$adi_matrix_groups,$adi_matrix_cfs,$adi_matrix_expiry_options,$adi_matrix_statuses,$adi_matrix_sort_options,$adi_matrix_sort_dir,$adi_matrix_timestamp_options,$adi_matrix_prefs,$adi_matrix_plugin_status,$adi_matrix_debug,$adi_matrix_glz_cfs,$adi_matrix_list,$adi_matrix_validation_errors,$adi_matrix_sort_type,$adi_matrix_categories,$adi_matrix_tabs,$adi_matrix_txp460;
  156. $adi_matrix_txp460 = (version_compare(txp_version,'4.6-dev','>='));
  157. # --- BEGIN PLUGIN TEXTPACK ---
  158. $adi_matrix_gtxt = array(
  159. 'adi_alphabetical' => 'Alphabetical',
  160. 'adi_any_category' => 'Any category',
  161. 'adi_any_child_category' => 'Any child category',
  162. 'adi_article_data' => 'Article Data',
  163. 'adi_article_matrix' => 'Article Matrix',
  164. 'adi_article_highlighting' => 'Article title highlighting',
  165. 'adi_article_limit' => 'Maximum number of articles',
  166. 'adi_articles_not_modified' => 'No articles modified',
  167. 'adi_article_selection' => 'Article Selection',
  168. 'adi_article_tooltips' => 'Article title tooltips',
  169. 'adi_article_update_fail' => 'Article update failed',
  170. 'adi_articles_saved' => 'Articles saved',
  171. 'adi_blank_url_title' => 'URL-only title blank',
  172. 'adi_cancel' => 'Cancel',
  173. 'adi_custom_condition' => 'Custom condition',
  174. 'adi_cf_links' => 'Custom field links',
  175. 'adi_default_sort' => 'Default sort',
  176. 'adi_display_article_id' => 'Display article ID#',
  177. 'adi_duplicate_url_title' => 'URL-only title already used',
  178. 'adi_edit_titles' => 'Edit titles',
  179. 'adi_expiry' => 'Expiry',
  180. 'adi_footer' => 'Footer',
  181. 'adi_has_expiry' => 'Has expiry',
  182. 'adi_include_descendent_cats' => 'Include descendent categories',
  183. 'adi_install_fail' => 'Unable to install',
  184. 'adi_installed' => 'Installed',
  185. 'adi_invalid_timestamp' => 'Invalid timestamp',
  186. 'adi_jquery_ui' => 'jQuery UI script file',
  187. 'adi_jquery_ui_css' => 'jQuery UI CSS file',
  188. 'adi_logged_in_user' => 'Logged in user',
  189. 'adi_matrix' => 'Matrix',
  190. 'adi_matrix_admin' => 'Article Matrix Admin',
  191. 'adi_matrix_total_articles' => 'Total articles in matrix:',
  192. 'adi_matrix_cfs_modified' => 'Custom field list modified',
  193. 'adi_matrix_delete_fail' => 'Matrix delete failed',
  194. 'adi_matrix_deleted' => 'Matrix deleted',
  195. 'adi_matrix_input_field_tooltips' => 'Input field tooltips',
  196. 'adi_matrix_validation_error' => 'Validation errors',
  197. 'adi_matrix_name' => 'Matrix name',
  198. 'adi_matrix_update_fail' => 'Matrix settings update failed',
  199. 'adi_matrix_updated' => 'Matrix settings updated',
  200. 'adi_new_article' => 'New article',
  201. 'adi_no_category' => 'No category',
  202. 'adi_no_expiry' => 'No expiry',
  203. 'adi_not_installed' => 'Not installed',
  204. 'adi_numerical' => 'Numerical',
  205. 'adi_ok' => 'OK',
  206. 'adi_one_category' => 'One category',
  207. 'adi_any_parent_category' => 'Any parent category',
  208. 'adi_pref_update_fail' => 'Preference update failed',
  209. 'adi_reset' => 'Reset',
  210. 'adi_scroll' => 'Scroll',
  211. 'adi_show_section' => 'Show section',
  212. 'adi_sort_type' => 'Sort type',
  213. 'adi_tab' => 'Tab',
  214. 'adi_textpack_fail' => 'Textpack installation failed',
  215. 'adi_textpack_feedback' => 'Textpack feedback',
  216. 'adi_textpack_online' => 'Textpack also available online',
  217. 'adi_tiny_mce' => 'TinyMCE',
  218. 'adi_tiny_mce_dir_path' => 'TinyMCE directory path',
  219. 'adi_tiny_mce_hak' => 'TinyMCE (hak_tinymce)',
  220. 'adi_tiny_mce_javascript' =>'TinyMCE (Javascript)',
  221. 'adi_tiny_mce_jquery' => 'TinyMCE (jQuery)',
  222. 'adi_tiny_mce_config' => 'TinyMCE configuration',
  223. 'adi_two_categories' => 'Two categories',
  224. 'adi_uninstall' => 'Uninstall',
  225. 'adi_uninstall_fail' => 'Unable to uninstall',
  226. 'adi_uninstalled' => 'Uninstalled',
  227. 'adi_update_matrix' => 'Update matrix settings',
  228. 'adi_update_prefs' => 'Update preferences',
  229. 'adi_upgrade_fail' => 'Unable to upgrade',
  230. 'adi_upgrade_required' => 'Upgrade required',
  231. 'adi_upgraded' => 'Upgraded',
  232. 'adi_user' => 'User',
  233. );
  234. # --- END PLUGIN TEXTPACK ---
  235. // update $textarray
  236. $textarray += $adi_matrix_gtxt;
  237. // Textpack
  238. $adi_matrix_url = array(
  239. 'textpack' => 'http://www.greatoceanmedia.com.au/files/adi_textpack.txt',
  240. 'textpack_download' => 'http://www.greatoceanmedia.com.au/textpack/download',
  241. 'textpack_feedback' => 'http://www.greatoceanmedia.com.au/textpack/?plugin=adi_matrix',
  242. );
  243. if (strpos($prefs['plugin_cache_dir'],'adi') !== FALSE) // use Adi's local version
  244. $adi_matrix_url['textpack'] = $prefs['plugin_cache_dir'].'/adi_textpack.txt';
  245. // plugin lifecycle
  246. register_callback('adi_matrix_lifecycle','plugin_lifecycle.adi_matrix');
  247. // adi_matrix admin tab
  248. add_privs('adi_matrix_admin'); // add priv group - defaults to priv '1' only
  249. register_tab('extensions','adi_matrix_admin',gTxt('adi_article_matrix')); // add new tab under 'Extensions'
  250. register_callback('adi_matrix_admin','adi_matrix_admin');
  251. // look for glz_custom_fields
  252. $adi_matrix_glz_cfs = load_plugin('glz_custom_fields');
  253. /* User privilege summary:
  254. 0 - none - can't even login
  255. 1 - publisher - full matrix data & adi_matrix admin capability
  256. 2 - manager - matrix data only
  257. 3 - copy editor - matrix data only
  258. 4 - staff writer - matrix data only
  259. 5 - freelancer - matrix data only
  260. 6 - designer - matrix data only
  261. Standard article editing privileges:
  262. 'article.edit' => '1,2,3',
  263. 'article.edit.published' => '1,2,3',
  264. 'article.edit.own' => '1,2,3,4,5,6',
  265. 'article.edit.own.published' => '1,2,3,4',
  266. */
  267. // defines privileges required to view a matrix with privilege restriction (same indexing as $txp_groups)
  268. $adi_matrix_privs = array(
  269. 1 => '1', // publisher
  270. 2 => '1,2', // managing_editor
  271. 3 => '1,2,3', // copy_editor
  272. 4 => '1,2,3,4', // staff_writer
  273. 5 => '1,2,3,4,5', // freelancer
  274. 6 => '1,6', // designer
  275. );
  276. // set up user privilege names
  277. $adi_matrix_groups = $txp_groups; // to get: 1 => 'publisher', 2 => 'managing_editor' etc
  278. unset($adi_matrix_groups[0]); // lose index zero (none) - gets us a blank select option too!
  279. foreach ($adi_matrix_groups as $index => $group)
  280. $adi_matrix_groups[$index] = gTxt($group); // to get: 1 => 'Publisher', 2 => 'Managing Editor' etc in the language 'de jour'
  281. // discover custom fields (standard 1-10 & glz 11+) and their non-lowercased titles
  282. $adi_matrix_cfs = getCustomFields();
  283. foreach ($adi_matrix_cfs as $index => $value)
  284. $adi_matrix_cfs[$index] = $prefs['custom_'.$index.'_set']; // index = custom fields number, value = custom field title
  285. // build a picture of article categories
  286. $adi_matrix_categories = adi_matrix_categories(getTree('root','article'));
  287. // article expiry options
  288. $adi_matrix_expiry_options = array(
  289. 0 => '',
  290. 1 => gTxt('adi_no_expiry'),
  291. 2 => gTxt('adi_has_expiry'),
  292. 3 => gTxt('expired'),
  293. );
  294. // article status code translation
  295. $adi_matrix_statuses = array(
  296. 1 => gTxt('draft'),
  297. 2 => gTxt('hidden'),
  298. 3 => gTxt('pending'),
  299. 4 => gTxt('live'),
  300. 5 => gTxt('sticky'),
  301. );
  302. // article sort options
  303. $adi_matrix_sort_options = array(
  304. 'posted' => gTxt('posted'),
  305. 'title' => gTxt('title'),
  306. 'id' => gTxt('id'),
  307. 'lastmod' => gTxt('article_modified'),
  308. 'expires' => gTxt('expires'),
  309. 'status' => gTxt('status'),
  310. 'keywords' => gTxt('keywords'),
  311. 'article_image' => gTxt('article_image'),
  312. 'category1' => gTxt('category1'),
  313. 'category2' => gTxt('category2'),
  314. 'section' => gTxt('section'),
  315. );
  316. foreach ($adi_matrix_cfs as $index => $value) // add custom fields to sort options
  317. $adi_matrix_sort_options['custom_'.$index] = $adi_matrix_cfs[$index];
  318. // article sort direction
  319. $adi_matrix_sort_dir = array(
  320. 'desc' => gTxt('descending'),
  321. 'asc' => gTxt('ascending'),
  322. );
  323. // article sort type
  324. $adi_matrix_sort_type = array(
  325. 'alphabetical' => gTxt('adi_alphabetical'),
  326. 'numerical' => gTxt('adi_numerical'),
  327. );
  328. // article timestamp options
  329. $adi_matrix_timestamp_options = array(
  330. 'any' => gTxt('time_any'),
  331. 'past' => gTxt('time_past'),
  332. 'future' => gTxt('time_future'),
  333. );
  334. // validation errors
  335. $adi_matrix_validation_errors = array(
  336. 0 => gTxt('adi_invalid_timestamp'),
  337. 1 => gTxt('article_expires_before_postdate'),
  338. 2 => gTxt('adi_duplicate_url_title'),
  339. 3 => gTxt('adi_blank_url_title'),
  340. );
  341. // default preferences
  342. $adi_matrix_prefs = array(
  343. 'adi_matrix_article_highlighting' => array('value' => '1', 'input' => 'yesnoradio'),
  344. 'adi_matrix_article_tooltips' => array('value' => '1', 'input' => 'yesnoradio'),
  345. 'adi_matrix_display_id' => array('value' => '0', 'input' => 'yesnoradio'),
  346. 'adi_matrix_input_field_tooltips' => array('value' => '0', 'input' => 'yesnoradio'),
  347. 'adi_matrix_jquery_ui' => array('value' => '../scripts/jquery-ui.js', 'input' => 'text_input'),
  348. 'adi_matrix_jquery_ui_css' => array('value' => '../scripts/jquery-ui.css', 'input' => 'text_input'),
  349. 'adi_matrix_tiny_mce' => array('value' => '0', 'input' => 'yesnoradio'),
  350. 'adi_matrix_tiny_mce_type' => array('value' => 'custom', 'input' => 'text_input'),
  351. 'adi_matrix_tiny_mce_dir' => array('value' => '../scripts/tiny_mce', 'input' => 'text_input'),
  352. 'adi_matrix_tiny_mce_config' => array('value' => 'see below', 'input' => 'text_area'),
  353. );
  354. $adi_matrix_prefs['adi_matrix_tiny_mce_config']['value'] = '
  355. language : "en",
  356. theme : "advanced",
  357. plugins : "safari,pagebreak,style,layer,table,save,advhr,advlink,emotions,iespell,insertdatetime,preview,media,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,template",
  358. theme_advanced_buttons1 : "pagebreak,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect,fontselect,fontsizeselect",
  359. theme_advanced_buttons2 : "cut,copy,paste,pastetext,pasteword,|,search,replace,|,bullist,numlist,|,outdent,indent,blockquote,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code,|,insertdate,inserttime,preview,|,forecolor,backcolor",
  360. theme_advanced_buttons3 : "tablecontrols",
  361. theme_advanced_toolbar_location : "top",
  362. theme_advanced_toolbar_align : "left",
  363. theme_advanced_statusbar_location : "bottom",
  364. theme_advanced_resizing : true,
  365. extended_valid_elements: "style[*]",
  366. width: "600",
  367. height: "400",
  368. ';
  369. // tabs
  370. $adi_matrix_tabs = array(
  371. 'content' => gTxt('tab_content'),
  372. 'start' => gTxt('tab_start'),
  373. );
  374. // plugin options
  375. $adi_matrix_plugin_status = fetch('status','txp_plugin','name','adi_matrix',$adi_matrix_debug);
  376. if ($adi_matrix_plugin_status) { // proper install - options under Plugins tab
  377. add_privs('plugin_prefs.adi_matrix'); // add priv set - defaults to priv '1' only
  378. register_callback('adi_matrix_options','plugin_prefs.adi_matrix');
  379. }
  380. else { // txpdev - options under Extensions tab
  381. add_privs('adi_matrix_options'); // add priv set - defaults to priv '1' only
  382. register_tab('extensions','adi_matrix_options','adi_matrix options');
  383. register_callback('adi_matrix_options','adi_matrix_options');
  384. }
  385. // glz_custom_fields stuff
  386. if ($adi_matrix_glz_cfs) {
  387. if (strstr($event, 'adi_matrix_matrix_')) {
  388. // date & time pickers
  389. add_privs('glz_custom_fields_css_js',"1,2,3,4,5,6");
  390. register_callback('glz_custom_fields_css_js','admin_side','head_end');
  391. // TinyMCE
  392. if (adi_matrix_pref('adi_matrix_tiny_mce')) {
  393. register_callback('adi_matrix_tiny_mce_style','admin_side','head_end');
  394. register_callback('adi_matrix_tiny_mce_'.adi_matrix_pref('adi_matrix_tiny_mce_type'),'admin_side','footer');
  395. }
  396. }
  397. }
  398. // article matrix tabs
  399. $adi_matrix_list = array();
  400. if (adi_matrix_installed())
  401. $adi_matrix_list = adi_matrix_read_settings(adi_matrix_upgrade());
  402. $all_privs = '1,2,3,4,5,6'; // everybody
  403. foreach ($adi_matrix_list as $index => $matrix) {
  404. $matrix_event = 'adi_matrix_matrix_'.$index;
  405. $matrix_tab_name = $matrix['name'];
  406. if ($matrix['privs'])
  407. $priv_set = $adi_matrix_privs[$matrix['privs']];
  408. else
  409. $priv_set = $all_privs; // everybody's welcome
  410. add_privs($matrix_event,$priv_set); // add priv set for each matrix event (to $txp_permissions)
  411. if ($matrix['user'])
  412. $user_allowed = ($txp_user == $matrix['user']);
  413. else // open to all users
  414. $user_allowed = TRUE;
  415. $has_privs = has_privs($matrix_event);
  416. $register_this_tab = ($user_allowed && $has_privs) || has_privs('adi_matrix_admin');
  417. if ($register_this_tab) {
  418. $tab = $matrix['tab'];
  419. if ($tab == 'start') // switch on Home tab
  420. add_privs('tab.start',$all_privs); // all privs
  421. register_tab($tab,$matrix_event,$matrix_tab_name);
  422. register_callback("adi_matrix_matrix",$matrix_event);
  423. }
  424. if ($adi_matrix_debug) {
  425. echo "MATRIX: index=$index, name=".$matrix['name'].", user=".$matrix['user'].", privs=".$matrix['privs'].", priv_set=$matrix_event($priv_set), tab=".$matrix['tab'].br;
  426. $user_privs = safe_field('privs','txp_users',"name='$txp_user'");
  427. echo "USER: user=$txp_user, user_privs=$user_privs, user_allowed=$user_allowed, has_privs=$has_privs".br;
  428. echo "TAB: register_this_tab=$register_this_tab".br.br;
  429. }
  430. }
  431. if ($adi_matrix_debug) {
  432. echo '<b>$adi_matrix_privs:</b>';
  433. dmp($adi_matrix_privs);
  434. echo '<b>adi_matrix added priv sets ($txp_permissions):</b>'.br;
  435. foreach ($txp_permissions as $index => $value)
  436. if (strpos($index,'adi_matrix') === 0)
  437. echo $index.' = '.$value.br;
  438. }
  439. // style
  440. if (strstr($event,'adi_matrix_matrix_') || ($event == 'adi_matrix_admin'))
  441. register_callback('adi_matrix_style','admin_side','head_end');
  442. // script
  443. if (strstr($event,'adi_matrix_admin'))
  444. register_callback('adi_matrix_admin_script','admin_side','head_end');
  445. if (strstr($event,'adi_matrix_matrix_'))
  446. register_callback('adi_matrix_matrix_script','admin_side','head_end');
  447. }
  448. function adi_matrix_style() {
  449. // some style (Classic: table#list, Remora/Hive: table.txp-list)
  450. global $prefs,$adi_matrix_txp460;
  451. echo '<style type="text/css">
  452. /* adi_matrix */
  453. /* general */
  454. .txp-body { max-width:none }
  455. table#list td { padding:0.5em }
  456. .adi_matrix_button { margin:1em auto; text-align:center }
  457. .txp-list { width:auto; margin:0 auto }
  458. /* admin tab */
  459. .adi_matrix_admin input.radio { margin-left:0.5em }
  460. .adi_matrix_admin form { text-align:center }
  461. .adi_matrix_admin table#list td { padding:0.5em 0.5em 0 }
  462. .adi_matrix_field { text-align:left }
  463. .adi_matrix_field label { display:block; float:left; width:8em }
  464. .adi_matrix_field label.adi_matrix_label2 { width:auto }
  465. .adi_matrix_field p { overflow:hidden; margin-top:0; min-height:1.4em }
  466. .adi_matrix_field p > span { float:left; width:8em } /* pseudo label */
  467. .adi_matrix_field p > span + label, .adi_matrix_field p > span + label + label { width:auto } /* radio labels */
  468. .adi_matrix_field p label.adi_matrix_checkbox { width:auto }
  469. .adi_matrix_field p label.adi_matrix_checkbox input { float:left; margin-top:0.2em }
  470. .adi_matrix_field p label.adi_matrix_checkbox span { display:block; float:left; width:8em }
  471. .adi_matrix_custom_field label { width:12em }
  472. .adi_matrix_multi_checkboxes { margin:0.3em 0 0.5em; height:5em; padding:0.2em; overflow:auto; border:1px solid #ccc }
  473. .adi_matrix_multi_checkboxes label { float:none; width:auto }
  474. .adi_matrix_prefs { margin-top:5em; text-align:center }
  475. .adi_matrix_prefs input.checkbox { margin-left:0.5em }
  476. .adi_matrix_prefs input.smallerbox { margin-left:0 }
  477. .adi_matrix_prefs .adi_matrix_radio label { margin-right:1em }
  478. .adi_matrix_prefs .adi_matrix_radio input { margin-left:0.5em }
  479. .adi_matrix_admin .adi_matrix_delete a { font-size:120% }
  480. /* matrix tabs */
  481. .adi_matrix_matrix h1 { margin-top:0; text-align:center; font-weight:bold }
  482. .adi_matrix_matrix table#list th.adi_matrix_noborder { border:0 }
  483. .adi_matrix_matrix table#list .adi_matrix_delete { font-weight:normal; text-align:center }
  484. .adi_matrix_matrix table#list .adi_matrix_delete a { font-size:120% }
  485. .adi_matrix_matrix table#list td.adi_matrix_add { font-size:120% }
  486. .adi_matrix_matrix .date input { margin-top:0 }
  487. .adi_matrix_none { margin-top:2em; text-align:center }
  488. .adi_matrix_field_title { white-space:nowrap } /* stops edit link dropping below */
  489. .adi_matrix_timestamp { white-space:nowrap } /* stops date or time being split */
  490. .adi_matrix_future a { font-weight:bold }
  491. .adi_matrix_expired a { font-style:italic }
  492. .adi_matrix_error input { border-color:#b22222; color:#b22222 }
  493. .adi_matrix_matrix .adi_matrix_matrix_prefs { margin-top:4em; text-align:center }
  494. .adi_matrix_grand_total { text-align:center }
  495. .adi_matrix_edit_link a { display:inline-block; width:21px; height:21px; line-height:2; border:1px solid #ccc; border-radius:0.4em; background:url(theme/classic/view-text.png) 50% 50% no-repeat #FFF8DD }
  496. .adi_matrix_edit_link a:hover, .adi_matrix_edit_link a:active { text-decoration:none; background-color:#fff }
  497. /* matrix tabs 4.5 */
  498. .txp-list .adi_matrix_timestamp .time input { margin-top:0.5em }
  499. .txp-list .adi_matrix_timestamp { min-width:11em }
  500. /* matrix tabs 4.6 */
  501. .txp-list th,.txp-list td { padding-left:0.5em }
  502. /* glz_custom_fields */
  503. html[xmlns] td.glz_custom_date-picker_field.clearfix { display:table-cell!important } /* override clearfix - for date-picker field */
  504. /*.adi_matrix_matrix input.date-picker { float:left; width:7em }*/
  505. .adi_matrix_matrix input.date-picker { width:7em } /* 2.0 layout tweak */
  506. .adi_matrix_matrix td.glz_custom_date-picker_field a.dp-choose-date { display:block; clear:left } /* 2.0 layout tweak */
  507. /*.adi_matrix_matrix td.glz_custom_date-picker_field { min-width:10em }*/ /* 2.0 layout tweak */
  508. .adi_matrix_matrix input.time-picker { width:4em }
  509. /* tinyMCE */
  510. .adi_matrix_matrix .glz_text_area_field div.tie_div { overflow-y:scroll; width:17.6em; height:5.6em; padding:0.2em; border:1px solid; border-color:#aaa #eee #eee #aaa; background-color: #eee }
  511. /* scrolling matrix */
  512. .adi_matrix_scroll table#list th:first-child,
  513. .adi_matrix_scroll table#list td:first-child { position:absolute; width:13%; left:0; top:auto; padding-right:1em; border-bottom-width:0 }
  514. .adi_matrix_scroll table#list thead th:first-child { border-bottom-width:1px }
  515. .adi_matrix_scroll div.scroll_box { width:87%; margin-left:13%; padding-bottom:1em;overflow-x:scroll; overflow-y:visible; border:solid #eee; border-width:0 1px }
  516. .adi_matrix_scroll table#list tfoot td:first-child { border-top:1px solid #ddd }
  517. .adi_matrix_scroll table#list tfoot td { border-bottom:0 }
  518. .adi_matrix_scroll table#list tfoot td:first-child a { display:inline }
  519. /* footer */
  520. table#list tfoot td { font-weight:bold }
  521. table#list tfoot td.desc a,
  522. table#list tfoot td.asc a { width:auto; background-color:transparent; background-image:url("./txp_img/arrowupdn.gif"); background-repeat: no-repeat; background-attachment: scroll; background-position: right -18px; padding-right: 14px; margin-right: 0pt }
  523. table#list tfoot td.asc a { background-position: right 2px }
  524. ';
  525. if ($prefs['theme_name'] == 'hive')
  526. echo '
  527. /* Hive theme (mostly stolen from Hive textpattern.css) */
  528. .txp-list tfoot td.desc a, table#list tfoot td.asc a { background-image:none }
  529. .txp-list tfoot td { text-shadow:1px 1px 0 rgba(255, 255, 255, 0.4); background-color:#eee; background-image:linear-gradient(#eee, #ddd); border-top:1px solid #ddd; border-right:1px solid #d0d0d0; border-bottom:1px solid #c4c4c4 }
  530. .txp-list tfoot td:first-child { border-left:1px solid #ddd }
  531. .txp-list tfoot td a { position:relative; display:block; color:#333; margin-right:.5em }
  532. .txp-list tfoot td a:hover { color:#333; text-decoration:none }
  533. .txp-list tfoot td a:after { position:absolute; top:.53846153846154em; right:-0.76923em; z-index:10; width:0; height:0; display:inline-block; *display:inline; *zoom:1; vertical-align:top; opacity:.5; text-indent:110%; white-space:nowrap; overflow:hidden }
  534. .txp-list tfoot td a:hover:after { opacity:1 }
  535. .txp-list tfoot td.desc a:after { content:"&#8595;"; border-left:.30769230769231em solid transparent; border-right:.30769230769231em solid transparent; border-top:0.30769em solid #333; border-bottom:0 }
  536. .txp-list tfoot td.asc a:after { content:"&#8593;"; border-left:.30769230769231em solid transparent; border-right:.30769230769231em solid transparent; border-top:0; border-bottom:0.30769em solid #333 }
  537. p.prev-next, form.pageby { text-align:center }
  538. .adi_matrix_edit_link a { border:1px solid #eee; border-radius:0.5em; background:url(theme/classic/view-text.png) 50% 50% no-repeat #eee }
  539. .adi_matrix_edit_link a:hover, .adi_matrix_edit_link a:active { background-color:#FFF6D3 }
  540. ';
  541. if ($adi_matrix_txp460) {
  542. echo '
  543. /* TXP 4.6 only */
  544. .adi_matrix_edit_link a { width:1.6em; height:1.8em; background-image:url(admin-themes/hive/assets/img/ui-icon-sprite-333333.svg); background-size:320px 340px; background-position: -78px -140px; background-repeat: no-repeat; background-color:transparent; border:0 }
  545. .adi_matrix_edit_link a:hover, .adi_matrix_edit_link a:active { background-color:transparent }
  546. .adi_matrix_view_link span + span { display:none }
  547. ';
  548. // if ($prefs['theme_name'] == 'hive')
  549. // echo '
  550. // /* TXP 4.6 Hive only */
  551. // .adi_matrix_edit_link a { border:0; border-radius:0.5em }
  552. // .adi_matrix_edit_link a:hover, .adi_matrix_edit_link a:active { background-color:#FFF6D3 }
  553. // ';
  554. }
  555. echo '</style>'.n;
  556. }
  557. /*
  558. .ui-icon {
  559. display: inline-block;
  560. position: relative;
  561. width: 16px;
  562. height: 16px;
  563. background-image: url("../img/ui-icon-sprite-333333.svg");
  564. background-repeat: no-repeat;
  565. background-size: 256px 272px;
  566. text-indent: -9999px;
  567. overflow: hidden;
  568. vertical-align: text-bottom;
  569. }
  570. background-position: -64px -112px;
  571. */
  572. function adi_matrix_admin_script() {
  573. // jQuery magic for admin tab
  574. echo <<<END_SCRIPT
  575. <script type="text/javascript">
  576. $(function(){
  577. $("#peekaboo").hide();
  578. $('input[name="adi_matrix_tiny_mce"][value="1"]:checked').each(function(){
  579. $("#peekaboo").show();
  580. });
  581. $('input[name="adi_matrix_tiny_mce"]:radio:eq(0)').change(function(){
  582. $("#peekaboo").show();
  583. });
  584. $('input[name="adi_matrix_tiny_mce"]:radio:eq(1)').change(function(){
  585. $("#peekaboo").hide();
  586. });
  587. });
  588. </script>
  589. END_SCRIPT;
  590. }
  591. function adi_matrix_matrix_script() {
  592. // jQuery action
  593. // add class to <body>
  594. echo <<<END_SCRIPT
  595. <script type="text/javascript">
  596. $(function(){
  597. $('body').addClass('adi_matrix');
  598. // enforce unique ids on glz checkboxes
  599. $('table.adi_matrix_matrix td.glz_custom_checkbox_field input.checkbox').each(function() {
  600. var name = $(this).attr('name'); // get value of name (contains article id)
  601. var new_name = name.replace('article_','');
  602. var matches = new_name.match(/^[0-9,new]*/); // extract article id#
  603. var new_id = this.id + '_' + matches[0]; // use article id# as suffix for tag id
  604. $(this).attr('id',new_id); // set id on input tag
  605. var td = $(this).parent();
  606. $('label',td).attr('for',new_id); // set id on label tag
  607. // console.log(name,new_name,res[0],td);
  608. });
  609. });
  610. </script>
  611. END_SCRIPT;
  612. }
  613. function adi_matrix_read_settings($just_the_basics=FALSE) {
  614. // get matrix settings from database
  615. global $adi_matrix_cfs,$adi_matrix_debug;
  616. $rs = safe_rows_start('*','adi_matrix',"1=1");
  617. $matrix_list = array();
  618. if ($rs)
  619. while ($a = nextRow($rs)) {
  620. extract($a);
  621. // just enough to display matrix tab
  622. $matrix_list[$id]['name'] = $name;
  623. $matrix_list[$id]['user'] = $user;
  624. $matrix_list[$id]['privs'] = $privs;
  625. if (!isset($tab)) // tab introduced in v2.0, so may not be present during upgrade install
  626. $tab = 'content';
  627. $matrix_list[$id]['tab'] = $tab;
  628. // load in the rest
  629. if (!$just_the_basics) {
  630. $the_rest = array('sort','dir','sort_type','scroll','footer','title','publish','show_section','cf_links','criteria_section','criteria_category','criteria_descendent_cats','criteria_status','criteria_author','criteria_keywords','criteria_timestamp','criteria_expiry','criteria_condition','status','keywords','article_image','category1','category2','posted','expires','section');
  631. foreach ($the_rest as $item)
  632. $matrix_list[$id][$item] = $$item;
  633. // custom fields
  634. foreach ($adi_matrix_cfs as $index => $value) {
  635. $custom_x = 'custom_'.$index;
  636. if (isset($$custom_x)) // check that custom field is known to adi_matrix
  637. $matrix_list[$id][$custom_x] = $$custom_x;
  638. }
  639. }
  640. }
  641. return $matrix_list;
  642. }
  643. function adi_matrix_where($criteria=array()) {
  644. // take matrix criteria & create a WHERE clause
  645. // mostly ripped off from doArticles() in publish.php
  646. global $adi_matrix_debug,$adi_matrix_categories;
  647. if ($adi_matrix_debug) {
  648. echo "<b>Criteria:</b>";
  649. dmp($criteria);
  650. }
  651. extract($criteria);
  652. $excerpted = '';
  653. $month = '';
  654. $time = $timestamp;
  655. // categories
  656. $cats = array();
  657. if ($category == '!no_category!')
  658. $category = " and (Category1 = '' and Category2 = '')";
  659. else if ($category == '!any_category!')
  660. $category = " and (Category1 != '' or Category2 != '')";
  661. else if ($category == '!one_category!')
  662. $category = " and (Category1 != '' and Category2 = '') or (Category1 = '' and Category2 != '')";
  663. else if ($category == '!two_categories!')
  664. $category = " and (Category1 != '' and Category2 != '')";
  665. else if ($category == '!any_parent_category!') {
  666. foreach ($adi_matrix_categories as $name => $this_cat)
  667. if ($this_cat['children'])
  668. $cats[] = $name;
  669. $category = implode(',',$cats);
  670. $category = implode("','", doSlash(do_list($category)));
  671. $category = (!$category) ? '' : " and (Category1 IN ('".$category."') or Category2 IN ('".$category."'))";
  672. }
  673. else if ($category == '!any_child_category!') {
  674. foreach ($adi_matrix_categories as $name => $this_cat)
  675. if ($this_cat['parent'] != 'root')
  676. $cats[] = $name;
  677. $category = implode(',',$cats);
  678. $category = implode("','", doSlash(do_list($category)));
  679. $category = (!$category) ? '' : " and (Category1 IN ('".$category."') or Category2 IN ('".$category."'))";
  680. }
  681. else { // single category (perhaps with optional descendents)
  682. if ($descendent_cats)
  683. $category .= ','.implode(',',$adi_matrix_categories[$category]['children']);
  684. $category = implode("','", doSlash(do_list($category)));
  685. $category = (!$category) ? '' : " and (Category1 IN ('".$category."') or Category2 IN ('".$category."'))";
  686. }
  687. $section = (!$section) ? '' : " and Section IN ('".implode("','", doSlash(do_list($section)))."')";
  688. $excerpted = ($excerpted=='y') ? " and Excerpt !=''" : '';
  689. if ($author == '!logged_in_user!')
  690. $author = $txp_user;
  691. $author = (!$author) ? '' : " and AuthorID IN ('".implode("','", doSlash(do_list($author)))."')";
  692. $month = (!$month) ? '' : " and Posted like '".doSlash($month)."%'";
  693. // posted timestamp
  694. switch ($time) {
  695. case 'any':
  696. $time = "";
  697. break;
  698. case 'future':
  699. $time = " and Posted > now()";
  700. break;
  701. default:
  702. $time = " and Posted <= now()";
  703. }
  704. // expiry
  705. switch ($expiry) {
  706. case '1': // no expiry set
  707. $time .= " and Expires = ".NULLDATETIME;
  708. break;
  709. case '2': // has expiry set
  710. $time .= " and Expires != ".NULLDATETIME;
  711. break;
  712. case '3': // expired
  713. $time .= " and now() > Expires and Expires != ".NULLDATETIME;
  714. break;
  715. }
  716. $custom = ''; // MAY GET CONFUSING WITH criteria_condition
  717. // if ($customFields) {
  718. // foreach($customFields as $cField) {
  719. // if (isset($atts[$cField]))
  720. // $customPairs[$cField] = $atts[$cField];
  721. // }
  722. // if(!empty($customPairs)) {
  723. // $custom = buildCustomSql($customFields,$customPairs);
  724. // }
  725. // }
  726. if ($keywords) {
  727. $keys = doSlash(do_list($keywords));
  728. foreach ($keys as $key) {
  729. $keyparts[] = "FIND_IN_SET('".$key."',Keywords)";
  730. }
  731. $keywords = " and (" . implode(' or ',$keyparts) . ")";
  732. }
  733. if ($status)
  734. $statusq = ' and Status = '.intval($status);
  735. else // either blank or zero
  736. $statusq = ''; // all statuses
  737. if ($condition)
  738. $conditionq = ' and '.$condition;
  739. else
  740. $conditionq = '';
  741. $where = '1'.$statusq.$time.$category.$section.$excerpted.$month.$author.$keywords.$custom.$conditionq;
  742. if ($adi_matrix_debug) {
  743. echo "<b>WHERE clause:</b> $where".br;
  744. }
  745. return $where;
  746. }
  747. function adi_matrix_order_by($sort,$dir,$sort_type) {
  748. // generate ORDER BY clause
  749. // mostly ripped off from doArticles() in publish.php
  750. global $adi_matrix_debug;
  751. // map columns to sort query
  752. switch ($sort) {
  753. case 'posted':
  754. $sortq = 'Posted';
  755. break;
  756. case 'expires':
  757. $sortq = 'Expires';
  758. break;
  759. case 'lastmod':
  760. $sortq = 'LastMod';
  761. break;
  762. case 'title':
  763. $sortq = 'Title';
  764. break;
  765. case 'id':
  766. $sortq = 'ID';
  767. break;
  768. case 'status':
  769. $sortq = 'Status';
  770. break;
  771. case 'article_image':
  772. $sortq = 'Image';
  773. break;
  774. case 'category1':
  775. $sortq = 'Category1';
  776. break;
  777. case 'category2':
  778. $sortq = 'Category2';
  779. break;
  780. case 'section':
  781. $sortq = 'Section';
  782. break;
  783. default: // custom_x will fall through to here
  784. $rs = safe_query('SHOW FIELDS FROM '.safe_pfx('textpattern')." LIKE '$sort'",$adi_matrix_debug); // find out if column (glz custom field probably) still exists
  785. $a = nextRow($rs);
  786. if (empty($a))
  787. $sortq = 'Posted';
  788. else
  789. $sortq = $sort;
  790. }
  791. // sort type
  792. if ($sort_type == 'numerical')
  793. $sort_typeq = ' + 0';
  794. else
  795. $sort_typeq = '';
  796. // sort it all out
  797. $sortq = ' ORDER BY '.$sortq.$sort_typeq.' '.$dir.', Posted desc'; // add direction ... & also secondary sort (pointless but harmless with ID, Posted & Expires)
  798. if ($adi_matrix_debug) {
  799. echo "<b>Sort:</b> sort=$sort, dir=$dir, sort_type=$sort_type".br;
  800. echo "<b>ORDER BY clause:</b> $sortq".br;
  801. }
  802. return $sortq;
  803. }
  804. function adi_matrix_get_articles($where='1',$sortq='',$matrix_index,$offset,$limit) {
  805. // read required articles from database and populate $adi_matrix_articles
  806. global $adi_matrix_debug,$adi_matrix_cfs,$adi_matrix_list,$adi_matrix_sort_options,$txp_user,$adi_matrix_timestamp_options;
  807. $adi_matrix_articles = array();
  808. // get the required articles from database
  809. $rs = safe_rows_start(
  810. "*, unix_timestamp(Posted) as uPosted, unix_timestamp(Expires) as uExpires, unix_timestamp(LastMod) as uLastMod"
  811. ,'textpattern'
  812. ,$where.doSlash($sortq).' LIMIT '.intval($offset).', '.intval($limit)
  813. ,$adi_matrix_debug
  814. );
  815. if ($rs) // populate $adi_matrix_articles array
  816. while ($a = nextRow($rs)) {
  817. extract($a);
  818. $adi_matrix_articles[$ID] = array();
  819. $adi_matrix_articles[$ID]['title'] = html_entity_decode($Title, ENT_QUOTES, 'UTF-8');
  820. $adi_matrix_articles[$ID]['section'] = $Section;
  821. $adi_matrix_articles[$ID]['author'] = $AuthorID; // need author for article edit priv check
  822. $adi_matrix_articles[$ID]['status'] = $Status; // need status for article edit priv check
  823. $adi_matrix_articles[$ID]['keywords'] = $Keywords;
  824. $adi_matrix_articles[$ID]['article_image'] = $Image;
  825. $adi_matrix_articles[$ID]['category1'] = $Category1;
  826. $adi_matrix_articles[$ID]['category2'] = $Category2;
  827. foreach ($adi_matrix_cfs as $index => $cf_name) {
  828. $custom_x = 'custom_'.$index;
  829. $adi_matrix_articles[$ID][$custom_x] = $$custom_x;
  830. }
  831. // article timestamps
  832. $adi_matrix_articles[$ID]['uposted'] = $uPosted; // unix timestamp format (in server timezone)
  833. $adi_matrix_articles[$ID]['posted'] = $Posted; // article date/time string (YY-MM-DD HH:MM:SS) from database
  834. $adi_matrix_articles[$ID]['display_posted'] = safe_strftime('%Y-%m-%d %X',$uPosted); // article date/time string (YY-MM-DD HH:MM:SS) displayed to user (TXP time)
  835. $adi_matrix_articles[$ID]['uexpires'] = $uExpires; // unix timestamp format (in server timezone)
  836. $adi_matrix_articles[$ID]['expires'] = $Expires; // article date/time string (YY-MM-DD HH:MM:SS) from database
  837. if ($Expires == '0000-00-00 00:00:00')
  838. $adi_matrix_articles[$ID]['display_expires'] = $Expires; // keep it zeroed
  839. else
  840. $adi_matrix_articles[$ID]['display_expires'] = safe_strftime('%Y-%m-%d %X',$uExpires); // article date/time string (YY-MM-DD HH:MM:SS) displayed to user (TXP time)
  841. // highlighting
  842. $highlight = 0;
  843. $now = time();
  844. if (($now > $uExpires) && ($uExpires != 0)) // expired article
  845. $highlight = 1;
  846. if ($now < $uPosted) // future article
  847. $highlight = 2;
  848. $adi_matrix_articles[$ID]['highlight'] = $highlight;
  849. }
  850. return $adi_matrix_articles;
  851. }
  852. function adi_matrix_update_article($id,$data) {
  853. // translate $_POSTED article data into SQL-speak
  854. global $adi_matrix_debug,$txp_user,$adi_matrix_cfs,$adi_matrix_articles,$vars,$prefs;
  855. include_once txpath.'/include/txp_article.php'; // to get textile_main_fields()
  856. // set up variables in the style of $vars
  857. $Title = $Title_plain = isset($data['title']) ? $data['title'] : '';
  858. $Status = isset($data['status']) ? $data['status'] : '';
  859. $Section = isset($data['section']) ? $data['section'] : '';
  860. $Keywords = isset($data['keywords']) ? trim(preg_replace('/( ?[\r\n\t,])+ ?/s', ',', preg_replace('/ +/', ' ', $data['keywords'])), ', ') : '';
  861. $Image = isset($data['article_image']) ? $data['article_image'] : '';
  862. $Category1 = isset($data['category1']) ? $data['category1'] : '';
  863. $Category2 = isset($data['category2']) ? $data['category2'] : '';
  864. // posted
  865. if (isset($data['posted']['reset_time']))
  866. $publish_now = '1';
  867. else
  868. $publish_now = '';
  869. if (isset($data['posted'])) { // this is in TXP date/time
  870. extract($data['posted']);
  871. $Posted = $year.'-'.$month.'-'.$day.' '.$hour.':'.$minute.':'.$second;
  872. }
  873. else // force now
  874. $publish_now = '1'; // NOT SURE WHY DOING THIS, BUT DOESN'T DO ANY HARM (IS IGNORED IF POSTED NOT CHANGED)
  875. // expires
  876. if (isset($data['expires'])) { // this is in TXP date/time
  877. foreach ($data['expires'] as $index => $value) { // convert expiry vars ($year -> $exp_year) to align with $vars in txp_article.php
  878. $var = 'exp_'.$index;
  879. $$var = $value;
  880. }
  881. $Expires = $exp_year.'-'.$exp_month.'-'.$exp_day.' '.$exp_hour.':'.$exp_minute.':'.$exp_second;
  882. }
  883. else // force no expiry
  884. $exp_year = '0000';
  885. // custom Fields
  886. foreach ($adi_matrix_cfs as $index => $cf_name) {
  887. $custom_x = 'custom_'.$index;
  888. if (isset($data[$custom_x]))
  889. $$custom_x = $data[$custom_x];
  890. else
  891. $$custom_x = '';
  892. }
  893. // set the rest (not used by adi_matrix_update_article)
  894. $Body = '';
  895. $Body_html = '';
  896. $Excerpt = '';
  897. $Excerpt_html = '';
  898. $textile_body = $prefs['use_textile'];
  899. $textile_excerpt = $prefs['use_textile'];
  900. $Annotate = '0';
  901. $override_form = '';
  902. $AnnotateInvite = '';
  903. // package them all up
  904. $updates = compact($vars);
  905. if ($adi_matrix_debug) {
  906. echo '<b>Article '.$id.' data:</b>';
  907. dmp($updates);
  908. }
  909. // do some validation, textilation & slashing
  910. $incoming = array_map('assert_string',$updates);
  911. $incoming = textile_main_fields($incoming); // converts ampersands to &amp; in titles
  912. extract(doSlash($incoming));
  913. if (isset($data['status']))
  914. extract(array_map('assert_int', array('Status' => $Status)));
  915. // title
  916. if (isset($data['title']))
  917. $titleq = "Title='$Title', ";
  918. else
  919. $titleq = '';
  920. // status
  921. $old_status = $new_status = $adi_matrix_articles[$id]['status'];
  922. if (isset($data['status'])) {
  923. $new_status = $Status;
  924. // tweak status according to privs
  925. if (!has_privs('article.publish') && $new_status >= STATUS_LIVE)
  926. $new_status = STATUS_PENDING;
  927. $statusq = 'Status='.doSlash($new_status).', ';
  928. if ($new_status >= STATUS_LIVE) // live & sticky articles only
  929. update_lastmod();
  930. }
  931. else
  932. $statusq = '';
  933. // section
  934. if (isset($data['section']))
  935. $sectionq = "Section='$Section', ";
  936. else
  937. $sectionq = '';
  938. // keywords
  939. if (isset($data['keywords']))
  940. $keywordsq = "Keywords='$Keywords', ";
  941. else
  942. $keywordsq = '';
  943. // article image
  944. if (isset($data['article_image']))
  945. $article_imageq = "Image='$Image', ";
  946. else
  947. $article_imageq = '';
  948. // categories
  949. if (isset($data['category1']))
  950. $categoryq = "Category1='$Category1', ";
  951. else
  952. $categoryq = '';
  953. if (isset($data['category2']))
  954. $categoryq .= "Category2='$Category2', ";
  955. else
  956. $categoryq .= '';
  957. // posted
  958. $postedq = '';
  959. if (isset($data['posted'])) {
  960. if ($publish_now)
  961. $postedq = "Posted=now(), ";
  962. else { // convert TXP date/time to DB timestamp
  963. $ts = strtotime($Posted);
  964. $date_error = ($ts === false || $ts === -1);
  965. if (!$date_error) {
  966. $when_ts = $ts - tz_offset($ts);
  967. $when = "from_unixtime($when_ts)";
  968. $postedq = "Posted=$when, ";
  969. }
  970. }
  971. }
  972. // expires
  973. $expiresq = '';
  974. if (isset($data['expires'])) {
  975. if ($exp_year == '0000')
  976. $expiry = 0;
  977. else { // convert TXP date/time to DB timestamp
  978. $ts = strtotime($Expires);
  979. $expiry = $ts - tz_offset($ts);
  980. }
  981. if ($expiry) {
  982. $date_error = ($ts === false || $ts === -1);
  983. if (!$date_error) {
  984. $expires = $ts - tz_offset($ts);
  985. $whenexpires = "from_unixtime($expires)";
  986. $expiresq = "Expires=$whenexpires, ";
  987. }
  988. }
  989. else
  990. $expiresq = "Expires=".NULLDATETIME.", ";
  991. }
  992. // custom fields
  993. $cfq = array();
  994. foreach($adi_matrix_cfs as $i => $cf_name) {
  995. $custom_x = "custom_{$i}";
  996. if (isset($data[$custom_x]))
  997. $cfq[] = "custom_$i = '".$$custom_x."'";
  998. }
  999. $cfq = implode(', ', $cfq);
  1000. // update article in database
  1001. $res = safe_update("textpattern",
  1002. $titleq.$sectionq.$statusq.$keywordsq.$article_imageq.$categoryq.$postedq.$expiresq.(($cfq) ? $cfq.', ' : '')."LastMod=now(), LastModID='$txp_user'",
  1003. "ID=$id",
  1004. $adi_matrix_debug
  1005. );
  1006. if ($new_status >= STATUS_LIVE && $old_status < STATUS_LIVE)
  1007. do_pings();
  1008. if ($new_status >= STATUS_LIVE || $old_status >= STATUS_LIVE)
  1009. update_lastmod();
  1010. return $res;
  1011. }
  1012. function adi_matrix_update_articles($updates,$matrix_index) {
  1013. // update articles
  1014. $res = TRUE;
  1015. if ($updates) {
  1016. foreach ($updates as $id => $data)
  1017. if ($id == 'new')
  1018. $res = $res && adi_matrix_publish_article($data,$matrix_index);
  1019. else
  1020. $res = $res && adi_matrix_update_article($id,$data);
  1021. }
  1022. return $res;
  1023. }
  1024. function adi_matrix_article_defaults($matrix_index) {
  1025. // default values for new article, adjusted for specified matrix
  1026. global $adi_matrix_debug,$adi_matrix_list,$prefs,$adi_matrix_cfs,$adi_matrix_glz_cfs;
  1027. // Article field $defaults['xx'] Who determines Default values
  1028. // ------------- --------------- -------------- --------------
  1029. // ID - MySQL generated on publish
  1030. // Posted posted adi_matrix_article_defaults,user current date/time
  1031. // Expires expires adi_matrix_article_defaults,user blank (converted to 0000-00-00 00:00:00 by adi_matrix_validate_post_data)
  1032. // AuthorID - adi_matrix_publish_article current user
  1033. // LastMod - adi_matrix_publish_article generated on publish
  1034. // LastModID - adi_matrix_publish_article current user
  1035. // Title title adi_matrix_article_defaults,user blank
  1036. // Title_html - adi_matrix_publish_article blank
  1037. // Body - adi_matrix_publish_article blank
  1038. // Body_html - adi_matrix_publish_article blank
  1039. // Excerpt - adi_matrix_publish_article blank
  1040. // Excerpt_html - adi_matrix_publish_article blank
  1041. // Image article_image adi_matrix_article_defaults,user blank
  1042. // Category1 category1 adi_matrix_article_defaults,user criteria_category (if specific category set), blank
  1043. // Category2 category2 adi_matrix_article_defaults,user blank
  1044. // Annotate - adi_matrix_publish_article 0
  1045. // AnnotateInvite - adi_matrix_publish_article blank
  1046. // comments_count - MySQL default
  1047. // Status status adi_matrix_article_defaults,user criteria_status (if set), "live"
  1048. // textile_body - adi_matrix_publish_article 'use_textile' from $prefs
  1049. // textile_excerpt - adi_matrix_publish_article 'use_textile' from $prefs
  1050. // Section section adi_matrix_article_defaults first section from criteria_section (if set), 'default_section' from $prefs
  1051. // override_form - adi_matrix_publish_article blank
  1052. // Keywords keywords adi_matrix_article_defaults,user criteria_keywords (if set), blank
  1053. // url_title - adi_matrix_publish_article generated-from-title
  1054. // custom_x custom_x adi_matrix_article_defaults,user blank (if TXP CFs), GLZ default value (if GLZ CFs)
  1055. // uid - adi_matrix_publish_article generated on publish
  1056. // feed_time - adi_matrix_publish_article generated on publish
  1057. $defaults = array();
  1058. // title - blank
  1059. $defaults['title'] = '';
  1060. // status - from criteria (or live if not set)
  1061. if ($adi_matrix_list[$matrix_index]['criteria_status'])
  1062. $defaults['status'] = $adi_matrix_list[$matrix_index]['criteria_status'];
  1063. else
  1064. $defaults['status'] = '4';
  1065. // article image - blank
  1066. $defaults['article_image'] = '';
  1067. // keywords - from criteria
  1068. $defaults['keywords'] = $adi_matrix_list[$matrix_index]['criteria_keywords'];
  1069. // category1 - if specific category set - assign it to cat1, otherwise leave it up to user (i.e. blank)
  1070. if (($adi_matrix_list[$matrix_index]['criteria_category']) && (strpos($adi_matrix_list[$matrix_index]['criteria_category'],'!') === FALSE))
  1071. $defaults['category1'] = $adi_matrix_list[$matrix_index]['criteria_category'];
  1072. else
  1073. $defaults['category1'] = '';
  1074. // category2 - leave blank
  1075. $defaults['category2'] = '';
  1076. // posted
  1077. $defaults['uposted'] = time();
  1078. $defaults['posted'] = date("Y-m-d H:i:s",$defaults['uposted']);
  1079. // expires - blank
  1080. $defaults['uexpires'] = '';
  1081. $defaults['expires'] = '';
  1082. // section - $prefs default_section if blank, else first section on list if criteria set
  1083. if ($adi_matrix_list[$matrix_index]['criteria_section']) {
  1084. $sections = explode(',',$adi_matrix_list[$matrix_index]['criteria_section']);
  1085. $defaults['section'] = $sections[0];
  1086. }
  1087. else
  1088. $defaults['section'] = $prefs['default_section'];
  1089. // custom fields - blank
  1090. foreach ($adi_matrix_cfs as $index => $cf_name) {
  1091. $custom_x = 'custom_'.$index;
  1092. $defaults[$custom_x] = '';
  1093. }
  1094. // glean GLZ CF defaults & apply them
  1095. if ($adi_matrix_glz_cfs) {
  1096. $all_custom_sets = glz_custom_fields_MySQL("all"); // array indexed by custom_xx_set, value array(name,position,type)
  1097. if ($adi_matrix_debug)
  1098. echo "<b>GLZ custom field defaults</b>:".br;
  1099. foreach ($all_custom_sets as $custom => $custom_set) { // index format is "custom_x_set"
  1100. $arr_custom_field_values = glz_custom_fields_MySQL("values",$custom,'',array('custom_set_name' => $custom_set['name']));
  1101. $default_value = glz_return_clean_default(glz_default_value($arr_custom_field_values));
  1102. $custom_x = str_replace('_set','',$custom); // convert custom_x_set to custom_x
  1103. if ($adi_matrix_debug) echo $custom_x.' default = '.'['.$default_value.']'.br;
  1104. $defaults[$custom_x] = $default_value; // use GLZ default
  1105. }
  1106. }
  1107. if ($adi_matrix_debug) {
  1108. echo br.'<b>New article defaults:</b>';
  1109. dmp($defaults);
  1110. }
  1111. return $defaults;
  1112. }
  1113. function adi_matrix_publish_article($data,$matrix_index) {
  1114. // new article - based on article_post() from txp_article.php
  1115. // update database with posted data or article defaults
  1116. global $adi_matrix_debug,$adi_matrix_cfs,$txp_user,$prefs,$vars,$step,$adi_matrix_list,$adi_matrix_article_defaults;
  1117. include_once txpath.'/include/txp_article.php'; // to get article_validate() (TXP 4.5.0+), textile_main_fields()
  1118. $defaults = $adi_matrix_article_defaults; // life's still to short, so make variable name short
  1119. // translate adi_matrix stuff into article_post() stuff
  1120. $Title = $Title_plain = $data['title'];
  1121. $Body = '';
  1122. $Body_html = '';
  1123. $Excerpt = '';
  1124. $Excerpt_html = '';
  1125. $textile_body = $prefs['use_textile'];
  1126. $textile_excerpt = $prefs['use_textile'];
  1127. $Annotate = '0';
  1128. $override_form = '';
  1129. $AnnotateInvite = '';
  1130. // article image
  1131. if (isset($data['article_image']))
  1132. $Image = $data['article_image'];
  1133. else
  1134. $Image = $defaults['article_image'];
  1135. // keywords
  1136. if (isset($data['keywords']))
  1137. $Keywords = trim(preg_replace('/( ?[\r\n\t,])+ ?/s', ',', preg_replace('/ +/', ' ', $data['keywords'])), ', ');
  1138. else
  1139. $Keywords = $defaults['keywords'];
  1140. // status
  1141. if (isset($data['status']))
  1142. $Status = $data['status'];
  1143. else
  1144. $Status = $defaults['status'];
  1145. // posted
  1146. if (isset($data['posted']['reset_time']))
  1147. $publish_now = '1';
  1148. else
  1149. $publish_now = '';
  1150. if (isset($data['posted'])) { // this is in TXP date/time
  1151. extract($data['posted']);
  1152. $Posted = $year.'-'.$month.'-'.$day.' '.$hour.':'.$minute.':'.$second;
  1153. }
  1154. else // force now
  1155. $publish_now = '1';
  1156. // expires
  1157. if (isset($data['expires'])) { // this is in TXP date/time
  1158. foreach ($data['expires'] as $index => $value) { // convert expiry vars ($year -> $exp_year) to align with $vars in txp_article.php
  1159. $var = 'exp_'.$index;
  1160. $$var = $value;
  1161. }
  1162. $Expires = $exp_year.'-'.$exp_month.'-'.$exp_day.' '.$exp_hour.':'.$exp_minute.':'.$exp_second;
  1163. }
  1164. else // force no expiry
  1165. $exp_year = '0000';
  1166. // section
  1167. if (isset($data['section']))
  1168. $Section = $data['section'];
  1169. else
  1170. $Section = $defaults['section'];
  1171. // categories
  1172. $Category1 = isset($data['category1']) ? $data['category1'] : $defaults['category1'];
  1173. $Category2 = isset($data['category2']) ? $data['category2'] : $defaults['category2'];
  1174. // custom Fields
  1175. foreach ($adi_matrix_cfs as $index => $cf_name) {
  1176. $custom_x = 'custom_'.$index;
  1177. if (array_key_exists($custom_x,$adi_matrix_list[$matrix_index])) // check that custom field is known to adi_matrix
  1178. if (isset($data[$custom_x])) // present in data posted
  1179. $$custom_x = $data[$custom_x];
  1180. else // not present in posted data, so set default
  1181. $$custom_x = $defaults[$custom_x];
  1182. }
  1183. // package them all up
  1184. $new = compact($vars);
  1185. if ($adi_matrix_debug) {
  1186. echo '<b>New article data:</b>';
  1187. dmp($new);
  1188. }
  1189. // all fields are strings ...
  1190. $incoming = array_map('assert_string',$new);
  1191. // textilation (converts ampersands to &amp; in titles)
  1192. $incoming = textile_main_fields($incoming);
  1193. // slash attack
  1194. extract(doSlash($incoming));
  1195. // ... except some are more integer than string
  1196. extract(array_map('assert_int', array('Status' => $Status, 'textile_body' => $textile_body, 'textile_excerpt' => $textile_excerpt)));
  1197. $Annotate = (int) $Annotate;
  1198. // set posted timestamp (already validated by adi_matrix_validate_post_data)
  1199. if ($publish_now == 1) {
  1200. $when = 'now()';
  1201. $when_ts = time();
  1202. }
  1203. else { // convert TXP date/time to DB timestamp
  1204. $ts = strtotime($year.'-'.$month.'-'.$day.' '.$hour.':'.$minute.':'.$second);
  1205. $when_ts = $ts - tz_offset($ts);
  1206. $when = "from_unixtime($when_ts)";
  1207. }
  1208. // and I quote: "Force a reasonable 'last modified' date for future articles, keep recent articles list in order"
  1209. $lastmod = ($when_ts > time() ? 'now()' : $when);
  1210. // set expiry timestamp (already validated/massaged by adi_matrix_get_post_data)
  1211. if ($exp_year == '0000')
  1212. $expires = 0;
  1213. else { // convert TXP date/time to DB timestamp
  1214. $ts = strtotime($exp_year.'-'.$exp_month.'-'.$exp_day.' '.$exp_hour.':'.$exp_minute.':'.$exp_second);
  1215. $expires = $ts - tz_offset($ts);
  1216. }
  1217. if ($expires)
  1218. $whenexpires = "from_unixtime($expires)";
  1219. else
  1220. $whenexpires = NULLDATETIME;
  1221. // who's doing the doing?
  1222. $user = doSlash($txp_user);
  1223. $msg = '';
  1224. // tweak status according to privs
  1225. if (!has_privs('article.publish') && $Status >= STATUS_LIVE)
  1226. $Status = STATUS_PENDING;
  1227. // set url-title
  1228. if (empty($url_title))
  1229. $url_title = stripSpace($Title_plain, 1);
  1230. // custom fields
  1231. $cfq = array();
  1232. foreach($adi_matrix_cfs as $i => $cf_name) {
  1233. $custom_x = "custom_{$i}";
  1234. if (isset($$custom_x))
  1235. $cfq[] = "custom_$i = '".$$custom_x."'";
  1236. }
  1237. $cfq = implode(', ',$cfq);
  1238. $rs = compact($vars);
  1239. if ($adi_matrix_debug) {
  1240. article_validate($rs, $msg);
  1241. echo '<b>article_validate():</b>';
  1242. dmp($msg);
  1243. }
  1244. if (article_validate($rs, $msg)) {
  1245. $ok = safe_insert(
  1246. "textpattern",
  1247. "Title = '$Title',
  1248. Body = '$Body',
  1249. Body_html = '$Body_html',
  1250. Excerpt = '$Excerpt',
  1251. Excerpt_html = '$Excerpt_html',
  1252. Image = '$Image',
  1253. Keywords = '$Keywords',
  1254. Status = $Status,
  1255. Posted = $when,
  1256. Expires = $whenexpires,
  1257. AuthorID = '$user',
  1258. LastMod = $lastmod,
  1259. LastModID = '$user',
  1260. Section = '$Section',
  1261. Category1 = '$Category1',
  1262. Category2 = '$Category2',
  1263. textile_body = $textile_body,
  1264. textile_excerpt = $textile_excerpt,
  1265. Annotate = $Annotate,
  1266. override_form = '$override_form',
  1267. url_title = '$url_title',
  1268. AnnotateInvite = '$AnnotateInvite',"
  1269. .(($adi_matrix_cfs) ? $cfq.',' : '').
  1270. "uid = '".md5(uniqid(rand(),true))."',
  1271. feed_time = now()"
  1272. ,$adi_matrix_debug
  1273. );
  1274. if ($ok) {
  1275. if ($Status >= STATUS_LIVE) {
  1276. do_pings();
  1277. update_lastmod();
  1278. }
  1279. return TRUE;
  1280. }
  1281. }
  1282. return FALSE;
  1283. }
  1284. function adi_matrix_delete_article($id) {
  1285. // delete an article - ripped off from list_multi_edit() in txp_list.php
  1286. global $txp_user,$adi_matrix_debug;
  1287. // keeping the multi-edit/array thing going - just in case
  1288. $selected = array();
  1289. $selected[] = $id;
  1290. // is allowed?
  1291. if (!has_privs('article.delete')) {
  1292. $allowed = array();
  1293. if (has_privs('article.delete.own'))
  1294. $allowed = safe_column_num('ID', 'textpattern', 'ID in('.implode(',',$selected).') and AuthorID=\''.doSlash($txp_user).'\'',$adi_matrix_debug);
  1295. $selected = $allowed;
  1296. }
  1297. // in the bin
  1298. foreach ($selected as $id) {
  1299. if (safe_delete('textpattern', "ID = $id",$adi_matrix_debug))
  1300. $ids[] = $id;
  1301. }
  1302. // housekeeping
  1303. $changed = implode(', ', $ids);
  1304. if ($changed) {
  1305. safe_update('txp_discuss', "visible = ".MODERATE, "parentid in($changed)",$adi_matrix_debug);
  1306. return TRUE;
  1307. }
  1308. return FALSE;
  1309. }
  1310. function adi_matrix_glz_cfs_input($custom_x,$var,$val,$id) {
  1311. // output custom field input according to glz_custom_fields format
  1312. global $adi_matrix_debug;
  1313. $row = safe_row('html','txp_prefs',"name = '".$custom_x."_set'"); // get html input type from prefs
  1314. $html = $row['html'];
  1315. $arr_custom_field_values = glz_custom_fields_MySQL("values", $custom_x."_set", '', array('custom_set_name' => $custom_x."_set"));
  1316. $default_value = glz_return_clean_default(glz_default_value($arr_custom_field_values));
  1317. if (is_array($arr_custom_field_values))
  1318. array_walk($arr_custom_field_values, "glz_clean_default_array_values"); // from glz_custom_fields_replace()
  1319. // glz radio reset - relies on name="field", which has to match for="field" in main label, which picks up for="field_value" in sub labels but adi_matrix don't have main label & needs name="article_xx[field_xx]" anyway - ne'er the twain shall neet! (would have to write our own reset jQuery I guess)
  1320. // glz radio - uses an ID based on field & value i.e. field_value, but adi_matrix ends up as article_2[custom_3]_value which ain't valid (& don't work in jQuery anyway)
  1321. // glz checkbox - uses an ID based on value only, so may get duplicate ID warnings on Write tab (& definitely on matrix tab)!!!
  1322. if ($html == 'radio') { // create a clean ID prefix (i.e. without [ or ]) for radio buttons - to get rid of some error messages
  1323. $glz_id_prefix = str_replace('[','_',$var);
  1324. $glz_id_prefix = str_replace(']','_',$glz_id_prefix);
  1325. }
  1326. // else if ($html == 'checkbox') {
  1327. // NO GOOD SETTING $glz_id_prefix COZ glz_checkbox(), called by glz_format_custom_set_by_type(), don't use it!
  1328. // HAVE HAD TO USE jQUERY TO ENFORCE UNIQUE IDs
  1329. // }
  1330. else
  1331. $glz_id_prefix = '';
  1332. $out = glz_format_custom_set_by_type($var,$glz_id_prefix,$html,$arr_custom_field_values,$val,$default_value);
  1333. return $out; // html in $out[0], glz class in $out[1]
  1334. }
  1335. function adi_matrix_get_post_data($adi_matrix_articles,$matrix_index) {
  1336. // analyse submitted article data ($_POST), massage if necessary, & create new list of articles & data ($adi_matrix_post)
  1337. global $adi_matrix_list,$adi_matrix_cfs,$adi_matrix_glz_cfs,$adi_matrix_debug;
  1338. if ($adi_matrix_debug) {
  1339. echo '<b>$_POST:</b>';
  1340. dmp($_POST);
  1341. }
  1342. // copy $_POST['article_xx'] to $adi_matrix_post[xx] (where xx is article ID or "new")
  1343. $adi_matrix_post = array();
  1344. foreach ($_POST as $index => $value) {
  1345. $this_index = explode('_',$index);
  1346. if (strpos($index,'article_') === 0) { // pick out anything from $_POST that starts with "article_" ... i.e. article_xx or article_new
  1347. if ($adi_matrix_glz_cfs) // tweak POSTED values to convert from array to bar|separated|list - based on glz_custom_fields_before_save()
  1348. foreach ($value as $key => $val) {
  1349. if (strstr($key, 'custom_') && is_array($val)) { // check for custom fields with multiple values e.g. arrays
  1350. $val = implode($val,'|');
  1351. $value[$key] = $val;
  1352. }
  1353. }
  1354. $adi_matrix_post[$this_index[1]] = $value;
  1355. }
  1356. }
  1357. // new article fiddling
  1358. if (isset($adi_matrix_post['new'])) {
  1359. if (trim($adi_matrix_post['new']['title']) == '') // remove from the equation if title is blank
  1360. unset($adi_matrix_post['new']);
  1361. }
  1362. // check for missing GLZ custom field values & fire blanks if necessary - required for checkboxes/multiselects that have been completely unchecked (otherwise updates not registered)
  1363. // will also pick up radios & multiselects (though deselected multiselect may be present in $_POST anyway)
  1364. if ($adi_matrix_glz_cfs) {
  1365. if ($adi_matrix_debug) echo '<b>GLZ blanks generated for:</b>'.br;
  1366. foreach ($adi_matrix_articles as $id => $article_data) { // check all articles (& new) on page (article may be absent from POST if checkbox is the only data field & it's completely unticked)
  1367. if ($adi_matrix_debug) echo "Article $id - ";
  1368. if (!array_key_exists($id,$adi_matrix_post)) { // article missing from POST completely
  1369. if ($adi_matrix_debug) echo "(article absent) ";
  1370. $adi_matrix_post[$id] = array();
  1371. }
  1372. foreach ($adi_matrix_cfs as $index => $title) { // check each custom field
  1373. if ($adi_matrix_list[$matrix_index]['custom_'.$index]) { // only interested in custom field if it's visible in this matrix
  1374. if (!array_key_exists('custom_'.$index,$adi_matrix_post[$id])) { // custom field absent from article in POST
  1375. $adi_matrix_post[$id]['custom_'.$index] = ''; // fire a blank
  1376. if ($adi_matrix_debug) echo "custom_$index ";
  1377. }
  1378. }
  1379. }
  1380. if ($adi_matrix_debug) echo br;
  1381. }
  1382. if ($adi_matrix_debug) echo br;
  1383. }
  1384. // expires - change all blanks to all zeroes (existing & "new"), coz stored as zeroes but displayed as blanks
  1385. foreach ($adi_matrix_post as $id => $this_article) { // check each article
  1386. if (array_key_exists('expires',$this_article))
  1387. if (($this_article['expires']['year'] == '') && ($this_article['expires']['month'] == '') && ($this_article['expires']['day'] == '') && ($this_article['expires']['hour'] == '') && ($this_article['expires']['minute'] == '') && ($this_article['expires']['second'] == '')) {
  1388. $adi_matrix_post[$id]['expires']['year'] = '0000';
  1389. $adi_matrix_post[$id]['expires']['month'] = $adi_matrix_post[$id]['expires']['day'] = $adi_matrix_post[$id]['expires']['hour'] = $adi_matrix_post[$id]['expires']['minute'] = $adi_matrix_post[$id]['expires']['second'] = '00';
  1390. }
  1391. }
  1392. if ($adi_matrix_debug) {
  1393. echo '<b>$adi_matrix_post:</b>';
  1394. dmp($adi_matrix_post);
  1395. }
  1396. return $adi_matrix_post;
  1397. }
  1398. function adi_matrix_get_updates($adi_matrix_post,$adi_matrix_articles) {
  1399. // compare submitted article data with database data & create $adi_matrix_updates[id][field] if changed
  1400. global $adi_matrix_debug;
  1401. if ($adi_matrix_debug)
  1402. echo '<b>Update processing (adi_matrix_get_updates):</b>'.br;
  1403. $adi_matrix_updates = array();
  1404. foreach ($adi_matrix_post as $id => $data) {
  1405. foreach ($data as $field => $new_value) {
  1406. if (($field == 'posted') || ($field == 'expires'))
  1407. $date_string = $new_value['year'].'-'.$new_value['month'].'-'.$new_value['day'].' '.$new_value['hour'].':'.$new_value['minute'].':'.$new_value['second']; // set up new date/time string
  1408. if ($id == 'new') { // new article
  1409. $adi_matrix_updates[$id][$field] = $new_value;
  1410. if (($field == 'posted') || ($field == 'expires'))
  1411. $new_value = $date_string; // use new time date/time string
  1412. if ($adi_matrix_debug) echo 'id='.$id.', field='.$field.', new_value='.$new_value.' (NEW ARTICLE)'.br;
  1413. }
  1414. else { // existing article
  1415. $equal = TRUE;
  1416. $old_value = $adi_matrix_articles[$id][$field];
  1417. $test_value = $new_value;
  1418. if ($field == 'keywords') // remove human friendly spaces after commas
  1419. $test_value = str_replace(', ' ,',', $new_value);
  1420. if (($field == 'posted') || ($field == 'expires')) // date/time requires special attention (because DB time may be different to TXP human time, so direct comparison not valid)
  1421. if (array_key_exists('reset_time',$new_value)) {
  1422. $equal = FALSE; // force inequality - "NOW()" time will be set in database update
  1423. if ($adi_matrix_debug) echo 'id='.$id.', field='.$field.' (RESET)';
  1424. }
  1425. else { // use article's DB unix timestamp & convert to TXP date/time for comparison
  1426. $ufield = 'u'.$field; // tweak field name from posted/expires to uposted/uexpires
  1427. if ($adi_matrix_articles[$id][$ufield])
  1428. $old_value = safe_strftime("%Y-%m-%d %X",$adi_matrix_articles[$id][$ufield]); // use DB unix timestamp & convert to TXP date/time
  1429. else
  1430. $old_value = '0000-00-00 00:00:00';
  1431. $test_value = $date_string; // use new time date/time string
  1432. if ($adi_matrix_debug) echo 'id='.$id.', field='.$field.', old_value='.$old_value.', test_value='.$test_value;
  1433. }
  1434. else
  1435. if ($adi_matrix_debug) echo 'id='.$id.', field='.$field.', new_value='.$new_value.', old_value='.$old_value.', test_value='.$test_value;
  1436. $equal = $equal && (strcmp($test_value,$old_value) == 0);
  1437. if ($adi_matrix_debug)
  1438. if ($equal) echo " (EQUAL)".br; else echo " <b>(NOT EQUAL)</b>".br;
  1439. if (!$equal)
  1440. $adi_matrix_updates[$id][$field] = $new_value;
  1441. }
  1442. }
  1443. }
  1444. if ($adi_matrix_debug) {
  1445. echo br.'<b>$adi_matrix_updates:</b>';
  1446. dmp($adi_matrix_updates);
  1447. }
  1448. return $adi_matrix_updates;
  1449. }
  1450. function adi_matrix_validate_post_data($adi_matrix_articles,$post_data) {
  1451. // article data validation
  1452. global $adi_matrix_debug,$adi_matrix_validation_errors;
  1453. // create array of empties indexed by $adi_matrix_validation_errors id
  1454. $new_error_list = array();
  1455. foreach ($adi_matrix_validation_errors as $i => $v)
  1456. $new_error_list[$i] = array();
  1457. foreach ($post_data as $id => $data) {
  1458. // add empty "error" slots for article
  1459. foreach ($adi_matrix_validation_errors as $i => $v)
  1460. $new_error_list[$i][$id] = array();
  1461. // remember old timestamp values (existing articles only)
  1462. if ($id != 'new') {
  1463. $posted = $adi_matrix_articles[$id]['posted'];
  1464. $expires = $adi_matrix_articles[$id]['expires'];
  1465. }
  1466. // iterate through $data (OTT but may change in the future)
  1467. foreach ($data as $field => $value) {
  1468. // do some date/time checking
  1469. if (($field == 'posted') || ($field == 'expires')) {
  1470. // record new (i.e. $_POSTed) timestamp values
  1471. $$field = $value['year'].'-'.$value['month'].'-'.$value['day'].' '.$value['hour'].':'.$value['minute'].':'.$value['second'];
  1472. if ($field == 'posted')
  1473. if (array_key_exists('reset_time',$value))
  1474. $$field = date('Y-m-d H:i:s',time()); // have to predict the reset date/time (Article tab does it this way too!)
  1475. // check it's a valid date/time
  1476. $error = (!is_numeric($value['year']) || !is_numeric($value['month']) || !is_numeric($value['day']) || !is_numeric($value['hour']) || !is_numeric($value['minute']) || !is_numeric($value['second']));
  1477. $ts = strtotime($value['year'].'-'.$value['month'].'-'.$value['day'].' '.$value['hour'].':'.$value['minute'].':'.$value['second']);
  1478. $error = $error || ($ts === FALSE || $ts === -1);
  1479. // special case - allow all blanks in expires
  1480. if ($error && ($field == 'expires'))
  1481. $error = !(empty($value['year']) && empty($value['month']) && empty($value['day']) && empty($value['hour']) && empty($value['minute']) && empty($value['second']));
  1482. if ($error) {
  1483. if ($id != 'new')
  1484. $$field = $adi_matrix_articles[$id][$field]; // restore old value (so it doesn't influence later "expires before posted" checking)
  1485. $new_error_list['0'][$id][] = $field;
  1486. }
  1487. }
  1488. }
  1489. // check expires is not before posted (but only if expires is set) TXP 4.6 - EXPIRES CAN BE BLANK TOO
  1490. if ((strtotime($expires) < strtotime($posted)) && ($expires != '0000-00-00 00:00:00') && ($expires != '')) {
  1491. $new_error_list['1'][$id][] = 'posted';
  1492. $new_error_list['1'][$id][] = 'expires';
  1493. }
  1494. // check URL-titles (duplicates & blanks)
  1495. // title supplied if new or edited, get title if not supplied
  1496. if (isset($data['title']))
  1497. $title = $data['title'];
  1498. else
  1499. $title = $adi_matrix_articles[$id]['title'];
  1500. $msg = 0;
  1501. $url_title = stripSpace($title, 1);
  1502. if (trim($url_title) == '') // blank
  1503. $msg = 3;
  1504. if ($msg) {
  1505. $new_error_list[$msg][$id][] = 'url_title';
  1506. }
  1507. $msg = 0;
  1508. // duplicates?
  1509. $url_title_count = safe_count('textpattern',"url_title = '$url_title'");
  1510. if (($url_title_count > 1) || (($id == 'new') && $url_title_count)) { // duplicates found (existing articles: multiple in DB, new article: one or more in DB)
  1511. $msg = 2;
  1512. // get ids of all other articles with matching URL-only titles (they may not be in this matrix, or in this page of this matrix)
  1513. $duplicates = safe_rows('id','textpattern',"url_title = '$url_title'"); // returns array of arrays containing 'id' => id#
  1514. if ($id == 'new')
  1515. $duplicates[]['id'] = gTxt('adi_new_article'); // using "new article" in duplicates list coz don't have new article list
  1516. }
  1517. if ($msg) {
  1518. foreach ($duplicates as $duplicate) {
  1519. $new_error_list[$msg][$duplicate['id']][] = 'url_title';
  1520. }
  1521. }
  1522. }
  1523. // lose the empties
  1524. $new_error_list = array_filter(array_map('array_filter', $new_error_list));
  1525. if ($adi_matrix_debug) {
  1526. echo '<b>Invalid fields:</b>';
  1527. dmp($new_error_list);
  1528. }
  1529. return $new_error_list;
  1530. }
  1531. function adi_matrix_remove_errors($updates,$errors) {
  1532. // remove fields with invalid data from article update list
  1533. global $adi_matrix_debug;
  1534. foreach ($errors as $article)
  1535. foreach ($article as $id => $fields)
  1536. foreach ($fields as $field)
  1537. unset($updates[$id][$field]);
  1538. return $updates;
  1539. }
  1540. function adi_matrix_debug($adi_matrix_articles,$matrix_index) {
  1541. // plot in the title
  1542. global $event,$step,$adi_matrix_cfs,$adi_matrix_list,$adi_matrix_glz_cfs,$adi_matrix_categories,$txp_user;
  1543. echo "<b>Event:</b> ".$event.", <b>Step:</b> ".$step.br;
  1544. echo "<b>Date/time:</b> "
  1545. .'date = '.date("Y-m-d H:i:s")
  1546. .'; tz_offset() = '.tz_offset()
  1547. .'; date + tz_offset() = '.date("Y-m-d H:i:s",time()+tz_offset()) // this is actual (TXP adjusted) local time (incl DST) regardless of server timezone
  1548. .br;
  1549. $rs = safe_query('SELECT NOW()');
  1550. $a = nextRow($rs);
  1551. if ($a)
  1552. echo '<b>Article timestamp in DB &hellip; SELECT NOW()</b> = '.current($a).br;
  1553. else
  1554. echo 'Unable to determine article DB time'.br;
  1555. $rs = safe_query('SELECT UNIX_TIMESTAMP(NOW())');
  1556. $a = nextRow($rs);
  1557. $article_time = current($a);
  1558. if ($a) {
  1559. echo '<b>Article time displayed in article tab &hellip; safe_strftime("%Y-%m-%d %X")</b> = '.safe_strftime("%Y-%m-%d %X",$article_time).br;
  1560. $posted = safe_strftime('%Y-%m-%d %X');
  1561. $ts = strtotime($posted);
  1562. $when_ts = $ts - tz_offset($ts);
  1563. $rs = safe_query("SELECT FROM_UNIXTIME($when_ts)");
  1564. $a = nextRow($rs);
  1565. if ($a)
  1566. echo '<b>Article date/time written to DB</b> = '.current($a).br;
  1567. else
  1568. echo 'Unable to determine date/time written to DB'.br;
  1569. }
  1570. else
  1571. echo 'Unable to determine article tab timestamp'.br;
  1572. echo br;
  1573. echo '<b>This matrix:</b>';
  1574. dmp($adi_matrix_list[$matrix_index]);
  1575. echo '<b>$adi_matrix_cfs:</b>';
  1576. dmp($adi_matrix_cfs);
  1577. if ($adi_matrix_glz_cfs) {
  1578. echo '<b>Custom field input types:</b>',br;
  1579. foreach ($adi_matrix_cfs as $index => $title) {
  1580. $row = safe_row('html','txp_prefs',"name = 'custom_".$index."_set'"); // get html input type from prefs
  1581. echo 'custom_'.$index.' - '.$row['html'].br;
  1582. }
  1583. echo br;
  1584. }
  1585. echo '<b>$adi_matrix_categories:</b>'.br;
  1586. dmp($adi_matrix_categories);
  1587. echo '<b>$adi_matrix_articles:</b>';
  1588. dmp($adi_matrix_articles);
  1589. }
  1590. function adi_matrix_table_head($matrix_index,$type) {
  1591. // matrix <table> header stuff
  1592. // note that clicking a column header will reset back to the first page, which is standard TXP behaviour
  1593. // - to fix would involve a custom elink() function to pass the 'page' variable on
  1594. global $event,$adi_matrix_cfs,$adi_matrix_list;
  1595. // get current sort settings
  1596. list($sort,$dir,$sort_type) = explode(',',get_pref($event.'_sort',$adi_matrix_list[$matrix_index]['sort'].','.$adi_matrix_list[$matrix_index]['dir'].','.$adi_matrix_list[$matrix_index]['sort_type']));
  1597. if ($type == 'header') {
  1598. $tag = 'th';
  1599. $wraptag = 'thead';
  1600. }
  1601. else {
  1602. $tag = 'td';
  1603. $wraptag = 'tfoot';
  1604. }
  1605. // article id/title heading
  1606. $field_list = array('id','title');
  1607. foreach ($field_list as $field) {
  1608. $var = $field.'_hcell';
  1609. $class = array();
  1610. if ($field == $sort) // sort value matches field
  1611. $dir == 'desc' ? $class[] = 'desc' : $class[] = 'asc'; // up/down arrow
  1612. else ; // no arrow - sort set in admin
  1613. $class[] = 'adi_matrix_field_'.$field; // add field name to class
  1614. $class = ' class="'.implode(' ',$class).'"';
  1615. $$var = tag(elink($event,'','sort',$field,gTxt($field),'dir',($dir == 'asc' ? 'desc' : 'asc'),''),$tag,$class); // column heading/toggle sort
  1616. }
  1617. // standard field headings
  1618. $field_list = array('status','article_image','keywords','category1','category2','posted','expires','section');
  1619. foreach ($field_list as $field) {
  1620. $var = $field.'_hcell';
  1621. $class = array();
  1622. if ($field == $sort) // sort value matches field
  1623. $dir == 'desc' ? $class[] = 'desc' : $class[] = 'asc'; // up/down arrow
  1624. else ; // no arrow - sort set in admin
  1625. $class[] = 'adi_matrix_field_'.$field; // add field name to class
  1626. $class = ' class="'.implode(' ',$class).'"';
  1627. $adi_matrix_list[$matrix_index][$field] ? $$var = tag(elink($event,'','sort',$field,gTxt($field),'dir',($dir == 'asc' ? 'desc' : 'asc'),''),$tag,$class) : $$var = ''; // column heading/toggle sort
  1628. }
  1629. // custom field headings
  1630. $cf_hcell = '';
  1631. foreach ($adi_matrix_cfs as $index => $cf_name) {
  1632. $custom_x = 'custom_'.$index;
  1633. $class = array();
  1634. if ($field == $sort) // sort value matches field
  1635. $dir == 'desc' ? $class[] = 'desc' : $class[] = 'asc'; // up/down arrow
  1636. else ; // no arrow - sort set in admin
  1637. $class[] = 'adi_matrix_field_'.$custom_x; // add field name to class
  1638. $class = ' class="'.implode(' ',$class).'"';
  1639. if (array_key_exists($custom_x,$adi_matrix_list[$matrix_index])) // check that custom field is known to adi_matrix
  1640. if ($adi_matrix_list[$matrix_index][$custom_x])
  1641. $cf_hcell .= tag(elink($event,'','sort',$custom_x,$cf_name,'dir',($dir == 'asc' ? 'desc' : 'asc'),''),$tag,$class);
  1642. }
  1643. // delete heading placeholder
  1644. $del_hcell = tag(sp,$tag,' class="adi_matrix_delete"'); // spacer
  1645. // "Show section" heading
  1646. if ($sort == 'section') // sort value matches field
  1647. $dir == 'desc' ? $class = ' class="desc section"' : $class = ' class="asc section"'; // up/down arrow
  1648. else
  1649. $class = ' class= "section"'; // no arrow - sort set in admin
  1650. $show_section_hcell = tag(elink($event,'','sort','section',gTxt('section'),'dir',($dir == 'asc' ? 'desc' : 'asc'),''),$tag,$class);
  1651. return
  1652. tag(
  1653. tr(
  1654. (adi_matrix_pref('adi_matrix_display_id') ? $id_hcell : '')
  1655. .$title_hcell
  1656. .($adi_matrix_list[$matrix_index]['show_section'] ? $show_section_hcell : '') // THIS NEEDS SORTING OUT
  1657. .($adi_matrix_list[$matrix_index]['section'] ? $section_hcell : '') // THIS NEEDS SORTING OUT
  1658. .$status_hcell
  1659. .$cf_hcell
  1660. .$article_image_hcell
  1661. .$keywords_hcell
  1662. .$category1_hcell
  1663. .$category2_hcell
  1664. .$posted_hcell
  1665. .$expires_hcell
  1666. .($adi_matrix_list[$matrix_index]['publish'] ? $del_hcell : '')
  1667. )
  1668. ,$wraptag
  1669. );
  1670. }
  1671. function adi_matrix_table($adi_matrix_articles,$matrix_index,$page,$errors=array(),$updates=array()) {
  1672. // generates matrix <table> and <form> for article data updates
  1673. // stylish classes:
  1674. // tr (article ids): adi_matrix_article_xx, adi_matrix_article_new
  1675. // td (field type): adi_matrix_timestamp, adi_matrix_category
  1676. // td (field specific): adi_matrix_field_id, adi_matrix_field_title, adi_matrix_field_custom_x etc etc
  1677. global $step,$adi_matrix_debug,$adi_matrix_cfs,$adi_matrix_statuses,$adi_matrix_list,$txp_user,$txp_user,$adi_matrix_glz_cfs,$adi_matrix_validation_errors,$adi_matrix_txp460;
  1678. $out = '';
  1679. $out .= adi_matrix_table_head($matrix_index,'header');
  1680. if ($adi_matrix_list[$matrix_index]['footer'])
  1681. $out .= adi_matrix_table_head($matrix_index,'footer');
  1682. $out .= '<tbody>';
  1683. if ($adi_matrix_articles) {
  1684. foreach ($adi_matrix_articles as $id => $data) {
  1685. // set up validation error flags for this article
  1686. $article_errors = array();
  1687. foreach ($errors as $error_type)
  1688. if (isset($error_type[$id]))
  1689. $article_errors = array_merge($article_errors,$error_type[$id]);
  1690. $article_errors = array_unique($article_errors);
  1691. if ($adi_matrix_debug && ($step == 'update')) {
  1692. echo '<b>Validation errors #'.$id.':</b>';
  1693. dmp($article_errors);
  1694. }
  1695. // based on standard save button in txp_article.php
  1696. $Status = $data['status'];
  1697. $AuthorID = $data['author'];
  1698. $has_privs = // work out if user has a right to fiddle with article
  1699. (($Status >= 4 and has_privs('article.edit.published'))
  1700. or ($Status >= 4 and $AuthorID==$txp_user and has_privs('article.edit.own.published'))
  1701. or ($Status < 4 and has_privs('article.edit'))
  1702. or ($Status < 4 and $AuthorID==$txp_user and has_privs('article.edit.own')));
  1703. $prefix = 'article_'.$id; // use array index 'article_id' rather than 'id' in POST data (clearer/safer?)
  1704. $out .= '<tr class="adi_matrix_'.$prefix.'">';
  1705. $highlight = $data['highlight'];
  1706. // article title link tooltip text
  1707. // tooltip (&#10; = newline in non-Firefox tooltip)
  1708. if (adi_matrix_pref('adi_matrix_article_tooltips')) {
  1709. $title_text = '#'.$id.', '.gTxt('posted').' '.$data['display_posted'];
  1710. if ($data['expires'] != '0000-00-00 00:00:00')
  1711. $title_text .= ', '.gTxt('expires').' '.$data['display_expires'];
  1712. if ($highlight == 1)
  1713. $title_text .= ' ('.gTxt('expired').')';
  1714. if ($highlight == 2)
  1715. $title_text .= ' ('.gTxt('time_future').')';
  1716. $title_text .= ', '.$data['section'];
  1717. $title_text .= ', '.$AuthorID;
  1718. }
  1719. else
  1720. $title_text = gTxt('edit');
  1721. $class = '';
  1722. // highlighting for expired/future articles
  1723. if (adi_matrix_pref('adi_matrix_article_highlighting')) {
  1724. if ($highlight) {
  1725. if ($highlight == 1) $class = ' class="adi_matrix_expired"';
  1726. if ($highlight == 2) $class = ' class="adi_matrix_future"';
  1727. }
  1728. }
  1729. // ID
  1730. if (adi_matrix_pref('adi_matrix_display_id')) {
  1731. $id_link = eLink('article','edit','ID',$id,$id);
  1732. $out .= tag($id_link,'td',' class="adi_matrix_field_id"');
  1733. }
  1734. // title
  1735. $article_title = trim($data['title']);
  1736. if ($article_title == '') // blank title
  1737. $title_link = tag(eLink('article','edit','ID',$id,gTxt('untitled'),'','',$title_text),'em');
  1738. else
  1739. $title_link = eLink('article','edit','ID',$id,$article_title,'','',$title_text);
  1740. $title_link = '<span title="'.$title_text.'"'.$class.'>'.$title_link.'</span>';
  1741. $arrow_link = sp.tag(eLink('article','edit','ID',$id,sp,'','',$title_text),'span',' class="adi_matrix_edit_link"'); // was &rarr;
  1742. if ($adi_matrix_list[$matrix_index]['title'] && adi_matrix_pref('adi_matrix_display_id')) // don't need arrow if got IDs
  1743. $arrow_link = '';
  1744. if ($adi_matrix_list[$matrix_index]['title']) {
  1745. $has_privs ? // decide if user gets input fields or not
  1746. $out .= tda(finput("text",$prefix."[title]",$data['title'],'',(adi_matrix_pref('adi_matrix_input_field_tooltips') ?htmlspecialchars($data['title']):'')).$arrow_link,' class="adi_matrix_field_title"') :
  1747. $out .= tda($title_link,' class="adi_matrix_field_title"');
  1748. }
  1749. else
  1750. $out .= tag($title_link,'td',' class="adi_matrix_field_title"');
  1751. // section
  1752. if ($adi_matrix_list[$matrix_index]['show_section'])
  1753. $out .= tda($data['section']);
  1754. if ($adi_matrix_list[$matrix_index]['section']) {
  1755. $has_privs ? // decide if user gets input fields or not
  1756. $out .= tda(adi_matrix_section_popup($prefix."[section]",$data['section'],$adi_matrix_list[$matrix_index]['criteria_section']),' class="adi_matrix_field_section"') :
  1757. $out .= ($data['section'] ? tda($data['section'],' class="adi_matrix_field_section"') : tda(sp,' class="adi_matrix_field_section"'));
  1758. }
  1759. // status
  1760. if ($adi_matrix_list[$matrix_index]['status'])
  1761. $has_privs ? // decide if user gets input fields or not
  1762. $out .= tda(selectInput($prefix.'[status]',$adi_matrix_statuses,$data['status']),' class="adi_matrix_field_status"') :
  1763. $out .= tda($adi_matrix_statuses[$data['status']],' class="adi_matrix_field_status"');
  1764. // custom fields
  1765. foreach ($adi_matrix_cfs as $index => $cf_name) {
  1766. $custom_x = 'custom_'.$index;
  1767. if (array_key_exists($custom_x,$adi_matrix_list[$matrix_index])) // check that custom field is known to adi_matrix
  1768. if ($adi_matrix_list[$matrix_index][$custom_x])
  1769. if ($has_privs) // decide if user gets input fields or not
  1770. if ($adi_matrix_glz_cfs) {
  1771. $glz_input_stuff = adi_matrix_glz_cfs_input($custom_x,$prefix."[$custom_x]",$data[$custom_x],$id);
  1772. if ($glz_input_stuff[1] == 'glz_custom_radio_field') // don't apply glz_class coz can't handle glz reset function properly yet - see below
  1773. $out .= tda($glz_input_stuff[0],' class="adi_matrix_field_'.$custom_x.'"');
  1774. else
  1775. $out .= tda($glz_input_stuff[0],' class="'.$glz_input_stuff[1].' adi_matrix_field_'.$custom_x.'"');
  1776. }
  1777. else
  1778. $out .= tda(finput("text",$prefix."[$custom_x]",$data[$custom_x],'',(adi_matrix_pref('adi_matrix_input_field_tooltips')?htmlspecialchars($data[$custom_x]):'')),' class="adi_matrix_field_'.$custom_x.'"');
  1779. else
  1780. $out .= ($data[$custom_x] ? tda($data[$custom_x],' class="adi_matrix_field_'.$custom_x.'"') : tda(sp,' class="adi_matrix_field_'.$custom_x.'"')); // make sure the table cell stretches if no data
  1781. }
  1782. // article image
  1783. if ($adi_matrix_list[$matrix_index]['article_image']) {
  1784. $arrow_link = '';
  1785. // CUSTOM FIELD LINKS DISABLED
  1786. // if (trim($data['article_image']) && ($adi_matrix_list[$matrix_index]['cf_links'] == 'article_image')) {
  1787. // $image_ids = explode(',',$data['article_image']);
  1788. // $image_id = $image_ids[0];
  1789. // if (safe_count('txp_image',"id=$image_id",$adi_matrix_debug))
  1790. // $arrow_link = sp.eLink('image','image_edit','id',$image_id,'&rarr;','','',gTxt('edit_image').' #'.$image_id);
  1791. // else // image not found
  1792. // $arrow_link = sp.'?';
  1793. // }
  1794. $has_privs ? // decide if user gets input fields or not
  1795. $out .= tda(finput("text",$prefix."[article_image]",$data['article_image'],'',(adi_matrix_pref('adi_matrix_input_field_tooltips')?htmlspecialchars($data['article_image']):'')).$arrow_link,' class="adi_matrix_field_image"') :
  1796. $out .= ($data['article_image'] ? tda($data['article_image'].$arrow_link,' class="adi_matrix_field_image"') : tda(sp,' class="adi_matrix_field_image"')); // make sure the table cell stretches if no data
  1797. }
  1798. // keywords
  1799. if ($adi_matrix_list[$matrix_index]['keywords'])
  1800. $has_privs ? // decide if user gets input fields or not
  1801. $out .= tda('<textarea name="'.$prefix."[keywords]".'" cols="18" rows="5" class="mceNoEditor">'.htmlspecialchars(str_replace(',' ,', ', $data['keywords'])).'</textarea>',' class="adi_matrix_field_keywords"') :
  1802. $out .= ($data['keywords'] ? tda($data['keywords'],' class="adi_matrix_field_keywords"') : tda(sp,' class="adi_matrix_field_keywords"'));
  1803. // category1
  1804. if ($adi_matrix_list[$matrix_index]['category1'])
  1805. $has_privs ? // decide if user gets input fields or not
  1806. $out .= tda(adi_matrix_category_popup($prefix."[category1]",$data['category1'],FALSE),' class="adi_matrix_category adi_matrix_field_category1"') :
  1807. $out .= ($data['category1'] ? tda($data['category1'],' class="adi_matrix_field_category1"') : tda(sp,' class="adi_matrix_category adi_matrix_field_category1"'));
  1808. // category2
  1809. if ($adi_matrix_list[$matrix_index]['category2'])
  1810. $has_privs ? // decide if user gets input fields or not
  1811. $out .= tda(adi_matrix_category_popup($prefix."[category2]",$data['category2'],FALSE),' class="adi_matrix_category adi_matrix_field_category2"') :
  1812. $out .= ($data['category2'] ? tda($data['category2'],' class="adi_matrix_field_category2"') : tda(sp,' class="adi_matrix_category adi_matrix_field_category2"'));
  1813. // posted
  1814. $class = 'adi_matrix_timestamp adi_matrix_field_posted';
  1815. if (array_search('posted',$article_errors) !== FALSE)
  1816. $class .= ' adi_matrix_error';
  1817. if ($adi_matrix_list[$matrix_index]['posted'])
  1818. $has_privs ? // decide if user gets input fields or not
  1819. $out .= tda(adi_matrix_timestamp_input($prefix."[posted]",$data['posted'],$data['uposted'],'posted'),' class="'.$class.'"') :
  1820. $out .= ($data['posted'] ? tda($data['posted']) : tda(sp));
  1821. // expires
  1822. $class = 'adi_matrix_timestamp adi_matrix_field_expires';
  1823. if (array_search('expires',$article_errors) !== FALSE)
  1824. $class .= ' adi_matrix_error';
  1825. if ($adi_matrix_list[$matrix_index]['expires'])
  1826. $has_privs ? // decide if user gets input fields or not
  1827. $out .= tda(adi_matrix_timestamp_input($prefix."[expires]",$data['expires'],$data['uexpires'],'expires'),' class="'.$class.'"') :
  1828. $out .= ($data['expires'] ? tda($data['expires']) : tda(sp));
  1829. // delete button
  1830. if ($adi_matrix_list[$matrix_index]['publish']) { // got publish? - might delete!
  1831. // a closer look at credentials - override delete priv OR (delete own priv and it's yours to delete)
  1832. if (has_privs('article.delete') || (has_privs('article.delete.own') && ($AuthorID == $txp_user))) {
  1833. if ($adi_matrix_txp460)
  1834. $button =
  1835. href(
  1836. span('Delete',' class="ui-icon ui-icon-close"')
  1837. ,array(
  1838. 'event' => 'adi_matrix_matrix_'.$matrix_index,
  1839. 'step' => 'delete',
  1840. 'id' => $id,
  1841. 'page' => $page,
  1842. '_txp_token' => form_token(),
  1843. )
  1844. ,array(
  1845. 'class' => 'dlink destroy',
  1846. 'title' => gTxt('delete'),
  1847. 'data-verify' => gTxt('confirm_delete_popup'),
  1848. )
  1849. );
  1850. else {
  1851. $url = '?event='.'adi_matrix_matrix_'.$matrix_index.a.'step=delete'.a.'id='.$id.a.'page='.$page;
  1852. $button =
  1853. '<a href="'
  1854. .$url
  1855. .'" class="dlink" title="Delete?" onclick="return verify(\''
  1856. .addslashes(htmlentities($data['title']))
  1857. .' - '
  1858. .gTxt('confirm_delete_popup')
  1859. .'\')">&#215;</a>';
  1860. }
  1861. $out .= tda($button,' class="adi_matrix_delete"');
  1862. }
  1863. else
  1864. $out .= tda(sp);
  1865. }
  1866. $out .= '</tr>';
  1867. }
  1868. }
  1869. if ($adi_matrix_list[$matrix_index]['publish'] && has_privs('article'))
  1870. $out .= adi_matrix_new_article($matrix_index);
  1871. $out .= '</tbody>';
  1872. return $out;
  1873. }
  1874. function adi_matrix_new_article($matrix_index) {
  1875. // data input fields for new article
  1876. // styles as per adi_matrix_table()
  1877. global $adi_matrix_debug,$adi_matrix_cfs,$adi_matrix_statuses,$adi_matrix_list,$adi_matrix_glz_cfs,$adi_matrix_article_defaults;
  1878. $defaults = $adi_matrix_article_defaults; // life's too short to type
  1879. $prefix = 'article_new';
  1880. $out = '<tr class="adi_matrix_'.$prefix.'">';
  1881. // ID placeholder
  1882. if (adi_matrix_pref('adi_matrix_display_id'))
  1883. $out .= tag('&#43;','td',' class="adi_matrix_add adi_matrix_field_id"'); // plus
  1884. // title
  1885. $out .= tda(finput("text",$prefix."[title]",$defaults['title']),' class="adi_matrix_field_title"');
  1886. // section
  1887. if ($adi_matrix_list[$matrix_index]['show_section'])
  1888. $out .= tda($defaults['section'],' class="adi_matrix_field_section"');
  1889. else if ($adi_matrix_list[$matrix_index]['section'])
  1890. $out .= tda(adi_matrix_section_popup($prefix."[section]",$defaults['section'],$adi_matrix_list[$matrix_index]['criteria_section']),' class="adi_matrix_field_section"');
  1891. // status
  1892. if ($adi_matrix_list[$matrix_index]['status'])
  1893. $out .= tda(selectInput($prefix.'[status]',$adi_matrix_statuses,$defaults['status']),' class="adi_matrix_field_status"');
  1894. // custom fields
  1895. foreach ($adi_matrix_cfs as $index => $cf_name) {
  1896. $custom_x = 'custom_'.$index;
  1897. if (array_key_exists($custom_x,$adi_matrix_list[$matrix_index])) // check that custom field is known to adi_matrix
  1898. if ($adi_matrix_list[$matrix_index][$custom_x])
  1899. if ($adi_matrix_glz_cfs) {
  1900. $glz_input_stuff = adi_matrix_glz_cfs_input($custom_x,$prefix."[$custom_x]",$defaults[$custom_x],0);
  1901. if ($glz_input_stuff[1] == 'glz_custom_radio_field') // don't apply glz_class coz can't handle glz reset function properly yet - see below
  1902. $out .= tda($glz_input_stuff[0],' class="adi_matrix_field_'.$custom_x.'"');
  1903. else
  1904. $out .= tda($glz_input_stuff[0],' class="'.$glz_input_stuff[1].' adi_matrix_field_'.$custom_x.'"');
  1905. }
  1906. else
  1907. $out .= tda(finput("text",$prefix."[$custom_x]",$defaults[$custom_x],'',(adi_matrix_pref('adi_matrix_input_field_tooltips')?htmlspecialchars($defaults[$custom_x]):'')),' class="adi_matrix_field_'.$custom_x.'"');
  1908. }
  1909. // article image
  1910. if ($adi_matrix_list[$matrix_index]['article_image'])
  1911. $out .= tda(finput("text",$prefix."[article_image]",$defaults['title']),' class="adi_matrix_field_image"');
  1912. // keywords
  1913. if ($adi_matrix_list[$matrix_index]['keywords'])
  1914. $out .= tda('<textarea name="'.$prefix."[keywords]".'" cols="18" rows="5" class="mceNoEditor">'.htmlspecialchars(str_replace(',' ,', ', $defaults['keywords'])).'</textarea>',' class="adi_matrix_field_keywords"');
  1915. // category1
  1916. if ($adi_matrix_list[$matrix_index]['category1'])
  1917. $out .= tda(adi_matrix_category_popup($prefix."[category1]",$defaults['category1'],FALSE),' class="adi_matrix_category adi_matrix_field_category1"');
  1918. // category2
  1919. if ($adi_matrix_list[$matrix_index]['category2'])
  1920. $out .= tda(adi_matrix_category_popup($prefix."[category2]",$defaults['category2'],FALSE),' class="adi_matrix_category adi_matrix_field_category2"');
  1921. // posted
  1922. if ($adi_matrix_list[$matrix_index]['posted'])
  1923. $out .= tda(adi_matrix_timestamp_input($prefix."[posted]",$defaults['posted'],$defaults['uposted'],'posted'),' class="adi_matrix_timestamp adi_matrix_field_posted"');
  1924. // expires
  1925. if ($adi_matrix_list[$matrix_index]['expires'])
  1926. $out .= tda(adi_matrix_timestamp_input($prefix."[expires]",$defaults['expires'],$defaults['uexpires'],'expires'),' class="adi_matrix_timestamp adi_matrix_field_expires"');
  1927. // Delete placeholder
  1928. if ($adi_matrix_list[$matrix_index]['publish'])
  1929. $out .= tag(sp,'td',' class="adi_matrix_delete"');
  1930. $out .= '</tr>';
  1931. return $out;
  1932. }
  1933. function adi_matrix_matrix($event,$step) {
  1934. // a matrix tab
  1935. global $prefs,$adi_matrix_debug,$adi_matrix_dump,$adi_matrix_list,$adi_matrix_articles,$adi_matrix_cfs,$adi_matrix_sort_dir,$adi_matrix_sort_type,$adi_matrix_sort_options,$adi_matrix_validation_errors,$adi_matrix_article_defaults;
  1936. // extract matrix index from event (e.g. adi_matrix_matrix_0 => 0)
  1937. $matrix_index = str_replace('adi_matrix_matrix_','',$event);
  1938. // bomb out if upgrade needed
  1939. $upgrade_required = adi_matrix_upgrade();
  1940. if ($upgrade_required) {
  1941. pagetop($adi_matrix_list[$matrix_index]['name'],array(gTxt('adi_upgrade_required'),E_WARNING));
  1942. return;
  1943. }
  1944. // current sort settings (read from user pref, default to matrix settings)
  1945. list($sort,$dir,$sort_type) = explode(',',get_pref($event.'_sort',$adi_matrix_list[$matrix_index]['sort'].','.$adi_matrix_list[$matrix_index]['dir'].','.$adi_matrix_list[$matrix_index]['sort_type']));
  1946. // user sort changes
  1947. $new_sort = doStripTags(gps('sort'));
  1948. $new_dir = doStripTags(gps('dir'));
  1949. $new_sort_type = doStripTags(gps('sort_type'));
  1950. $reset_sort = doStripTags(gps('reset_sort'));
  1951. // sort it all out
  1952. if ($new_sort || $new_dir || $new_sort_type || $reset_sort) {
  1953. if ($new_sort && $new_dir) // column heading clicked
  1954. adi_matrix_pref($event.'_sort',$new_sort.','.$new_dir.','.$sort_type,TRUE); // update user pref with sort & dir
  1955. else if ($new_sort_type) // sort_type change
  1956. adi_matrix_pref($event.'_sort',$sort.','.$dir.','.$new_sort_type,TRUE); // update user pref with sort_type
  1957. else if ($reset_sort) { // reset sort to default
  1958. safe_delete('txp_prefs',"name = '".$event."_sort'",$adi_matrix_debug); // delete user pref
  1959. unset($prefs[$event.'_sort']);
  1960. }
  1961. // reread user pref, defaulting to matrix settings
  1962. list($sort,$dir,$sort_type) = explode(',',get_pref($event.'_sort',$adi_matrix_list[$matrix_index]['sort'].','.$adi_matrix_list[$matrix_index]['dir'].','.$adi_matrix_list[$matrix_index]['sort_type']));
  1963. }
  1964. // initialise some bits
  1965. $message = '';
  1966. $updates = $errors = array();
  1967. // article selection criteria
  1968. $criteria = array();
  1969. $criteria['section'] = $adi_matrix_list[$matrix_index]['criteria_section'];
  1970. $criteria['category'] = $adi_matrix_list[$matrix_index]['criteria_category'];
  1971. $criteria['descendent_cats'] = $adi_matrix_list[$matrix_index]['criteria_descendent_cats'];
  1972. $criteria['status'] = $adi_matrix_list[$matrix_index]['criteria_status'];
  1973. $criteria['author'] = $adi_matrix_list[$matrix_index]['criteria_author'];
  1974. $criteria['keywords'] = $adi_matrix_list[$matrix_index]['criteria_keywords'];
  1975. $criteria['timestamp'] = $adi_matrix_list[$matrix_index]['criteria_timestamp'];
  1976. $criteria['expiry'] = $adi_matrix_list[$matrix_index]['criteria_expiry'];
  1977. $criteria['condition'] = $adi_matrix_list[$matrix_index]['criteria_condition'];
  1978. // article selection WHERE clause
  1979. $where = adi_matrix_where($criteria);
  1980. // article sort query
  1981. $sortq = adi_matrix_order_by($sort,$dir,$sort_type);
  1982. // paging Mr. Matrix
  1983. if ($step == $event.'_change_pageby') { // change of page length
  1984. $qty = gps('qty');
  1985. adi_matrix_pref($event.'_pageby',$qty,TRUE);
  1986. }
  1987. $page = gps('page'); // get page number
  1988. $pageby = get_pref($event.'_pageby',15); // get current page size (default to 15, if not saved as pref)
  1989. $total = safe_count('textpattern',"$where");
  1990. list($page,$offset,$num_pages) = pager($total,$pageby,$page);
  1991. if ($adi_matrix_debug)
  1992. echo "<b>Paging:</b> pageby=$pageby, total=$total, page=$page, offset=$offset, num_pages=$num_pages".br;
  1993. // get a page of articles
  1994. $adi_matrix_articles = adi_matrix_get_articles($where,$sortq,$matrix_index,$offset,$pageby);
  1995. // article defaults
  1996. $adi_matrix_article_defaults = adi_matrix_article_defaults($matrix_index);
  1997. // $step aerobics
  1998. if ($step == 'update') {
  1999. $post_data = adi_matrix_get_post_data($adi_matrix_articles,$matrix_index);
  2000. $errors = adi_matrix_validate_post_data($adi_matrix_articles,$post_data);
  2001. $updates = adi_matrix_get_updates(adi_matrix_remove_errors($post_data,$errors),$adi_matrix_articles);
  2002. if ($updates) {
  2003. $ok = adi_matrix_update_articles($updates,$matrix_index);
  2004. $ok ? $message = gTxt('adi_articles_saved') : $message = array(gTxt('adi_article_update_fail'),E_WARNING);
  2005. }
  2006. else
  2007. $message = gTxt('adi_articles_not_modified');
  2008. if ($errors) {
  2009. $message .= '. '.gTxt('adi_matrix_validation_error');
  2010. foreach ($errors as $i => $v)
  2011. $message .= ' '.$adi_matrix_validation_errors[$i].' ('.implode(',',array_keys($v)).')';
  2012. $message = array($message,E_WARNING);
  2013. }
  2014. }
  2015. else if ($step == 'delete') {
  2016. $id = gps('id');
  2017. if (isset($adi_matrix_articles[$id])) {
  2018. $ok = adi_matrix_delete_article($id);
  2019. $message = gTxt('article_deleted').' ('.$id.')';
  2020. }
  2021. else {
  2022. $message = array(gTxt('adi_article_delete_fail'),E_ERROR);
  2023. }
  2024. }
  2025. // regenerate articles list & count array again?
  2026. if (($step == 'update') || ($step == 'delete')) {
  2027. $adi_matrix_articles = adi_matrix_get_articles($where,$sortq,$matrix_index,$offset,$pageby);
  2028. $total = safe_count('textpattern',"$where");
  2029. }
  2030. if ($adi_matrix_debug) {
  2031. $matrix_page_id_list = implode(',',array_keys($adi_matrix_articles)); // list if all article ids on this page
  2032. echo "<b>Article ID list (on this page):</b> $matrix_page_id_list".br;
  2033. $col = safe_column('ID','textpattern',$where.$sortq);
  2034. $matrix_id_list = implode(',',array_keys($col));
  2035. echo "<b>Article ID list (in matrix):</b> $matrix_id_list".br.br;
  2036. }
  2037. if ($adi_matrix_dump) {
  2038. // dump article data (all articles in matrix)
  2039. $rows = safe_rows('*','textpattern',"ID IN (".implode(',',array_keys($adi_matrix_articles)).")");
  2040. echo 'START ARTICLE MATRIX DUMP'.br;
  2041. foreach ($rows as $i => $a) {
  2042. foreach ($a as $f => $d)
  2043. echo htmlentities("$f=$d,");
  2044. echo br;
  2045. }
  2046. echo 'END ARTICLE MATRIX DUMP'.br;
  2047. }
  2048. // generate page
  2049. pagetop($adi_matrix_list[$matrix_index]['name'],$message);
  2050. // output matrix table & input form
  2051. $table = adi_matrix_table($adi_matrix_articles,$matrix_index,$page,$errors,$updates);
  2052. $tags = array('<input', '<textarea', '<select'); // tags which indicate that a save button is deserved
  2053. $save_button = FALSE;
  2054. foreach ($tags as $tag)
  2055. $save_button = $save_button || strpos($table,$tag);
  2056. $class = 'adi_matrix_matrix';
  2057. if ($adi_matrix_list[$matrix_index]['scroll'])
  2058. $class .= ' adi_matrix_scroll';
  2059. $class .= ' txp-list';
  2060. echo form(
  2061. tag($adi_matrix_list[$matrix_index]['name'],'h1')
  2062. .'<div class="scroll_box">'
  2063. .startTable('list','',$class)
  2064. .$table
  2065. .endTable()
  2066. .'</div>'
  2067. .(empty($adi_matrix_articles) ?
  2068. graf(tag(gTxt('no_articles_recorded'),'em'),' class="adi_matrix_none"')
  2069. : ''
  2070. )
  2071. .($save_button ?
  2072. tag(
  2073. hInput('page',$page) // pass on paging
  2074. .fInput("submit", "do_something", gTxt('save'), "publish")
  2075. .eInput("adi_matrix_matrix_".$matrix_index).sInput("update"),
  2076. 'div',
  2077. ' class="adi_matrix_button"'
  2078. )
  2079. : ''
  2080. )
  2081. .tag(
  2082. graf(
  2083. gTxt('adi_default_sort')
  2084. .sp.sp
  2085. .elink(
  2086. $event
  2087. ,''
  2088. ,'reset_sort'
  2089. ,1
  2090. ,$adi_matrix_sort_options[$adi_matrix_list[$matrix_index]['sort']]
  2091. .', '
  2092. .$adi_matrix_sort_dir[$adi_matrix_list[$matrix_index]['dir']]
  2093. .', '
  2094. .$adi_matrix_sort_type[$adi_matrix_list[$matrix_index]['sort_type']]
  2095. ,'','','' // to override TXP 4.5 default title "Edit"
  2096. )
  2097. .br
  2098. .gTxt('adi_sort_type')
  2099. .sp.sp
  2100. .strong(gTxt('adi_'.$sort_type))
  2101. .' / '
  2102. .elink(
  2103. $event
  2104. ,''
  2105. ,'sort_type'
  2106. ,($sort_type == 'numerical' ? 'alphabetical' : 'numerical')
  2107. ,gTxt(($sort_type == 'numerical' ? 'adi_alphabetical' : 'adi_numerical'))
  2108. ,'','','' // to override TXP 4.5 default title "Edit"
  2109. )
  2110. )
  2111. ,'div',' class="adi_matrix_matrix_prefs"')
  2112. ,''
  2113. ,''
  2114. ,'post'
  2115. ,$class
  2116. );
  2117. // flashing message
  2118. if ($errors) {
  2119. echo <<<END_SCRIPT
  2120. <script type="text/javascript">
  2121. <!--
  2122. $(document).ready( function(){
  2123. $('#messagepane').fadeOut(800).fadeIn(800);
  2124. $('#messagepane').fadeOut(800).fadeIn(800);
  2125. } )
  2126. // -->
  2127. </script>
  2128. END_SCRIPT;
  2129. }
  2130. // grand total
  2131. echo graf(gTxt('adi_matrix_total_articles').sp.sp.$total,' class="adi_matrix_grand_total"');
  2132. // paging
  2133. echo tag(
  2134. // prev/next page buttons (if muliple pages)
  2135. ($total > $pageby ? nav_form($event,$page,$num_pages,$sort,$dir,'','',$total,$pageby,'') : '') // set empty step (to avoid confusion), coz default is "list"
  2136. // page length select
  2137. .pageby_form($event,$pageby)
  2138. ,'div'
  2139. ,' id="list_navigation" class="txp-navigation"'
  2140. );
  2141. if ($adi_matrix_debug)
  2142. adi_matrix_debug($adi_matrix_articles,$matrix_index);
  2143. }
  2144. function adi_matrix_installed($table='adi_matrix') {
  2145. // test if database table is present
  2146. $rs = safe_query("SHOW TABLES LIKE '".safe_pfx($table)."'");
  2147. $a = nextRow($rs);
  2148. if ($a)
  2149. return TRUE;
  2150. else
  2151. return FALSE;
  2152. }
  2153. function adi_matrix_install() {
  2154. // install adi_matrix table in database
  2155. global $adi_matrix_debug,$adi_matrix_cfs;
  2156. $cfq = '';
  2157. foreach ($adi_matrix_cfs as $index => $value) {
  2158. $cfq .= ', `custom_'.$index.'` TINYINT(1) DEFAULT 0 NOT NULL';
  2159. }
  2160. $res = safe_query(
  2161. "CREATE TABLE IF NOT EXISTS "
  2162. .safe_pfx('adi_matrix')
  2163. ." (
  2164. `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  2165. `name` VARCHAR(255) NOT NULL,
  2166. `sort` VARCHAR(32) NOT NULL DEFAULT 'posted',
  2167. `sort_type` VARCHAR(32) NOT NULL DEFAULT 'alphabetical',
  2168. `dir` VARCHAR(32) NOT NULL DEFAULT 'desc',
  2169. `user` VARCHAR(64) NOT NULL DEFAULT '',
  2170. `privs` VARCHAR(16) NOT NULL DEFAULT '',
  2171. `scroll` TINYINT(1) DEFAULT 0 NOT NULL,
  2172. `footer` TINYINT(1) DEFAULT 0 NOT NULL,
  2173. `title` TINYINT(1) DEFAULT 0 NOT NULL,
  2174. `publish` TINYINT(1) DEFAULT 0 NOT NULL,
  2175. `show_section` TINYINT(1) DEFAULT 0 NOT NULL,
  2176. `cf_links` VARCHAR(128) NOT NULL DEFAULT '',
  2177. `tab` VARCHAR(16) NOT NULL DEFAULT 'content',
  2178. `criteria_section` VARCHAR(128) NOT NULL DEFAULT '',
  2179. `criteria_category` VARCHAR(128) NOT NULL DEFAULT '',
  2180. `criteria_status` INT(2) NOT NULL DEFAULT '4',
  2181. `criteria_author` VARCHAR(64) NOT NULL DEFAULT '',
  2182. `criteria_keywords` VARCHAR(255) NOT NULL DEFAULT '',
  2183. `criteria_timestamp` VARCHAR(16) NOT NULL DEFAULT 'any',
  2184. `criteria_expiry` INT(2) NOT NULL DEFAULT '0',
  2185. `criteria_descendent_cats` TINYINT(1) DEFAULT 0 NOT NULL,
  2186. `criteria_condition` VARCHAR(255) NOT NULL DEFAULT '',
  2187. `status` TINYINT(1) DEFAULT 0 NOT NULL,
  2188. `keywords` TINYINT(1) DEFAULT 0 NOT NULL,
  2189. `article_image` TINYINT(1) DEFAULT 0 NOT NULL,
  2190. `category1` VARCHAR(128) NOT NULL DEFAULT '',
  2191. `category2` VARCHAR(128) NOT NULL DEFAULT '',
  2192. `posted` TINYINT(1) DEFAULT 0 NOT NULL,
  2193. `expires` TINYINT(1) DEFAULT 0 NOT NULL,
  2194. `section` TINYINT(1) DEFAULT 0 NOT NULL
  2195. "
  2196. .$cfq
  2197. .");"
  2198. ,$adi_matrix_debug
  2199. );
  2200. return $res;
  2201. }
  2202. function adi_matrix_uninstall() {
  2203. // uninstall adi_matrix
  2204. global $adi_matrix_debug;
  2205. // delete table
  2206. $res = safe_query("DROP TABLE ".safe_pfx('adi_matrix').";",$adi_matrix_debug);
  2207. // delete preferences
  2208. $res = $res && safe_delete('txp_prefs',"name LIKE 'adi_matrix_%'",$adi_matrix_debug);
  2209. return $res;
  2210. }
  2211. function adi_matrix_lifecycle($event,$step) {
  2212. // a matter of life & death
  2213. // $event: "plugin_lifecycle.adi_matrix"
  2214. // $step: "installed", "enabled", disabled", "deleted"
  2215. // TXP 4.5: upgrade/reinstall only triggers "installed" event (now have to manually detect whether upgrade required)
  2216. global $adi_matrix_debug;
  2217. $result = '?';
  2218. // set upgrade flag if upgrading/reinstalling in TXP 4.5+
  2219. $upgrade = (($step == "installed") && adi_matrix_installed());
  2220. if ($step == 'enabled') {
  2221. $result = $upgrade = adi_matrix_install();
  2222. }
  2223. else if ($step == 'deleted')
  2224. $result = adi_matrix_uninstall();
  2225. if ($upgrade)
  2226. $result = $result && adi_matrix_upgrade(TRUE);
  2227. if ($adi_matrix_debug)
  2228. echo "Event=$event Step=$step Result=$result Upgrade=$upgrade";
  2229. }
  2230. function adi_matrix_upgrade($do_upgrade=FALSE) {
  2231. // check/perform upgrade
  2232. global $adi_matrix_debug;
  2233. $upgrade_required = FALSE;
  2234. // version 0.2
  2235. $rs = safe_query('SHOW FIELDS FROM '.safe_pfx('adi_matrix')." LIKE 'article_image'",$adi_matrix_debug); // find out if column exists
  2236. $a = nextRow($rs);
  2237. $v0_2 = empty($a);
  2238. $upgrade_required = $upgrade_required || $v0_2;
  2239. // version 0.3
  2240. $rs = safe_query('SHOW FIELDS FROM '.safe_pfx('adi_matrix')." LIKE 'criteria_timestamp'",$adi_matrix_debug);
  2241. $a = nextRow($rs);
  2242. $v0_3t = empty($a);
  2243. $upgrade_required = $upgrade_required || $v0_3t;
  2244. // version 0.3
  2245. $rs = safe_query('SHOW FIELDS FROM '.safe_pfx('adi_matrix')." LIKE 'criteria_expiry'",$adi_matrix_debug);
  2246. $a = nextRow($rs);
  2247. $v0_3e = empty($a);
  2248. $upgrade_required = $upgrade_required || $v0_3e;
  2249. // version 1.0
  2250. $rs = safe_query('SHOW FIELDS FROM '.safe_pfx('adi_matrix')." LIKE 'scroll'",$adi_matrix_debug);
  2251. $a = nextRow($rs);
  2252. $v1_0 = empty($a);
  2253. $upgrade_required = $upgrade_required || $v1_0;
  2254. // version 1.1
  2255. $rs = safe_query('SHOW FIELDS FROM '.safe_pfx('adi_matrix')." LIKE 'footer'",$adi_matrix_debug);
  2256. $a = nextRow($rs);
  2257. $v1_1 = empty($a);
  2258. $upgrade_required = $upgrade_required || $v1_1;
  2259. // version 2.0
  2260. $rs = safe_query('SHOW FIELDS FROM '.safe_pfx('adi_matrix')." LIKE 'title'",$adi_matrix_debug);
  2261. $a = nextRow($rs);
  2262. $v2_0 = empty($a);
  2263. $upgrade_required = $upgrade_required || $v2_0;
  2264. if ($do_upgrade && $upgrade_required) {
  2265. $res = TRUE;
  2266. if ($v0_2)
  2267. $res = $res && safe_query("ALTER TABLE ".safe_pfx("adi_matrix")." ADD `article_image` TINYINT(1) DEFAULT 0 NOT NULL",$adi_matrix_debug);
  2268. if ($v0_3t)
  2269. $res = $res && safe_query("ALTER TABLE ".safe_pfx("adi_matrix")." ADD `criteria_timestamp` VARCHAR(16) NOT NULL DEFAULT 'any'",$adi_matrix_debug);
  2270. if ($v0_3e)
  2271. $res = $res && safe_query("ALTER TABLE ".safe_pfx("adi_matrix")." ADD `criteria_expiry` INT(2) NOT NULL DEFAULT '0'",$adi_matrix_debug);
  2272. if ($v1_0) {
  2273. $res = $res && safe_query("ALTER TABLE ".safe_pfx("adi_matrix")." ADD `scroll` TINYINT(1) DEFAULT 0 NOT NULL",$adi_matrix_debug);
  2274. $res = $res && safe_query("ALTER TABLE ".safe_pfx("adi_matrix")." ADD `category1` VARCHAR(128) NOT NULL DEFAULT ''",$adi_matrix_debug);
  2275. $res = $res && safe_query("ALTER TABLE ".safe_pfx("adi_matrix")." ADD `category2` VARCHAR(128) NOT NULL DEFAULT ''",$adi_matrix_debug);
  2276. $res = $res && safe_query("ALTER TABLE ".safe_pfx("adi_matrix")." ADD `dir` VARCHAR(32) NOT NULL DEFAULT '1'",$adi_matrix_debug);
  2277. // convert old `sort` to new `sort` & `dir`
  2278. // OLD sort=1 (Posted desc) -> NEW sort=1, dir=1
  2279. // OLD sort=2 (Posted asc) -> NEW sort=1, dir=2
  2280. // OLD sort=3 (Title) -> NEW sort=2, dir=''
  2281. // OLD sort=4 (LastMod desc) -> NEW sort=3, dir=1
  2282. // OLD sort=5 (LastMod asc) -> NEW sort=3, dir=2
  2283. $res = $res && safe_update('adi_matrix',"`dir` = '1'","`sort` IN ('1','4')",$adi_matrix_debug);
  2284. $res = $res && safe_update('adi_matrix',"`dir` = '2'","`sort` IN ('2','5')",$adi_matrix_debug);
  2285. $res = $res && safe_update('adi_matrix',"`sort` = '1'","`sort` = '2'",$adi_matrix_debug);
  2286. $res = $res && safe_update('adi_matrix',"`sort` = '2'","`sort` = '3'",$adi_matrix_debug);
  2287. $res = $res && safe_update('adi_matrix',"`sort` = '3'","`sort` IN ('4','5')",$adi_matrix_debug);
  2288. }
  2289. if ($v1_1) {
  2290. $res = $res && safe_query("ALTER TABLE ".safe_pfx("adi_matrix")." ADD `footer` TINYINT(1) DEFAULT 0 NOT NULL",$adi_matrix_debug);
  2291. $res = $res && safe_query("ALTER TABLE ".safe_pfx("adi_matrix")." ADD `sort_type` VARCHAR(32) NOT NULL DEFAULT 'alphabetical'",$adi_matrix_debug);
  2292. $res = $res && safe_query("ALTER TABLE ".safe_pfx("adi_matrix")." ADD `posted` TINYINT(1) DEFAULT 0 NOT NULL",$adi_matrix_debug);
  2293. $res = $res && safe_query("ALTER TABLE ".safe_pfx("adi_matrix")." ADD `expires` TINYINT(1) DEFAULT 0 NOT NULL",$adi_matrix_debug);
  2294. $res = $res && safe_query("ALTER TABLE ".safe_pfx("adi_matrix")." ADD `criteria_descendent_cats` TINYINT(1) DEFAULT 0 NOT NULL",$adi_matrix_debug);
  2295. // one day sort will be sorted
  2296. // OLD sort=1, NEW sort='posted'
  2297. // OLD sort=2, NEW sort='title',
  2298. // OLD sort=3, NEW sort='lastmod',
  2299. // OLD sort=4, NEW sort='expires',
  2300. $res = $res && safe_update('adi_matrix',"`sort` = 'posted'","`sort` = '1'",$adi_matrix_debug);
  2301. $res = $res && safe_update('adi_matrix',"`sort` = 'title'","`sort` = '2'",$adi_matrix_debug);
  2302. $res = $res && safe_update('adi_matrix',"`sort` = 'lastmod'","`sort` = '3'",$adi_matrix_debug);
  2303. $res = $res && safe_update('adi_matrix',"`sort` = 'expires'","`sort` = '4'",$adi_matrix_debug);
  2304. // sort_type "+ 0 asc/desc" now "numerical"
  2305. $res = $res && safe_update('adi_matrix',"`sort_type` = 'alphabetical'","`dir` IN ('1','2')",$adi_matrix_debug);
  2306. $res = $res && safe_update('adi_matrix',"`sort_type` = 'numerical'","`dir` IN ('3','4')",$adi_matrix_debug);
  2307. // sort direction
  2308. $res = $res && safe_update('adi_matrix',"`dir` = 'desc'","`dir` IN ('1','4')",$adi_matrix_debug);
  2309. $res = $res && safe_update('adi_matrix',"`dir` = 'asc'","`dir` IN ('2','3')",$adi_matrix_debug);
  2310. }
  2311. if ($v2_0) {
  2312. $res = $res && safe_query("ALTER TABLE ".safe_pfx("adi_matrix")." ADD `title` TINYINT(1) DEFAULT 0 NOT NULL",$adi_matrix_debug);
  2313. $res = $res && safe_query("ALTER TABLE ".safe_pfx("adi_matrix")." ADD `publish` TINYINT(1) DEFAULT 0 NOT NULL",$adi_matrix_debug);
  2314. $res = $res && safe_query("ALTER TABLE ".safe_pfx("adi_matrix")." ADD `show_section` TINYINT(1) DEFAULT 0 NOT NULL",$adi_matrix_debug);
  2315. $res = $res && safe_query("ALTER TABLE ".safe_pfx("adi_matrix")." ADD `cf_links` VARCHAR(128) NOT NULL DEFAULT ''",$adi_matrix_debug);
  2316. $res = $res && safe_query("ALTER TABLE ".safe_pfx("adi_matrix")." ADD `tab` VARCHAR(16) NOT NULL DEFAULT 'content'",$adi_matrix_debug);
  2317. $res = $res && safe_query("ALTER TABLE ".safe_pfx("adi_matrix")." ADD `section` TINYINT(1) DEFAULT 0 NOT NULL",$adi_matrix_debug);
  2318. $res = $res && safe_query("ALTER TABLE ".safe_pfx("adi_matrix")." ADD `criteria_condition` VARCHAR(255) NOT NULL DEFAULT ''",$adi_matrix_debug);
  2319. $res = $res && safe_delete('txp_prefs',"name='adi_matrix_article_limit'",$adi_matrix_debug); // made redundant by paging
  2320. }
  2321. return $res;
  2322. }
  2323. else // report back only
  2324. return $upgrade_required;
  2325. }
  2326. function adi_matrix_downgrade() {
  2327. // downgrade to previous version - 2.0 to 1.1/1.2 only
  2328. global $adi_matrix_debug;
  2329. $res = TRUE;
  2330. $res = $res && safe_query("ALTER TABLE ".safe_pfx("adi_matrix")." DROP `title`",$adi_matrix_debug);
  2331. $res = $res && safe_query("ALTER TABLE ".safe_pfx("adi_matrix")." DROP `publish`",$adi_matrix_debug);
  2332. $res = $res && safe_query("ALTER TABLE ".safe_pfx("adi_matrix")." DROP `show_section`",$adi_matrix_debug);
  2333. $res = $res && safe_query("ALTER TABLE ".safe_pfx("adi_matrix")." DROP `cf_links`",$adi_matrix_debug);
  2334. $res = $res && safe_query("ALTER TABLE ".safe_pfx("adi_matrix")." DROP `tab`",$adi_matrix_debug);
  2335. $res = $res && safe_query("ALTER TABLE ".safe_pfx("adi_matrix")." DROP `section`",$adi_matrix_debug);
  2336. $res = $res && safe_query("ALTER TABLE ".safe_pfx("adi_matrix")." DROP `criteria_condition`",$adi_matrix_debug);
  2337. return $res;
  2338. }
  2339. function adi_matrix_cat_tree($list,$parent='root') {
  2340. // generate a tree of parent/child relationships
  2341. $return = array();
  2342. foreach ($list as $cat)
  2343. if ($cat['parent'] == $parent)
  2344. $return[$cat['name']] = adi_matrix_cat_tree($list,$cat['name']);
  2345. return $return;
  2346. }
  2347. function adi_matrix_cat_descendents($tree,$parent=NULL,$found=FALSE) {
  2348. // find all descendents of a given parent
  2349. $return = array();
  2350. foreach ($tree as $name => $children) {
  2351. if ($found)
  2352. $return[] = $name;
  2353. $return = array_merge($return,adi_matrix_cat_descendents($children,$parent,(($name == $parent) OR ($found))));
  2354. }
  2355. return $return;
  2356. }
  2357. function adi_matrix_categories($getTree_array) {
  2358. // create adi_matrix_categories array, indexed by cat name containing pertinent information
  2359. global $adi_matrix_debug;
  2360. // $getTree_array is array of arrays:
  2361. // 'id' => 'xx',
  2362. // 'name' => 'category-name',
  2363. // 'title' => 'Category Title',
  2364. // 'level' => 0, (in category hierarchy)
  2365. // 'children' => 2, (no. of children)
  2366. // 'parent' => 'root', (name of parent)
  2367. $cat_tree = adi_matrix_cat_tree($getTree_array);
  2368. $categories = array();
  2369. foreach ($getTree_array as $this_cat) {
  2370. $categories[$this_cat['name']]['parent'] = $this_cat['parent'];
  2371. $categories[$this_cat['name']]['children'] = adi_matrix_cat_descendents($cat_tree,$this_cat['name']);
  2372. }
  2373. return $categories;
  2374. }
  2375. function adi_matrix_section_popup($select_name,$value,$list='') {
  2376. // generate section popup list for admin settings table
  2377. // where 'TRUE' not supported on MySQL 4.0.27 (OK in MySQL 5+), so use 1=1
  2378. $blank_allowed = TRUE;
  2379. $where = "name != 'default'";
  2380. // set up where condition if section list supplied
  2381. if ($list) {
  2382. $a = explode(',',$list);
  2383. foreach ($a as $i => $v)
  2384. $a[$i] = "'$v'";
  2385. $where .= 'AND name in ('.implode(',',$a).')';
  2386. $blank_allowed = FALSE;
  2387. }
  2388. $rs = safe_column('name', 'txp_section', $where);
  2389. if ($rs)
  2390. return selectInput($select_name, $rs, $value, $blank_allowed);
  2391. return FALSE;
  2392. }
  2393. function adi_matrix_section_checkboxes($field_name,$value) {
  2394. // generate section checkboxes
  2395. $section_list = explode(',',$value);
  2396. $out = '';
  2397. $rs = safe_column('name', 'txp_section', "name != 'default'");
  2398. if ($rs) {
  2399. foreach ($rs as $section)
  2400. $out .= tag(checkbox($field_name.'[]',$section,(array_search($section,$section_list) !== FALSE ? '1' : '0')).sp.$section,'label');
  2401. return $out;
  2402. }
  2403. return FALSE;
  2404. }
  2405. function adi_matrix_category_popup($select_name,$value,$admin=TRUE) {
  2406. // generate category popup list for admin settings table
  2407. $rs = getTree('root','article');
  2408. if ($rs) {
  2409. if ($admin) { /* create wildcards (wildcats?) */
  2410. $wildcard_list = array('no_category','any_category','one_category','two_categories','any_parent_category','any_child_category');
  2411. foreach (array_reverse($wildcard_list) as $wildcard)
  2412. /* add to front of array & renumber */
  2413. array_unshift($rs,array('id' => '0', 'name' => '!'.$wildcard.'!', 'title' => gTxt('adi_'.$wildcard), 'level' => '0', 'children' => '0', 'parent' => 'root'));
  2414. }
  2415. return treeSelectInput($select_name,$rs,$value,'',35);
  2416. }
  2417. return tag(gTxt('no_categories_exist'),'em');
  2418. }
  2419. function adi_matrix_status_popup($select_name,$value) {
  2420. // generate status popup list for admin settings table
  2421. global $adi_matrix_statuses;
  2422. return selectInput($select_name, $adi_matrix_statuses, $value, TRUE);
  2423. }
  2424. function adi_matrix_timestamp_popup($select_name,$value) {
  2425. // generate timestamp popup list for admin settings table
  2426. global $adi_matrix_timestamp_options;
  2427. return selectInput($select_name, $adi_matrix_timestamp_options, $value, FALSE);
  2428. }
  2429. function adi_matrix_expiry_popup($select_name,$value) {
  2430. // generate timestamp popup list for admin settings table
  2431. global $adi_matrix_expiry_options;
  2432. return selectInput($select_name, $adi_matrix_expiry_options, $value, FALSE);
  2433. }
  2434. function adi_matrix_user_popup($select_name,$value,$wildcard=FALSE) {
  2435. // generate user/author popup list for admin settings table
  2436. global $adi_matrix_statuses;
  2437. $rs = safe_column('name', 'txp_users', '1=1');
  2438. if ($rs) {
  2439. if ($wildcard) { /* create wildcard */
  2440. $logged_in_user = array('!logged_in_user!' => gTxt('adi_logged_in_user'));
  2441. $rs = $logged_in_user + $rs; /* add to front of array */
  2442. }
  2443. return selectInput($select_name, $rs, $value, TRUE);
  2444. }
  2445. return false;
  2446. }
  2447. function adi_matrix_privs_popup($select_name,$value) {
  2448. // generate privs popup list for admin settings table
  2449. global $adi_matrix_groups;
  2450. return selectInput($select_name, $adi_matrix_groups, $value, TRUE);
  2451. }
  2452. function adi_matrix_tab_popup($select_name,$value) {
  2453. // generate tab popup list for admin settings table
  2454. global $adi_matrix_tabs;
  2455. return selectInput($select_name, $adi_matrix_tabs, $value);
  2456. }
  2457. function adi_matrix_timestamp_input($name,$datetime,$ts,$type='posted') {
  2458. // date/time input fields - code stolen from include/txp_article.php
  2459. if ($datetime == '0000-00-00 00:00:00')
  2460. $ts = 0;
  2461. $class = ' '.$type;
  2462. if ($type == 'posted')
  2463. $class .= ' created';
  2464. $out =
  2465. tag(
  2466. adi_matrix_tsi($name.'[year]','%Y',$ts,'',$type)
  2467. .' /'
  2468. .adi_matrix_tsi($name.'[month]','%m',$ts,'',$type)
  2469. .' /'
  2470. .adi_matrix_tsi($name.'[day]','%d',$ts,'',$type)
  2471. ,'div'
  2472. ,' class="date'.$class.'"'
  2473. )
  2474. .tag(
  2475. adi_matrix_tsi($name.'[hour]','%H',$ts,'',$type)
  2476. .' :'
  2477. .adi_matrix_tsi($name.'[minute]','%M',$ts,'',$type)
  2478. .' :'
  2479. .adi_matrix_tsi($name.'[second]','%S',$ts,'',$type)
  2480. .($type == 'posted' ? br.tag(gTxt('adi_reset'),'label',' class="reset_time-now"').sp.checkbox($name.'[reset_time]','1','0') : '')
  2481. ,'div'
  2482. ,' class="time'.$class.'"'
  2483. );
  2484. return $out;
  2485. }
  2486. function adi_matrix_tsi($name,$datevar,$time,$tab='',$type='') {
  2487. // date/time item input - adapted from txplib_forms.php tsi()
  2488. preg_match_all('/.*\[(.*)\]$/',$name,$matches); // to get 'year' etc from article_x[posted][year]
  2489. $short_name = $matches[1][0];
  2490. if ($type == 'expires')
  2491. $short_name = 'exp_'.$short_name;
  2492. $size = ($short_name == 'year' or $short_name == 'exp_year') ? 4 : 2;
  2493. $s = ($time == 0) ? '' : safe_strftime($datevar, $time); // convert DB time to TXP date/time
  2494. return
  2495. n
  2496. .'<input type="text" name="'.$name
  2497. .'" value="'
  2498. .$s
  2499. .'" size="'
  2500. .$size
  2501. .'" maxlength="'
  2502. .$size
  2503. .'" class="edit '
  2504. .$short_name
  2505. .'"'
  2506. .(empty($tab) ? '' : ' tabindex="'.$tab.'"')
  2507. .' title="'
  2508. .gTxt('article_'.$short_name)
  2509. .'" />';
  2510. }
  2511. function adi_matrix_delete_button($matrix_list,$matrix_index) {
  2512. // matrix delete button [X]
  2513. global $adi_matrix_txp460;
  2514. $event = 'adi_matrix_admin';
  2515. $step = 'delete';
  2516. // $url = '?event='.$event.a.'step='.$step.a.'matrix='.$matrix_index;
  2517. // if ($matrix_index == 'new') // don't want delete button
  2518. // return '&nbsp;';
  2519. // else
  2520. // return
  2521. // '<a href="'
  2522. // .$url
  2523. // .'" class="dlink" title="'.gTxt('delete').'?" onclick="return verify(\''
  2524. // .$matrix_list[$matrix_index]['name']
  2525. // .' &mdash; '
  2526. // .gTxt('confirm_delete_popup')
  2527. // .'\')">&#215;</a>'; // times
  2528. if ($matrix_index == 'new') // don't want delete button
  2529. return sp;
  2530. else {
  2531. if ($adi_matrix_txp460)
  2532. return
  2533. href(
  2534. span('Delete',' class="ui-icon ui-icon-close"')
  2535. ,array(
  2536. 'event' => $event,
  2537. 'step' => $step,
  2538. 'matrix' => $matrix_index,
  2539. '_txp_token' => form_token(),
  2540. )
  2541. ,array(
  2542. 'class' => 'dlink destroy',
  2543. 'title' => gTxt('delete'),
  2544. 'data-verify' => gTxt('confirm_delete_popup'),
  2545. )
  2546. );
  2547. else
  2548. return
  2549. '<a href="?event='.$event.a.'step='.$step.a.'matrix='.$matrix_index
  2550. .'" class="dlink" title="'.gTxt('delete').'" onclick="return verify(\''
  2551. .gTxt('confirm_delete_popup')
  2552. .'\')">'
  2553. .'&#215;'
  2554. .'</a>';
  2555. }
  2556. }
  2557. function adi_matrix_delete($matrix_index) {
  2558. // stick a matrix in the bin
  2559. global $adi_matrix_debug;
  2560. $res = safe_delete('adi_matrix', "`id`=$matrix_index", $adi_matrix_debug);
  2561. return $res;
  2562. }
  2563. function adi_matrix_update_settings() {
  2564. // analyse $_POST & update settings
  2565. global $adi_matrix_debug,$adi_matrix_cfs;
  2566. $res = FALSE;
  2567. foreach ($_POST as $index => $value) {
  2568. $data = doArray($value,'doStripTags'); // strip out monkey business
  2569. $this_index = explode('_',$index);
  2570. if ($this_index[0] == 'matrix') {
  2571. $matrix_index = $this_index[1];
  2572. // adjustments
  2573. if ($data['publish']) // if publish, then get title edit for free
  2574. $data['title'] = '1';
  2575. if (isset($data['section'])) // if section selected as data, then switch off show_section
  2576. $data['show_section'] = '0';
  2577. // sort
  2578. if ($data['sort'] == '')
  2579. $sortq = "sort='desc', ";
  2580. else
  2581. $sortq = "sort='".doSlash($data['sort'])."', ";
  2582. // section
  2583. if (array_key_exists('criteria_section',$data))
  2584. $criteria_sectionq = "criteria_section='".implode(',',$data['criteria_section'])."', ";
  2585. else
  2586. $criteria_sectionq = "criteria_section='', ";
  2587. // status
  2588. if (array_key_exists('status',$data))
  2589. $statusq = 'status=1, ';
  2590. else
  2591. $statusq = 'status=0, ';
  2592. // keywords
  2593. if (array_key_exists('keywords',$data))
  2594. $keywordsq = 'keywords=1, ';
  2595. else
  2596. $keywordsq = 'keywords=0, ';
  2597. // article image
  2598. if (array_key_exists('article_image',$data))
  2599. $article_imageq = 'article_image=1, ';
  2600. else
  2601. $article_imageq = 'article_image=0, ';
  2602. // category
  2603. if (array_key_exists('category1',$data))
  2604. $categoryq = 'category1=1, ';
  2605. else
  2606. $categoryq = 'category1=0, ';
  2607. if (array_key_exists('category2',$data))
  2608. $categoryq .= 'category2=1, ';
  2609. else
  2610. $categoryq .= 'category2=0, ';
  2611. // posted
  2612. if (array_key_exists('posted',$data))
  2613. $postedq = 'posted=1, ';
  2614. else
  2615. $postedq = 'posted=0, ';
  2616. // expires
  2617. if (array_key_exists('expires',$data))
  2618. $expiresq = 'expires=1, ';
  2619. else
  2620. $expiresq = 'expires=0, ';
  2621. // title
  2622. if (array_key_exists('title',$data))
  2623. $titleq = 'title=1, ';
  2624. else
  2625. $titleq = 'title=0, ';
  2626. // section
  2627. if (array_key_exists('section',$data))
  2628. $sectionq = 'section=1, ';
  2629. else
  2630. $sectionq = 'section=0, ';
  2631. // custom field
  2632. $cfq = '';
  2633. foreach ($adi_matrix_cfs as $index => $cf_name) {
  2634. $custom_x = 'custom_'.$index;
  2635. if (array_key_exists($custom_x,$data))
  2636. $cfq .= "custom_".$index."='1', ";
  2637. else
  2638. $cfq .= "custom_".$index."='0', ";
  2639. }
  2640. // category
  2641. if (!array_key_exists('criteria_category',$data)) // in case there're no categories defined
  2642. $data['criteria_category'] = '';
  2643. if (preg_match('/!.*!/',$data['criteria_category'])) // disable descendent cats option with wildcards
  2644. unset($data['criteria_descendent_cats']);
  2645. if (array_key_exists('criteria_descendent_cats',$data))
  2646. $criteria_descendent_catsq = 'criteria_descendent_cats=1, ';
  2647. else
  2648. $criteria_descendent_catsq = 'criteria_descendent_cats=0, ';
  2649. $matrix_sql_set =
  2650. "name='".doSlash($data['name'])."', "
  2651. .$sortq
  2652. ."dir='".doSlash($data['dir'])."', "
  2653. ."sort_type='".doSlash($data['sort_type'])."', "
  2654. ."user='".doSlash($data['user'])."', "
  2655. ."privs='".doSlash($data['privs'])."', "
  2656. ."scroll='".doSlash($data['scroll'])."', "
  2657. ."footer='".doSlash($data['footer'])."', "
  2658. ."publish='".doSlash($data['publish'])."', "
  2659. ."show_section='".doSlash($data['show_section'])."', "
  2660. ."cf_links='".doSlash($data['cf_links'])."', "
  2661. ."tab='".doSlash($data['tab'])."', "
  2662. .$criteria_sectionq
  2663. ."criteria_status='".doSlash($data['criteria_status'])."', "
  2664. ."criteria_author='".doSlash($data['criteria_author'])."', "
  2665. ."criteria_keywords='".doSlash($data['criteria_keywords'])."', "
  2666. ."criteria_timestamp='".doSlash($data['criteria_timestamp'])."', "
  2667. ."criteria_expiry='".doSlash($data['criteria_expiry'])."', "
  2668. ."criteria_condition='".doSlash($data['criteria_condition'])."', "
  2669. .$titleq
  2670. .$statusq
  2671. .$sectionq
  2672. .$keywordsq
  2673. .$article_imageq
  2674. .$postedq
  2675. .$expiresq
  2676. .$cfq
  2677. .$categoryq
  2678. .$criteria_descendent_catsq
  2679. ."criteria_category='".doSlash($data['criteria_category'])."' ";
  2680. if ($matrix_index == 'new') { // add new matrix to the mix
  2681. if (!empty($data['name'])) { // but don't add a blank one
  2682. $res = safe_insert(
  2683. 'adi_matrix',
  2684. $matrix_sql_set
  2685. ,$adi_matrix_debug
  2686. );
  2687. }
  2688. }
  2689. else { // update existing matrix
  2690. $res = safe_upsert(
  2691. 'adi_matrix',
  2692. $matrix_sql_set
  2693. ,"id='$matrix_index'"
  2694. ,$adi_matrix_debug
  2695. );
  2696. }
  2697. }
  2698. }
  2699. return $res;
  2700. }
  2701. function adi_matrix_admin_table_head($adi_matrix_cfs) {
  2702. // <table> header stuff
  2703. // custom field headings
  2704. $data_span = 2; // [status/keywords] plus [custom fields]
  2705. return
  2706. tag(
  2707. tr(
  2708. hcell(gTxt('adi_matrix'))
  2709. .hcell() // spacer for view link
  2710. .hcell(gTxt('adi_article_selection'))
  2711. .hcell(gTxt('adi_article_data'),'',' colspan="'.$data_span.'"')
  2712. .hcell('','',' class="adi_matrix_noborder"') // spacer for delete link
  2713. )
  2714. ,'thead'
  2715. );
  2716. }
  2717. function adi_matrix_admin_table($matrix_list,$matrix_cfs) {
  2718. // generate form fields for existing & new matrixes
  2719. global $adi_matrix_cfs,$adi_matrix_sort_options,$adi_matrix_sort_dir,$txp_user,$adi_matrix_sort_type,$prefs;
  2720. $out = '';
  2721. $out .= adi_matrix_admin_table_head($matrix_cfs);
  2722. // tack 'new' index onto end of $matrix_list (field defaults for adding new matrix)
  2723. $matrix_list['new'] = array(
  2724. 'name' => '',
  2725. 'sort' => 'posted',
  2726. 'dir' => 'desc',
  2727. 'sort_type' => 'alphabetical',
  2728. 'user' => $txp_user,
  2729. 'privs' => '',
  2730. 'scroll' => '0',
  2731. 'footer' => '0',
  2732. 'title' => '0',
  2733. 'publish' => '0',
  2734. 'show_section' => '0',
  2735. 'cf_links' => '',
  2736. 'tab' => '0',
  2737. 'criteria_section' => '',
  2738. 'criteria_category' => '',
  2739. 'criteria_descendent_cats' => '0',
  2740. 'criteria_status' => '0',
  2741. 'criteria_author' => '',
  2742. 'criteria_keywords' => '',
  2743. 'criteria_timestamp' => '',
  2744. 'criteria_expiry' => '',
  2745. 'criteria_condition' => '',
  2746. 'status' => '0',
  2747. 'keywords' => '0',
  2748. 'article_image' => '0',
  2749. 'category1' => '0',
  2750. 'category2' => '0',
  2751. 'posted' => '0',
  2752. 'expires' => '0',
  2753. 'section' => '0'
  2754. );
  2755. foreach ($adi_matrix_cfs as $index => $value) // add custom fields to $matrix_list['new']
  2756. $matrix_list['new']['custom_'.$index] = '0';
  2757. // existing matrixes followed by empty fields for a new one
  2758. foreach ($matrix_list as $matrix_index => $matrix) {
  2759. $cf_checkboxes = '';
  2760. foreach ($matrix_cfs as $index => $cf_name) {
  2761. $custom_x = 'custom_'.$index;
  2762. $cf_checkboxes .= graf(tag(checkbox("matrix_".$matrix_index."[$custom_x]",1,$matrix[$custom_x]).span(sp.$cf_name,'label'),'label',' class="adi_matrix_checkbox"'));
  2763. }
  2764. $cf_td = tda($cf_checkboxes,' class="adi_matrix_field adi_matrix_custom_field"');
  2765. $url = '?event=adi_matrix_matrix_'.$matrix_index;
  2766. if ($matrix_index == 'new')
  2767. $view_link = ' ';
  2768. else
  2769. $view_link =
  2770. '<a href="?event=adi_matrix_matrix_'.$matrix_index.'" title="'.gTxt('view').'" class="adi_matrix_view_link">'.'<span class="ui-icon ui-icon-notice"></span><span>'.gTxt('view').'</span></a>';
  2771. $out .= tr(
  2772. // matrix settings
  2773. tda(
  2774. graf(tag(gTxt('name'),'label').finput("text","matrix_".$matrix_index."[name]",$matrix['name']))
  2775. .graf(tag(gTxt('sort'),'label').selectInput("matrix_".$matrix_index."[sort]",$adi_matrix_sort_options,$matrix['sort'],FALSE))
  2776. .graf(tag(gTxt('sort_direction'),'label').selectInput("matrix_".$matrix_index."[dir]",$adi_matrix_sort_dir,$matrix['dir'],FALSE))
  2777. .graf(tag(gTxt('adi_sort_type'),'label').selectInput("matrix_".$matrix_index."[sort_type]",$adi_matrix_sort_type,$matrix['sort_type'],FALSE))
  2778. .graf(tag(gTxt('adi_user'),'label').adi_matrix_user_popup("matrix_".$matrix_index."[user]",$matrix['user']))
  2779. .graf(tag(gTxt('privileges'),'label').adi_matrix_privs_popup("matrix_".$matrix_index."[privs]",$matrix['privs']))
  2780. .graf(
  2781. span(gTxt('adi_scroll'))
  2782. .tag(
  2783. radio("matrix_".$matrix_index."[scroll]",'0',($matrix['scroll'] == '0'))
  2784. .sp
  2785. .gTxt('no')
  2786. ,'label'
  2787. )
  2788. .tag(
  2789. radio("matrix_".$matrix_index."[scroll]",'1',($matrix['scroll'] == '1'))
  2790. .sp
  2791. .gTxt('yes')
  2792. ,'label'
  2793. )
  2794. )
  2795. .graf(
  2796. span(gTxt('adi_footer'))
  2797. .tag(
  2798. radio("matrix_".$matrix_index."[footer]",'0',($matrix['footer'] == '0'))
  2799. .sp
  2800. .gTxt('no')
  2801. ,'label'
  2802. )
  2803. .sp.sp
  2804. .tag(
  2805. radio("matrix_".$matrix_index."[footer]",'1',($matrix['footer'] == '1'))
  2806. .sp
  2807. .gTxt('yes')
  2808. ,'label'
  2809. )
  2810. )
  2811. .graf(
  2812. span(gTxt('adi_show_section'))
  2813. .tag(
  2814. radio("matrix_".$matrix_index."[show_section]",'0',($matrix['show_section'] == '0'))
  2815. .sp
  2816. .gTxt('no')
  2817. ,'label'
  2818. )
  2819. .sp.sp
  2820. .tag(
  2821. radio("matrix_".$matrix_index."[show_section]",'1',($matrix['show_section'] == '1'))
  2822. .sp
  2823. .gTxt('yes')
  2824. ,'label'
  2825. )
  2826. )
  2827. .graf(
  2828. span(gTxt('adi_cf_links'))
  2829. .tag(
  2830. radio("matrix_".$matrix_index."[cf_links]",'',(empty($matrix['cf_links']))) // will be comma list one day
  2831. .sp
  2832. .gTxt('no')
  2833. ,'label'
  2834. )
  2835. .sp.sp
  2836. .tag(
  2837. radio("matrix_".$matrix_index."[cf_links]",'article_image',(!empty($matrix['cf_links']))) // will be comma list one day
  2838. .sp
  2839. .gTxt('yes')
  2840. ,'label'
  2841. )
  2842. ,' style="display:none"'
  2843. )
  2844. .graf(
  2845. span(gTxt('publish'))
  2846. .tag(
  2847. radio("matrix_".$matrix_index."[publish]",'0',($matrix['publish'] == '0'))
  2848. .sp
  2849. .gTxt('no')
  2850. ,'label'
  2851. )
  2852. .sp.sp
  2853. .tag(
  2854. radio("matrix_".$matrix_index."[publish]",'1',($matrix['publish'] == '1'))
  2855. .sp
  2856. .gTxt('yes')
  2857. ,'label'
  2858. )
  2859. )
  2860. .graf(tag(gTxt('adi_tab'),'label').adi_matrix_tab_popup("matrix_".$matrix_index."[tab]",$matrix['tab']))
  2861. ,' class="adi_matrix_field"'
  2862. )
  2863. .tda($view_link)
  2864. // article selection
  2865. .tda(
  2866. gTxt('section').br
  2867. .tag(adi_matrix_section_checkboxes("matrix_".$matrix_index."[criteria_section]",$matrix['criteria_section']),'div',' class="adi_matrix_multi_checkboxes"')
  2868. .graf(tag(gTxt('category'),'label').adi_matrix_category_popup("matrix_".$matrix_index."[criteria_category]",$matrix['criteria_category']))
  2869. .graf(tag(checkbox("matrix_".$matrix_index."[criteria_descendent_cats]",1,$matrix['criteria_descendent_cats']).sp.gTxt('adi_include_descendent_cats'),'label',' class="adi_matrix_label2"'))
  2870. .graf(tag(gTxt('status'),'label').adi_matrix_status_popup("matrix_".$matrix_index."[criteria_status]",$matrix['criteria_status']))
  2871. .graf(tag(gTxt('author'),'label').adi_matrix_user_popup("matrix_".$matrix_index."[criteria_author]",$matrix['criteria_author'],TRUE))
  2872. .graf(tag(gTxt('keywords'),'label').finput("text","matrix_".$matrix_index."[criteria_keywords]",$matrix['criteria_keywords']))
  2873. .graf(tag(gTxt('timestamp'),'label').adi_matrix_timestamp_popup("matrix_".$matrix_index."[criteria_timestamp]",$matrix['criteria_timestamp']))
  2874. .graf(tag(gTxt('adi_expiry'),'label').adi_matrix_expiry_popup("matrix_".$matrix_index."[criteria_expiry]",$matrix['criteria_expiry']))
  2875. .graf(tag(gTxt('adi_custom_condition'),'label').finput("text","matrix_".$matrix_index."[criteria_condition]",$matrix['criteria_condition']))
  2876. ,' class="adi_matrix_field"'
  2877. )
  2878. // article data
  2879. .tda(
  2880. graf(tag(checkbox("matrix_".$matrix_index."[status]",1,$matrix['status']).span(sp.gTxt('status')),'label',' class="adi_matrix_checkbox"'))
  2881. .graf(tag(checkbox("matrix_".$matrix_index."[keywords]",1,$matrix['keywords']).span(sp.gTxt('keywords')),'label',' class="adi_matrix_checkbox"'))
  2882. .graf(tag(checkbox("matrix_".$matrix_index."[article_image]",1,$matrix['article_image']).span(sp.gTxt('article_image')),'label',' class="adi_matrix_checkbox"'))
  2883. .graf(tag(checkbox("matrix_".$matrix_index."[category1]",1,$matrix['category1']).span(sp.gTxt('category1')),'label',' class="adi_matrix_checkbox"'))
  2884. .graf(tag(checkbox("matrix_".$matrix_index."[category2]",1,$matrix['category2']).span(sp.gTxt('category2')),'label',' class="adi_matrix_checkbox"'))
  2885. .graf(tag(checkbox("matrix_".$matrix_index."[posted]",1,$matrix['posted']).span(sp.gTxt('posted')),'label',' class="adi_matrix_checkbox"'))
  2886. .graf(tag(checkbox("matrix_".$matrix_index."[expires]",1,$matrix['expires']).span(sp.gTxt('expires')),'label',' class="adi_matrix_checkbox"'))
  2887. .graf(tag(checkbox("matrix_".$matrix_index."[title]",1,$matrix['title']).span(sp.gTxt('title')),'label',' class="adi_matrix_checkbox"'))
  2888. .graf(tag(checkbox("matrix_".$matrix_index."[section]",1,$matrix['section']).span(sp.gTxt('section')),'label',' class="adi_matrix_checkbox"'))
  2889. ,' class="adi_matrix_field"'
  2890. )
  2891. .$cf_td
  2892. .tda(adi_matrix_delete_button($matrix_list,$matrix_index),' class="adi_matrix_delete"')
  2893. );
  2894. }
  2895. return $out;
  2896. }
  2897. function adi_matrix_pref($name,$value=NULL,$private=FALSE) {
  2898. // read or set pref
  2899. global $prefs,$adi_matrix_prefs;
  2900. if ($value === NULL) {
  2901. if (isset($adi_matrix_prefs[$name]['value'])) // may be dynamically generated pref
  2902. return get_pref($name,$adi_matrix_prefs[$name]['value']);
  2903. else
  2904. return get_pref($name);
  2905. }
  2906. else {
  2907. if (array_key_exists($name,$adi_matrix_prefs))
  2908. $html = $adi_matrix_prefs[$name]['input'];
  2909. else
  2910. $html = 'text_input';
  2911. $res = set_pref($name,$value,'adi_matrix_admin',2,$html,0,$private);
  2912. if (isset($adi_matrix_prefs[$name]['value'])) // may be dynamically generated pref
  2913. $prefs[$name] = get_pref($name,$adi_matrix_prefs[$name]['value'],TRUE);
  2914. return $res;
  2915. }
  2916. }
  2917. function adi_matrix_tiny_mce_custom() {
  2918. // TinyMCE implementation in a modal window
  2919. global $adi_matrix_cfs;
  2920. $jquery_ui = adi_matrix_pref('adi_matrix_jquery_ui');
  2921. $tiny_mce_dir = adi_matrix_pref('adi_matrix_tiny_mce_dir');
  2922. $adi_matrix_tiny_mce_config = adi_matrix_pref('adi_matrix_tiny_mce_config');
  2923. $title = gTxt('edit');
  2924. $ok = gTxt('adi_ok');
  2925. $cancel = gTxt('adi_cancel');
  2926. $script = <<<END_SCRIPT
  2927. <script src="$jquery_ui" type="text/javascript"></script>
  2928. <script type="text/javascript" src="$tiny_mce_dir/tiny_mce.js"></script>
  2929. <script type="text/javascript">
  2930. //<![CDATA[
  2931. $(document).ready(function(){
  2932. var i = 0;
  2933. $('.adi_matrix_matrix .glz_text_area_field textarea').each(function(){
  2934. // hide textareas
  2935. $(this).css({display:"none"});
  2936. // assign unique class
  2937. i++;
  2938. $(this).addClass('mceNoEditor tie' + i);
  2939. // create div containing textarea contents (with same unique class)
  2940. var text = $(this).val();
  2941. $(this).after('<div class="tie_div tie' + i + '">' + text + '<\/div>');
  2942. });
  2943. $('.adi_matrix_matrix div.tie_div').click(function(){
  2944. // get unique class (actually the last class - potentially dodgy?)
  2945. var thisClass = $(this).attr('class').split(' ').slice(-1);
  2946. // get corresponding textarea
  2947. var thisTextarea = $('textarea.' + thisClass);
  2948. // get textarea name attribute (e.g. article_2[custom_6])
  2949. // WILL NEED TO SET THIS INFO IN THE DOM IN ADVANCE - TEXTAREA TITLE ATTR?
  2950. // var thisName = $(thisTextarea).attr('name');
  2951. $('#dialog').remove();
  2952. $('body').append('<div id="dialog" \/>');
  2953. $('#dialog').dialog({
  2954. autoOpen: false,
  2955. bgiframe: true,
  2956. resizable: false,
  2957. width: 700,
  2958. position: ['center',35],
  2959. overlay: { backgroundColor: '#000', opacity: 0.6 },
  2960. open: function(e, ui){
  2961. },
  2962. beforeclose: function(event, ui) {
  2963. tinyMCE.get('editor').remove();
  2964. $('#editor').remove();
  2965. }
  2966. });
  2967. $('#dialog').dialog('option', 'title', '$title');
  2968. $('#dialog').dialog('option', 'modal', true);
  2969. $('#dialog').dialog('option', 'buttons', {
  2970. $cancel: function() {
  2971. $(this).dialog('close');
  2972. },
  2973. $ok: function() {
  2974. var content = tinyMCE.get('editor').getContent();
  2975. // feed edited contents into textarea
  2976. $(thisTextarea).val(content);
  2977. // feed edited contents into div
  2978. $('div.' + thisClass).html(content);
  2979. $(this).dialog('close');
  2980. }
  2981. });
  2982. $('#dialog').html('<textarea name="editor" id="editor"><\/textarea>');
  2983. $('#dialog').dialog('open');
  2984. tinyMCE.init({
  2985. mode : "specific_textareas",
  2986. editor_deselector : "mceNoEditor",
  2987. // start of user configurable options
  2988. $adi_matrix_tiny_mce_config
  2989. // end of user-configurable options
  2990. setup : function(ed) {
  2991. ed.onInit.add(function(ed) {
  2992. tinyMCE.get('editor').setContent($(thisTextarea).val());
  2993. tinyMCE.execCommand('mceRepaint');
  2994. });
  2995. }
  2996. });
  2997. return false;
  2998. });
  2999. });
  3000. //]]></script>
  3001. END_SCRIPT;
  3002. echo $script;
  3003. }
  3004. function adi_matrix_tiny_mce_style() {
  3005. // jQuery UI CSS for TinyMCE modal window
  3006. $jquery_ui_css = adi_matrix_pref('adi_matrix_jquery_ui_css');
  3007. echo '<link href="'.$jquery_ui_css.'" type="text/css" rel="stylesheet" />';
  3008. }
  3009. function adi_matrix_admin($event, $step) {
  3010. // adi_matrix admin tab
  3011. global $adi_matrix_debug,$adi_matrix_cfs,$adi_matrix_prefs,$adi_matrix_url,$prefs,$textarray,$adi_matrix_privs,$adi_matrix_groups,$txp_permissions,$adi_matrix_glz_cfs,$adi_matrix_sort_options;
  3012. $message = '';
  3013. $installed = adi_matrix_installed();
  3014. if ($installed) {
  3015. $upgrade_required = adi_matrix_upgrade();
  3016. if ($upgrade_required)
  3017. $message = array(gTxt('adi_upgrade_required'),E_WARNING);
  3018. else { // custom field musical chairs
  3019. $cfs_fiddled = FALSE;
  3020. // add additional custom fields that may have suddenly appeared (glz_cfs: custom_11+)
  3021. foreach ($adi_matrix_cfs as $index => $value) {
  3022. $rs = safe_query('SHOW FIELDS FROM '.safe_pfx('adi_matrix')." LIKE 'custom_$index'",$adi_matrix_debug); // find out if column exists
  3023. $a = nextRow($rs);
  3024. if (empty($a)) {
  3025. safe_query("ALTER TABLE ".safe_pfx('adi_matrix')." ADD `custom_$index` TINYINT(1) DEFAULT 0 NOT NULL",$adi_matrix_debug);
  3026. $cfs_fiddled = TRUE;
  3027. }
  3028. }
  3029. // remove custom fields that may have been deleted in glz_cfs
  3030. $rs = safe_query('SHOW FIELDS FROM '.safe_pfx('adi_matrix')." LIKE 'custom%'",$adi_matrix_debug);
  3031. $current_cfs = array();
  3032. while ($a = nextRow($rs)) { // get list of cf indexes from adi_matrix
  3033. $index = substr($a['Field'],7); // strip 'custom_' from 'custom_x'
  3034. $current_cfs[$index] = TRUE;
  3035. }
  3036. foreach ($current_cfs as $index => $value)
  3037. if (!array_key_exists($index,$adi_matrix_cfs)) {
  3038. safe_query("ALTER TABLE ".safe_pfx('adi_matrix')." DROP COLUMN `custom_$index`",$adi_matrix_debug);
  3039. $cfs_fiddled = TRUE;
  3040. }
  3041. if ($cfs_fiddled)
  3042. $message = gTxt('adi_matrix_cfs_modified');
  3043. }
  3044. }
  3045. else
  3046. $message = array(gTxt('adi_not_installed'),E_ERROR);
  3047. // admin $step aerobics
  3048. if ($step == 'update') {
  3049. $result = adi_matrix_update_settings();
  3050. $result ? $message = gTxt('adi_matrix_updated') : $message = array(gTxt('adi_matrix_update_fail'),E_ERROR);
  3051. }
  3052. else if ($step == 'delete') {
  3053. $matrix_index = gps('matrix');
  3054. $result = adi_matrix_delete($matrix_index);
  3055. $result ? $message = gTxt('adi_matrix_deleted') : $message = array(gTxt('adi_matrix_delete_fail'),E_ERROR);
  3056. }
  3057. else if ($step == 'update_prefs') {
  3058. $result = TRUE;
  3059. foreach ($adi_matrix_prefs as $name => $data) {
  3060. if (array_key_exists($name,$_POST))
  3061. $value = $_POST[$name];
  3062. else if ($data['input'] == 'yesnoradio')
  3063. $value = '0';
  3064. else
  3065. $value = $data['value'];
  3066. // some values not allowed to be blank, reset to default
  3067. $non_blanks = array('adi_matrix_tiny_mce_dir','adi_matrix_jquery_ui','adi_matrix_jquery_ui_css');
  3068. foreach ($non_blanks as $non_blank)
  3069. if (($name == $non_blank) && (trim($value) == ''))
  3070. $value = $adi_matrix_prefs[$non_blank]['value'];
  3071. $result = $result && adi_matrix_pref($name,$value);
  3072. }
  3073. $result ? $message = gTxt('preferences_saved') : $message = array(gTxt('adi_pref_update_fail'),E_ERROR);
  3074. }
  3075. // generate page
  3076. pagetop(gTxt('adi_matrix_admin'),$message);
  3077. $installed = adi_matrix_installed();
  3078. if ($installed && !$upgrade_required) {
  3079. $adi_matrix_list = adi_matrix_read_settings();
  3080. // output table & input form
  3081. echo form(
  3082. startTable('list','','txp-list')
  3083. .adi_matrix_admin_table($adi_matrix_list,$adi_matrix_cfs)
  3084. .endTable()
  3085. .tag(
  3086. fInput("submit","do_something",gTxt('save'),"publish")
  3087. .eInput("adi_matrix_admin")
  3088. .sInput("update")
  3089. ,'div'
  3090. ,' class="adi_matrix_button"'
  3091. )
  3092. ,''
  3093. ,''
  3094. ,'post'
  3095. ,'adi_matrix_admin'
  3096. );
  3097. // preferences
  3098. echo form(
  3099. tag(
  3100. tag(gTxt('edit_preferences'),'h2')
  3101. // display article id
  3102. .graf(
  3103. tag(
  3104. checkbox2("adi_matrix_display_id",adi_matrix_pref('adi_matrix_display_id'))
  3105. .sp
  3106. .gTxt('adi_display_article_id')
  3107. ,'label')
  3108. .sp.sp
  3109. .tag(
  3110. checkbox2("adi_matrix_article_highlighting",adi_matrix_pref('adi_matrix_article_highlighting'))
  3111. .sp
  3112. .gTxt('adi_article_highlighting')
  3113. ,'label')
  3114. )
  3115. // article tooltips
  3116. .graf(
  3117. tag(
  3118. checkbox2("adi_matrix_article_tooltips",adi_matrix_pref('adi_matrix_article_tooltips'))
  3119. .sp
  3120. .gTxt('adi_article_tooltips')
  3121. ,'label')
  3122. .sp.sp
  3123. .tag(
  3124. checkbox2("adi_matrix_input_field_tooltips",adi_matrix_pref('adi_matrix_input_field_tooltips'))
  3125. .sp
  3126. .gTxt('adi_matrix_input_field_tooltips')
  3127. ,'label')
  3128. )
  3129. .( $adi_matrix_glz_cfs ?
  3130. // tinymce
  3131. graf(
  3132. gTxt('adi_tiny_mce')
  3133. .sp
  3134. .tag(
  3135. radio("adi_matrix_tiny_mce",'0',(adi_matrix_pref('adi_matrix_tiny_mce') == '0'))
  3136. .sp
  3137. .gTxt('no')
  3138. ,'label'
  3139. )
  3140. .sp.sp
  3141. .tag(
  3142. radio("adi_matrix_tiny_mce",'1',(adi_matrix_pref('adi_matrix_tiny_mce') == '1'))
  3143. .sp
  3144. .gTxt('yes')
  3145. ,'label'
  3146. )
  3147. )
  3148. .'<div id="peekaboo">'
  3149. // tinymce dir
  3150. .graf(
  3151. tag(gTxt('adi_tiny_mce_dir_path'),'label')
  3152. .finput("text",'adi_matrix_tiny_mce_dir',adi_matrix_pref('adi_matrix_tiny_mce_dir'),'','','',40)
  3153. )
  3154. // jquery ui
  3155. .graf(
  3156. tag(gTxt('adi_jquery_ui').':','label')
  3157. .finput("text",'adi_matrix_jquery_ui',adi_matrix_pref('adi_matrix_jquery_ui'),'','','',40)
  3158. )
  3159. // jquery ui css
  3160. .graf(
  3161. tag(gTxt('adi_jquery_ui_css').':','label')
  3162. .finput("text",'adi_matrix_jquery_ui_css',adi_matrix_pref('adi_matrix_jquery_ui_css'),'','','',40)
  3163. )
  3164. // tinymce config
  3165. .graf(
  3166. tag(gTxt('adi_tiny_mce_config').':','label')
  3167. )
  3168. .graf(
  3169. text_area('adi_matrix_tiny_mce_config',300,600,adi_matrix_pref('adi_matrix_tiny_mce_config'))
  3170. )
  3171. .'</div>'
  3172. : '')
  3173. .fInput("submit", "do_something", gTxt('adi_update_prefs'), "smallerbox")
  3174. .eInput("adi_matrix_admin").sInput("update_prefs")
  3175. ,'div'
  3176. ,' class="adi_matrix_prefs"'
  3177. )
  3178. );
  3179. }
  3180. if ($adi_matrix_debug) {
  3181. echo "<b>Event:</b> ".$event.", <b>Step:</b> ".$step.br.br;
  3182. echo '<b>$_POST:</b>';
  3183. dmp($_POST);
  3184. if ($installed) {
  3185. echo '<b>PREFS:</b>'.br;
  3186. foreach ($adi_matrix_prefs as $name => $this_pref)
  3187. echo $name.' = '.adi_matrix_pref($name).br;
  3188. echo br;
  3189. echo '<b>$adi_matrix_list:</b>';
  3190. dmp(adi_matrix_read_settings());
  3191. echo '<b>$adi_matrix_sort_options:</b>';
  3192. dmp($adi_matrix_sort_options);
  3193. echo '<b>$adi_matrix_groups:</b>';
  3194. dmp($adi_matrix_groups);
  3195. echo '<b>$adi_matrix_cfs:</b>';
  3196. dmp($adi_matrix_cfs);
  3197. echo '<b>glz_custom_fields plugin:</b> is';
  3198. if (!$adi_matrix_glz_cfs)
  3199. echo ' NOT';
  3200. echo ' installed'.br;
  3201. }
  3202. }
  3203. }
  3204. function adi_matrix_options($event,$step) {
  3205. // plugin options page
  3206. global $adi_matrix_debug,$adi_matrix_url,$adi_matrix_plugin_status,$textarray;
  3207. $message = '';
  3208. $installed = adi_matrix_installed();
  3209. if ($installed) {
  3210. $upgrade_required = adi_matrix_upgrade();
  3211. if ($upgrade_required)
  3212. $step = 'upgrade';
  3213. }
  3214. // dance steps
  3215. if ($step == 'textpack') {
  3216. if (function_exists('install_textpack')) {
  3217. $adi_textpack = file_get_contents($adi_matrix_url['textpack']);
  3218. if ($adi_textpack) {
  3219. $result = install_textpack($adi_textpack);
  3220. $message = gTxt('textpack_strings_installed', array('{count}' => $result));
  3221. $textarray = load_lang(LANG); // load in new strings
  3222. }
  3223. else
  3224. $message = array(gTxt('adi_textpack_fail'),E_ERROR);
  3225. }
  3226. }
  3227. else if ($step == 'upgrade') {
  3228. $result = adi_matrix_upgrade(TRUE);
  3229. $result ? $message = gTxt('adi_upgraded') : $message = array(gTxt('adi_upgrade_fail'),E_ERROR);
  3230. }
  3231. else if ($step == 'downgrade') {
  3232. $result = adi_matrix_downgrade();
  3233. $result ? $message = gTxt('adi_downgraded') : $message = array(gTxt('adi_downgrade_fail'),E_ERROR);
  3234. }
  3235. else if ($step == 'tweak') { // for development updates
  3236. $result = safe_query("ALTER TABLE ".safe_pfx("adi_matrix")." ADD `cf_links` VARCHAR(255) NOT NULL DEFAULT ''",$adi_matrix_debug);
  3237. $result ? $message = 'Tweaked' : $message = array('Tweak failed',E_ERROR);
  3238. }
  3239. else if ($step == 'install') {
  3240. $result = adi_matrix_install();
  3241. $result ? $message = gTxt('adi_installed') : $message = array(gTxt('adi_install_fail'),E_ERROR);
  3242. }
  3243. else if ($step == 'uninstall') {
  3244. $result = adi_matrix_uninstall();
  3245. $result ? $message = gTxt('adi_uninstalled') : $message = array(gTxt('adi_uninstall_fail'),E_ERROR);
  3246. }
  3247. // generate page
  3248. pagetop('adi_matrix - '.gTxt('plugin_prefs'),$message);
  3249. $install_button =
  3250. tag(
  3251. form(
  3252. fInput("submit", "do_something", gTxt('install'), "publish","",'return verify(\''.gTxt('are_you_sure').'\')')
  3253. .eInput($event).sInput("install")
  3254. ,'','','post','adi_matrix_nstall_button'
  3255. )
  3256. ,'div'
  3257. ,' style="text-align:center"'
  3258. );
  3259. $uninstall_button =
  3260. tag(
  3261. form(
  3262. fInput("submit", "do_something", gTxt('adi_uninstall'), "publish","",'return verify(\''.gTxt('are_you_sure').'\')')
  3263. .eInput($event).sInput("uninstall")
  3264. ,'','','post','adi_matrix_nstall_button adi_matrix_uninstall_button'
  3265. )
  3266. ,'div'
  3267. ,' style="margin-top:5em"');
  3268. if ($adi_matrix_plugin_status) // proper plugin install, so lifecycle takes care of install/uninstall
  3269. $install_button = $uninstall_button = '';
  3270. $installed = adi_matrix_installed();
  3271. if ($installed) {
  3272. // options
  3273. echo tag(
  3274. tag('adi_matrix '.gTxt('plugin_prefs'),'h2')
  3275. // textpack links
  3276. .graf(href(gTxt('install_textpack'),'?event='.$event.'&amp;step=textpack'))
  3277. .graf(href(gTxt('adi_textpack_online'),$adi_matrix_url['textpack_download']))
  3278. .graf(href(gTxt('adi_textpack_feedback'),$adi_matrix_url['textpack_feedback']))
  3279. .$uninstall_button
  3280. ,'div'
  3281. ,' style="text-align:center"'
  3282. );
  3283. }
  3284. else // install button
  3285. echo $install_button;
  3286. if ($adi_matrix_debug) {
  3287. echo "<p><b>Event:</b> ".$event.", <b>Step:</b> ".$step."</p>";
  3288. echo '<b>$adi_textpack ('.$adi_matrix_url['textpack'].'):</b>';
  3289. $adi_textpack = file_get_contents($adi_matrix_url['textpack']);
  3290. dmp($adi_textpack);
  3291. }
  3292. }
  3293. # --- END PLUGIN CODE ---
  3294. if (0) {
  3295. ?>
  3296. <!--
  3297. # --- BEGIN PLUGIN HELP ---
  3298. <h1><strong>adi_matrix</strong> &#8211; Multi-article update tabs</h1>
  3299. <p>This plugin provides a way of viewing and updating multiple articles from a single <span class="caps">TXP</span> admin tab.</p>
  3300. <p>Matrixes give you a summary view of multiple articles, where you can make changes to selected data &amp; update them all in one go.</p>
  3301. <p>Two new tabs do the work:</p>
  3302. <ul>
  3303. <li>adi_matrix admin tab under Extensions</li>
  3304. <li>article matrix tab(s) under Contents or Home</li>
  3305. </ul>
  3306. <p>The admin tab defines the matrixes and the article matrix tabs display the required articles with their data.</p>
  3307. <h2><strong>Installation</strong></h2>
  3308. <p>Installation of <strong>adi_matrix</strong> adds a new table to your Textpattern database which should not interfere with anything else.</p>
  3309. <p><strong>adi_matrix</strong> is designed to make changes to groups of article. I suggest that you make backups before installation of this plugin and during initial testing on your site. I can thoroughly recommend <a href="http://forum.textpattern.com/viewtopic.php?id=10395" rel=" rel="1"">rss_admin_db_manager</a> to do database backups before installation.</p>
  3310. <h2><strong>adi_matrix admin tab</strong></h2>
  3311. <p>This is where you set up the article matrixes. There are three aspects to this:</p>
  3312. <h3>Matrix appearance</h3>
  3313. <p>Here you can:</p>
  3314. <ul>
  3315. <li>give the matrix a name (which will be used to list it under the Contents tab)</li>
  3316. <li>specify the order in which articles should be listed</li>
  3317. <li>specify whether a single user or all users are to get access to the matrix</li>
  3318. <li>specify whether access to the matrix is based on privileges or not</li>
  3319. <li>specify which tab to display the matrix under</li>
  3320. <li>permit users to add/delete articles</li>
  3321. <li>define how the matrix is laid out</li>
  3322. </ul>
  3323. <h3>Article selection criteria</h3>
  3324. <p>By default all articles will be listed in the matrix, but you can narrow it down according to:</p>
  3325. <ul>
  3326. <li>section</li>
  3327. <li>category</li>
  3328. <li>article status</li>
  3329. <li>author</li>
  3330. <li>keywords</li>
  3331. <li>posted &amp; expires timestamps</li>
  3332. <li>custom <span class="caps">WHERE</span> clause condition</li>
  3333. </ul>
  3334. <h3>Article data display</h3>
  3335. <p>This is where you define what data the user can see and change. Article that can be viewed &amp; updated in matrixes:</p>
  3336. <ul>
  3337. <li>article status</li>
  3338. <li>custom fields</li>
  3339. <li>article image</li>
  3340. <li>keywords</li>
  3341. <li>categories</li>
  3342. <li>posted &amp; expires timestamps</li>
  3343. <li>title</li>
  3344. <li>section</li>
  3345. </ul>
  3346. <h3>Preferences</h3>
  3347. <ul>
  3348. <li>maximum number of articles to be listed</li>
  3349. <li>display article ID</li>
  3350. <li>article title highlighting (indicate future or expired articles)</li>
  3351. <li>article title tooltips (show ID, posted &amp; expires timestamps in tooltip)</li>
  3352. <li>input field tooltips (show contents of input field in a tooltip)</li>
  3353. </ul>
  3354. <h2><strong>Getting started</strong></h2>
  3355. <p>A new matrix can be added in <strong>adi_matrix</strong> admin tab simply by entering its details into the blank spaces. As a minimum, a matrix name needs to be provided.</p>
  3356. <p>Once a matrix has been defined, it&#8217;s settings can be changed at any time. The new matrix will seen under the Contents or Home tabs after you have visited at least one other <span class="caps">TXP</span> tab (a hop is required so that the the tab contents are refreshed).</p>
  3357. <h2><strong>Article matrixes</strong></h2>
  3358. <p>The matrix tabs show a number of articles, with their associated &#8220;data&#8221;. If you are the article author or have sufficient overriding privileges then you can make changes to the data &amp; update all articles with a single click.</p>
  3359. <p>Note that only articles where you have actually changed anything will be updated &#8211; together with their <i>Last Modified Date</i> and <i>Author</i>.</p>
  3360. <p><strong>adi_matrix</strong> respects all the standard restrictions on who can make changes to articles &#8211; based on authorship &amp; privilege level.</p>
  3361. <h2><strong>Textpack</strong></h2>
  3362. <p>To install the Textpack, go to the plugin&#8217;s options page and click on &#8220;Install textpack&#8221;. This will copy &amp; install it from a remote server. The number of language strings installed for your language will be displayed.</p>
  3363. <p>If the Textpack installation fails (possibly due to an error accessing the remote site), the alternative is to click the <a href="http://www.greatoceanmedia.com.au/textpack" rel=" rel="1"">Textpack also available online</a> link. This will take you to a website where the Textpack can be manually copied &amp; pasted into the <span class="caps">TXP</span> Admin &#8211; Language tab.</p>
  3364. <p>Updates and corrections to the Textpack are welcome &#8211; please use the <a href="http://www.greatoceanmedia.com.au/textpack/?plugin=adi_matrix" rel=" rel="1"">Textpack feedback</a> form.</p>
  3365. <h2><strong>glz_custom_fields</strong></h2>
  3366. <p><strong>adi_matrix</strong> will automatically detect if <strong>glz_custom_fields</strong> is installed and should play nicely.</p>
  3367. <h2><strong>TinyMCE</strong></h2>
  3368. <p>If <strong>glz_custom_fields</strong> is installed you have the opportunity to use <a href="http://www.tinymce.com/" rel=" rel="1"">TinyMCE</a> to edit textarea custom fields. Note that TinyMCE must be installed separately. To use it with <strong>adi_matrix</strong>, switch it on in the admin tab and fill in the configuration details.</p>
  3369. <h2><strong>Uninstalling adi_matrix</strong></h2>
  3370. <p>To uninstall <strong>adi_matrix</strong>, simply go to the Plugins tab and delete it. No articles will be harmed in the process.</p>
  3371. <h2><strong>Additional information</strong></h2>
  3372. <p>Support and further information can be obtained from the <a href="http://forum.textpattern.com/viewtopic.php?id=35972" rel=" rel="1"">Textpattern support forum</a>. A copy of this help is also available <a href="http://www.greatoceanmedia.com.au/txp/?plugin=adi_matrix" rel=" rel="1"">online</a>. More adi_plugins can be found <a href="http://www.greatoceanmedia.com.au/txp/" rel=" rel="1"">here</a>.</p>
  3373. # --- END PLUGIN HELP ---
  3374. -->
  3375. <?php
  3376. }
  3377. ?>