PageRenderTime 68ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 1ms

/~enabled/bot_write_tab_customize.php

https://bitbucket.org/mrdale/txp-plugins
PHP | 1251 lines | 890 code | 246 blank | 115 comment | 147 complexity | c19854a7f5f89d16f6ef561bc238b2f8 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'] = 'bot_write_tab_customize';
  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'] = '0.7.3';
  16. $plugin['author'] = 'redbot (mod mrdale)';
  17. $plugin['author_uri'] = 'http://www.redbot.it/txp';
  18. $plugin['description'] = 'Rearrange and style items in the write tab';
  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'] = '3';
  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'] = '2';
  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. //<?
  62. if(@txpinterface == 'admin') {
  63. add_privs('bot_wtc_tab', '1,2');
  64. register_tab('extensions', 'bot_wtc_tab', 'Write tab customize');
  65. register_callback('bot_wtc_tab', 'bot_wtc_tab');
  66. register_callback('bot_wtc_css','admin_side','head_end');
  67. register_callback('bot_wtc', 'admin_side', 'head_end');
  68. register_callback('bot_hide_per_section', 'admin_side', 'head_end');
  69. register_callback('bot_hidden_sections', 'admin_side', 'head_end');
  70. register_callback('bot_wtc_update','plugin_lifecycle.bot_write_tab_customize', 'enabled');
  71. }
  72. // ===========================================
  73. $bot_arr_selectors = array(
  74. 'textile_help' => '$("#textile_group")',
  75. 'advanced_options' => '$("#advanced_group")',
  76. 'article_markup' => '$(".markup-body")',
  77. 'excerpt_markup' => '$(".markup-excerpt")',
  78. 'override_default_form' => '$(".override-form")',
  79. 'custom' => '$("#custom_field_group")',
  80. 'article_image' => '$("#image_group")',
  81. 'meta' => '$("#meta_group")',
  82. 'keywords' => '$(".keywords")',
  83. 'url_title' => '$(".url-title")',
  84. 'recent_articles' => '$("#recent_group")',
  85. 'title' => '$(".title")',
  86. 'body' => '$(".body")',
  87. 'excerpt' => '$(".excerpt")',
  88. 'create_new' => '$(".action-create")',
  89. 'page_article_nav_hed' => '$(".nav-tertiary")',
  90. 'status' => '$("#write-status")',
  91. 'sort_display' => '$("#write-sort")',
  92. 'category1' => '$(".category-1")',
  93. 'category2' => '$(".category-2")',
  94. 'section' => '$(".section")',
  95. 'date_settings' => '$("#dates_group")',
  96. 'comments' => '$("#comments_group")',
  97. 'timestamp' => '$("#write-timestamp")',
  98. 'expires' => '$("#write-expires")',
  99. 'publish' => '$("#write-publish")',
  100. 'save' => '$("#write-save")',
  101. 'logged_in_as' => '$("#moniker")',
  102. 'TD Column 1' => '$("#article-col-1")',
  103. 'TD Column 2' => '$("#article-col-2")',
  104. 'TD Main column' => '$("#article-main")',
  105. 'TD !bot!preview!bot! etc.' => '$("#article-tabs")',
  106. );
  107. // creates the translated main plugins array ($bot_items)
  108. global $bot_items;
  109. foreach ( $bot_arr_selectors as $title => $selector ) {
  110. bot_wtc_insert_in_main_array($title, $selector);
  111. }
  112. natcasesort($bot_items);
  113. // ===========================================================
  114. // Helper functions
  115. // ===========================================================
  116. function bot_wtc_gTxt($what) {
  117. global $event;
  118. if($event !== 'article') {
  119. return;
  120. }
  121. global $language;
  122. $en_us = array(
  123. 'install_message' => 'bot_wtc is not yet properly initialized. Use the button below to create the preferences table.',
  124. 'upgrade_message' => 'bot_wtc must be upgraded. Use the button below to add the new fields to the preferences table.',
  125. 'uninstall' => 'Uninstall',
  126. 'uninstall_message' => 'Using the button below will remove all preferences from the db. <br />Use before a complete uninstall or to reset all preferences. ',
  127. 'uninstall_confirm' => 'Are you sure you want to delete the preferences table?',
  128. 'td_warning' => 'Columns cannot be moved relative to single items and vice-versa',
  129. 'same_item_warning' => 'Oops! You are trying to move an item relative to itself',
  130. 'combo_warning' => 'Oops! You tried to insert an incomplete rule',
  131. );
  132. $lang = array(
  133. 'en-us' => $en_us
  134. );
  135. $language = (isset($lang[$language])) ? $language : 'en-us';
  136. $msg = (isset($lang[$language][$what])) ? $lang[$language][$what] : $what;
  137. return $msg;
  138. }
  139. // ===========================================
  140. function bot_wtc_insert_in_main_array ($title, $selector) // helps build the main array
  141. {
  142. global $bot_items;
  143. if (strpos($title, '!bot!'))
  144. {
  145. $split_titles = explode("!bot!", $title);
  146. $title = '';
  147. for ($i = 0; $i < count($split_titles); $i++)
  148. {
  149. $title .= gTxt($split_titles[$i]); // split and build translated title
  150. }
  151. }
  152. else
  153. {
  154. $title = gTxt($title);// gets the title to allow translation
  155. }
  156. $bot_items [$selector] = gTxt($title);
  157. return $bot_items;
  158. }
  159. // ===========================================
  160. function bot_wtc_fetch_db() // creates an array of values extracted from the database
  161. {
  162. if(bot_wtc_check_install()){
  163. $out = safe_rows('id, item, position, destination, sections, class', 'bot_wtc ','1=1');
  164. return $out;
  165. }
  166. }
  167. // ===========================================================
  168. function bot_get_cfs() // creates an array of all cfs for selectInput
  169. {
  170. $r = safe_rows_start('name, val, html', 'txp_prefs','event = "custom" AND val != ""');
  171. if ($r) {
  172. global $arr_custom_fields;
  173. while ($a = nextRow($r)) {
  174. $name = str_replace('_set', '', $a['name']);
  175. $html = $a['html'];
  176. if ($html == 'checkbox' || $html == 'multi-select') {
  177. $selector = '$("p:has(*[name=\''.$name.'[]\'])")';
  178. }
  179. else
  180. {
  181. $selector = '$("p:has(*[name=\''.$name.'\'])")';
  182. }
  183. $val = $a['val'];
  184. $arr_custom_fields[$selector] = $val;
  185. }
  186. }
  187. if ($arr_custom_fields) {
  188. natcasesort($arr_custom_fields); // sort cfs - used instead of asort because is case-insensitive
  189. return $arr_custom_fields;
  190. }
  191. };
  192. // ===========================================================
  193. function bot_get_sections() // creates an array of all sections for selectInput
  194. {
  195. $r = safe_rows_start('name, title', 'txp_section','1=1');
  196. if ($r) {
  197. while ($a = nextRow($r)) {
  198. $name = $a['name'];
  199. $title = $a['title'];
  200. $sections[$name] = $title;
  201. }
  202. }
  203. natcasesort($sections);
  204. return $sections;
  205. }
  206. // ===========================================================
  207. function bot_update_button()
  208. {
  209. return n.'<div class="bot_update_button">' // update button
  210. .n.eInput('bot_wtc_tab')
  211. .n.sInput('update')
  212. .n.fInput('submit', 'update', 'Update', 'publish')
  213. .'</div>';
  214. }
  215. // ===========================================================
  216. function bot_wtc_is_td($item) // checks if item is a table td
  217. {
  218. $item = get_magic_quotes_gpc() ? $item : mysql_real_escape_string($item) ;
  219. if($item == '$(\"#article-col-1\")'
  220. || $item == '$(\"#article-col-2\")'
  221. || $item == '$(\"#article-main\")'
  222. || $item == '$(\"#article-tabs\")'
  223. )
  224. {
  225. return 1;
  226. }
  227. return 0;
  228. }
  229. // ===========================================================
  230. function bot_warning($warning) // outputs html for warnings
  231. {
  232. return graf(hed(bot_wtc_gTxt($warning),'3', ' id="bot_warning"'));
  233. };
  234. //===========================================
  235. function bot_wtc_install()
  236. {
  237. // figure out what MySQL version we are using (from _update.php)
  238. $mysqlversion = mysql_get_server_info();
  239. $tabletype = (intval($mysqlversion[0]) >= 5 || preg_match('#^4\.(0\.[2-9]|(1[89]))|(1\.[2-9])#',$mysqlversion))
  240. ? " ENGINE=MyISAM "
  241. : " TYPE=MyISAM ";
  242. if (isset($txpcfg['dbcharset']) && (intval($mysqlversion[0]) >= 5 || preg_match('#^4\.[1-9]#',$mysqlversion))) {
  243. $tabletype .= " CHARACTER SET = ". $txpcfg['dbcharset'] ." ";
  244. }
  245. // Create the bot_wtc table
  246. $bot_wtc = safe_query("CREATE TABLE `".PFX."bot_wtc` (
  247. `id` INT NOT NULL AUTO_INCREMENT,
  248. `item` VARCHAR(255) NOT NULL,
  249. `position` VARCHAR(255) NOT NULL,
  250. `destination` VARCHAR(255) NOT NULL,
  251. `sections` TEXT NOT NULL,
  252. `class` VARCHAR(255) NOT NULL,
  253. PRIMARY KEY (`id`)
  254. ) $tabletype");
  255. set_pref ('bot_wtc_script','', 'bot_wtc_','2'); // entry in txp_prefs table
  256. set_pref ('bot_wtc_static_sections','', 'bot_wtc_', '2'); // entry in txp_prefs table
  257. }
  258. // ===========================================================
  259. function bot_wtc_update() // updates cfs selectors in db | introduced in bot_wtc 0.7.1
  260. {
  261. global $event;
  262. if($event !== 'article') {
  263. return;
  264. }
  265. if (!bot_wtc_check_install()) { // poceeds only if plugin is already installed
  266. return;
  267. }
  268. safe_alter('bot_wtc', 'CHANGE sections sections TEXT',1);
  269. $db_values = bot_wtc_fetch_db(); // array
  270. for ($i =0; $i < count($db_values); $i++) {
  271. $id = $db_values[$i]['id'];
  272. $item = $db_values[$i]['item'];
  273. $destination = $db_values[$i]['destination'];
  274. // updates cfs
  275. if (strpos($item,'custom')) { // if item contains the substring 'custom'
  276. $cf_number = preg_replace("/[^0-9]/", '', $item); // ditch anything that is not a number
  277. $type = safe_field('html', 'txp_prefs', 'name = "custom_'.$cf_number.'_set"'); // retrieve cfs type
  278. if ($type == 'checkbox' || $type == 'multi-select') {
  279. $selector = '$("p:has(*[name=\'custom_'.$cf_number.'[]\'])")'; // adds the '[]' part
  280. }
  281. else
  282. {
  283. $selector = '$("p:has(*[name=\'custom_'.$cf_number.'\'])")';
  284. }
  285. safe_update('bot_wtc', 'item = "'.doslash($selector).'"', 'id = "'.$id.'"');
  286. }
  287. if (strpos($destination,'custom')) { // if destination contains the substring 'custom'
  288. $cf_number = preg_replace("/[^0-9]/", '', $destination); // ditch anything that is not a number
  289. $type = safe_field('html', 'txp_prefs', 'name = "custom_'.$cf_number.'_set"'); // retrieve cfs type
  290. if ($type == 'checkbox' || $type == 'multi-select') {
  291. $selector = '$("p:has(*[name=\'custom_'.$cf_number.'[]\'])")'; // adds the '[]' part
  292. }
  293. else
  294. {
  295. $selector = '$("p:has(*[name=\'custom_'.$cf_number.'\'])")';
  296. }
  297. safe_update('bot_wtc', 'destination = "'.doslash($selector).'"', 'id = "'.$id.'"');
  298. }
  299. }
  300. }
  301. // ===========================================================
  302. function bot_wtc_check_install()
  303. {
  304. // Check if the bot_wtc table exists
  305. if (getThings("Show tables like '".PFX."bot_wtc'")) {
  306. return true;
  307. }
  308. return false;
  309. }
  310. //===========================================
  311. function bot_all_items_selectinput() // outputs all items for selectInput() (used for destination dropdown)
  312. {
  313. global $bot_items;
  314. $cfs = bot_get_cfs(); // get cfs array in the form: cf_selector => cf_name
  315. // final values for the txp function selectInput (including cfs if any)
  316. if (is_array($cfs)) { // if there is at least one custom field set adds cfs to $bot_items array
  317. $all_items_select = array_merge($cfs, $bot_items);
  318. }
  319. else {
  320. $all_items_select = $bot_items;
  321. }
  322. return $all_items_select;
  323. natcasesort($all_items_select);
  324. }
  325. //===========================================
  326. function bot_contextual_selectinput($current = "") // outputs only 'yet-not-used' items for selectInput() (used for items dropdown)
  327. {
  328. global $bot_items;
  329. $db_values = bot_wtc_fetch_db(); // array of values from the db
  330. $all_items = bot_all_items_selectinput();
  331. if (bot_wtc_check_install()) {
  332. $used_items = safe_column('item', 'bot_wtc', '1=1'); // numeric array of item values from the db
  333. foreach ($all_items as $item => $title) {
  334. if (!in_array($item, $used_items)) {
  335. $items_selectInput[$item] = $title;
  336. }
  337. }
  338. }
  339. else {
  340. $items_selectInput = $all_items;
  341. }
  342. if ($current) { // if the parameter is given adds current value to array
  343. $items_selectInput[$current] = $all_items[$current];
  344. }
  345. return $items_selectInput;
  346. }
  347. // ===========================================================
  348. // bot_wtc tab
  349. // ===========================================================
  350. function bot_wtc_output_rows() // outputs the rows for the html table in the bot_wtc_tab
  351. {
  352. global $bot_items;
  353. $selectInput_for_position = array('insertBefore'=>'before','insertAfter'=>'after'); // position values for the txp function selectInput
  354. $db_values = bot_wtc_fetch_db(); // array of values from the db
  355. $destination_selectInput = bot_all_items_selectinput();
  356. $items_selectInput = bot_contextual_selectinput();
  357. // builds rows for new item sections list
  358. $sections= bot_get_sections(); // get sections array
  359. $new_item_sections_rows = '';
  360. foreach ($sections as $key => $value) {
  361. $new_item_sections_row = '<label>'.checkbox('new_item_sections[]', $key, '0').$value.'</label><br />';
  362. $new_item_sections_rows .= $new_item_sections_row;
  363. }
  364. $new_item_sections_rows .= '<p ><a href="#" class="bot_all">'.gTxt("all").'</a> | <a href="#" class="bot_none">'.gTxt("none").'</a></p>'; // hide all/none
  365. // new item insertion
  366. $rows = "";
  367. $input_row = tr(
  368. td(selectInput('new_item',bot_contextual_selectinput(), '', '1'), '', 'bot_hilight')
  369. .td(selectInput('new_item_position', $selectInput_for_position, '', '1'))
  370. .td(selectInput('new_item_destination',bot_all_items_selectinput(), '', '1'))
  371. .td('<p><a href="#" class="bot_push">'.gTxt("tag_section_list").'</a></p><div class="bot_collapse">'.$new_item_sections_rows.'</div>')
  372. .td(finput('text','new_item_class', ''))
  373. .td()
  374. );
  375. $rows .= $input_row;
  376. // other rows - output if at least one record was already set
  377. if ($db_values){
  378. for ($i = 0; $i < count( $db_values ); $i++){
  379. // data for "sections to show" selectinput - decides wether a section is checked or not
  380. $bot_hide_in_this_sections_array = explode('|', $db_values[$i]['sections']);
  381. $item_sections_rows = '';
  382. foreach ($sections as $key => $value) { // if section is in db mark as checked
  383. $checked = in_array($key, $bot_hide_in_this_sections_array) ? '1': '0';
  384. $item_sections_row = '<label>'.checkbox('bot_wtc_sections_for_id_'.$db_values[$i]['id'].'[]', $key, $checked).$value.'</label><br />';
  385. $item_sections_rows .= $item_sections_row;
  386. }
  387. $item_sections_rows .= '<p><a href="#" class="bot_all">'.gTxt("all").'</a> | <a href="#" class="bot_none">'.gTxt("none").'</a></p>'; // hide all/none
  388. $single_row = tr(
  389. td(selectInput('item[]',bot_contextual_selectinput($db_values[$i]['item']), $db_values[$i]['item'],'0'), '', 'bot_hilight')
  390. .td(selectInput('item_position[]', $selectInput_for_position, $db_values[$i]['position'], '1'))
  391. .td(selectInput('item_destination[]',bot_all_items_selectinput(), $db_values[$i]['destination'],'1'))
  392. .td('<p><a href="#" class="bot_push">'.gTxt("tag_section_list").'</a></p><div class="bot_collapse">'.$item_sections_rows.'</div>')
  393. .td(finput('text', 'item_class[]', $db_values[$i]['class']))
  394. .td(checkbox('bot_delete_id[]', $db_values[$i]['id'], '0').'<label for="bot_delete_id"> '.gTxt('delete').'</label>'))
  395. .hInput('bot_wtc_id[]', $db_values[$i]['id']);
  396. $rows .= $single_row;
  397. }
  398. };
  399. return $rows;
  400. }
  401. //===========================================
  402. function bot_wtc_static_sections_select()
  403. {
  404. // builds rows for sections list
  405. $sections= bot_get_sections(); // get sections array
  406. $static_sections = safe_field('val', 'txp_prefs', 'name = "bot_wtc_static_sections"'); // fetch prefs value for bot_wtc_static_sections
  407. $static_sections = explode('|', $static_sections); // creates an array of statica sections from the string in txp_prefs
  408. $static_sections_rows = '';
  409. foreach ($sections as $key => $value) {
  410. // if section is in db mark as checked
  411. $checked = in_array($key, $static_sections) ? '1': '0';
  412. $static_sections_row = '<label>'.checkbox('static_sections[]', $key, $checked).$value.'</label><br />';
  413. $static_sections_rows .= $static_sections_row;
  414. }
  415. return $static_sections_rows;
  416. }
  417. //===========================================
  418. function bot_advanced()
  419. {
  420. global $bot_items;
  421. $items = bot_all_items_selectinput(); // get items array
  422. $item_rows = '';
  423. foreach ($items as $key => $value) {
  424. $item_row = '<label>'.checkbox('bot_adv_items[]', htmlspecialchars($key), '0').$value.'</label><br />';
  425. $item_rows .= $item_row;
  426. $sections= bot_get_sections(); // get sections array
  427. }
  428. $sections_rows = '';
  429. foreach ($sections as $key => $value) {
  430. $sections_row = '<label>'.checkbox('bot_adv_sections[]', $key, '0').$value.'</label><br />';
  431. $sections_rows .= $sections_row;
  432. }
  433. return '<section role="region" class="txp-details" id="bot_advanced" aria-labelledby="bot_advanced-label">'
  434. .n.'<h3 id="bot_advanced-label">Advanced/Multiple selection</h3>'
  435. .n.'<div role="group">'
  436. .n.form(n.bot_update_button()
  437. .n.'<div id="bot_adv_items"><h4>Items</h4>'.$item_rows.'</div>' // items list
  438. .n.'<div id="bot_adv_hide"><h4>Hide in sections</h4>'.$sections_rows.'<p><a href="#" class="bot_all">'.gTxt("all").'</a> | <a href="#" class="bot_none">'.gTxt("none").'</a></p></div>' // sections list
  439. .n.'<div id="bot_adv_class"><h4>Set css class</h4>'.finput('text','bot_adv_class', '').'</div>' // class
  440. .n.bot_update_button()
  441. .n.'</div>'
  442. .n.'</section>'
  443. );
  444. }
  445. //===========================================
  446. function bot_wtc_tab($event, $step)
  447. {
  448. global $bot_items;
  449. $cfs = bot_get_cfs();
  450. pagetop('Write tab customize '.gTxt('preferences'), ($step == 'update' ? gTxt('preferences_saved') : ''));
  451. echo hed('Write tab customize','2');
  452. if ($step == 'install'){
  453. // Install the preferences table.
  454. bot_wtc_install();
  455. }
  456. if ($step == 'uninstall'){
  457. //remove table
  458. safe_query("DROP TABLE ".PFX."bot_wtc");
  459. safe_delete('txp_prefs', 'event = "bot_wtc_"' );
  460. }
  461. if ($step == 'update'){
  462. // set function variables
  463. $new_item = ps('new_item'); //variable
  464. $new_item_position = ps('new_item_position'); //variable
  465. $new_item_destination = ps('new_item_destination'); //variable
  466. $new_item_sections = ps('new_item_sections'); //array
  467. $new_item_class = ps('new_item_class'); //variable
  468. $bot_wtc_script = ps('bot_wtc_script'); //variable
  469. $static_sections = ps('static_sections'); //variable
  470. $item = ps('item'); //array
  471. $item_position = ps('item_position'); //array
  472. $item_destination = ps('item_destination'); //array
  473. $item_class = ps('item_class'); //array
  474. $bot_wtc_id = ps('bot_wtc_id'); //array
  475. $delete_id = ps('bot_delete_id'); //array
  476. $bot_adv_items = ps('bot_adv_items'); //array
  477. $bot_adv_sections = ps('bot_adv_sections'); //array
  478. $bot_adv_class = ps('bot_adv_class'); //variable
  479. // db update for existing items
  480. if ($item){ // if at least a saved item exists
  481. $db_values = bot_wtc_fetch_db(); // array of values from the db
  482. for ($i = 0; $i < count($item); $i++){
  483. // builds the posted variable name for current item sections
  484. $item_posted_sections_name = 'bot_wtc_sections_for_id_'.$db_values[$i]['id'];
  485. $item_sections = isset($_POST[$item_posted_sections_name]) ? $_POST[$item_posted_sections_name] : ''; //array
  486. // builds sections string for current item
  487. $item_sections_string = $item_sections ? implode('|', $item_sections): '';
  488. // allowed input data combinations
  489. if (($item[$i] && $item_destination[$i] && $item_position[$i])
  490. || ($item[$i] && $item_class[$i] && !$item_destination[$i] && !$item_position[$i])
  491. || ($item[$i] && $item_sections_string && !$item_destination[$i] && !$item_position[$i])) {
  492. // check if a column is linked with a non-column item BUT ONLY IF both items are set (otherwise couldn't apply i.e. class to a single td)
  493. if (!((bot_wtc_is_td($item[$i]) XOR bot_wtc_is_td($item_destination[$i])) && $item_destination[$i])){
  494. // check if item is different from destination
  495. if($item[$i] != $item_destination[$i]){
  496. safe_update("bot_wtc",
  497. "position = '"
  498. .doslash($item_position[$i])
  499. ."', destination = '"
  500. .doslash($item_destination[$i])
  501. ."', item = '"
  502. .doslash($item[$i])
  503. ."', sections = '"
  504. .doslash($item_sections_string)
  505. ."', class = '"
  506. .doslash($item_class[$i])
  507. ."'", "id = '".$bot_wtc_id[$i]."'");
  508. }
  509. else {
  510. echo bot_warning('same_item_warning');
  511. }
  512. }
  513. else {
  514. echo bot_warning('td_warning');
  515. }
  516. }
  517. else {
  518. echo bot_warning('combo_warning');
  519. }
  520. }
  521. }
  522. // db insert for new item
  523. // allowed input combinations
  524. if (($new_item && $new_item_destination && $new_item_position)
  525. || ($new_item && $new_item_class && !$new_item_destination && !$new_item_position)
  526. || ($new_item && $new_item_sections && !$new_item_destination && !$new_item_position)){
  527. // check if a column is linked with a non-column item
  528. if (!((bot_wtc_is_td($new_item) XOR bot_wtc_is_td($new_item_destination)) && $new_item_destination)){
  529. // check items are not the same
  530. if($new_item != $new_item_destination){
  531. // transforms the sections array in a string
  532. $new_item_sections_string = $new_item_sections ? implode('|', $new_item_sections) : '';
  533. safe_insert("bot_wtc",
  534. "position = '"
  535. .doslash($new_item_position)
  536. ."', destination = '"
  537. .doslash($new_item_destination)
  538. ."', class = '"
  539. .doslash($new_item_class)
  540. ."', sections = '"
  541. .doslash($new_item_sections_string)
  542. ."', item = '"
  543. .doslash($new_item)
  544. ."'");
  545. }
  546. else {
  547. echo bot_warning('same_item_warning');
  548. }
  549. }
  550. else {
  551. echo bot_warning('td_warning');
  552. }
  553. }
  554. elseif ($new_item || $new_item_destination || $new_item_position || $new_item_class || $new_item_sections){
  555. echo bot_warning('combo_warning');
  556. }
  557. if ($delete_id){ // checks if there is something to delete
  558. foreach ($delete_id as $id) {
  559. safe_delete('bot_wtc', 'id ="'.$id.'"' );
  560. }
  561. }
  562. // update advanced prefereces
  563. if ($bot_adv_items AND ($bot_adv_sections || $bot_adv_class)) { // check if item AND section OR class is selected
  564. $db_values = bot_wtc_fetch_db(); // first array: all values from db
  565. if ($bot_adv_sections) {
  566. $bot_db_sections = array(); // more specific array: only item => sections
  567. for ($i =0; $i < count($db_values); $i++) {
  568. $bot_db_sections[$db_values[$i]['item']] = $db_values[$i]['sections'];
  569. }
  570. foreach ($bot_adv_items as $item) { // iterates posted items
  571. // fetch -if any- existing sections from db for current item and merges arrays eliminating duplicates
  572. if (is_array($bot_db_sections) AND array_key_exists($item, $bot_db_sections)) {
  573. $db_sect_array = explode('|', $bot_db_sections[$item]);
  574. $final_array = array_unique(array_merge($db_sect_array, $bot_adv_sections));
  575. $bot_adv_sections_string = implode('|', $final_array); // new sections string
  576. }
  577. else {
  578. $bot_adv_sections_string = implode('|', $bot_adv_sections);
  579. }
  580. safe_upsert(
  581. "bot_wtc",
  582. "sections = '"
  583. .doslash($bot_adv_sections_string)
  584. ."'",
  585. "item = '".doslash($item)."'"
  586. );
  587. }
  588. }
  589. if ($bot_adv_class) {
  590. $bot_db_classes = array(); // more specific array: only item => classes
  591. for ($i =0; $i < count($db_values); $i++) {
  592. $bot_db_classes[$db_values[$i]['item']] = $db_values[$i]['class'];
  593. }
  594. foreach ($bot_adv_items as $item) { // iterates posted items
  595. // fetch -if any- existing class from db for current item and merges arrays eliminating duplicates
  596. if (is_array($bot_db_classes) AND array_key_exists($item, $bot_db_classes)) {
  597. $db_class_array = explode(' ', $bot_db_classes[$item]);
  598. $posted_class_array = explode(' ', $bot_adv_class);
  599. $final_array = array_unique(array_merge($db_class_array, $posted_class_array));
  600. $bot_adv_classes_string = implode(' ', $final_array); // new sections string
  601. }
  602. else {
  603. $bot_adv_classes_string = $bot_adv_class;
  604. }
  605. safe_upsert(
  606. "bot_wtc",
  607. "class = '"
  608. .doslash($bot_adv_classes_string)
  609. ."'",
  610. "item = '".doslash($item)."'"
  611. );
  612. }
  613. }
  614. }
  615. elseif ($bot_adv_sections || $bot_adv_class) {
  616. echo bot_warning('Warning: at least an item must be selected');
  617. }
  618. // updates static sections prefs
  619. if ($static_sections) {
  620. $static_sections_string = implode('|', $static_sections);
  621. safe_update('txp_prefs', 'val= "'.doslash($static_sections_string).'", html="text_input" ', 'name = "bot_wtc_static_sections"' );
  622. }
  623. // updates script prefs
  624. if ($bot_wtc_script) {
  625. safe_update('txp_prefs', 'val= \''.doslash($bot_wtc_script).'\', html=\'textarea\' ', 'name = \'bot_wtc_script\'' );
  626. }
  627. }
  628. if (bot_wtc_check_install()) { // what to show when accessing tab
  629. $bot_wtc_script = safe_field('val', 'txp_prefs', 'name = "bot_wtc_script"'); // fetch prefs value for bot_wtc_script
  630. echo n.t.'<div class="txp-layout-textbox">'; // main div
  631. echo '<p id="bot_controls" class="nav-tertiary">
  632. <a id="bot_expand_all" class="navlink" href="#">Expand all</a>
  633. <a id="bot_collapse_all" class="navlink" href="#">Collapse all</a>
  634. <a id="bot_advanced_open" class="navlink" href="#">Toggle advanced</a>
  635. </p>';
  636. echo n.t.bot_advanced();
  637. echo n.t.'<div id="bot_main">'; // main div
  638. echo form( // beginning of the form
  639. '<table id="bot_wtc_table" class="txp-list">' // beginning of the table
  640. .'<thead>'
  641. .tr(hcell(strong(gTxt('Item')))
  642. .hcell(strong(gTxt('Position')))
  643. .hcell(strong(gTxt('Destination')))
  644. .hcell(strong(gTxt('Hide in:')))
  645. .hcell(strong(gTxt('Class')))
  646. .hcell() // collapse all/show all)
  647. ).'</thead>'
  648. .bot_wtc_output_rows() // html rows generated by "bot_wtc_output_rows()"
  649. .'</table>' // end of the table
  650. .bot_update_button()
  651. .n.'<section role="region" class="txp-details" id="bot_static_sections" aria-labelledby="bot_static_sections-label">' // static sections
  652. .n.'<h3 id="bot_static_sections-label" class="txp-summary expanded">'
  653. .n.'<a class="bot_push toggle" role="button" href="#bot_static_sections-details" aria-expanded="true">Hide sections in sections dropdown</a>'
  654. .n.'</h3>'
  655. .n.'<div id="bot_static_sections-details" class="bot_collapse">'
  656. .bot_wtc_static_sections_select()
  657. .bot_update_button()
  658. .n.'</div>'
  659. .n.'</section>'
  660. .n.'<section role="region" class="txp-details" id="bot_js_box" aria-labelledby="bot_js_box-label">' // js code box
  661. .n.'<h3 id="bot_js_box-label" class="txp-summary expanded">'
  662. .n.'<a class="bot_push toggle" href="#" role="button" href="#bot_js_box-details" aria-expanded="true">Additional js code</a>'
  663. .n.'</h3>'
  664. .n.'<div id="bot_js_box-details" class="bot_collapse">'
  665. .n.'<a id="bot_js_link" href="#">Add external script</a> | <a id="bot_jq_link" href="#">Add Jquery script</a>'
  666. .n.'<textarea id="bot_wtc_script" name="bot_wtc_script" cols="60" rows="10">'.$bot_wtc_script.'</textarea>' // script textarea
  667. .n.bot_update_button()
  668. .n.'</div>'
  669. .n.'</section>'
  670. );
  671. echo n.t.'<section role="region" class="txp-details" id="bot_uninstall" aria-labelledby="bot_uninstall-label">' // js code box
  672. .n.'<h3 id="bot_uninstall-label" class="txp-summary expanded">'
  673. .n.'<a class="bot_push toggle" href="#" role="button" href="#bot_uninstall-details" aria-expanded="true">'.bot_wtc_gTxt('uninstall').'</a>'
  674. .n.'</h3>'
  675. .n.'<div id="bot_uninstall-details" class="bot_collapse">'
  676. .n.t.t.graf(bot_wtc_gTxt('uninstall_message'))
  677. .n.form(
  678. n.eInput('bot_wtc_tab')
  679. .n.sInput('uninstall')
  680. .n.n.fInput('submit', 'uninstall', 'Uninstall ', 'smallerbox'),"","confirm('".bot_wtc_gTxt('uninstall_confirm')."')"
  681. )
  682. .n.'</div>'
  683. .n.'</section>';
  684. }
  685. else { // install button
  686. echo n.t.'<div id="bot_install">'.
  687. n.t.t.hed(gTxt('install'), '1').
  688. n.graf(bot_wtc_gTxt('install_message')).
  689. n.n.form(
  690. n.eInput('bot_wtc_tab').
  691. n.sInput('install').
  692. n.n.fInput('submit', 'install', 'Install ', 'publish')
  693. )
  694. .'</div>'
  695. .'</div>';
  696. }
  697. // snippets to insert in the script box
  698. $bot_jquery_snippet = '<script type=\"text/javascript\">\n $(document).ready(function() {\n //your code here\n });\n<\/script>\n';
  699. $bot_js_snippet = '<script type=\"text/javascript\" src=\"path_to_script\"><\/script>\n';
  700. echo // add some jquery action
  701. '<script type="text/javascript">'.n.
  702. ' $(document).ready(function() {'.n.
  703. '$("div.bot_collapse").hide()'.n.
  704. '$("section#bot_advanced").hide()'.n.
  705. '$("a.bot_push").click(function(){'.n.
  706. ' $(this).toggleClass("bot_arrow").parent().next().slideToggle();'.n.
  707. ' return false;'.n.
  708. '});'.n.
  709. '$("#bot_collapse_all").click(function(){'.n.
  710. ' $("div.bot_collapse").slideUp();'.n.
  711. ' return false;'.n.
  712. '});'.n.
  713. '$("#bot_expand_all").click(function(){'.n.
  714. ' $("div.bot_collapse").slideDown();'.n.
  715. ' return false;'.n.
  716. '});'.n.
  717. '$("#bot_advanced_open").click(function(){'.n.
  718. ' $("section#bot_advanced").slideToggle();'.n.
  719. ' $("div#bot_main").toggle();'.n.
  720. ' return false;'.n.
  721. '});'.n.
  722. '$("a.bot_all").click(function(){'.n.
  723. ' $(this).parent().parent().find("input").attr("checked", true);'.n.
  724. ' return false;'.n.
  725. '});'.n.
  726. '$("a.bot_none").click(function(){'.n.
  727. ' $(this).parent().parent().find("input").attr("checked", false);'.n.
  728. ' return false;'.n.
  729. '});'.n.
  730. '$("#bot_jq_link").click(function(){'.n.
  731. ' var areaValue = $("#bot_wtc_script").val();'.n.
  732. ' $("#bot_wtc_script").val(areaValue + "'.$bot_jquery_snippet.'");'.n.
  733. ' return(false);'.n.
  734. '});'.n.
  735. '$("#bot_js_link").click(function(){'.n.
  736. ' var areaValue = $("#bot_wtc_script").val();'.n.
  737. ' $("#bot_wtc_script").val(areaValue + "'.$bot_js_snippet.'");'.n.
  738. ' return(false);'.n.
  739. '});'.n.
  740. ' });'.n.
  741. '</script>';
  742. }
  743. // ===========================================================
  744. // plugins output
  745. // ===========================================================
  746. function bot_wtc_css() { // css for the plugin tab under extensions
  747. global $event;
  748. if($event != 'bot_wtc_tab') { // Outputs css only in 'bot_wtc' extensions tab.
  749. return;
  750. }
  751. echo '<style type="text/css">
  752. #bot_main {
  753. margin: auto; width:800px;
  754. }
  755. #page-bot_wtc_tab h2 {
  756. text-align: center; margin:20px auto; padding-bottom:10px;
  757. }
  758. #bot_controls {
  759. margin: 20px auto;
  760. }
  761. #bot_controls a{margin-right:-5px}
  762. #bot_expand_all,
  763. #bot_collapse_all,
  764. #bot_advanced_open {
  765. font-size:10px;
  766. }
  767. #bot_wtc_table {
  768. padding:10px 0 20px; margin-left:0;
  769. }
  770. #bot_wtc_table td {
  771. vertical-align:center;
  772. padding:5px;
  773. white-space:nowrap;
  774. }
  775. #bot_wtc_table td p{margin:3px 0 0 0}
  776. #bot_advanced {}
  777. #bot_adv_items,
  778. #bot_adv_hide,
  779. #bot_adv_class
  780. {
  781. width:260px; float:left; margin-bottom:20px;
  782. }
  783. #bot_uninstall-details,
  784. #bot_static_sections-details,
  785. #bot_js_box-details {
  786. padding:0 20px;
  787. }
  788. #bot_uninstall-details{padding-bottom:20px;}
  789. #bot_wtc_script {
  790. width:100%; border:dotted #ccc 1px;
  791. }
  792. .bot_update_button {
  793. margin:20px 0; clear:both;
  794. }
  795. #bot_uninstall {
  796. }
  797. #bot_install {
  798. margin: auto; width:800px;
  799. }
  800. .bot_hilight {
  801. background:#eaeaea
  802. }
  803. a.bot_push {
  804. font-weight:bold; background: url(txp_img/arrowupdn.gif) no-repeat right bottom; padding-right:13px;
  805. }
  806. #bot_warning {
  807. text-align:center; background:#990000; color:#fff; margin: 20px auto; padding:10px; text-shadow:none;
  808. }
  809. </style>';
  810. }
  811. // ===========================================================
  812. function bot_hide_per_section_array(){ // builds array of sections to hide
  813. $db_values = bot_wtc_fetch_db(); // array of values from the db
  814. for ($i =0; $i<count($db_values); $i++) {
  815. if ($db_values[$i]['sections']) {
  816. $sections_to_hide = explode('|', $db_values[$i]['sections']);
  817. foreach ($sections_to_hide as $section) {
  818. $bot_hide_per_section[$section][] = $db_values[$i]['item'];
  819. }
  820. }
  821. }
  822. if (isset($bot_hide_per_section)) { // return array only if values exist
  823. return $bot_hide_per_section;
  824. }
  825. }
  826. // ===========================================================
  827. function bot_wtc_jquery_hide_sections_rows(){ // js rows dealing with items to hide on section change AND on page load
  828. $bot_hide_per_section = bot_hide_per_section_array();
  829. foreach ($bot_hide_per_section as $section => $fields) {
  830. echo n.' if (value=="'.$section.'"){'.n;
  831. for ($i =0; $i<count($fields); $i++) {
  832. echo ' '.$fields[$i].'.hide();'.n;
  833. }
  834. echo ' }'.n;
  835. }
  836. }
  837. // ===========================================================
  838. function bot_wtc_jquery_restore_rows(){ // js rows to restore every previously hidden item on section change
  839. $bot_hide_per_section = bot_hide_per_section_array();
  840. foreach ($bot_hide_per_section as $section => $fields) {
  841. for ($i =0; $i<count($fields); $i++) {
  842. $out[] = $fields[$i];
  843. }
  844. }
  845. $out = array_unique($out);
  846. foreach ($out as $value) {
  847. echo ' '.$value.'.show();'.n;
  848. }
  849. }
  850. // ===========================================================
  851. function bot_hide_per_section(){ // builds the script
  852. global $event;
  853. if($event !== 'article') {
  854. return;
  855. }
  856. $bot_hide_per_section = bot_hide_per_section_array();
  857. if ($bot_hide_per_section) { // output js only if values exist
  858. echo
  859. '<script type="text/javascript">'.n.
  860. ' $(document).ready(function() {'.n;
  861. echo
  862. ' $("select#section").change(function(){'.n;
  863. bot_wtc_jquery_restore_rows();
  864. echo
  865. ' var value = $("select#section").val();';
  866. bot_wtc_jquery_hide_sections_rows();
  867. echo
  868. ' }).change();'.n.
  869. ' });'.n.
  870. '</script>';
  871. }
  872. }
  873. // ===========================================================
  874. function bot_hidden_sections(){ // invisible sections in section list
  875. $bot_hidden_sections = safe_field('val', 'txp_prefs', 'name = "bot_wtc_static_sections"'); // fetch prefs value for bot_wtc_static_sections
  876. if ($bot_hidden_sections) { // output js only if values exist
  877. $sections = explode("|", $bot_hidden_sections);
  878. echo
  879. '<script type="text/javascript">'.n.
  880. ' $(document).ready(function() {'.n;
  881. foreach ($sections as $value) {
  882. echo ' $("select#section option:not(:selected)[value=\''.$value.'\']").remove();'.n;
  883. }
  884. echo
  885. ' });'.n.
  886. '</script>';
  887. }
  888. }
  889. // ===========================================================
  890. function bot_wtc_jquery_rows()
  891. {
  892. global $bot_items;
  893. $db_values = bot_wtc_fetch_db(); // array of values from the db
  894. $rows = '';
  895. for ($i = 0; $i <count($db_values); $i++)
  896. {
  897. $item = ($db_values[$i]['item'] != '') ? $db_values[$i]['item'] : '';
  898. $position = ($db_values[$i]['position'] != '') ? '.'.$db_values[$i]['position'] : '';
  899. $destination = ($db_values[$i]['destination'] != '') ? '('.$db_values[$i]['destination'].')' : '';
  900. $class = ($db_values[$i]['class'] != '') ? '.addClass("'.$db_values[$i]['class'].'")' : '';
  901. $row = $item.$position.$destination.$class.';'.n;
  902. $rows .= $row;
  903. }
  904. return $rows;
  905. };
  906. // ===========================================================
  907. function bot_wtc()
  908. {
  909. $bot_wtc_script = safe_field('val', 'txp_prefs', 'name = "bot_wtc_script"'); // fetch prefs value for bot_wtc_script
  910. $position = safe_column('position', 'bot_wtc', '1=1'); // fetch 'position' from db to check if a move is saved
  911. $class = safe_column('class', 'bot_wtc', '1=1'); // fetch 'class' from db to check if a class is saved
  912. if(isset($position) || isset($class)){ // output code only if a preference is saved
  913. echo
  914. '<script type="text/javascript">'.n.
  915. ' $(document).ready(function() {'.n.
  916. bot_wtc_jquery_rows().n.
  917. ' });'.n.
  918. '</script>';
  919. }
  920. if ($bot_wtc_script) {
  921. echo n.$bot_wtc_script.n;
  922. };
  923. }
  924. # --- END PLUGIN CODE ---
  925. if (0) {
  926. ?>
  927. <!--
  928. # --- BEGIN PLUGIN HELP ---
  929. <h2>Write tab customize help</h2>
  930. <h3>Overview</h3>
  931. <p>This plugin aims to be an all-in-one solution for the "write" tab customization. It allows to rearrange items, hide them on a per-section basis, remove some sections from the <em>sections </em>dropdown and much more. By combining its features you can get a totally different <em>write</em> tab arrangement depending on which section you choose in the <em>sections</em> dropdown. Used alone or togheter with other plugins (glz_custom_fields and bot_admin_body_class to name a few) it will help you customize the site backend for your clients quickly and easily. </p>
  932. <h3>Features</h3>
  933. <ul>
  934. <li>Single items (custom fields, body, excerpt etc.) or whole columns can be moved around relative to other single items or columns</li>
  935. <li>Items can be hidden on a per-section basis</li>
  936. <li>Sections can be removed from the "write" tab sections dropdown (for static sections like "about us" or "search") </li>
  937. <li>A custom css class can be set for each item. This let's you define classes for items that normally couldn't be targeted with simple css (i.e. a &lt;p&gt; surrounding a specific custom field and his label - if you are using glz_custom_fields). This feature has now a reduced importance with txp 3.0 since a lot more page elements can be directly targeted by css. Nonetheless it can still prove useful in some cases</li>
  938. <li>Javascript code can be set directly throught the plugin interface. Particularly useful for use with an external jquery plugin and in conjunction with the ability to add a css class to any item on the page. The script will be executed only in the <em>write</em> tab </li>
  939. <li>Advanced preferences allows for multiple items hiding and class attribution, speeding up the customization process if a lot of custom fields are set. </li>
  940. <li>Compatible with glz_custom_fields, rah_section_titles and rah_write_each_section </li>
  941. </ul>
  942. <p>Note that the rearrange capability is mainly intended to be an intermediate step in the customization process. To to fine-tune your customization you <em>may</em> need to modify the "textpattern.css" file.</p>
  943. <h3>A simple example</h3>
  944. <p>Suppose you want a custom field called "Files" to be the first item at the top left corner of the <em>write</em> tab.<br/>
  945. Quite easy: set the rule "Files" before "advanced Options ".</p>
  946. <p>Ok, now you want it to show only in section "Media".<br/>
  947. Easy too: in the "hide in" column check all sections <em>but</em> the "Media" section.</p>
  948. <p>But wait. You now want it to have a different look compared to other custom fields and you are using glz_custom_fields (which applies to all cfs a generic "glz_custom_field" class removing the default more-specific default class). In this case set an arbitrary class for the item and, in the textpattern.css, set a corresponding css rule, or - if you are in a rush - define the rule directly in the js box.</p>
  949. <p>That's not enough? Maybe you want the field to perform an animation using a jquery plugin when you hover on it?<br/>
  950. Then again, set a class for the item, reference the plugin and write the appropriate code in the js box like this:</p>
  951. <p><code>&lt;script type="text/javascript" src= "../js/your_jquery_animations_plugin.js"&gt;&lt;/script&gt;<br/>
  952. &lt;script language="javascript" type="text/javascript"&gt;<br/>
  953. $(document).ready(function() {<br/>
  954. $(".animate").your_jquery_animations_plugin();<br/>
  955. });<br/>
  956. &lt;/script&gt;</code></p>
  957. <h3>A little tip </h3>
  958. <p>Textpattern 4.3 brought a lot of cool enhancements to the "write" tab but also a few drawbacks.</p>
  959. <p>On the 'enhancement' side almost every item has now an id or a class. This means a snappier jquery execution and, above all, the possibility to hide these elements with simple css. Unfortunately there are some little drawbacks in the way the page is designed (IMHO). I'm referring to the several collapsible groups which crowd the 'write' tab. </p>
  960. <p> The issue here is while you can easily hide a group <em>label</em> (well, actually it isn't an html label but an h3) with css, this may lead to trouble if the group is already collapsed. In this case a user will not be able to expand it anymore being there nothing to be clicked.<br/>
  961. Of course this is nothing dramatic and can be fixed inserting a tiny jquery rule in the js box. Something like:</p>
  962. <p><code>&lt;script type="text/javascript"&gt;<br/>
  963. $(document).ready(function() {<br/>
  964. $(".toggle").show();<br/>
  965. });<br/>
  966. &lt;/script&gt;</code></p>
  967. <p>will keep everything expanded so you can safely hide any <em>label</em> with css (in your textpattern.css file</p>
  968. <h3>Upgrade notes </h3>
  969. <p> The plugin should take care of updating the data stored in the db on activation, anyway I strongly reccommend - especially if you have a lot of rules set - to backup your db before upgrading in case something goes wrong. </p>
  970. <h3>Notes</h3>
  971. <ul>
  972. <li>The order in which the rules for moving items are inserted <strong>does</strong> matter. Rules execution goes from top to bottom so in case the sequence gets garbled it's advisable to delete all and start over </li>
  973. <li>Class names must be inserted <strong>without</strong> the dot</li>
  974. <li>If you want to hide an item in <strong>all </strong>sections set a rule directly in your textpattern css file. For example: .override-form {display:none;} Is <strong>a lot</strong> more efficient than hiding the item in each section using this plugin.</li>
  975. <li>This plugin may not function properly if you have the Suhosing module (a security-related module for PHP) installed. In this case follow <a href="http://forum.textpattern.com/viewtopic.php?pid=243861#p243861">these instructions</a> (thanks maniqui!) </li>
  976. </ul>
  977. <h3>Installation</h3>
  978. <p> Paste the code into the Admin &gt; Plugins tab, install and enable the plugin. Visit the "Extensions" tab and click the <em>Install </em> button.</p>
  979. <h3>Changelog</h3>
  980. <p>v 7.1</p>
  981. <ul>
  982. <li> fixed <a href="http://forum.textpattern.com/viewtopic.php?pid=245511#p245511">issue with multiselect and checkboxes</a> cfs</li>
  983. <li> fixed deprecated jquery</li>
  984. <li> changed 'sections' field <a href="http://forum.textpattern.com/viewtopic.php?pid=254132#p254132">from varchar to text</a></li>
  985. <li> added missing semicolon at the end of line 903</li>
  986. <li> removed deprecated language attribute from 'script' tag</li>
  987. <li> updated help</li>
  988. <li> cleaned up code</li>
  989. # --- END PLUGIN HELP ---
  990. -->
  991. <?php
  992. }
  993. ?>