PageRenderTime 70ms CodeModel.GetById 30ms 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

Large files files are truncated, but you can click here to view the full 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 $

Large files files are truncated, but you can click here to view the full file