PageRenderTime 46ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/plugins/advanced-custom-fields/acf.php

https://bitbucket.org/JacobTyler/fame4good-wp
PHP | 1614 lines | 815 code | 378 blank | 421 comment | 82 complexity | ba074c1072de7b4559e4d51df63497d0 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-3.0, AGPL-1.0, LGPL-2.1, GPL-2.0
  1. <?php
  2. /*
  3. Plugin Name: Advanced Custom Fields
  4. Plugin URI: http://www.advancedcustomfields.com/
  5. Description: Fully customise WordPress edit screens with powerful fields. Boasting a professional interface and a powerfull API, itâ&#x20AC;&#x2122;s a must have for any web developer working with WordPress. Field types include: Wysiwyg, text, textarea, image, file, select, checkbox, page link, post object, date picker, color picker, repeater, flexible content, gallery and more!
  6. Version: 3.5.7.2
  7. Author: Elliot Condon
  8. Author URI: http://www.elliotcondon.com/
  9. License: GPL
  10. Copyright: Elliot Condon
  11. */
  12. include('core/api.php');
  13. $acf = new Acf();
  14. class Acf
  15. {
  16. var $dir,
  17. $path,
  18. $version,
  19. $upgrade_version,
  20. $fields,
  21. $cache,
  22. $defaults,
  23. // controllers
  24. $upgrade,
  25. $settings,
  26. $field_groups,
  27. $field_group,
  28. $input,
  29. $options_page,
  30. $everything_fields,
  31. $third_party,
  32. $location;
  33. /*
  34. * Constructor
  35. *
  36. * @description:
  37. * @since 1.0.0
  38. * @created: 23/06/12
  39. */
  40. function __construct()
  41. {
  42. // vars
  43. $this->path = plugin_dir_path(__FILE__);
  44. $this->dir = plugins_url('',__FILE__);
  45. $this->version = '3.5.7.2';
  46. $this->upgrade_version = '3.4.1'; // this is the latest version which requires an upgrade
  47. $this->cache = array(); // basic array cache to hold data throughout the page load
  48. $this->defaults = array(
  49. 'options_page' => array(
  50. 'capability' => 'edit_posts', // capability to view options page
  51. 'title' => __('Options','acf'), // title / menu name ('Site Options')
  52. 'pages' => array(), // an array of sub pages ('Header, Footer, Home, etc')
  53. ),
  54. 'activation_codes' => array(
  55. 'repeater' => '', // activation code for the repeater add-on (XXXX-XXXX-XXXX-XXXX)
  56. 'options_page' => '', // activation code for the options page add-on (XXXX-XXXX-XXXX-XXXX)
  57. 'flexible_content' => '', // activation code for the flexible content add-on (XXXX-XXXX-XXXX-XXXX)
  58. 'gallery' => '', // activation code for the gallery add-on (XXXX-XXXX-XXXX-XXXX)
  59. ),
  60. );
  61. // set text domain
  62. load_plugin_textdomain('acf', false, basename(dirname(__FILE__)).'/lang' );
  63. // controllers
  64. $this->setup_controllers();
  65. // actions
  66. add_action('init', array($this, 'init'));
  67. add_action('admin_menu', array($this,'admin_menu'));
  68. add_action('admin_head', array($this,'admin_head'));
  69. add_action('acf_save_post', array($this, 'acf_save_post'), 10); // save post, called from many places (api, input, everything, options)
  70. // filters
  71. add_filter('acf_load_field', array($this, 'acf_load_field'), 5);
  72. add_filter('post_updated_messages', array($this, 'post_updated_messages'));
  73. add_filter('acf_parse_value', array($this, 'acf_parse_value'));
  74. return true;
  75. }
  76. /*
  77. * Init
  78. *
  79. * @description:
  80. * @since 1.0.0
  81. * @created: 23/06/12
  82. */
  83. function init()
  84. {
  85. // setup defaults
  86. $this->defaults = apply_filters('acf_settings', $this->defaults);
  87. // allow for older filters
  88. $this->defaults['options_page']['title'] = apply_filters('acf_options_page_title', $this->defaults['options_page']['title']);
  89. // setup fields
  90. $this->setup_fields();
  91. // Create ACF post type
  92. $labels = array(
  93. 'name' => __( 'Field&nbsp;Groups', 'acf' ),
  94. 'singular_name' => __( 'Advanced Custom Fields', 'acf' ),
  95. 'add_new' => __( 'Add New' , 'acf' ),
  96. 'add_new_item' => __( 'Add New Field Group' , 'acf' ),
  97. 'edit_item' => __( 'Edit Field Group' , 'acf' ),
  98. 'new_item' => __( 'New Field Group' , 'acf' ),
  99. 'view_item' => __('View Field Group', 'acf'),
  100. 'search_items' => __('Search Field Groups', 'acf'),
  101. 'not_found' => __('No Field Groups found', 'acf'),
  102. 'not_found_in_trash' => __('No Field Groups found in Trash', 'acf'),
  103. );
  104. register_post_type('acf', array(
  105. 'labels' => $labels,
  106. 'public' => false,
  107. 'show_ui' => true,
  108. '_builtin' => false,
  109. 'capability_type' => 'page',
  110. 'hierarchical' => true,
  111. 'rewrite' => false,
  112. 'query_var' => "acf",
  113. 'supports' => array(
  114. 'title',
  115. ),
  116. 'show_in_menu' => false,
  117. ));
  118. // register acf scripts
  119. $scripts = array(
  120. 'acf-fields' => $this->dir . '/js/fields.js',
  121. 'acf-input-actions' => $this->dir . '/js/input-actions.js',
  122. 'acf-input-ajax' => $this->dir . '/js/input-ajax.js',
  123. 'acf-datepicker' => $this->dir . '/core/fields/date_picker/jquery.ui.datepicker.js',
  124. );
  125. foreach( $scripts as $k => $v )
  126. {
  127. wp_register_script( $k, $v, array('jquery'), $this->version );
  128. }
  129. // register acf styles
  130. $styles = array(
  131. 'acf' => $this->dir . '/css/acf.css',
  132. 'acf-fields' => $this->dir . '/css/fields.css',
  133. 'acf-global' => $this->dir . '/css/global.css',
  134. 'acf-input' => $this->dir . '/css/input.css',
  135. 'acf-datepicker' => $this->dir . '/core/fields/date_picker/style.date_picker.css',
  136. );
  137. foreach( $styles as $k => $v )
  138. {
  139. wp_register_style( $k, $v, false, $this->version );
  140. }
  141. }
  142. /*
  143. * get_cache
  144. *
  145. * @description: Simple ACF (once per page) cache
  146. * @since 3.1.9
  147. * @created: 23/06/12
  148. */
  149. function get_cache($key = false)
  150. {
  151. // key is required
  152. if( !$key )
  153. return false;
  154. // does cache at key exist?
  155. if( !isset($this->cache[$key]) )
  156. return false;
  157. // return cahced item
  158. return $this->cache[$key];
  159. }
  160. /*
  161. * set_cache
  162. *
  163. * @description: Simple ACF (once per page) cache
  164. * @since 3.1.9
  165. * @created: 23/06/12
  166. */
  167. function set_cache($key = false, $value = null)
  168. {
  169. // key is required
  170. if( !$key )
  171. return false;
  172. // update the cache array
  173. $this->cache[$key] = $value;
  174. // return true. Probably not needed
  175. return true;
  176. }
  177. /*
  178. * setup_fields
  179. *
  180. * @description: Create an array of field objects, including custom registered field types
  181. * @since 1.0.0
  182. * @created: 23/06/12
  183. */
  184. function setup_fields()
  185. {
  186. // include parent field
  187. include_once('core/fields/acf_field.php');
  188. // include child fields
  189. include_once('core/fields/acf_field.php');
  190. include_once('core/fields/tab.php');
  191. include_once('core/fields/text.php');
  192. include_once('core/fields/textarea.php');
  193. include_once('core/fields/wysiwyg.php');
  194. include_once('core/fields/image.php');
  195. include_once('core/fields/file.php');
  196. include_once('core/fields/number.php');
  197. include_once('core/fields/select.php');
  198. include_once('core/fields/checkbox.php');
  199. include_once('core/fields/radio.php');
  200. include_once('core/fields/true_false.php');
  201. include_once('core/fields/page_link.php');
  202. include_once('core/fields/post_object.php');
  203. include_once('core/fields/relationship.php');
  204. include_once('core/fields/date_picker/date_picker.php');
  205. include_once('core/fields/color_picker.php');
  206. // add child fields
  207. $this->fields['none'] = new acf_Field($this);
  208. $this->fields['tab'] = new acf_Tab($this);
  209. $this->fields['text'] = new acf_Text($this);
  210. $this->fields['textarea'] = new acf_Textarea($this);
  211. $this->fields['wysiwyg'] = new acf_Wysiwyg($this);
  212. $this->fields['image'] = new acf_Image($this);
  213. $this->fields['file'] = new acf_File($this);
  214. $this->fields['number'] = new acf_Number($this);
  215. $this->fields['select'] = new acf_Select($this);
  216. $this->fields['checkbox'] = new acf_Checkbox($this);
  217. $this->fields['radio'] = new acf_Radio($this);
  218. $this->fields['true_false'] = new acf_True_false($this);
  219. $this->fields['page_link'] = new acf_Page_link($this);
  220. $this->fields['post_object'] = new acf_Post_object($this);
  221. $this->fields['relationship'] = new acf_Relationship($this);
  222. $this->fields['date_picker'] = new acf_Date_picker($this);
  223. $this->fields['color_picker'] = new acf_Color_picker($this);
  224. // add repeater
  225. if($this->is_field_unlocked('repeater'))
  226. {
  227. include_once('core/fields/repeater.php');
  228. $this->fields['repeater'] = new acf_Repeater($this);
  229. }
  230. // add flexible content
  231. if($this->is_field_unlocked('flexible_content'))
  232. {
  233. include_once('core/fields/flexible_content.php');
  234. $this->fields['flexible_content'] = new acf_Flexible_content($this);
  235. }
  236. // add gallery
  237. if($this->is_field_unlocked('gallery'))
  238. {
  239. include_once('core/fields/gallery.php');
  240. $this->fields['gallery'] = new acf_Gallery($this);
  241. }
  242. // hook to load in third party fields
  243. $custom = apply_filters('acf_register_field',array());
  244. if(!empty($custom))
  245. {
  246. foreach($custom as $v)
  247. {
  248. //var_dump($v['url']);
  249. include($v['url']);
  250. $name = $v['class'];
  251. $custom_field = new $name($this);
  252. $this->fields[$custom_field->name] = $custom_field;
  253. }
  254. }
  255. }
  256. /*
  257. * setup_fields
  258. *
  259. * @description:
  260. * @since 3.2.6
  261. * @created: 23/06/12
  262. */
  263. function setup_controllers()
  264. {
  265. // Settings
  266. include_once('core/controllers/settings.php');
  267. $this->settings = new acf_settings($this);
  268. // upgrade
  269. include_once('core/controllers/upgrade.php');
  270. $this->upgrade = new acf_upgrade($this);
  271. // field_groups
  272. include_once('core/controllers/field_groups.php');
  273. $this->field_groups = new acf_field_groups($this);
  274. // field_group
  275. include_once('core/controllers/field_group.php');
  276. $this->field_group = new acf_field_group($this);
  277. // input
  278. include_once('core/controllers/input.php');
  279. $this->input = new acf_input($this);
  280. // options page
  281. include_once('core/controllers/options_page.php');
  282. $this->options_page = new acf_options_page($this);
  283. // everthing fields
  284. include_once('core/controllers/everything_fields.php');
  285. $this->everything_fields = new acf_everything_fields($this);
  286. // Third Party Compatibility
  287. include_once('core/controllers/third_party.php');
  288. $this->third_party = new acf_third_party($this);
  289. // Location
  290. include_once('core/controllers/location.php');
  291. $this->location = new acf_location($this);
  292. }
  293. /*
  294. * admin_menu
  295. *
  296. * @description:
  297. * @since 1.0.0
  298. * @created: 23/06/12
  299. */
  300. function admin_menu() {
  301. // add acf page to options menu
  302. add_utility_page(__("Custom Fields",'acf'), __("Custom Fields",'acf'), 'manage_options', 'edit.php?post_type=acf');
  303. }
  304. /*
  305. * post_updated_messages
  306. *
  307. * @description: messages for saving a field group
  308. * @since 1.0.0
  309. * @created: 23/06/12
  310. */
  311. function post_updated_messages( $messages )
  312. {
  313. global $post, $post_ID;
  314. $messages['acf'] = array(
  315. 0 => '', // Unused. Messages start at index 1.
  316. 1 => __('Field group updated.', 'acf'),
  317. 2 => __('Custom field updated.', 'acf'),
  318. 3 => __('Custom field deleted.', 'acf'),
  319. 4 => __('Field group updated.', 'acf'),
  320. /* translators: %s: date and time of the revision */
  321. 5 => isset($_GET['revision']) ? sprintf( __('Field group restored to revision from %s', 'acf'), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
  322. 6 => __('Field group published.', 'acf'),
  323. 7 => __('Field group saved.', 'acf'),
  324. 8 => __('Field group submitted.', 'acf'),
  325. 9 => __('Field group scheduled for.', 'acf'),
  326. 10 => __('Field group draft updated.', 'acf'),
  327. );
  328. return $messages;
  329. }
  330. /*--------------------------------------------------------------------------------------
  331. *
  332. * admin_head
  333. *
  334. * @author Elliot Condon
  335. * @since 1.0.0
  336. *
  337. *-------------------------------------------------------------------------------------*/
  338. function admin_head()
  339. {
  340. // hide upgrade page from nav
  341. echo '<style type="text/css">
  342. #adminmenu #toplevel_page_edit-post_type-acf a[href="edit.php?post_type=acf&page=acf-upgrade"]{ display:none; }
  343. #adminmenu #toplevel_page_edit-post_type-acf .wp-menu-image { background-position: 1px -33px; }
  344. #adminmenu #toplevel_page_edit-post_type-acf:hover .wp-menu-image,
  345. #adminmenu #toplevel_page_edit-post_type-acf.wp-menu-open .wp-menu-image { background-position: 1px -1px; }
  346. </style>';
  347. }
  348. /*--------------------------------------------------------------------------------------
  349. *
  350. * get_field_groups
  351. *
  352. * This function returns an array of post objects found in the get_posts and the
  353. * register_field_group calls.
  354. *
  355. * @author Elliot Condon
  356. * @since 3.0.6
  357. *
  358. *-------------------------------------------------------------------------------------*/
  359. function get_field_groups()
  360. {
  361. // return cache
  362. $cache = $this->get_cache('acf_field_groups');
  363. if($cache != false)
  364. {
  365. return $cache;
  366. }
  367. // vars
  368. $acfs = array();
  369. // get acf's
  370. $result = get_posts(array(
  371. 'numberposts' => -1,
  372. 'post_type' => 'acf',
  373. 'orderby' => 'menu_order title',
  374. 'order' => 'asc',
  375. 'suppress_filters' => false,
  376. ));
  377. // populate acfs
  378. if($result)
  379. {
  380. foreach($result as $acf)
  381. {
  382. $acfs[] = array(
  383. 'id' => $acf->ID,
  384. 'title' => get_the_title($acf->ID),
  385. 'fields' => $this->get_acf_fields($acf->ID),
  386. 'location' => $this->get_acf_location($acf->ID),
  387. 'options' => $this->get_acf_options($acf->ID),
  388. 'menu_order' => $acf->menu_order,
  389. );
  390. }
  391. }
  392. // hook to load in registered field groups
  393. $acfs = apply_filters('acf_register_field_group', $acfs);
  394. // update cache
  395. $this->set_cache('acf_field_groups', $acfs);
  396. // return
  397. if(empty($acfs))
  398. {
  399. return false;
  400. }
  401. return $acfs;
  402. }
  403. /*--------------------------------------------------------------------------------------
  404. *
  405. * get_acf_fields
  406. * - returns an array of fields for a acf object
  407. *
  408. * @author Elliot Condon
  409. * @since 1.0.0
  410. *
  411. *-------------------------------------------------------------------------------------*/
  412. function get_acf_fields($post_id)
  413. {
  414. // vars
  415. global $wpdb;
  416. $return = array();
  417. // get field from postmeta
  418. $rows = $wpdb->get_results( $wpdb->prepare("SELECT meta_key FROM $wpdb->postmeta WHERE post_id = %d AND meta_key LIKE %s", $post_id, 'field\_%'), ARRAY_A);
  419. if( $rows )
  420. {
  421. foreach( $rows as $row )
  422. {
  423. $field = $this->get_acf_field( $row['meta_key'], $post_id );
  424. $return[ $field['order_no'] ] = $field;
  425. }
  426. ksort($return);
  427. }
  428. // return
  429. return $return;
  430. }
  431. /*--------------------------------------------------------------------------------------
  432. *
  433. * get_acf_field
  434. * - returns a field
  435. * - $post_id can be passed to make sure the correct field is loaded. Eg: a duplicated
  436. * field group may have the same field_key, but a different post_id
  437. *
  438. * @author Elliot Condon
  439. * @since 1.0.0
  440. *
  441. *-------------------------------------------------------------------------------------*/
  442. function get_acf_field( $field_key, $post_id = false )
  443. {
  444. // return cache
  445. $cache = $this->get_cache('acf_field_' . $field_key);
  446. if($cache != false)
  447. {
  448. return $cache;
  449. }
  450. // vars
  451. global $wpdb;
  452. // get field from postmeta
  453. $sql = $wpdb->prepare("SELECT post_id, meta_value FROM $wpdb->postmeta WHERE meta_key = %s", $field_key);
  454. if( $post_id )
  455. {
  456. $sql .= $wpdb->prepare("AND post_id = %d", $post_id);
  457. }
  458. $row = $wpdb->get_results( $sql, ARRAY_A );
  459. if( $row )
  460. {
  461. $row = $row[0];
  462. // return field if it is not in a trashed field group
  463. if( get_post_status( $row['post_id'] ) != "trash" )
  464. {
  465. $row['meta_value'] = maybe_unserialize( $row['meta_value'] );
  466. $row['meta_value'] = maybe_unserialize( $row['meta_value'] ); // run again for WPML
  467. // store field
  468. $field = $row['meta_value'];
  469. // apply filters
  470. $field = apply_filters('acf_load_field', $field);
  471. $keys = array('type', 'name', 'key');
  472. foreach( $keys as $key )
  473. {
  474. if( isset($field[ $key ]) )
  475. {
  476. $value = apply_filters('acf_load_field-' . $field[ $key ], $field);
  477. }
  478. }
  479. // set cache
  480. $this->set_cache('acf_field_' . $field_key, $field);
  481. return $field;
  482. }
  483. }
  484. // hook to load in registered field groups
  485. $acfs = $this->get_field_groups();
  486. if($acfs)
  487. {
  488. // loop through acfs
  489. foreach($acfs as $acf)
  490. {
  491. // loop through fields
  492. if($acf['fields'])
  493. {
  494. foreach($acf['fields'] as $field)
  495. {
  496. if($field['key'] == $field_key)
  497. {
  498. // apply filters
  499. $field = apply_filters('acf_load_field', $field);
  500. $keys = array('type', 'name', 'key');
  501. foreach( $keys as $key )
  502. {
  503. if( isset($field[ $key ]) )
  504. {
  505. $value = apply_filters('acf_load_field-' . $field[ $key ], $field);
  506. }
  507. }
  508. // set cache
  509. $this->set_cache('acf_field_' . $field_key, $field);
  510. return $field;
  511. }
  512. }
  513. }
  514. // if($acf['fields'])
  515. }
  516. // foreach($acfs as $acf)
  517. }
  518. // if($acfs)
  519. return null;
  520. }
  521. /*
  522. * acf_load_field
  523. *
  524. * @description:
  525. * @since 3.5.1
  526. * @created: 14/10/12
  527. */
  528. function acf_load_field( $field )
  529. {
  530. if( !is_array($field) )
  531. {
  532. return $field;
  533. }
  534. $defaults = array(
  535. 'key' => '',
  536. 'label' => '',
  537. 'name' => '',
  538. 'type' => 'text',
  539. 'order_no' => 1,
  540. 'instructions' => '',
  541. 'required' => 0,
  542. 'conditional_logic' => array(
  543. 'status' => 0,
  544. 'allorany' => 'all',
  545. 'rules' => 0
  546. ),
  547. );
  548. $field = array_merge($defaults, $field);
  549. // Parse Values
  550. $field = apply_filters( 'acf_parse_value', $field );
  551. // trim name
  552. $field['name'] = trim( $field['name'] );
  553. return $field;
  554. }
  555. /*
  556. * acf_parse_value
  557. *
  558. * @description:
  559. * @since: 2.0.4
  560. * @created: 9/12/12
  561. */
  562. function acf_parse_value( $value )
  563. {
  564. // is value another array?
  565. if( is_array($value) )
  566. {
  567. foreach( $value as $k => $v )
  568. {
  569. $value[ $k ] = apply_filters( 'acf_parse_value', $v );
  570. }
  571. }
  572. else
  573. {
  574. // numbers
  575. if( is_numeric($value) )
  576. {
  577. // float / int
  578. if( strpos($value,'.') !== false )
  579. {
  580. $value = floatval( $value );
  581. }
  582. else
  583. {
  584. $value = intval( $value );
  585. }
  586. }
  587. }
  588. // return
  589. return $value;
  590. }
  591. /*--------------------------------------------------------------------------------------
  592. *
  593. * create_field
  594. *
  595. * @author Elliot Condon
  596. * @since 1.0.0
  597. *
  598. *-------------------------------------------------------------------------------------*/
  599. function create_field($field)
  600. {
  601. if(!isset($this->fields[$field['type']]) || !is_object($this->fields[$field['type']]))
  602. {
  603. _e('Error: Field Type does not exist!','acf');
  604. return false;
  605. }
  606. // defaults - class
  607. if( ! isset($field['class']) )
  608. {
  609. $field['class'] = $field['type'];
  610. }
  611. // defaults - id
  612. if( ! isset($field['id']) )
  613. {
  614. $id = $field['name'];
  615. $id = str_replace('][', '_', $id);
  616. $id = str_replace('fields[', '', $id);
  617. $id = str_replace('[', '-', $id); // location rules (select) does'nt have "fields[" in it
  618. $id = str_replace(']', '', $id);
  619. $field['id'] = 'acf-' . $id;
  620. }
  621. $this->fields[ $field['type'] ]->create_field($field);
  622. // conditional logic
  623. // - isset is needed for the edit field group page where fields are created without many parameters
  624. if( isset($field['conditional_logic']['status']) && $field['conditional_logic']['status'] ):
  625. $join = ' && ';
  626. if( $field['conditional_logic']['allorany'] == "any" )
  627. {
  628. $join = ' || ';
  629. }
  630. ?>
  631. <script type="text/javascript">
  632. (function($){
  633. // create the conditional function
  634. $(document).live('acf/conditional_logic/<?php echo $field['key']; ?>', function(){
  635. var field = $('.field-<?php echo $field['key']; ?>');
  636. <?php
  637. $if = array();
  638. foreach( $field['conditional_logic']['rules'] as $rule )
  639. {
  640. $if[] = 'acf.conditional_logic.calculate({ field : "'. $field['key'] .'", toggle : "' . $rule['field'] . '", operator : "' . $rule['operator'] .'", value : "' . $rule['value'] . '"})' ;
  641. }
  642. ?>
  643. if(<?php echo implode( $join, $if ); ?>)
  644. {
  645. field.removeClass('acf-conditional_logic-hide').addClass('acf-conditional_logic-show');
  646. }
  647. else
  648. {
  649. field.removeClass('acf-conditional_logic-show').addClass('acf-conditional_logic-hide');
  650. }
  651. });
  652. // add change events to all fields
  653. <?php foreach( $field['conditional_logic']['rules'] as $rule ): ?>
  654. $('.field-<?php echo $rule['field']; ?> *[name]').live('change', function(){
  655. $(document).trigger('acf/conditional_logic/<?php echo $field['key']; ?>');
  656. });
  657. <?php endforeach; ?>
  658. $(document).live('acf/setup_fields', function(e, postbox){
  659. $(document).trigger('acf/conditional_logic/<?php echo $field['key']; ?>');
  660. });
  661. })(jQuery);
  662. </script>
  663. <?php
  664. endif;
  665. }
  666. /*--------------------------------------------------------------------------------------
  667. *
  668. * get_acf_location
  669. *
  670. * @author Elliot Condon
  671. * @since 1.0.0
  672. *
  673. *-------------------------------------------------------------------------------------*/
  674. function get_acf_location($post_id)
  675. {
  676. // defaults
  677. $return = array(
  678. 'rules' => array(),
  679. 'allorany' => 'all',
  680. );
  681. // vars
  682. $allorany = get_post_meta($post_id, 'allorany', true);
  683. if( $allorany )
  684. {
  685. $return['allorany'] = $allorany;
  686. }
  687. // get all fields
  688. $rules = get_post_meta($post_id, 'rule', false);
  689. if($rules)
  690. {
  691. foreach($rules as $rule)
  692. {
  693. // if field group was duplicated, it may now be a serialized string!
  694. $rule = maybe_unserialize($rule);
  695. $return['rules'][$rule['order_no']] = $rule;
  696. }
  697. }
  698. // sort
  699. ksort($return['rules']);
  700. // return fields
  701. return $return;
  702. }
  703. /*--------------------------------------------------------------------------------------
  704. *
  705. * get_acf_options
  706. *
  707. * @author Elliot Condon
  708. * @since 1.0.0
  709. *
  710. *-------------------------------------------------------------------------------------*/
  711. function get_acf_options($post_id)
  712. {
  713. // defaults
  714. $options = array(
  715. 'position' => 'normal',
  716. 'layout' => 'no_box',
  717. 'hide_on_screen' => array(),
  718. );
  719. // vars
  720. $position = get_post_meta($post_id, 'position', true);
  721. if( $position )
  722. {
  723. $options['position'] = $position;
  724. }
  725. $layout = get_post_meta($post_id, 'layout', true);
  726. if( $layout )
  727. {
  728. $options['layout'] = $layout;
  729. }
  730. $hide_on_screen = get_post_meta($post_id, 'hide_on_screen', true);
  731. if( $hide_on_screen )
  732. {
  733. $hide_on_screen = maybe_unserialize($hide_on_screen);
  734. $options['hide_on_screen'] = $hide_on_screen;
  735. }
  736. // return
  737. return $options;
  738. }
  739. /*--------------------------------------------------------------------------------------
  740. *
  741. * get_value
  742. *
  743. * @author Elliot Condon
  744. * @since 3.0.0
  745. *
  746. *-------------------------------------------------------------------------------------*/
  747. function get_value($post_id, $field)
  748. {
  749. if( empty($this->fields) )
  750. {
  751. $this->setup_fields();
  752. }
  753. if( !isset($field['type'], $this->fields[ $field['type'] ]) )
  754. {
  755. return false;
  756. }
  757. return $this->fields[$field['type']]->get_value($post_id, $field);
  758. }
  759. /*--------------------------------------------------------------------------------------
  760. *
  761. * get_value_for_api
  762. *
  763. * @author Elliot Condon
  764. * @since 3.0.0
  765. *
  766. *-------------------------------------------------------------------------------------*/
  767. function get_value_for_api($post_id, $field)
  768. {
  769. if( empty($this->fields) )
  770. {
  771. $this->setup_fields();
  772. }
  773. if( !isset($field['type'], $this->fields[ $field['type'] ]) )
  774. {
  775. return false;
  776. }
  777. return $this->fields[$field['type']]->get_value_for_api($post_id, $field);
  778. }
  779. /*--------------------------------------------------------------------------------------
  780. *
  781. * update_value
  782. *
  783. * @author Elliot Condon
  784. * @since 3.0.0
  785. *
  786. *-------------------------------------------------------------------------------------*/
  787. function update_value($post_id, $field, $value)
  788. {
  789. if( isset($field['type'], $this->fields[ $field['type'] ]) )
  790. {
  791. $this->fields[$field['type']]->update_value($post_id, $field, $value);
  792. }
  793. }
  794. /*--------------------------------------------------------------------------------------
  795. *
  796. * update_field
  797. *
  798. * @author Elliot Condon
  799. * @since 3.0.0
  800. *
  801. *-------------------------------------------------------------------------------------*/
  802. function update_field($post_id, $field)
  803. {
  804. // apply filters
  805. $field = apply_filters('acf_save_field', $field );
  806. $field = apply_filters('acf_save_field-' . $field['type'], $field );
  807. // save
  808. update_post_meta($post_id, $field['key'], $field);
  809. }
  810. /*--------------------------------------------------------------------------------------
  811. *
  812. * format_value_for_api
  813. *
  814. * @author Elliot Condon
  815. * @since 3.0.0
  816. *
  817. *-------------------------------------------------------------------------------------*/
  818. function format_value_for_api($value, $field)
  819. {
  820. return $this->fields[$field['type']]->format_value_for_api($value, $field);
  821. }
  822. /*--------------------------------------------------------------------------------------
  823. *
  824. * create_format_data
  825. *
  826. * @author Elliot Condon
  827. * @since 3.0.0
  828. *
  829. *-------------------------------------------------------------------------------------*/
  830. function create_format_data($field)
  831. {
  832. return $this->fields[$field['type']]->create_format_data($field);
  833. }
  834. /*
  835. * render_fields_for_input
  836. *
  837. * @description:
  838. * @since 3.1.6
  839. * @created: 23/06/12
  840. */
  841. function render_fields_for_input($fields, $post_id)
  842. {
  843. // create fields
  844. if($fields)
  845. {
  846. foreach($fields as $field)
  847. {
  848. // if they didn't select a type, skip this field
  849. if(!$field['type'] || $field['type'] == 'null') continue;
  850. // set value
  851. if( ! isset($field['value']) )
  852. {
  853. $field['value'] = $this->get_value($post_id, $field);
  854. }
  855. $required_class = "";
  856. $required_label = "";
  857. if( $field['required'] )
  858. {
  859. $required_class = ' required';
  860. $required_label = ' <span class="required">*</span>';
  861. }
  862. echo '<div id="acf-' . $field['name'] . '" class="field field-' . $field['type'] . ' field-' . $field['key'] . $required_class . '" data-field_name="' . $field['name'] . '" data-field_key="' . $field['key'] . '">';
  863. echo '<p class="label">';
  864. echo '<label for="fields[' . $field['key'] . ']">' . $field['label'] . $required_label . '</label>';
  865. echo $field['instructions'];
  866. echo '</p>';
  867. $field['name'] = 'fields[' . $field['key'] . ']';
  868. $this->create_field($field);
  869. echo '</div>';
  870. }
  871. // foreach($fields as $field)
  872. }
  873. // if($fields)
  874. }
  875. /*--------------------------------------------------------------------------------------
  876. *
  877. * get_input_metabox_ids
  878. * - called by function.fields to hide / show metaboxes
  879. *
  880. * @author Elliot Condon
  881. * @since 2.0.5
  882. *
  883. *-------------------------------------------------------------------------------------*/
  884. function get_input_metabox_ids( $options = array() )
  885. {
  886. // vars
  887. $defaults = array(
  888. 'post_id' => 0,
  889. 'post_type' => 0,
  890. 'page_template' => 0,
  891. 'page_parent' => 0,
  892. 'page_type' => 0,
  893. 'page' => 0,
  894. 'post' => 0,
  895. 'post_category' => 0,
  896. 'post_format' => 0,
  897. 'taxonomy' => 0,
  898. 'lang' => 0,
  899. 'return' => 'php'
  900. );
  901. // merge in $options
  902. $options = array_merge($defaults, $options);
  903. // merge in $_POST
  904. if( isset($_POST) )
  905. {
  906. $options = array_merge($options, $_POST);
  907. }
  908. // Parse values
  909. $options = apply_filters( 'acf_parse_value', $options );
  910. // WPML
  911. if( $options['lang'] )
  912. {
  913. global $sitepress;
  914. $sitepress->switch_lang( $options['lang'] );
  915. }
  916. // find all acf objects
  917. $acfs = $this->get_field_groups();
  918. // blank array to hold acfs
  919. $return = array();
  920. if( $acfs )
  921. {
  922. foreach( $acfs as $acf )
  923. {
  924. // vars
  925. $add_box = false;
  926. // if all of the rules are required to match, start at true and let any !$match set $add_box to false
  927. if( $acf['location']['allorany'] == 'all' )
  928. {
  929. $add_box = true;
  930. }
  931. if( $acf['location']['rules'] )
  932. {
  933. // defaults
  934. $rule_defaults = array(
  935. 'param' => '',
  936. 'operator' => '==',
  937. 'value' => ''
  938. );
  939. foreach($acf['location']['rules'] as $rule)
  940. {
  941. // make sure rule has all 3 keys
  942. $rule = array_merge( $rule_defaults, $rule );
  943. // $match = true / false
  944. $match = false;
  945. $match = apply_filters( 'acf/location_rules/match/' . $rule['param'] , $match, $rule, $options );
  946. if( $acf['location']['allorany'] == 'all' && !$match )
  947. {
  948. // if all of the rules are required to match and this rule did not, don't add this box!
  949. $add_box = false;
  950. }
  951. elseif($acf['location']['allorany'] == 'any' && $match )
  952. {
  953. // if any of the rules are required to match and this rule did, add this box!
  954. $add_box = true;
  955. }
  956. }
  957. }
  958. // add ID to array
  959. if( $add_box )
  960. {
  961. $return[] = $acf['id'];
  962. }
  963. }
  964. }
  965. // if json
  966. if( $options['return'] == 'json' )
  967. {
  968. echo json_encode($return);
  969. die;
  970. }
  971. // not json, normal return
  972. return $return;
  973. }
  974. /*--------------------------------------------------------------------------------------
  975. *
  976. * is_field_unlocked
  977. *
  978. * @author Elliot Condon
  979. * @since 3.0.0
  980. *
  981. *-------------------------------------------------------------------------------------*/
  982. function is_field_unlocked($field_name)
  983. {
  984. $hashes = array(
  985. 'repeater' => 'bbefed143f1ec106ff3a11437bd73432',
  986. 'options_page' => '1fc8b993548891dc2b9a63ac057935d8',
  987. 'flexible_content' => 'd067e06c2b4b32b1c1f5b6f00e0d61d6',
  988. 'gallery' => '69f4adc9883195bd206a868ffa954b49',
  989. );
  990. $hash = md5( $this->get_license_key($field_name) );
  991. if( $hashes[$field_name] == $hash )
  992. {
  993. return true;
  994. }
  995. return false;
  996. }
  997. /*--------------------------------------------------------------------------------------
  998. *
  999. * is_field_unlocked
  1000. *
  1001. * @author Elliot Condon
  1002. * @since 3.0.0
  1003. *
  1004. *-------------------------------------------------------------------------------------*/
  1005. function get_license_key($field_name)
  1006. {
  1007. $value = '';
  1008. if( isset( $this->defaults['activation_codes'][ $field_name ] ) )
  1009. {
  1010. $value = $this->defaults['activation_codes'][ $field_name ];
  1011. }
  1012. if( !$value )
  1013. {
  1014. $value = get_option('acf_' . $field_name . '_ac');
  1015. }
  1016. return $value;
  1017. }
  1018. /*--------------------------------------------------------------------------------------
  1019. *
  1020. * admin_message
  1021. *
  1022. * @author Elliot Condon
  1023. * @since 2.0.5
  1024. *
  1025. *-------------------------------------------------------------------------------------*/
  1026. function admin_message($message = "", $type = 'updated')
  1027. {
  1028. $GLOBALS['acf_mesage'] = $message;
  1029. $GLOBALS['acf_mesage_type'] = $type;
  1030. add_action('admin_notices', array($this, 'acf_admin_notice'));
  1031. }
  1032. function acf_admin_notice()
  1033. {
  1034. echo '<div class="' . $GLOBALS['acf_mesage_type'] . '" id="message">'.$GLOBALS['acf_mesage'].'</div>';
  1035. }
  1036. /*--------------------------------------------------------------------------------------
  1037. *
  1038. * get_taxonomies_for_select
  1039. *
  1040. *---------------------------------------------------------------------------------------
  1041. *
  1042. * returns a multidimentional array of taxonomies grouped by the post type / taxonomy
  1043. *
  1044. * @author Elliot Condon
  1045. * @since 3.0.2
  1046. *
  1047. *-------------------------------------------------------------------------------------*/
  1048. function get_taxonomies_for_select( $args = array() )
  1049. {
  1050. // vars
  1051. $post_types = get_post_types();
  1052. $choices = array();
  1053. $defaults = array(
  1054. 'simple_value' => false,
  1055. );
  1056. $options = array_merge($defaults, $args);
  1057. if($post_types)
  1058. {
  1059. foreach($post_types as $post_type)
  1060. {
  1061. $post_type_object = get_post_type_object($post_type);
  1062. $taxonomies = get_object_taxonomies($post_type);
  1063. if($taxonomies)
  1064. {
  1065. foreach($taxonomies as $taxonomy)
  1066. {
  1067. if(!is_taxonomy_hierarchical($taxonomy)) continue;
  1068. $terms = get_terms($taxonomy, array('hide_empty' => false));
  1069. if($terms)
  1070. {
  1071. foreach($terms as $term)
  1072. {
  1073. $value = $taxonomy . ':' . $term->term_id;
  1074. if( $options['simple_value'] )
  1075. {
  1076. $value = $term->term_id;
  1077. }
  1078. $choices[$post_type_object->label . ': ' . $taxonomy][$value] = $term->name;
  1079. }
  1080. }
  1081. }
  1082. }
  1083. }
  1084. }
  1085. return $choices;
  1086. }
  1087. /*
  1088. * get_all_image_sizes
  1089. *
  1090. * @description: returns an array holding all the image sizes
  1091. * @since 3.2.8
  1092. * @created: 6/07/12
  1093. */
  1094. function get_all_image_sizes()
  1095. {
  1096. // find all sizes
  1097. $all_sizes = get_intermediate_image_sizes();
  1098. // define default sizes
  1099. $image_sizes = array(
  1100. 'thumbnail' => __("Thumbnail",'acf'),
  1101. 'medium' => __("Medium",'acf'),
  1102. 'large' => __("Large",'acf'),
  1103. 'full' => __("Full",'acf')
  1104. );
  1105. // add extra registered sizes
  1106. foreach($all_sizes as $size)
  1107. {
  1108. if (!isset($image_sizes[$size]))
  1109. {
  1110. $image_sizes[$size] = ucwords( str_replace('-', ' ', $size) );
  1111. }
  1112. }
  1113. // return array
  1114. return $image_sizes;
  1115. }
  1116. /*
  1117. * acf_save_post
  1118. *
  1119. * @description:
  1120. * @created: 4/09/12
  1121. */
  1122. function acf_save_post( $post_id )
  1123. {
  1124. // load from post
  1125. if( !isset($_POST['fields']) )
  1126. {
  1127. return false;
  1128. }
  1129. // loop through and save
  1130. if( $_POST['fields'] )
  1131. {
  1132. foreach( $_POST['fields'] as $key => $value )
  1133. {
  1134. // get field
  1135. $field = $this->get_acf_field($key);
  1136. $this->update_value($post_id, $field, $value);
  1137. }
  1138. // foreach($fields as $key => $value)
  1139. }
  1140. // if($fields)
  1141. return true;
  1142. }
  1143. /*
  1144. * get_post_language
  1145. *
  1146. * @description: finds the translation code for a post
  1147. * @since 3.3.9
  1148. * @created: 17/08/12
  1149. */
  1150. /*function get_post_language( $post )
  1151. {
  1152. // global
  1153. global $wpdb;
  1154. // vars
  1155. $table = $wpdb->prefix.'icl_translations';
  1156. $element_type = 'post_' . $post->post_type;
  1157. $element_id = $post->ID;
  1158. $lang = $wpdb->get_var("SELECT language_code FROM $table WHERE element_type = '$element_type' AND element_id = '$element_id'");
  1159. return ' (' . $lang . ')';
  1160. }*/
  1161. /*
  1162. * get_post_types
  1163. *
  1164. * @description:
  1165. * @since: 3.5.5
  1166. * @created: 16/12/12
  1167. */
  1168. function get_post_types( $exclude = array(), $include = array() )
  1169. {
  1170. // get all custom post types
  1171. $post_types = get_post_types();
  1172. // core include / exclude
  1173. $acf_includes = array_merge( array(), $include );
  1174. $acf_excludes = array_merge( array( 'acf', 'revision', 'nav_menu_item' ), $exclude );
  1175. // include
  1176. foreach( $acf_includes as $p )
  1177. {
  1178. if( post_type_exists($p) )
  1179. {
  1180. $post_types[ $p ] = $p;
  1181. }
  1182. }
  1183. // exclude
  1184. foreach( $acf_excludes as $p )
  1185. {
  1186. unset( $post_types[ $p ] );
  1187. }
  1188. return $post_types;
  1189. }
  1190. /*
  1191. * get_next_field_id
  1192. *
  1193. * @description:
  1194. * @since: 3.5.5
  1195. * @created: 31/12/12
  1196. */
  1197. function get_next_field_id()
  1198. {
  1199. // vars
  1200. global $wpdb;
  1201. $exists = true;
  1202. // get next id
  1203. $next_id = intval( get_option('acf_next_field_id', 1) );
  1204. // while doesnt exist
  1205. while( $exists == true )
  1206. {
  1207. // get field from postmeta
  1208. $row = $wpdb->get_row($wpdb->prepare(
  1209. "
  1210. SELECT meta_id
  1211. FROM $wpdb->postmeta
  1212. WHERE meta_key = %s
  1213. ",
  1214. 'field_' . $next_id
  1215. ), ARRAY_A );
  1216. // loop again or break through?
  1217. if( ! $row )
  1218. {
  1219. $exists = false;
  1220. }
  1221. else
  1222. {
  1223. $next_id++;
  1224. }
  1225. }
  1226. // update the acf_next_field_id
  1227. update_option('acf_next_field_id', ($next_id + 1) );
  1228. // return
  1229. return $next_id;
  1230. }
  1231. }
  1232. ?>