/lib/post.php

  1. <?php 
  2. /** 
  3. * License: GPLv3 
  4. * License URI: https://www.gnu.org/licenses/gpl.txt 
  5. * Copyright 2012-2017 Jean-Sebastien Morisset (https://surniaulula.com/) 
  6. */ 
  7.  
  8. if ( ! defined( 'ABSPATH' ) ) { 
  9. die( 'These aren\'t the droids you\'re looking for...' ); 
  10.  
  11. if ( ! class_exists( 'NgfbPost' ) ) { 
  12.  
  13. /** 
  14. * This class is extended by gpl/util/post.php or pro/util/post.php 
  15. * and the class object is created as $this->p->m['util']['post']. 
  16. */ 
  17. class NgfbPost extends NgfbMeta { 
  18.  
  19. public function __construct() { 
  20.  
  21. protected function add_actions() { 
  22.  
  23. if ( is_admin() ) { 
  24. if ( ! empty( $_GET ) || basename( $_SERVER['PHP_SELF'] ) === 'post-new.php' ) { 
  25. // load_meta_page() priorities: 100 post, 200 user, 300 term 
  26. // sets the NgfbMeta::$head_meta_tags and NgfbMeta::$head_meta_info class properties 
  27. add_action( 'current_screen', array( &$this, 'load_meta_page' ), 100, 1 ); 
  28. add_action( 'add_meta_boxes', array( &$this, 'add_metaboxes' ) ); 
  29.  
  30. add_action( 'save_post', array( &$this, 'save_options' ), NGFB_META_SAVE_PRIORITY ); 
  31. add_action( 'save_post', array( &$this, 'clear_cache' ), NGFB_META_CACHE_PRIORITY ); 
  32. add_action( 'edit_attachment', array( &$this, 'save_options' ), NGFB_META_SAVE_PRIORITY ); 
  33. add_action( 'edit_attachment', array( &$this, 'clear_cache' ), NGFB_META_CACHE_PRIORITY ); 
  34.  
  35. // add the columns when doing AJAX as well to allow Quick Edit to add the required columns 
  36. if ( is_admin() || SucomUtil::get_const( 'DOING_AJAX' ) ) { 
  37.  
  38. // only use public post types (to avoid menu items, product variations, etc.) 
  39. $post_type_names = $this->p->util->get_post_types( 'names' ); 
  40.  
  41. if ( is_array( $post_type_names ) ) { 
  42. foreach ( $post_type_names as $post_type ) { 
  43.  
  44. if ( $this->p->debug->enabled ) { 
  45. $this->p->debug->log( 'adding column filters for post type '.$post_type ); 
  46.  
  47. // https://codex.wordpress.org/Plugin_API/Filter_Reference/manage_$post_type_posts_columns 
  48. add_filter( 'manage_'.$post_type.'_posts_columns',  
  49. array( &$this, 'add_post_column_headings' ), NGFB_ADD_COLUMN_PRIORITY, 1 ); 
  50.  
  51. add_filter( 'manage_edit-'.$post_type.'_sortable_columns',  
  52. array( &$this, 'add_sortable_columns' ), 10, 1 ); 
  53.  
  54. // https://codex.wordpress.org/Plugin_API/Action_Reference/manage_$post_type_posts_custom_column 
  55. add_action( 'manage_'.$post_type.'_posts_custom_column',  
  56. array( &$this, 'show_column_content' ), 10, 2 ); 
  57.  
  58. if ( $this->p->debug->enabled ) { 
  59. $this->p->debug->log( 'adding column filters for media library' ); 
  60.  
  61. add_filter( 'manage_media_columns', array( &$this, 'add_media_column_headings' ), NGFB_ADD_COLUMN_PRIORITY, 1 ); 
  62. add_filter( 'manage_upload_sortable_columns', array( &$this, 'add_sortable_columns' ), 10, 1 ); 
  63. add_action( 'manage_media_custom_column', array( &$this, 'show_column_content' ), 10, 2 ); 
  64.  
  65. /** 
  66. * The 'parse_query' action is hooked ONCE in the NgfbPost class 
  67. * to set the column orderby for post, term, and user edit tables. 
  68. */ 
  69. add_action( 'parse_query', array( &$this, 'set_column_orderby' ), 10, 1 ); 
  70. add_action( 'get_post_metadata', array( &$this, 'check_sortable_metadata' ), 10, 4 ); 
  71.  
  72.  
  73. if ( ! empty( $this->p->options['plugin_shortlink'] ) ) { 
  74. if ( $this->p->debug->enabled ) { 
  75. $this->p->debug->log( 'adding get_shortlink filter' ); 
  76. // filters the shortlink for a post 
  77. add_filter( 'get_shortlink', array( &$this, 'get_shortlink' ), 9000, 4 ); 
  78.  
  79. if ( ! empty( $this->p->options['plugin_clear_for_comment'] ) ) { 
  80. if ( $this->p->debug->enabled ) { 
  81. $this->p->debug->log( 'adding clear cache for comment actions' ); 
  82. // fires when a comment is inserted into the database 
  83. add_action ( 'comment_post', array( &$this, 'clear_cache_for_new_comment' ), 10, 2 ); 
  84.  
  85. // fires before transitioning a comment's status from one to another 
  86. add_action ( 'wp_set_comment_status', array( &$this, 'clear_cache_for_comment_status' ), 10, 2 ); 
  87.  
  88. public function get_mod( $mod_id ) { 
  89. if ( $this->p->debug->enabled ) { 
  90. $this->p->debug->mark(); 
  91.  
  92. $mod = NgfbMeta::$mod_defaults; 
  93. $mod['id'] = (int) $mod_id; 
  94. $mod['name'] = 'post'; 
  95. $mod['obj'] =& $this; 
  96. /** 
  97. * Post 
  98. */ 
  99. $mod['is_post'] = true; 
  100. $mod['is_home_page'] = SucomUtil::is_home_page( $mod_id ); 
  101. $mod['is_home_index'] = $mod['is_home_page'] ? false : SucomUtil::is_home_index( $mod_id ); 
  102. $mod['is_home'] = $mod['is_home_page'] || $mod['is_home_index'] ? true : false; 
  103. $mod['post_type'] = get_post_type( $mod_id ); // post type name 
  104. $mod['post_status'] = get_post_status( $mod_id ); // post status name 
  105. $mod['post_author'] = (int) get_post_field( 'post_author', $mod_id ); // post author id 
  106.  
  107. // hooked by the 'coauthors' pro module 
  108. return apply_filters( $this->p->cf['lca'].'_get_post_mod', $mod, $mod_id ); 
  109.  
  110. public function get_posts( array $mod, $posts_per_page = false, $paged = false ) { 
  111. if ( $this->p->debug->enabled ) 
  112. $this->p->debug->mark(); 
  113.  
  114. $lca = $this->p->cf['lca']; 
  115.  
  116. if ( $posts_per_page === false ) 
  117. $posts_per_page = apply_filters( $lca.'_posts_per_page',  
  118. get_option( 'posts_per_page' ), $mod ); 
  119.  
  120. if ( $paged === false ) 
  121. $paged = get_query_var( 'paged' ); 
  122.  
  123. if ( ! $paged > 1 ) 
  124. $paged = 1; 
  125.  
  126. return get_posts( array( 
  127. 'posts_per_page' => $posts_per_page,  
  128. 'paged' => $paged,  
  129. 'post_status' => 'publish',  
  130. 'has_password' => false, // since wp 3.9 
  131. 'post_parent' => $mod['id'] ? $mod['id'] : null,  
  132. ) ); 
  133.  
  134. // filters the shortlink for a post 
  135. public function get_shortlink( $shortlink, $post_id, $context, $allow_slugs ) { 
  136.  
  137. if ( $this->p->debug->enabled ) { 
  138. $this->p->debug->log_args( array(  
  139. 'shortlink' => $shortlink,  
  140. 'post_id' => $post_id,  
  141. 'context' => $context,  
  142. 'allow_slugs' => $allow_slugs,  
  143. ) ); 
  144.  
  145. if ( isset( $this->p->options['plugin_shortener'] ) && 
  146. $this->p->options['plugin_shortener'] !== 'none' ) { 
  147.  
  148. $mod = $this->get_mod( $post_id ); 
  149.  
  150. if ( empty( $mod['post_type'] ) ) { 
  151. if ( $this->p->debug->enabled ) { 
  152. $this->p->debug->log( 'exiting early: post_type is empty' ); 
  153. return $shortlink; 
  154. } elseif ( empty( $mod['post_status'] ) ) { 
  155. if ( $this->p->debug->enabled ) { 
  156. $this->p->debug->log( 'exiting early: post_status is empty' ); 
  157. return $shortlink; 
  158. } elseif ( $mod['post_status'] === 'auto-draft' ) { 
  159. if ( $this->p->debug->enabled ) { 
  160. $this->p->debug->log( 'exiting early: post_status is auto-draft' ); 
  161. return $shortlink; 
  162.  
  163. $long_url = $this->p->util->get_sharing_url( $mod, false ); // $add_page = false 
  164. $short_url = apply_filters( $this->p->cf['lca'].'_shorten_url',  
  165. $long_url, $this->p->options['plugin_shortener'] ); 
  166.  
  167. if ( $long_url !== $short_url ) { // just in case 
  168. return $short_url; 
  169. } elseif ( $this->p->debug->enabled ) { 
  170. $this->p->debug->log( 'no shortener defined for shortlinks' ); 
  171.  
  172. return $shortlink; 
  173.  
  174. public function add_post_column_headings( $columns ) {  
  175. return $this->add_mod_column_headings( $columns, 'post' ); 
  176.  
  177. public function add_media_column_headings( $columns ) {  
  178. return $this->add_mod_column_headings( $columns, 'media' ); 
  179.  
  180. public function show_column_content( $column_name, $post_id ) { 
  181. echo $this->get_column_content( '', $column_name, $post_id ); 
  182.  
  183. public function get_column_content( $value, $column_name, $post_id ) { 
  184. $lca = $this->p->cf['lca']; 
  185. if ( ! empty( $post_id ) ) { // just in case 
  186. $col_idx = str_replace( $lca.'_', '', $column_name ); 
  187. if ( ( $col_info = self::get_sortable_columns( $col_idx ) ) !== null ) { 
  188. if ( isset( $col_info['meta_key'] ) ) { // just in case 
  189. $value = (string) get_post_meta( $post_id, $col_info['meta_key'], true ); // $single = true 
  190. if ( $value === 'none' ) { 
  191. $value = ''; 
  192. return $value; 
  193.  
  194. public function update_sortable_meta( $post_id, $col_idx, $content ) {  
  195. if ( ! empty( $post_id ) ) { // just in case 
  196. if ( ( $col_info = self::get_sortable_columns( $col_idx ) ) !== null ) { 
  197. if ( isset( $col_info['meta_key'] ) ) { // just in case 
  198. update_post_meta( $post_id, $col_info['meta_key'], $content ); 
  199.  
  200. public function check_sortable_metadata( $value, $post_id, $meta_key, $single ) { 
  201. $lca = $this->p->cf['lca']; 
  202. if ( strpos( $meta_key, '_'.$lca.'_head_info_' ) !== 0 ) // example: _ngfb_head_info_og_img_thumb 
  203. return $value; // return null 
  204.  
  205. static $checked_metadata = array(); 
  206. if ( isset( $checked_metadata[$post_id][$meta_key] ) ) 
  207. return $value; // return null 
  208. else $checked_metadata[$post_id][$meta_key] = true; // prevent recursion 
  209.  
  210. if ( get_post_meta( $post_id, $meta_key, true ) === '' ) { // returns empty string if meta not found 
  211. $mod = $this->get_mod( $post_id ); 
  212. $head_meta_tags = $this->p->head->get_head_array( $post_id, $mod, true ); // $read_cache = true 
  213. $head_meta_info = $this->p->head->extract_head_info( $mod, $head_meta_tags ); 
  214.  
  215. return $value; // return null 
  216.  
  217. // hooked into the current_screen action 
  218. // sets the NgfbMeta::$head_meta_tags and NgfbMeta::$head_meta_info class properties 
  219. public function load_meta_page( $screen = false ) { 
  220.  
  221. if ( $this->p->debug->enabled ) { 
  222. $this->p->debug->mark(); 
  223.  
  224. // all meta modules set this property, so use it to optimize code execution 
  225. if ( NgfbMeta::$head_meta_tags !== false || ! isset( $screen->id ) ) { 
  226. return; 
  227.  
  228. if ( $this->p->debug->enabled ) { 
  229. $this->p->debug->log( 'screen id: '.$screen->id ); 
  230.  
  231. switch ( $screen->id ) { 
  232. case 'upload': 
  233. case ( strpos( $screen->id, 'edit-' ) === 0 ? true : false ): // posts list table 
  234. return; 
  235.  
  236. $post_obj = SucomUtil::get_post_object( true ); 
  237. $post_id = empty( $post_obj->ID ) ? 0 : $post_obj->ID; 
  238.  
  239. // make sure we have at least a post type and status 
  240. if ( ! is_object( $post_obj ) ) { 
  241. if ( $this->p->debug->enabled ) { 
  242. $this->p->debug->log( 'exiting early: post_obj is not an object' ); 
  243. return; 
  244. } elseif ( empty( $post_obj->post_type ) ) { 
  245. if ( $this->p->debug->enabled ) { 
  246. $this->p->debug->log( 'exiting early: post_type is empty' ); 
  247. return; 
  248. } elseif ( empty( $post_obj->post_status ) ) { 
  249. if ( $this->p->debug->enabled ) { 
  250. $this->p->debug->log( 'exiting early: post_status is empty' ); 
  251. return; 
  252.  
  253. $lca = $this->p->cf['lca']; 
  254. $mod = $this->get_mod( $post_id ); 
  255.  
  256. if ( $this->p->debug->enabled ) { 
  257. $this->p->debug->log( 'home url = '.get_option( 'home' ) ); 
  258. $this->p->debug->log( 'locale default = '.SucomUtil::get_locale( 'default' ) ); 
  259. $this->p->debug->log( 'locale current = '.SucomUtil::get_locale( 'current' ) ); 
  260. $this->p->debug->log( 'locale mod = '.SucomUtil::get_locale( $mod ) ); 
  261. $this->p->debug->log( SucomDebug::pretty_array( $mod ) ); 
  262.  
  263. if ( $post_obj->post_status === 'auto-draft' ) { 
  264. if ( $this->p->debug->enabled ) { 
  265. $this->p->debug->log( 'head meta skipped: post_status is auto-draft' ); 
  266. NgfbMeta::$head_meta_tags = array(); 
  267. } else { 
  268. $add_metabox = empty( $this->p->options['plugin_add_to_'.$post_obj->post_type] ) ? false : true; 
  269.  
  270. if ( apply_filters( $lca.'_add_metabox_post', $add_metabox, $post_id, $post_obj->post_type ) ) { 
  271.  
  272. // hooked by woocommerce module to load front-end libraries and start a session 
  273. do_action( $lca.'_admin_post_head', $mod, $screen->id ); 
  274.  
  275. if ( $this->p->debug->enabled ) { 
  276. $this->p->debug->log( 'setting head_meta_info static property' ); 
  277.  
  278. // $read_cache is false to generate notices etc. 
  279. NgfbMeta::$head_meta_tags = $this->p->head->get_head_array( $post_id, $mod, false ); 
  280. NgfbMeta::$head_meta_info = $this->p->head->extract_head_info( $mod, NgfbMeta::$head_meta_tags ); 
  281.  
  282. if ( $post_obj->post_status === 'publish' ) { 
  283.  
  284. // check for missing open graph image and description values 
  285. foreach ( array( 'image', 'description' ) as $mt_suffix ) { 
  286. if ( empty( NgfbMeta::$head_meta_info['og:'.$mt_suffix] ) ) { 
  287. if ( $this->p->debug->enabled ) { 
  288. $this->p->debug->log( 'og:'.$mt_suffix.' meta tag is value empty and required' ); 
  289. if ( $this->p->notice->is_admin_pre_notices() ) { // skip if notices already shown 
  290. $this->p->notice->err( $this->p->msgs->get( 'notice-missing-og-'.$mt_suffix ) ); 
  291.  
  292. // check duplicates only when the post is available publicly and we have a valid permalink 
  293. if ( current_user_can( 'manage_options' ) ) { 
  294. if ( apply_filters( $lca.'_check_post_head',  
  295. $this->p->options['plugin_check_head'], $post_id, $post_obj ) ) { 
  296. $this->check_post_head_duplicates( $post_id, $post_obj ); 
  297. }  
  298.  
  299. $action_query = $lca.'-action'; 
  300. if ( ! empty( $_GET[$action_query] ) ) { 
  301. $action_name = SucomUtil::sanitize_hookname( $_GET[$action_query] ); 
  302. if ( $this->p->debug->enabled ) { 
  303. $this->p->debug->log( 'found action query: '.$action_name ); 
  304. if ( empty( $_GET[ NGFB_NONCE ] ) ) { // NGFB_NONCE is an md5() string 
  305. if ( $this->p->debug->enabled ) { 
  306. $this->p->debug->log( 'nonce token query field missing' ); 
  307. } elseif ( ! wp_verify_nonce( $_GET[ NGFB_NONCE ], NgfbAdmin::get_nonce() ) ) { 
  308. $this->p->notice->err( sprintf( __( 'Nonce token validation failed for %1$s action "%2$s".',  
  309. 'nextgen-facebook' ), 'post', $action_name ) ); 
  310. } else { 
  311. $_SERVER['REQUEST_URI'] = remove_query_arg( array( $action_query, NGFB_NONCE ) ); 
  312. switch ( $action_name ) { 
  313. default:  
  314. do_action( $lca.'_load_meta_page_post_'.$action_name, $post_id, $post_obj ); 
  315. break; 
  316.  
  317. public function check_post_head_duplicates( $post_id = true, $post_obj = false ) { 
  318.  
  319. if ( $this->p->debug->enabled ) { 
  320. $this->p->debug->mark(); 
  321.  
  322. $lca = $this->p->cf['lca']; 
  323.  
  324. if ( empty( $this->p->options['plugin_check_head'] ) ) { 
  325. if ( $this->p->debug->enabled ) { 
  326. $this->p->debug->mark( 'exiting early: plugin_check_head option is disabled'); 
  327. return $post_id; 
  328.  
  329. if ( ! apply_filters( $lca.'_add_meta_name_'.$lca.':mark', true ) ) { 
  330. if ( $this->p->debug->enabled ) { 
  331. $this->p->debug->mark( 'exiting early: '.$lca.':mark meta tags are disabled'); 
  332. return $post_id; 
  333.  
  334. if ( ! is_object( $post_obj ) && ( $post_obj = SucomUtil::get_post_object( $post_id ) ) === false ) { 
  335. if ( $this->p->debug->enabled ) { 
  336. $this->p->debug->mark( 'exiting early: unable to determine the post_id'); 
  337. return $post_id; 
  338.  
  339. // only check publicly available posts 
  340. if ( ! isset( $post_obj->post_status ) || $post_obj->post_status !== 'publish' ) { 
  341. if ( $this->p->debug->enabled ) { 
  342. $this->p->debug->mark( 'exiting early: post_status \''.$post_obj->post_status.'\' not published'); 
  343. return $post_id; 
  344.  
  345. // only check public post types (to avoid menu items, product variations, etc.) 
  346. $post_type_names = $this->p->util->get_post_types( 'names' ); 
  347.  
  348. if ( empty( $post_obj->post_type ) || ! in_array( $post_obj->post_type, $post_type_names ) ) { 
  349. if ( $this->p->debug->enabled ) { 
  350. $this->p->debug->mark( 'exiting early: post_type \''.$post_obj->post_type.'\' not public' ); 
  351. return $post_id; 
  352.  
  353. $exec_count = (int) get_option( NGFB_POST_CHECK_NAME ); // changes false to 0 
  354. $max_count = (int) SucomUtil::get_const( 'NGFB_CHECK_HEADER_COUNT', 10 ); 
  355.  
  356. if ( $exec_count >= $max_count ) { 
  357. if ( $this->p->debug->enabled ) { 
  358. $this->p->debug->mark( 'exiting early: exec_count of '.$exec_count.' exceeds max_count of '.$max_count ); 
  359. return $post_id; 
  360.  
  361. if ( $this->p->debug->enabled ) { 
  362. $this->p->debug->mark( 'check head meta' ); // begin timer 
  363.  
  364. $charset = get_bloginfo( 'charset' ); 
  365. $shortlink = wp_get_shortlink( $post_id, 'post' ); // $context = post 
  366. $shortlink_encoded = SucomUtil::encode_emoji( htmlentities( urldecode( $shortlink ), ENT_QUOTES, $charset, false ) ); // double_encode = false 
  367. $check_opts = SucomUtil::preg_grep_keys( '/^add_/', $this->p->options, false, '' ); 
  368. $conflicts_found = 0; 
  369.  
  370. if ( $this->p->debug->enabled ) { 
  371. $this->p->debug->mark( 'checking '.$shortlink.' head meta for duplicates' ); 
  372.  
  373. if ( is_admin() ) { 
  374. $this->p->notice->inf( sprintf( __( 'Checking %1$s for duplicate meta tags', 'nextgen-facebook' ),  
  375. '<a href="'.$shortlink.'">'.$shortlink_encoded.'</a>' ).'...' ); 
  376.  
  377. // use the shortlink and have get_head_meta() remove our own meta tags 
  378. // to avoid issues with caching plugins that ignore query arguments 
  379. if ( ( $metas = $this->p->util->get_head_meta( $shortlink, '/html/head/link|/html/head/meta', true ) ) !== false ) { 
  380. foreach( array( 
  381. 'link' => array( 'rel' ),  
  382. 'meta' => array( 'name', 'property', 'itemprop' ),  
  383. ) as $tag => $types ) { 
  384. if ( isset( $metas[$tag] ) ) { 
  385. foreach( $metas[$tag] as $meta ) { 
  386. foreach( $types as $type ) { 
  387. if ( isset( $meta[$type] ) && $meta[$type] !== 'generator' &&  
  388. ! empty( $check_opts[$tag.'_'.$type.'_'.$meta[$type]] ) ) { 
  389. $conflicts_found++; 
  390. $this->p->notice->err( sprintf( __( 'Possible conflict detected — your theme or another plugin is adding a <code>%1$s</code> HTML tag to the head section of this webpage.', 'nextgen-facebook' ), $tag.' '.$type.'="'.$meta[$type].'"' ) ); 
  391.  
  392. if ( ! $conflicts_found ) { 
  393. update_option( NGFB_POST_CHECK_NAME, ++$exec_count, false ); // autoload = false 
  394. $this->p->notice->inf( sprintf( __( 'Awesome! No duplicate meta tags found. :-) %s more checks to go...',  
  395. 'nextgen-facebook' ), $max_count - $exec_count ) ); 
  396. } elseif ( $this->p->debug->enabled ) { 
  397. $this->p->debug->mark( 'returned head meta for '.$shortlink.' is false' ); 
  398.  
  399. if ( $this->p->debug->enabled ) { 
  400. $this->p->debug->mark( 'check head meta' ); // end timer 
  401.  
  402. return $post_id; 
  403.  
  404. public function add_metaboxes() { 
  405.  
  406. if ( $this->p->debug->enabled ) { 
  407. $this->p->debug->mark(); 
  408.  
  409. if ( ( $post_obj = SucomUtil::get_post_object( true ) ) === false || empty( $post_obj->post_type ) ) { 
  410. if ( $this->p->debug->enabled ) { 
  411. $this->p->debug->log( 'exiting early: object without post type' ); 
  412. return; 
  413. } else { 
  414. $post_id = empty( $post_obj->ID ) ? 0 : $post_obj->ID; 
  415.  
  416. if ( ( $post_obj->post_type === 'page' && ! current_user_can( 'edit_page', $post_id ) ) ||  
  417. ! current_user_can( 'edit_post', $post_id ) ) { 
  418.  
  419. if ( $this->p->debug->enabled ) { 
  420. $this->p->debug->log( 'insufficient privileges to add metabox for '.$post_obj->post_type.' ID '.$post_id ); 
  421. return; 
  422.  
  423. $lca = $this->p->cf['lca']; 
  424. $add_metabox = empty( $this->p->options[ 'plugin_add_to_'.$post_obj->post_type ] ) ? false : true; 
  425.  
  426. if ( apply_filters( $lca.'_add_metabox_post', $add_metabox, $post_id, $post_obj->post_type ) ) { 
  427.  
  428. if ( $this->p->debug->enabled ) { 
  429. $this->p->debug->log( 'adding metabox '.$lca.'_social_settings' ); 
  430.  
  431. add_meta_box( $lca.'_social_settings', _x( 'Social Settings', 'metabox title', 'nextgen-facebook' ),  
  432. array( &$this, 'show_metabox_social_settings' ), $post_obj->post_type, 'normal', 'low' ); 
  433.  
  434. } elseif ( $this->p->debug->enabled ) { 
  435. $this->p->debug->log( 'skipped metabox '.$lca.'_social_settings' ); 
  436.  
  437. public function show_metabox_social_settings( $post_obj ) { 
  438.  
  439. if ( $this->p->debug->enabled ) { 
  440. $this->p->debug->mark(); 
  441. $this->p->debug->log( 'post id = '.( empty( $post_obj->ID ) ? 0 : $post_obj->ID ) ); 
  442. $this->p->debug->log( 'post type = '.( empty( $post_obj->post_type ) ? 'empty' : $post_obj->post_type ) ); 
  443. $this->p->debug->log( 'post status = '.( empty( $post_obj->post_status ) ? 'empty' : $post_obj->post_status ) ); 
  444.  
  445. $lca = $this->p->cf['lca']; 
  446. $metabox = 'social_settings'; 
  447. $mod = $this->get_mod( $post_obj->ID ); 
  448. $tabs = $this->get_social_tabs( $metabox, $mod ); 
  449. $opts = $this->get_options( $post_obj->ID ); 
  450. $def_opts = $this->get_defaults( $post_obj->ID ); 
  451. $this->form = new SucomForm( $this->p, NGFB_META_NAME, $opts, $def_opts ); 
  452. wp_nonce_field( NgfbAdmin::get_nonce(), NGFB_NONCE ); 
  453.  
  454. if ( $this->p->debug->enabled ) 
  455. $this->p->debug->mark( $metabox.' table rows' ); // start timer 
  456.  
  457. $table_rows = array(); 
  458. foreach ( $tabs as $key => $title ) { 
  459. $table_rows[$key] = array_merge( $this->get_table_rows( $metabox, $key, NgfbMeta::$head_meta_info, $mod ),  
  460. apply_filters( $lca.'_'.$mod['name'].'_'.$key.'_rows', array(), $this->form, NgfbMeta::$head_meta_info, $mod ) ); 
  461. $this->p->util->do_metabox_tabs( $metabox, $tabs, $table_rows ); 
  462.  
  463. if ( $this->p->debug->enabled ) 
  464. $this->p->debug->mark( $metabox.' table rows' ); // end timer 
  465.  
  466. protected function get_table_rows( &$metabox, &$key, &$head, &$mod ) { 
  467.  
  468. $is_auto_draft = empty( $mod['post_status'] ) ||  
  469. $mod['post_status'] === 'auto-draft' ? true : false; 
  470. $auto_draft_msg = sprintf( __( 'Save a draft version or publish the %s to update this value.',  
  471. 'nextgen-facebook' ), SucomUtil::titleize( $mod['post_type'] ) ); 
  472.  
  473. $table_rows = array(); 
  474. switch ( $key ) { 
  475. case 'preview': 
  476. $table_rows = $this->get_rows_social_preview( $this->form, $head, $mod ); 
  477. break; 
  478.  
  479. case 'tags':  
  480. if ( $is_auto_draft ) { 
  481. $table_rows[] = '<td><blockquote class="status-info"><p class="centered">'. 
  482. $auto_draft_msg.'</p></blockquote></td>'; 
  483. } else { 
  484. $table_rows = $this->get_rows_head_tags( $this->form, $head, $mod ); 
  485. break;  
  486.  
  487. case 'validate': 
  488. if ( $is_auto_draft ) { 
  489. $table_rows[] = '<td><blockquote class="status-info"><p class="centered">'. 
  490. $auto_draft_msg.'</p></blockquote></td>'; 
  491. } else { 
  492. $table_rows = $this->get_rows_validate( $this->form, $head, $mod ); 
  493. break;  
  494. return $table_rows; 
  495.  
  496. public function clear_cache_for_new_comment( $comment_id, $comment_approved ) { 
  497. if ( $comment_id && $comment_approved === 1 ) { 
  498. if ( ( $comment = get_comment( $comment_id ) ) && $comment->comment_post_ID ) { 
  499. $post_id = $comment->comment_post_ID; 
  500. if ( $this->p->debug->enabled ) { 
  501. $this->p->debug->log( 'clearing post_id '.$post_id.' cache for comment_id '.$comment_id ); 
  502. $this->clear_cache( $post_id ); 
  503.  
  504. public function clear_cache_for_comment_status( $comment_id, $comment_status ) { 
  505. if ( $comment_id ) { // just in case 
  506. if ( ( $comment = get_comment( $comment_id ) ) && $comment->comment_post_ID ) { 
  507. $post_id = $comment->comment_post_ID; 
  508. if ( $this->p->debug->enabled ) { 
  509. $this->p->debug->log( 'clearing post_id '.$post_id.' cache for comment_id '.$comment_id ); 
  510. $this->clear_cache( $post_id ); 
  511.  
  512. public function clear_cache( $post_id, $rel_id = false ) { 
  513. switch ( get_post_status( $post_id ) ) { 
  514. case 'draft': 
  515. case 'pending': 
  516. case 'future': 
  517. case 'private': 
  518. case 'publish': 
  519. $lca = $this->p->cf['lca']; 
  520. $mod = $this->get_mod( $post_id ); 
  521. $sharing_url = $this->p->util->get_sharing_url( $mod ); 
  522. $cache_salt = SucomUtil::get_mod_salt( $mod, $sharing_url ); 
  523. $permalink = get_permalink( $post_id ); 
  524. $shortlink = wp_get_shortlink( $post_id, 'post' ); // $context = post 
  525.  
  526. $transients = array( 
  527. 'NgfbHead::get_head_array' => array( $cache_salt ),  
  528. 'SucomCache::get' => array( 'url:'.$permalink, 'url:'.$shortlink ),  
  529. ); 
  530. $transients = apply_filters( $lca.'_post_cache_transients', $transients, $mod, $sharing_url ); 
  531.  
  532. $wp_objects = array( 'NgfbPage::get_content' => array( $cache_salt ) ); 
  533. $wp_objects = apply_filters( $lca.'_post_cache_objects', $wp_objects, $mod, $sharing_url ); 
  534.  
  535. $deleted = $this->p->util->clear_cache_objects( $transients, $wp_objects ); 
  536.  
  537. if ( ! empty( $this->p->options['plugin_show_purge_count'] ) && $deleted > 0 ) { 
  538. $this->p->notice->inf( $deleted.' items removed from the WordPress object and transient caches.',  
  539. true, __FUNCTION__.'_show_purge_count', true ); // can be dismissed 
  540.  
  541. if ( function_exists( 'w3tc_pgcache_flush_post' ) ) { // w3 total cache 
  542. w3tc_pgcache_flush_post( $post_id ); 
  543.  
  544. if ( function_exists( 'wp_cache_post_change' ) ) { // wp super cache 
  545. wp_cache_post_change( $post_id ); 
  546.  
  547. break; 
  548.  
  549. return $post_id; 
  550.  
  551. public function get_og_type_reviews( $post_id, $og_type = 'product', $rating_meta = 'rating' ) { 
  552.  
  553. $ret = array(); 
  554.  
  555. if ( empty( $post_id ) ) { 
  556. return $ret; 
  557.  
  558. $comments = get_comments( array( 
  559. 'post_id' => $post_id,  
  560. 'status' => 'approve',  
  561. 'parent' => 0, // don't get replies 
  562. 'order' => 'DESC',  
  563. 'number' => get_option( 'page_comments' ), // limit number of comments 
  564. ) ); 
  565.  
  566. if ( is_array( $comments ) ) { 
  567. foreach( $comments as $num => $comment_obj ) { 
  568. $og_review = $this->get_og_review_mt( $comment_obj, $og_type, $rating_meta ); 
  569. if ( ! empty( $og_review ) ) { // just in case 
  570. $ret[] = $og_review; 
  571.  
  572. return $ret; 
  573.  
  574. public function get_og_review_mt( $comment_obj, $og_type = 'product', $rating_meta = 'rating' ) { 
  575.  
  576. $ret = array(); 
  577. $rating_value = (float) get_comment_meta( $comment_obj->comment_ID, $rating_meta, true ); 
  578.  
  579. $ret[$og_type.':review:id'] = $comment_obj->comment_ID; 
  580. $ret[$og_type.':review:url'] = get_comment_link( $comment_obj->comment_ID ); 
  581. $ret[$og_type.':review:author:id'] = $comment_obj->user_id; // author ID if registered (0 otherwise) 
  582. $ret[$og_type.':review:author:name'] = $comment_obj->comment_author; // author display name 
  583. $ret[$og_type.':review:created_time'] = mysql2date( 'c', $comment_obj->comment_date_gmt ); 
  584. $ret[$og_type.':review:excerpt'] = get_comment_excerpt( $comment_obj->comment_ID ); 
  585.  
  586. // rating values must be larger than 0 to include rating info 
  587. if ( $rating_value > 0 ) { 
  588. $ret[$og_type.':review:rating:value'] = $rating_value; 
  589. $ret[$og_type.':review:rating:worst'] = 1; 
  590. $ret[$og_type.':review:rating:best'] = 5; 
  591.  
  592. return $ret; 
  593.  
  594. ?> 
.