PageRenderTime 55ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/glz_custom_fields/glz_custom_fields.php

https://bitbucket.org/mrdale/txp-plugins
PHP | 1909 lines | 1301 code | 305 blank | 303 comment | 179 complexity | 8b1eb2fad9cfb2e3a86117fd730356d2 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'] = 'glz_custom_fields';
  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'] = '1.4.0-beta';
  16. $plugin['author'] = 'Gerhard Lazu';
  17. $plugin['author_uri'] = 'http://gerhardlazu.com';
  18. $plugin['description'] = 'Unlimited, super special custom fields.';
  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'] = '5';
  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. # glz_custom_fields v1.4.0-beta1
  62. # Unlimited, super special custom fields.
  63. #
  64. # Gerhard Lazu
  65. # http://gerhardlazu.com
  66. #
  67. # Contributors: Randy Levine, Sam Weiss, Luca Botti, Manfre, Vladimir Siljkovic, Julian Reisenberger, Steve Dickinson, Stef Dawson, Jean-Pol Dupont
  68. # Minimum requirements: Textpattern 4.5.1
  69. // Including helper files. If we can't have classes, we will use includes
  70. // -------------------------------------------------------------
  71. // messages that will be available throughout this plugin
  72. function glz_custom_fields_gTxt($get, $atts = array()) {
  73. $lang = array(
  74. 'no_name' => 'Ooops! <strong>custom set</strong> must have a name',
  75. 'deleted' => '<strong>{custom_set_name}</strong> was deleted',
  76. 'reset' => '<strong>{custom_set_name}</strong> was reset',
  77. 'created' => '<strong>{custom_set_name}</strong> was created',
  78. 'updated' => '<strong>{custom_set_name}</strong> was updated',
  79. 'exists' => 'Ooops! <strong>{custom_set_name}</strong> already exists',
  80. 'doesnt_exist' => 'Ooops! <strong>{custom_set_name}</strong> is not set',
  81. 'field_problems' => 'Ooops! <strong>{custom_set_name}</strong> has some problems. <a href="?event=glz_custom_fields">Go fix it</a>.',
  82. 'custom_set' => 'Text Input', # custom sets in TXP 4.2.0 are by type custom_set by default...
  83. 'text_input' => 'Text Input',
  84. 'select' => 'Select',
  85. 'multi-select' => 'Multi-Select',
  86. 'textarea' => 'Textarea',
  87. 'checkbox' => 'Checkbox',
  88. 'radio' => 'Radio',
  89. 'date-picker' => 'Date Picker',
  90. 'time-picker' => 'Time Picker',
  91. 'custom-script' => 'Custom Script',
  92. 'type_not_supported' => 'Type not supported',
  93. 'no_do' => 'Ooops! No action specified for method, abort.',
  94. 'not_specified' => 'Ooops! {what} is not specified',
  95. 'searchby_not_set' => '<strong>searcby</strong> cannot be left blank',
  96. 'jquery_missing' => 'Upgrade TXP to at least 4.0.5 or put <strong>jquery.js</strong> in your /textpattern folder. <a href="http://jquery.com" title="jQuery website">jQuery website</a>',
  97. 'check_path' => 'Make sure all your paths are correct. Check <strong>config.php</strong> and the Admin tab (mainly Advanced).',
  98. 'no_articles_found' => 'No articles with custom fields have been found.',
  99. 'migration_success' => 'Migrating custom fields was successful',
  100. 'migration_skip' => '<strong>custom_fields</strong> table already has data in it, migration skipped.',
  101. 'search_section_created' => '<strong>search</strong> section has been created',
  102. 'custom_sets_all_input' => 'All custom sets have been set back to input',
  103. 'preferences_updated' => 'Plugin preferences have been updated',
  104. 'not_found' => 'Ooops! <strong>{file}</strong> cannot be found, check path',
  105. 'not_callable' => 'Ooops! <strong>{function}()</strong> cannot be called. Ensure <strong>{file}</strong> can be executed.'
  106. );
  107. $out = ( strstr($lang[$get], "Ooops!") ) ? // Ooops! would appear 0 in the string...
  108. "<span class=\"red\">{$lang[$get]}</span>" :
  109. $lang[$get];
  110. return strtr($out, $atts);
  111. }
  112. // -------------------------------------------------------------
  113. // I would do this through a factory class, but some folks are still running PHP4...
  114. function glz_custom_fields_MySQL($do, $name='', $table='', $extra='') {
  115. if ( !empty($do) ) {
  116. switch ( $do ) {
  117. case 'all':
  118. return glz_all_custom_sets();
  119. break;
  120. case 'values':
  121. return glz_values_custom_field($name, $extra);
  122. break;
  123. case 'all_values' :
  124. return glz_all_existing_custom_values($name, $extra);
  125. break;
  126. case 'article_customs':
  127. return glz_article_custom_fields($name, $extra);
  128. break;
  129. case 'next_custom':
  130. return glz_next_empty_custom();
  131. break;
  132. case 'new':
  133. glz_new_custom_field($name, $table, $extra);
  134. glz_custom_fields_update_count();
  135. break;
  136. case 'update':
  137. return glz_update_custom_field($name, $table, $extra);
  138. break;
  139. case 'reset':
  140. return glz_reset_custom_field($name, $table, $extra);
  141. break;
  142. case 'delete':
  143. glz_delete_custom_field($name, $table);
  144. glz_custom_fields_update_count();
  145. break;
  146. case 'check_migration':
  147. return glz_check_migration();
  148. break;
  149. case 'mark_migration':
  150. return glz_mark_migration();
  151. break;
  152. case 'custom_set_exists':
  153. return glz_check_custom_set_exists($name);
  154. break;
  155. case 'plugin_preferences':
  156. return glz_plugin_preferences($name);
  157. break;
  158. case 'update_plugin_preferences':
  159. return glz_update_plugin_preferences($name);
  160. break;
  161. }
  162. }
  163. else
  164. trigger_error(glz_custom_fields_gTxt('no_do'));
  165. }
  166. function glz_all_custom_sets() {
  167. $all_custom_sets = getRows("
  168. SELECT
  169. `name` AS custom_set,
  170. `val` AS name,
  171. `position`,
  172. `html` AS type
  173. FROM
  174. `".PFX."txp_prefs`
  175. WHERE
  176. `event`='custom'
  177. ORDER BY
  178. `position`
  179. ");
  180. foreach ( $all_custom_sets as $custom_set ) {
  181. $out[$custom_set['custom_set']] = array(
  182. 'name' => $custom_set['name'],
  183. 'position' => $custom_set['position'],
  184. 'type' => $custom_set['type']
  185. );
  186. }
  187. return $out;
  188. }
  189. function glz_values_custom_field($name, $extra) {
  190. global $prefs;
  191. if ( is_array($extra) ) {
  192. extract($extra);
  193. if ( !empty($name) ) {
  194. switch ( $prefs['values_ordering'] ) {
  195. case "ascending":
  196. $orderby = "value ASC";
  197. break;
  198. case "descending":
  199. $orderby = "value DESC";
  200. break;
  201. default:
  202. $orderby = "id ASC";
  203. }
  204. $arr_values = getThings("
  205. SELECT
  206. `value`
  207. FROM
  208. `".PFX."custom_fields`
  209. WHERE
  210. `name` = '{$name}'
  211. ORDER BY
  212. {$orderby}
  213. ");
  214. if ( count($arr_values) > 0 ) {
  215. // decode all special characters e.g. ", & etc. and use them for keys
  216. foreach ( $arr_values as $key => $value )
  217. $arr_values_formatted[glz_return_clean_default(htmlspecialchars($value))] = stripslashes($value);
  218. // if this is a range, format ranges accordingly
  219. return glz_format_ranges($arr_values_formatted, $custom_set_name);
  220. }
  221. }
  222. }
  223. else
  224. trigger_error(glz_custom_fields_gTxt('not_specified', array('{what}' => "extra attributes")));
  225. }
  226. function glz_all_existing_custom_values($name, $extra) {
  227. if ( is_array($extra) ) {
  228. extract(lAtts(array(
  229. 'custom_set_name' => "",
  230. 'status' => 4
  231. ),$extra));
  232. // we might want to check the custom field values for all articles - think initial migration
  233. $status_condition = ($status == 0) ? "<> ''" : "= '$status'";
  234. if ( !empty($name) ) {
  235. $arr_values = getThings("
  236. SELECT DISTINCT
  237. `$name`
  238. FROM
  239. `".PFX."textpattern`
  240. WHERE
  241. `Status` $status_condition
  242. AND
  243. `$name` <> ''
  244. ORDER BY
  245. `$name`
  246. ");
  247. // trim all values
  248. foreach ( $arr_values as $key => $value )
  249. $arr_values[$key] = trim($value);
  250. // DEBUG
  251. // dmp($arr_values);
  252. // prepare our array for checking. We need a single string to check for | instances - seems quickest.
  253. $values_check = join('::', $arr_values);
  254. // DEBUG
  255. // dmp($values_check);
  256. // check if some of the values are multiple ones
  257. if ( strstr($values_check, '|') ) {
  258. // initialize $out
  259. $out = array();
  260. // put all values in an array
  261. foreach ( $arr_values as $value ) {
  262. $arr_values = explode('|', $value);
  263. $out = array_merge($out, $arr_values);
  264. }
  265. // keep only the unique ones
  266. $out = array_unique($out);
  267. // keys and values need to be the same
  268. $out = php4_array_combine($out, $out);
  269. }
  270. // check if this is a range
  271. else if ( strstr($values_check, '-') && strstr($custom_set_name, 'range') )
  272. // keys won't have the unit ($, ÂŁ, m<sup>3</sup>, etc.) values will
  273. $out = glz_format_ranges($arr_values, $custom_set_name);
  274. else
  275. // keys and values need to be the same
  276. $out = php4_array_combine($arr_values, $arr_values);
  277. // calling stripslashes on all array values
  278. array_map('glz_array_stripslashes', $out);
  279. return $out;
  280. }
  281. }
  282. else
  283. trigger_error(glz_custom_fields_gTxt('not_specified', array('{what}' => "extra attributes")));
  284. }
  285. function glz_article_custom_fields($name, $extra) {
  286. if ( is_array($extra) ) {
  287. // see what custom fields we need to query for
  288. foreach ( $extra as $custom => $custom_set )
  289. $select[] = glz_custom_number($custom);
  290. // prepare the select elements
  291. $select = implode(',', $select);
  292. $arr_article_customs = getRow("
  293. SELECT
  294. $select
  295. FROM
  296. `".PFX."textpattern`
  297. WHERE
  298. `ID`='$name'
  299. ");
  300. return $arr_article_customs;
  301. }
  302. else
  303. trigger_error(glz_custom_fields_gTxt('not_specified', array('{what}' => "extra attributes")));
  304. }
  305. function glz_new_custom_field($name, $table, $extra) {
  306. if ( is_array($extra) ) {
  307. extract($extra);
  308. // DRYing up, we'll be using this variable quiet often
  309. $custom_set = ( isset($custom_field_number) ) ?
  310. "custom_{$custom_field_number}_set" :
  311. $custom_set;
  312. if ( ($table == PFX."txp_prefs") ) {
  313. // if this is a new field without a position, use the $custom_field_number
  314. if (empty($custom_set_position)) $custom_set_position = $custom_field_number;
  315. $query = "
  316. INSERT INTO
  317. `".PFX."txp_prefs` (`prefs_id`, `name`, `val`, `type`, `event`, `html`, `position`)
  318. VALUES
  319. ('1', '{$custom_set}', '{$name}', '1', 'custom', '{$custom_set_type}', {$custom_set_position})
  320. ";
  321. }
  322. else if ( $table == PFX."txp_lang" ) {
  323. $query = "
  324. INSERT INTO
  325. `".PFX."txp_lang` (`id`,`lang`,`name`,`event`,`data`,`lastmod`)
  326. VALUES
  327. ('','{$lang}','{$custom_set}','prefs','{$name}',now())
  328. ";
  329. }
  330. else if ( $table == PFX."textpattern" ) {
  331. $column_type = ( $custom_set_type == "textarea" ) ? "TEXT" : "VARCHAR(255)";
  332. $query = "
  333. ALTER TABLE
  334. `".PFX."textpattern`
  335. ADD
  336. `custom_{$custom_field_number}` {$column_type} NOT NULL DEFAULT ''
  337. ";
  338. }
  339. else if ( $table == PFX."custom_fields" ) {
  340. $arr_values = array_unique(array_filter(explode("\r\n", $value), 'glz_arr_empty_values'));
  341. if ( is_array($arr_values) && !empty($arr_values) ) {
  342. $size_arr_values = count($arr_values);
  343. $insert = '';
  344. foreach ( $arr_values as $key => $value ) {
  345. // don't insert empty values
  346. if ( !empty($value) )
  347. // make sure special characters are escaped before inserting them in the database
  348. $value = addslashes(addslashes(trim($value)));
  349. // if this is the last value, query will have to be different
  350. $insert .= ($key+1 != $size_arr_values ) ?
  351. "('{$custom_set}','{$value}'), " :
  352. "('{$custom_set}','{$value}')";
  353. }
  354. $query = "
  355. INSERT INTO
  356. `".PFX."custom_fields` (`name`,`value`)
  357. VALUES
  358. {$insert}
  359. ";
  360. }
  361. }
  362. if ( isset($query) && !empty($query) )
  363. safe_query($query);
  364. }
  365. else
  366. trigger_error(glz_custom_fields_gTxt('not_specified', array('{what}' => "extra attributes")));
  367. }
  368. function glz_update_custom_field($name, $table, $extra) {
  369. if ( is_array($extra) )
  370. extract($extra);
  371. if ( ($table == PFX."txp_prefs") ) {
  372. safe_query("
  373. UPDATE
  374. `".PFX."txp_prefs`
  375. SET
  376. `val` = '{$custom_set_name}',
  377. `html` = '{$custom_set_type}',
  378. `position` = '{$custom_set_position}'
  379. WHERE
  380. `name`='{$name}'
  381. ");
  382. }
  383. else if ( ($table == PFX."textpattern") ) {
  384. $column_type = ( $custom_set_type == "textarea" ) ? "TEXT" : "VARCHAR(255)";
  385. safe_query("
  386. ALTER TABLE
  387. `".PFX."textpattern`
  388. MODIFY
  389. `{$custom_field}` {$column_type} NOT NULL DEFAULT ''
  390. ");
  391. }
  392. }
  393. function glz_reset_custom_field($name, $table, $extra) {
  394. if ( is_array($extra) )
  395. extract($extra);
  396. if ( $table == PFX."txp_prefs" ) {
  397. safe_query("
  398. UPDATE
  399. `".PFX."txp_prefs`
  400. SET
  401. `val` = '',
  402. `html` = 'text_input'
  403. WHERE
  404. `name`='{$name}'
  405. ");
  406. }
  407. else if ( $table == PFX."textpattern" ) {
  408. safe_query("UPDATE `".PFX."textpattern` SET `{$name}` = ''");
  409. safe_query("ALTER TABLE `".PFX."textpattern` MODIFY `{$custom_field}` VARCHAR(255) NOT NULL DEFAULT ''");
  410. }
  411. }
  412. function glz_delete_custom_field($name, $table) {
  413. // remember, custom fields under 10 MUST NOT be deleted
  414. if ( glz_custom_digit($name) > 10 ) {
  415. if ( in_array($table, array(PFX."txp_prefs", PFX."txp_lang", PFX."custom_fields")) ) {
  416. $query = "
  417. DELETE FROM
  418. `{$table}`
  419. WHERE
  420. `name`='{$name}'
  421. ";
  422. }
  423. else if ( $table == PFX."textpattern" ) {
  424. $query = "
  425. ALTER TABLE
  426. `".PFX."textpattern`
  427. DROP
  428. `{$name}`
  429. ";
  430. }
  431. safe_query($query);
  432. }
  433. else {
  434. if ( $table == PFX."txp_prefs" )
  435. glz_custom_fields_MySQL("reset", $name, $table);
  436. else if ( ($table == PFX."custom_fields") ) {
  437. safe_query("
  438. DELETE FROM
  439. `{$table}`
  440. WHERE
  441. `name`='{$name}'
  442. ");
  443. }
  444. }
  445. }
  446. // -------------------------------------------------------------
  447. // checks if custom_fields table has any values in it
  448. function glz_check_migration() {
  449. return getThing("
  450. SELECT
  451. COUNT(*)
  452. FROM
  453. `".PFX."custom_fields`
  454. ");
  455. }
  456. // -------------------------------------------------------------
  457. // make a note of glz_custom_fields migration in txp_prefs
  458. function glz_mark_migration() {
  459. set_pref("migrated", "1", "glz_custom_f");
  460. }
  461. // -------------------------------------------------------------
  462. // check if one of the special custom fields exists
  463. function glz_check_custom_set_exists($name) {
  464. if ( !empty($name) ) {
  465. return getThing("
  466. SELECT
  467. `name`, `val`
  468. FROM
  469. `".PFX."txp_prefs`
  470. WHERE
  471. `html` = '{$name}'
  472. AND
  473. `name` LIKE 'custom_%'
  474. ORDER BY
  475. `name`
  476. ");
  477. }
  478. }
  479. // -------------------------------------------------------------
  480. // updates max_custom_fields
  481. function glz_custom_fields_update_count() {
  482. set_pref('max_custom_fields', safe_count("txp_prefs", "event='custom'"));
  483. }
  484. // -------------------------------------------------------------
  485. // returns all plugin preferences
  486. function glz_plugin_preferences($arr_preferences) {
  487. $r = safe_rows_start('name, val', 'txp_prefs', "event = 'glz_custom_f'");
  488. if ($r) {
  489. while ($a = nextRow($r)) {
  490. $out[$a['name']] = stripslashes($a['val']);
  491. }
  492. }
  493. return $out;
  494. }
  495. // -------------------------------------------------------------
  496. // updates all plugin preferences
  497. function glz_update_plugin_preferences($arr_preferences) {
  498. // die(dmp($arr_preferences));
  499. foreach ($arr_preferences as $preference => $value) {
  500. set_pref($preference, addslashes(addslashes(trim($value))), "glz_custom_f", 10); // 10 so that it won't appear under TXP's prefs tab
  501. }
  502. }
  503. // -------------------------------------------------------------
  504. // goes through all custom sets, returns the first one which is not being used
  505. function glz_next_empty_custom() {
  506. global $all_custom_sets;
  507. foreach ( $all_custom_sets as $custom => $custom_set ) {
  508. if ( empty($custom_set['name']) )
  509. return $custom;
  510. }
  511. }
  512. // -------------------------------------------------------------
  513. // edit/delete buttons in custom_fields table require a form each
  514. function glz_form_buttons($action, $value, $custom_set, $custom_set_name, $custom_set_type, $custom_set_position, $onsubmit='') {
  515. $onsubmit = ($onsubmit) ?
  516. 'onsubmit="'.$onsubmit.'"' :
  517. '';
  518. return
  519. '<form method="post" action="index.php" '.$onsubmit.'>
  520. <input name="custom_set" value="'.$custom_set.'" type="hidden" />
  521. <input name="custom_set_name" value="'.$custom_set_name.'" type="hidden" />
  522. <input name="custom_set_type" value="'.$custom_set_type.'" type="hidden" />
  523. <input name="custom_set_position" value="'.$custom_set_position.'" type="hidden" />
  524. <input name="event" value="glz_custom_fields" type="hidden" />
  525. <input name="'.$action.'" value="'.$value.'" type="submit" />
  526. </form>';
  527. }
  528. // -------------------------------------------------------------
  529. // the types our custom fields can take
  530. function glz_custom_set_types() {
  531. return array(
  532. 'normal' => array(
  533. 'text_input',
  534. 'checkbox',
  535. 'radio',
  536. 'select',
  537. 'multi-select',
  538. 'textarea'),
  539. 'special' => array(
  540. 'date-picker',
  541. 'time-picker',
  542. 'custom-script')
  543. );
  544. }
  545. // -------------------------------------------------------------
  546. // outputs only custom fields that have been set, i.e. have a name assigned to them
  547. function glz_check_custom_set($all_custom_sets, $step) {
  548. $out = array();
  549. foreach ($all_custom_sets as $key => $custom_field) {
  550. if (!empty($custom_field['name'])) {
  551. if ( ($step == "body") && ($custom_field['type'] == "textarea") )
  552. $out[$key] = $custom_field;
  553. else if ( ($step == "custom_fields") && ($custom_field['type'] != "textarea") ) {
  554. $out[$key] = $custom_field;
  555. }
  556. }
  557. }
  558. return $out;
  559. }
  560. // -------------------------------------------------------------
  561. // removes { } from values which are marked as default
  562. function glz_return_clean_default($value) {
  563. $pattern = "/^.*\{(.*)\}.*/";
  564. return preg_replace($pattern, "$1", $value);
  565. }
  566. // -------------------------------------------------------------
  567. // return our default value from all custom_field values
  568. function glz_default_value($all_values) {
  569. if ( is_array($all_values) ) {
  570. preg_match("/(\{.*\})/", join(" ", $all_values), $default);
  571. return ( (!empty($default) && $default[0]) ? $default[0] : '');
  572. }
  573. }
  574. // -------------------------------------------------------------
  575. // calling the above function in an array context
  576. function glz_clean_default_array_values(&$value) {
  577. $value = glz_return_clean_default($value);
  578. }
  579. // -------------------------------------------------------------
  580. // custom_set without "_set" e.g. custom_1_set => custom_1
  581. // or custom set formatted for IDs e.g. custom-1
  582. function glz_custom_number($custom_set, $delimiter="_") {
  583. $custom_field = substr($custom_set, 0, -4);
  584. if ($delimiter != "_")
  585. $custom_field = str_replace("_", $delimiter, $custom_field);
  586. return $custom_field;
  587. }
  588. // -------------------------------------------------------------
  589. // custom_set digit e.g. custom_1_set => 1
  590. function glz_custom_digit($custom_set) {
  591. $out = explode("_", $custom_set);
  592. // $out[0] will always be custom
  593. return $out[1];
  594. }
  595. // -------------------------------------------------------------
  596. // removes empty values from arrays - used for new custom fields
  597. function glz_arr_empty_values($value) {
  598. if ( !empty($value) )
  599. return $value;
  600. }
  601. // -------------------------------------------------------------
  602. // returns the custom set from a custom set name e.g. "Rating" gives us custom_1_set
  603. function glz_get_custom_set($value) {
  604. global $all_custom_sets;
  605. // go through all custom fields and see if the one we're looking for exists
  606. foreach ( $all_custom_sets as $custom => $custom_set ) {
  607. if ( $custom_set['name'] == $value )
  608. return $custom;
  609. }
  610. // if it doesn't, return error message
  611. trigger_error(glz_custom_fields_gTxt('doesnt_exist', array('{custom_set_name}' => $value)));
  612. }
  613. // -------------------------------------------------------------
  614. // get the article ID, EVEN IF it's newly saved
  615. function glz_get_article_id() {
  616. return ( !empty($GLOBALS['ID']) ?
  617. $GLOBALS['ID'] :
  618. gps('ID') );
  619. }
  620. // -------------------------------------------------------------
  621. // helps with range formatting - just DRY
  622. function glz_format_ranges($arr_values, $custom_set_name) {
  623. //initialize $out
  624. $out = '';
  625. foreach ( $arr_values as $key => $value ) {
  626. $out[$key] = ( strstr($custom_set_name, 'range') ) ?
  627. glz_custom_fields_range($value, $custom_set_name) :
  628. $value;
  629. }
  630. return $out;
  631. }
  632. // -------------------------------------------------------------
  633. // acts as a callback for the above function
  634. function glz_custom_fields_range($custom_value, $custom_set_name) {
  635. // last part of the string will be the range unit (e.g. $, &pound;, m<sup>3</sup> etc.)
  636. $nomenclature = array_pop(explode(' ', $custom_set_name));
  637. // see whether range unit should go after
  638. if ( strstr($nomenclature, '(after)') ) {
  639. // trim '(after)' from the measuring unit
  640. $nomenclature = substr($nomenclature, 0, -7);
  641. $after = 1;
  642. }
  643. // check whether it's a range or single value
  644. $arr_value = explode('-', $custom_value);
  645. if ( is_array($arr_value) ) {
  646. // initialize $out
  647. $out = '';
  648. foreach ( $arr_value as $value ) {
  649. // check whether nomenclature goes before or after
  650. $out[] = ( !isset($after) ) ?
  651. $nomenclature.number_format($value) :
  652. number_format($value).$nomenclature;
  653. }
  654. return implode('-', $out);
  655. }
  656. // our range is a single value
  657. else {
  658. // check whether nomenclature goes before or after
  659. return ( !isset($after) ) ?
  660. $nomenclature.number_format($value) :
  661. number_format($value).$nomenclature;
  662. }
  663. }
  664. // -------------------------------------------------------------
  665. // returns the next available number for custom set
  666. function glz_custom_next($arr_custom_sets) {
  667. $arr_extra_custom_sets = array();
  668. foreach ( array_keys($arr_custom_sets) as $extra_custom_set) {
  669. $arr_extra_custom_sets[] = glz_custom_digit($extra_custom_set);
  670. }
  671. // order the array
  672. sort($arr_extra_custom_sets);
  673. for ( $i=0; $i < count($arr_extra_custom_sets); $i++ ) {
  674. if ($arr_extra_custom_sets[$i] > $i+1)
  675. return $i+1;
  676. }
  677. return count($arr_extra_custom_sets)+1;
  678. }
  679. // -------------------------------------------------------------
  680. // checks if the custom field name isn't already taken
  681. function glz_check_custom_set_name($arr_custom_fields, $custom_set_name, $custom_set='') {
  682. foreach ( $arr_custom_fields as $custom => $arr_custom_set ) {
  683. if ( ($custom_set_name == $arr_custom_set['name']) && (!empty($custom_set) && $custom_set != $custom) )
  684. return TRUE;
  685. }
  686. return FALSE;
  687. }
  688. // -------------------------------------------------------------
  689. // formats the custom set output based on its type
  690. function glz_format_custom_set_by_type($custom, $custom_id, $custom_set_type, $arr_custom_field_values, $custom_value = "", $default_value = "") {
  691. if ( is_array($arr_custom_field_values) )
  692. $arr_custom_field_values = array_map('glz_array_stripslashes', $arr_custom_field_values);
  693. switch ( $custom_set_type ) {
  694. // these are the normal custom fields
  695. case "text_input":
  696. return array(
  697. fInput("text", $custom, $custom_value, "edit", "", "", "22", "", $custom_id),
  698. 'glz_custom_field'
  699. );
  700. case "select":
  701. return array(
  702. glz_selectInput($custom, $custom_id, $arr_custom_field_values, $custom_value, $default_value),
  703. 'glz_custom_select_field'
  704. );
  705. case "multi-select":
  706. return array(
  707. glz_selectInput($custom, $custom_id, $arr_custom_field_values, $custom_value, $default_value, 1),
  708. 'glz_custom_multi-select_field'
  709. );
  710. case "checkbox":
  711. return array(
  712. glz_checkbox($custom, $arr_custom_field_values, $custom_value, $default_value),
  713. 'glz_custom_checkbox_field'
  714. );
  715. case "radio":
  716. return array(
  717. glz_radio($custom, $custom_id, $arr_custom_field_values, $custom_value, $default_value),
  718. 'glz_custom_radio_field'
  719. );
  720. case "textarea":
  721. return array(
  722. text_area($custom, 100, 500, $custom_value, $custom_id),
  723. 'glz_text_area_field'
  724. );
  725. // here start the special custom fields, might need to refactor the return, starting to repeat itself
  726. case "date-picker":
  727. return array(
  728. fInput("text", $custom, $custom_value, "edit date-picker", "", "", "22", "", $custom_id),
  729. 'glz_custom_date-picker_field clearfix'
  730. );
  731. case "time-picker":
  732. return array(
  733. fInput("text", $custom, $custom_value, "edit time-picker", "", "", "22", "", $custom_id),
  734. 'glz_custom_time-picker_field'
  735. );
  736. case "custom-script":
  737. global $custom_scripts_path;
  738. return array(
  739. glz_custom_script($custom_scripts_path."/".reset($arr_custom_field_values), $custom, $custom_id, $custom_value),
  740. 'glz_custom_field_script'
  741. );
  742. // a type has been passed that is not supported yet
  743. default:
  744. return array(
  745. glz_custom_fields_gTxt('type_not_supported'),
  746. 'glz_custom_field'
  747. );
  748. }
  749. }
  750. // -------------------------------------------------------------
  751. // had to duplicate the default selectInput() because trimming \t and \n didn't work + some other mods & multi-select
  752. function glz_selectInput($name = '', $id = '', $arr_values = '', $custom_value = '', $default_value = '', $multi = '') {
  753. if ( is_array($arr_values) ) {
  754. global $prefs;
  755. $out = array();
  756. // if there is no custom_value coming from the article, let's use our default one
  757. if ( empty($custom_value) )
  758. $custom_value = $default_value;
  759. foreach ($arr_values as $key => $value) {
  760. $selected = glz_selected_checked('selected', $key, $custom_value, $default_value);
  761. $out[] = "<option value=\"$key\"{$selected}>$value</option>";
  762. }
  763. // we'll need the extra attributes as well as a name that will produce an array
  764. if ($multi) {
  765. $multi = ' multiple="multiple" size="'.$prefs['multiselect_size'].'"';
  766. $name .= "[]";
  767. }
  768. return "<select id=\"".glz_idify($id)."\" name=\"$name\" class=\"list\"$multi>".
  769. ($default_value ? '' : "<option value=\"\"$selected>&nbsp;</option>").
  770. ( $out ? join('', $out) : '').
  771. "</select>";
  772. }
  773. else
  774. return glz_custom_fields_gTxt('field_problems', array('{custom_set_name}' => $name));
  775. }
  776. // -------------------------------------------------------------
  777. // had to duplicate the default checkbox() to keep the looping in here and check against existing value/s
  778. function glz_checkbox($name = '', $arr_values = '', $custom_value = '', $default_value = '') {
  779. if ( is_array($arr_values) ) {
  780. $out = array();
  781. // if there is no custom_value coming from the article, let's use our default one
  782. if ( empty($custom_value) )
  783. $custom_value = $default_value;
  784. foreach ( $arr_values as $key => $value ) {
  785. $checked = glz_selected_checked('checked', $key, $custom_value);
  786. // Putting an additional span around the input and label combination so the two can be floated together as a pair for left-right, left-right,... arrangement of checkboxes and radio buttons. Thanks Julian!
  787. $out[] = "<span><input type=\"checkbox\" name=\"{$name}[]\" value=\"$key\" class=\"checkbox\" id=\"".glz_idify($key)."\"{$checked} /><label for=\"".glz_idify($key)."\">$value</label></span><br />";
  788. }
  789. return join('', $out);
  790. }
  791. else
  792. return glz_custom_fields_gTxt('field_problems', array('{custom_set_name}' => $name));
  793. }
  794. // -------------------------------------------------------------
  795. // had to duplicate the default radio() to keep the looping in here and check against existing value/s
  796. function glz_radio($name = '', $id = '', $arr_values = '', $custom_value = '', $default_value = '') {
  797. if ( is_array($arr_values) ) {
  798. $out = array();
  799. // if there is no custom_value coming from the article, let's use our default one
  800. if ( empty($custom_value) )
  801. $custom_value = $default_value;
  802. foreach ( $arr_values as $key => $value ) {
  803. $checked = glz_selected_checked('checked', $key, $custom_value);
  804. // Putting an additional span around the input and label combination so the two can be floated together as a pair for left-right, left-right,... arrangement of checkboxes and radio buttons. Thanks Julian!
  805. $out[] = "<span><input type=\"radio\" name=\"$name\" value=\"$key\" class=\"radio\" id=\"{$id}_".glz_idify($key)."\"{$checked} /><label for=\"{$id}_".glz_idify($key)."\">$value</label></span><br />";
  806. }
  807. return join('', $out);
  808. }
  809. else
  810. return glz_custom_fields_gTxt('field_problems', array('{custom_set_name}' => $name));
  811. }
  812. // -------------------------------------------------------------
  813. // checking if this custom field has selected or checked values
  814. function glz_selected_checked($nomenclature, $value, $custom_value = '') {
  815. // we're comparing against a key which is a "clean" value
  816. $custom_value = htmlspecialchars($custom_value);
  817. // make an array if $custom_value contains multiple values
  818. if ( strpos($custom_value, '|') )
  819. $arr_custom_value = explode('|', $custom_value);
  820. if ( isset($arr_custom_value) )
  821. $out = ( in_array($value, $arr_custom_value) ) ? " $nomenclature=\"$nomenclature\"" : "";
  822. else
  823. $out = ($value == $custom_value) ? " $nomenclature=\"$nomenclature\"" : "";
  824. return $out;
  825. }
  826. //-------------------------------------------------------------
  827. // button gets more consistent styling across browsers rather than input type="submit"
  828. // included in this plugin until in makes it into TXP - if that ever happens...
  829. function glz_fButton($type, $name, $contents='Submit', $value, $class='', $id='', $title='', $onClick='', $disabled = false) {
  830. $o = '<button type="'.$type.'" name="'.$name.'"';
  831. $o .= ' value="'.htmlspecialchars($value).'"';
  832. $o .= ($class) ? ' class="'.$class.'"' : '';
  833. $o .= ($id) ? ' id="'.$id.'"' : '';
  834. $o .= ($title) ? ' title="'.$title.'"' : '';
  835. $o .= ($onClick) ? ' onclick="'.$onClick.'"' : '';
  836. $o .= ($disabled) ? ' disabled="disabled"' : '';
  837. $o .= '>';
  838. $o .= $contents;
  839. $o .= '</button>';
  840. return $o;
  841. }
  842. //-------------------------------------------------------------
  843. // evals a PHP script and displays output right under the custom field label
  844. function glz_custom_script($script, $custom, $custom_id, $custom_value) {
  845. if ( is_file($script) ) {
  846. include_once($script);
  847. $custom_function = basename($script, ".php");
  848. if ( is_callable($custom_function) ) {
  849. return call_user_func_array($custom_function, array($custom, $custom_id, $custom_value));
  850. }
  851. else
  852. return glz_custom_fields_gTxt('not_callable', array('{function}' => $custom_function, '{file}' => $script));
  853. }
  854. else
  855. return glz_custom_fields_gTxt('not_found', array('{file}' => $script));
  856. }
  857. // -------------------------------------------------------------
  858. // PHP4 doesn't come with array_combine... Thank you redbot!
  859. function php4_array_combine($keys, $values) {
  860. $result = array(); // initializing the array
  861. foreach ( array_map(null, $keys, $values) as $pair ) {
  862. $result[$pair[0]] = $pair[1];
  863. }
  864. return $result;
  865. }
  866. // -------------------------------------------------------------
  867. // converts all values into id safe ones
  868. function glz_idify($value) {
  869. $patterns[0] = "/\s/";
  870. $replacements[0] = "-";
  871. $patterns[1] = "/[^a-zA-Z0-9\-]/";
  872. $replacements[1] = "";
  873. return preg_replace($patterns, $replacements, strtolower($value));
  874. }
  875. // -------------------------------------------------------------
  876. // strips slashes in arrays, used in conjuction with e.g. array_map
  877. function glz_array_stripslashes(&$value) {
  878. return stripslashes($value);
  879. }
  880. // -------------------------------------------------------------
  881. // returns all sections/categories that are searchable
  882. function glz_all_searchable_sections_categories($type) {
  883. $type = (in_array($type, array('category', 'section')) ? $type : 'section');
  884. $condition = "";
  885. if ( $type == "section" )
  886. $condition .= "searchable='1'";
  887. else
  888. $condition .= "name <> 'root' AND type='article'";
  889. $result = safe_rows('*', "txp_{$type}", $condition);
  890. $out = array();
  891. foreach ($result as $value) {
  892. $out[$value['name']] = $value['title'];
  893. }
  894. return $out;
  895. }
  896. // -------------------------------------------------------------
  897. // will leave only [A-Za-z0-9 ] in the string
  898. function glz_clean_string($string) {
  899. if ($string)
  900. return preg_replace('/[^A-Za-z0-9\s\_\-]/', '', $string);
  901. }
  902. // -------------------------------------------------------------
  903. // replaces the default custom fields under write tab
  904. function glz_custom_fields_replace($event, $step, $data, $rs) {
  905. global $all_custom_sets, $date_picker;
  906. // get all custom fields & keep only the ones which are set, filter by step
  907. $arr_custom_fields = glz_check_custom_set($all_custom_sets, $step);
  908. // DEBUG
  909. // dmp($arr_custom_fields);
  910. $out = ' ';
  911. if ( is_array($arr_custom_fields) && !empty($arr_custom_fields) ) {
  912. // get all custom fields values for this article
  913. $arr_article_customs = glz_custom_fields_MySQL("article_customs", glz_get_article_id(), '', $arr_custom_fields);
  914. // DEBUG
  915. // dmp($arr_article_customs);
  916. if ( is_array($arr_article_customs) )
  917. extract($arr_article_customs);
  918. // let's see which custom fields are set
  919. foreach ( $arr_custom_fields as $custom => $custom_set ) {
  920. // get all possible/default value(s) for this custom set from custom_fields table
  921. $arr_custom_field_values = glz_custom_fields_MySQL("values", $custom, '', array('custom_set_name' => $custom_set['name']));
  922. // DEBUG
  923. // dmp($arr_custom_field_values);
  924. //custom_set formatted for id e.g. custom_1_set => custom-1 - don't ask...
  925. $custom_id = glz_custom_number($custom, "-");
  926. //custom_set without "_set" e.g. custom_1_set => custom_1
  927. $custom = glz_custom_number($custom);
  928. // if current article holds no value for this custom field and we have no default value, make it empty
  929. $custom_value = (!empty($$custom) ? $$custom : '');
  930. // DEBUG
  931. // dmp("custom_value: {$custom_value}");
  932. // check if there is a default value
  933. // if there is, strip the { }
  934. $default_value = glz_return_clean_default(glz_default_value($arr_custom_field_values));
  935. // DEBUG
  936. // dmp("default_value: {$default_value}");
  937. // now that we've found our default, we need to clean our custom_field values
  938. if (is_array($arr_custom_field_values))
  939. array_walk($arr_custom_field_values, "glz_clean_default_array_values");
  940. // DEBUG
  941. // dmp($arr_custom_field_values);
  942. // the way our custom field value is going to look like
  943. list($custom_set_value, $custom_class) = glz_format_custom_set_by_type($custom, $custom_id, $custom_set['type'], $arr_custom_field_values, $custom_value, $default_value);
  944. // DEBUG
  945. // dmp($custom_set_value);
  946. $out .= graf(
  947. "<label for=\"$custom_id\">{$custom_set['name']}</label><br />$custom_set_value", " class=\"$custom_class\""
  948. );
  949. }
  950. }
  951. // DEBUG
  952. // dmp($out);
  953. // if we're writing textarea custom fields, we need to include the excerpt as well
  954. if ($step == "body") {
  955. $out = $data.$out;
  956. }
  957. return $out;
  958. }
  959. // -------------------------------------------------------------
  960. // prep our custom fields for the db (watch out for multi-selects, checkboxes & radios, they might have multiple values)
  961. function glz_custom_fields_before_save() {
  962. // keep only the custom fields
  963. foreach ($_POST as $key => $value) {
  964. //check for custom fields with multiple values e.g. arrays
  965. if ( strstr($key, 'custom_') && is_array($value) ) {
  966. $value = implode($value, '|');
  967. // feed our custom fields back into the $_POST
  968. $_POST[$key] = $value;
  969. }
  970. }
  971. // DEBUG
  972. // dmp($_POST);
  973. }
  974. // -------------------------------------------------------------
  975. // adds the css & js we need
  976. function glz_custom_fields_css_js() {
  977. global $glz_notice, $date_picker, $time_picker, $prefs;
  978. // here come our custom stylesheetz
  979. $css = '<link rel="stylesheet" type="text/css" media="all" href="//'.$prefs['siteurl'].'/plugins/glz_custom_fields/glz_custom_fields.css">'.n;
  980. // and here come our javascriptz
  981. $js = '';
  982. if ( $date_picker ) {
  983. $css .= '<link rel="stylesheet" type="text/css" media="all" href="'.$prefs['datepicker_url'].'/datePicker.css" />'.n;
  984. foreach (array('date.js', 'datePicker.js') as $file) {
  985. $js .= '<script type="text/javascript" src="'.$prefs['datepicker_url']."/".$file.'"></script>'.n;
  986. }
  987. $js .= <<<EOF
  988. <script type="text/javascript">
  989. $(function() {
  990. if ($(".date-picker").length > 0) {
  991. try {
  992. Date.firstDayOfWeek = {$prefs['datepicker_first_day']};
  993. Date.format = '{$prefs['datepicker_format']}';
  994. Date.fullYearStart = '19';
  995. $(".date-picker").datePicker({startDate:'{$prefs['datepicker_start_date']}'});
  996. } catch(err) {
  997. $('#messagepane').html('<a href="//{$prefs['siteurl']}/textpattern/?event=plugin_prefs.glz_custom_fields">Fix the DatePicker jQuery plugin</a>');
  998. }
  999. }
  1000. });
  1001. </script>
  1002. EOF;
  1003. }
  1004. if ( $time_picker ) {
  1005. $css .= '<link rel="stylesheet" type="text/css" media="all" href="'.$prefs['timepicker_url'].'/timePicker.css" />'.n;
  1006. $js .= '<script type="text/javascript" src="'.$prefs['timepicker_url'].'/timePicker.js"></script>'.n;
  1007. $js .= <<<EOF
  1008. <script type="text/javascript">
  1009. $(function() {
  1010. if ($(".time-picker").length > 0) {
  1011. try {
  1012. $(".time-picker").timePicker({
  1013. startTime:'{$prefs['timepicker_start_time']}',
  1014. endTime: '{$prefs['timepicker_end_time']}',
  1015. step: {$prefs['timepicker_step']},
  1016. show24Hours: {$prefs['timepicker_show_24']}
  1017. });
  1018. } catch(err) {
  1019. $('#messagepane').html('<a href="//{$prefs['siteurl']}/textpattern/?event=plugin_prefs.glz_custom_fields">Fix the TimePicker jQuery plugin</a>');
  1020. }
  1021. }
  1022. });
  1023. </script>
  1024. EOF;
  1025. }
  1026. $js .= '<script type="text/javascript" src="//'.$prefs['siteurl'].'/plugins/glz_custom_fields/glz_custom_fields.js"></script>';
  1027. // displays the notices we have gathered throughout the entire plugin
  1028. if ( count($glz_notice) > 0 ) {
  1029. // let's turn our notices into a string
  1030. $glz_notice = join("<br />", array_unique($glz_notice));
  1031. $js .= '<script type="text/javascript">
  1032. <!--//--><![CDATA[//><!--
  1033. $(document).ready(function() {
  1034. // add our notices
  1035. $("#messagepane").html(\''.$glz_notice.'\');
  1036. });
  1037. //--><!]]>
  1038. </script>';
  1039. }
  1040. echo $js.n.t.$css.n.t;
  1041. }
  1042. // -------------------------------------------------------------
  1043. // we are setting up the pre-requisite values for glz_custom_fields
  1044. function before_glz_custom_fields() {
  1045. // we will be reusing these globals across the whole plugin
  1046. global $all_custom_sets, $glz_notice, $prefs, $date_picker, $time_picker;
  1047. // glz_notice collects all plugin notices
  1048. $glz_notice = array();
  1049. // let's get all custom field sets from prefs
  1050. $all_custom_sets = glz_custom_fields_MySQL("all");
  1051. // let's see if we have a date-picker custom field (first of the special ones)
  1052. $date_picker = glz_custom_fields_MySQL("custom_set_exists", "date-picker");
  1053. // let's see if we have a time-picker custom field
  1054. $time_picker = glz_custom_fields_MySQL("custom_set_exists", "time-picker");
  1055. }
  1056. // -------------------------------------------------------------
  1057. // bootstrapping routines, run through plugin_lifecycle
  1058. function glz_custom_fields_install() {
  1059. global $all_custom_sets, $glz_notice, $prefs;
  1060. // default custom fields are set to custom_set
  1061. // need to change this because it confuses our set_types()
  1062. safe_query("
  1063. UPDATE
  1064. `".PFX."txp_prefs`
  1065. SET
  1066. `html` = 'text_input'
  1067. WHERE
  1068. `event` = 'custom'
  1069. AND
  1070. `html` = 'custom_set'
  1071. ");
  1072. // set plugin preferences
  1073. $arr_plugin_preferences = array(
  1074. 'values_ordering' => "custom",
  1075. 'multiselect_size' => "5",
  1076. 'datepicker_url' => hu."plugins/glz_custom_fields/jquery.datePicker",
  1077. 'datepicker_format' => "dd/mm/yyyy",
  1078. 'datepicker_first_day' => 1,
  1079. 'datepicker_start_date' => "01/01/1990",
  1080. 'timepicker_url' => hu."plugins/glz_custom_fields/jquery.timePicker",
  1081. 'timepicker_start_time' => "00:00",
  1082. 'timepicker_end_time' => "23:30",
  1083. 'timepicker_step' => 30,
  1084. 'timepicker_show_24' => true,
  1085. 'custom_scripts_path' => $prefs['path_to_site']."/plugins/glz_custom_fields"
  1086. );
  1087. glz_custom_fields_MySQL("update_plugin_preferences", $arr_plugin_preferences);
  1088. // let's update plugin preferences, make sure they won't appear under Admin > Preferences
  1089. safe_query("
  1090. UPDATE
  1091. `".PFX."txp_prefs`
  1092. SET
  1093. `type` = '10'
  1094. WHERE
  1095. `event` = 'glz_custom_f'
  1096. ");
  1097. // if we don't have a search section, let's create it because we'll need it when searching by custom fields
  1098. if( !getRow("SELECT name FROM `".PFX."txp_section` WHERE name='search'") ) {
  1099. safe_query("
  1100. INSERT INTO
  1101. `".PFX."txp_section` (`name`, `page`, `css`, `in_rss`, `on_frontpage`, `searchable`, `title`)
  1102. VALUES
  1103. ('search', 'default', 'default', '0', '0', '0', 'Search')
  1104. ");
  1105. // add a notice that search section has bee created
  1106. $glz_notice[] = glz_custom_fields_gTxt("search_section_created");
  1107. }
  1108. // if we don't have the custom_fields table, let's create it
  1109. if ( !getRows("SHOW TABLES LIKE '".PFX."custom_fields'") ) {
  1110. safe_query("
  1111. CREATE TABLE `".PFX."custom_fields` (
  1112. `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  1113. `name` varchar(255) NOT NULL default '',
  1114. `value` varchar(255) NOT NULL default '',
  1115. PRIMARY KEY (id),
  1116. KEY (`name`)
  1117. ) ENGINE=MyISAM
  1118. ");
  1119. }
  1120. else {
  1121. // if there isn't and id column, add it
  1122. if ( !getRows("SHOW COLUMNS FROM ".PFX."custom_fields LIKE 'id'") ) {
  1123. safe_query("
  1124. ALTER TABLE `".PFX."custom_fields`
  1125. ADD `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT KEY
  1126. ");
  1127. }
  1128. // if we have definitely migrated using this function, skip everything
  1129. if ( isset($prefs['migrated']) )
  1130. return;
  1131. // abort the migration if there are values in custom_fields table, we don't want to overwrite anything
  1132. else if ( glz_custom_fields_MySQL('check_migration') > 0 ) {
  1133. // DEBUG
  1134. // dmp(glz_custom_fields_MySQL('check_migration'));
  1135. $glz_notice[] = glz_custom_fields_gTxt("migration_skip");
  1136. // make a note of this migration in txp_prefs
  1137. glz_custom_fields_MySQL('mark_migration');
  1138. return;
  1139. }
  1140. // go through all values in custom field columns in textpattern table one by one
  1141. foreach ($all_custom_sets as $custom => $custom_set) {
  1142. // check only for custom fields that have been set
  1143. if ( $custom_set['name'] ) {
  1144. // get all existing custom values for ALL articles
  1145. $all_values = glz_custom_fields_MySQL('all_values', glz_custom_number($custom), '', array('custom_set_name' => $custom_set['name'], 'status' => 0));
  1146. // if we have results, let's create SQL queries that will add them to custom_fields table
  1147. if ( count($all_values) > 0 ) {
  1148. // initialize insert
  1149. $insert = '';
  1150. foreach ( $all_values as $escaped_value => $value ) {
  1151. // don't insert empty values or values that are over 255 characters
  1152. // values over 255 characters hint to a textarea custom field
  1153. if ( !empty($escaped_value) && strlen($escaped_value) < 255 )
  1154. // if this is the last value, query will have to be different
  1155. $insert .= ( end($all_values) != $value ) ?
  1156. "('{$custom}','{$escaped_value}')," :
  1157. "('{$custom}','{$escaped_value}')";
  1158. }
  1159. $query = "
  1160. INSERT INTO
  1161. `".PFX."custom_fields` (`name`,`value`)
  1162. VALUES
  1163. {$insert}
  1164. ";
  1165. if ( isset($query) && !empty($query) ) {
  1166. // create all custom field values in custom_fields table
  1167. safe_query($query);
  1168. // update the type of this custom field to select (might want to make this user-adjustable at some point)
  1169. glz_custom_fields_MySQL("update", $custom, PFX."txp_prefs", array(
  1170. 'custom_set_name' => $custom_set['name'],
  1171. 'custom_set_type' => "select",
  1172. 'custom_set_position' => $custom_set['position']
  1173. ));
  1174. $glz_notice[] = glz_custom_fields_gTxt("migration_success");
  1175. }
  1176. }
  1177. }
  1178. }
  1179. // make a note of this migration in txp_prefs
  1180. glz_custom_fields_MySQL('mark_migration');
  1181. }
  1182. }
  1183. global $event;
  1184. // globals, expensive operations mostly
  1185. before_glz_custom_fields();
  1186. if (@txpinterface == "admin") {
  1187. // INSTALL ROUTINES
  1188. // checks if all tables exist and everything is setup properly
  1189. add_privs('glz_custom_fields_install', "1");
  1190. register_callback("glz_custom_fields_install", "plugin_lifecycle.glz_custom_fields", "installed");
  1191. // we'll be doing this only on the pages that we care about, not everywhere
  1192. if ( in_array($event, array("article", "prefs", "glz_custom_fields", "plugin_prefs.glz_custom_fields")) ) {
  1193. // we need some stylesheets & JS
  1194. add_privs('glz_custom_fields_css_js', "1,2,3,4,5,6");
  1195. register_callback('glz_custom_fields_css_js', "admin_side", 'head_end');
  1196. // we need to make sure that all custom field values will be converted to strings first - think checkboxes & multi-selects etc.
  1197. if ( (gps("step") == "edit") || (gps("step") == "create") ) {
  1198. add_privs('glz_custom_fields_before_save', "1,2,3,4,5,6");
  1199. register_callback('glz_custom_fields_before_save', "article", '', 1);
  1200. }
  1201. }
  1202. // Custom Fields tab under Extensions
  1203. add_privs('glz_custom_fields', "1,2");
  1204. register_tab("extensions", 'glz_custom_fields', "Custom Fields");
  1205. register_callback('glz_custom_fields', "glz_custom_fields");
  1206. // plugin preferences
  1207. add_privs('plugin_prefs.glz_custom_fields', "1,2");
  1208. register_callback('glz_custom_fields_preferences', 'plugin_prefs.glz_custom_fields');
  1209. // YES, finally the default custom fields are replaced by the new, pimped ones : )
  1210. add_privs('glz_custom_fields_replace', "1,2,3,4,5,6");
  1211. register_callback('glz_custom_fields_replace', 'article_ui', 'custom_fields');
  1212. // YES, now we have textarea custom fields as well ; )
  1213. register_callback('glz_custom_fields_replace', 'article_ui', 'body');
  1214. }
  1215. // -------------------------------------------------------------
  1216. // everything is happening in this function... generates the content for Extensions > Custom Fields
  1217. function glz_custom_fields() {
  1218. global $event, $all_custom_sets,

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