PageRenderTime 53ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/www/wp-content/plugins/ithemes-exchange/lib/products/class.products-post-type.php

https://github.com/ArzuA/gitwordpress
PHP | 814 lines | 532 code | 84 blank | 198 comment | 124 complexity | f7c60004216e4a8f073ab5f90e66d336 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1
  1. <?php
  2. /**
  3. * Creates the post type for Products
  4. *
  5. * @package IT_Exchange
  6. * @since 0.3.0
  7. */
  8. /**
  9. * Registers the it_exchange_prod post type
  10. *
  11. * @since 0.3.0
  12. */
  13. class IT_Exchange_Product_Post_Type {
  14. /**
  15. * Class Constructor
  16. *
  17. * @since 0.3.0
  18. * @return void
  19. */
  20. function IT_Exchange_Product_Post_Type() {
  21. $this->init();
  22. add_action( 'template_redirect', array( $this, 'load_product' ) );
  23. add_action( 'save_post_it_exchange_prod', array( $this, 'save_product' ) );
  24. add_action( 'admin_init', array( $this, 'set_add_new_item_label' ) );
  25. add_action( 'admin_init', array( $this, 'set_edit_item_label' ) );
  26. add_action( 'it_exchange_save_product_unvalidated', array( $this, 'set_initial_post_product_type' ) );
  27. add_action( 'admin_head-edit.php', array( $this, 'modify_post_new_file' ) );
  28. add_action( 'admin_head-post.php', array( $this, 'modify_post_new_file' ) );
  29. add_filter( 'manage_edit-it_exchange_prod_columns', array( $this, 'it_exchange_product_columns' ), 999 );
  30. add_filter( 'manage_edit-it_exchange_prod_sortable_columns', array( $this, 'it_exchange_product_sortable_columns' ) );
  31. add_filter( 'manage_it_exchange_prod_posts_custom_column', array( $this, 'it_exchange_prod_posts_custom_column_info' ) );
  32. add_filter( 'request', array( $this, 'modify_wp_query_request_on_edit_php' ) );
  33. add_filter( 'wp_insert_post_empty_content', array( $this, 'wp_insert_post_empty_content' ), 20, 2 );
  34. add_filter( 'post_updated_messages', array( $this, 'product_updated_messages' ) );
  35. add_action( 'it_exchange_add_edit_product_screen_layout_setup', array( $this, 'replace_core_slug_metabox' ) );
  36. add_action( 'it_exchange_save_wizard_settings', array( $this, 'create_sample_product' ) );
  37. if ( is_admin() && !empty( $_REQUEST['post_type'] ) && 'it_exchange_prod' === $_REQUEST['post_type'] )
  38. add_action( 'pre_get_posts', array( $this, 'remove_disabled_product_types_from_admin_list' ) );
  39. }
  40. /**
  41. * Load IT Exchange Product if looking at a single product page
  42. *
  43. * @since 0.4.4
  44. */
  45. function load_product() {
  46. if ( ! is_admin() ) {
  47. if ( is_singular( 'it_exchange_prod' ) ) {
  48. global $post;
  49. $GLOBALS['it_exchange']['product'] = it_exchange_get_product( $post );
  50. }
  51. }
  52. }
  53. /**
  54. * Removed disabled product-types from the list
  55. *
  56. * @since 0.4.0
  57. *
  58. * @return void
  59. */
  60. function remove_disabled_product_types_from_admin_list( $query ) {
  61. $post_type = $query->get( 'post_type' );
  62. if ( is_admin() && ! empty( $post_type ) && 'it_exchange_prod' == $post_type ) {
  63. // Preserve existing meta_query
  64. $meta_query = $query->get( 'meta_query' );
  65. // Add ours to existing
  66. $meta_query[] = array(
  67. 'key' => '_it_exchange_product_type',
  68. 'value' => array_keys( it_exchange_get_enabled_addons( array( 'category' => 'product-type' ) ) ),
  69. );
  70. $query->set( 'meta_query', $meta_query );
  71. }
  72. }
  73. /**
  74. * Allows empty title/description/excerpt products to be published to WP
  75. *
  76. * @since 0.4.0
  77. *
  78. * @return void
  79. */
  80. function wp_insert_post_empty_content( $maybe_empty, $postarr ) {
  81. if ( !empty( $postarr['action'] ) && 'editpost' === $postarr['action']
  82. && !empty( $postarr['post_type'] ) && 'it_exchange_prod' === $postarr['post_type'] ) {
  83. return false;
  84. }
  85. return $maybe_empty;
  86. }
  87. /**
  88. * Sets up the object
  89. *
  90. * @since 0.3.0
  91. *
  92. * @return void
  93. */
  94. function init() {
  95. $this->post_type = 'it_exchange_prod';
  96. $labels = array(
  97. 'name' => __( 'Products', 'it-l10n-ithemes-exchange' ),
  98. 'singular_name' => __( 'Product', 'it-l10n-ithemes-exchange' ),
  99. 'edit_item' => __( 'Edit Product', 'it-l10n-ithemes-exchange' ),
  100. 'view_item' => __( 'View Product', 'it-l10n-ithemes-exchange' ),
  101. );
  102. $this->options = array(
  103. 'labels' => $labels,
  104. 'description' => __( 'An iThemes Exchange Post Type for storing all Products in the system', 'it-l10n-ithemes-exchange' ),
  105. 'public' => true,
  106. 'show_ui' => true,
  107. 'show_in_nav_menus' => true,
  108. 'show_in_menu' => false, // We will be adding it manually with various labels based on available product-type add-ons
  109. 'show_in_admin_bar' => true,
  110. 'hierarchical' => false,
  111. 'supports' => array( // Support everything including page-attributes for add-on flexibility
  112. 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'trackbacks',
  113. 'custom-fields', 'comments', 'revisions', 'post-formats', 'page-attributes'
  114. //If you edit this, edit it in set_add_edit_screen_supports()
  115. //in lib/products/class.product.php
  116. ),
  117. 'register_meta_box_cb' => array( $this, 'meta_box_callback' ),
  118. 'rewrite' => array(
  119. 'slug' => 'product',
  120. 'with_front' => false,
  121. ),
  122. );
  123. // We need to register in a different order during admin to catch updating the permalinks.
  124. if ( is_admin() ) {
  125. // Normal Priorities
  126. $priorities['set_rewrite_slug'] = 9;
  127. $priorities['register_post_type'] = 10;
  128. // Special priorities for saving the wizard
  129. if ( ! empty( $_GET['page'] ) && 'it-exchange-setup' == $_GET['page'] ) {
  130. $priorities['set_rewrite_slug'] = 8;
  131. $priorities['register_post_type'] = 8;
  132. }
  133. add_action( 'admin_init', array( $this, 'set_rewrite_slug' ), $priorities['set_rewrite_slug'] );
  134. add_action( 'admin_init', array( $this, 'register_the_post_type' ), $priorities['register_post_type'] );
  135. }
  136. add_action( 'init', array( $this, 'set_rewrite_slug' ), 9 );
  137. add_action( 'init', array( $this, 'register_the_post_type' ) );
  138. }
  139. /**
  140. * Set rewrite rules according to settings
  141. *
  142. * @since 0.4.0
  143. *
  144. * @return void
  145. */
  146. function set_rewrite_slug() {
  147. if ( ! $slug = it_exchange_get_page_slug( 'product', true ) )
  148. return;
  149. $this->options['rewrite']['slug'] = $slug;
  150. $this->options['query_var'] = $slug;
  151. }
  152. /**
  153. * Actually registers the post type
  154. *
  155. * @since 0.3.0
  156. * @return void
  157. */
  158. function register_the_post_type() {
  159. register_post_type( $this->post_type, $this->options );
  160. it_exchange_flush_rewrite_rules();
  161. }
  162. /**
  163. * Call Back hook for product post type admin views
  164. *
  165. * @since 0.3.0
  166. * @uses it_exchange_get_enabled_add_ons()
  167. * @return void
  168. */
  169. function meta_box_callback( $post ) {
  170. $product = it_exchange_get_product( $post );
  171. // Add action for current product type
  172. if ( $product_types = it_exchange_get_enabled_addons( array( 'category' => array( 'product-type' ) ) ) ) {
  173. foreach( $product_types as $addon_slug => $params ) {
  174. if ( $addon_slug == $product->product_type )
  175. do_action( 'it_exchange_product_metabox_callback_' . $addon_slug, $product );
  176. }
  177. }
  178. remove_meta_box( 'submitdiv', __( 'Publish' ), 'post_submit_meta_box', null, 'it_exchange_advanced', 'core' );
  179. add_meta_box( 'submitdiv', __( 'Publish' ), array( $this, 'post_submit_meta_box' ), 'it_exchange_prod', 'it_exchange_side', 'high' );
  180. // Do action for any product type
  181. do_action( 'it_exchange_product_metabox_callback', $product );
  182. }
  183. function post_submit_meta_box( $post ) {
  184. global $action;
  185. $post_type = $post->post_type;
  186. $post_type_object = get_post_type_object($post_type);
  187. $can_publish = current_user_can($post_type_object->cap->publish_posts);
  188. // Grab the iThemes Exchange Product object from the WP $post object
  189. $product = it_exchange_get_product( $post );
  190. // Set the value of the visibility for this product
  191. $product_visibility = get_post_meta( $post->ID, '_it-exchange-visibility', true );
  192. $product_visibility = apply_filters( 'it_exchange_add_ediit_product_visibility', $product_visibility, $post->ID );
  193. ?>
  194. <div id="submitpost" class="it-exchange-submit-box">
  195. <?php do_action('post_submitbox_start'); ?>
  196. <div style="display:none;">
  197. <?php submit_button( __( 'Save' ), 'button', 'save' ); ?>
  198. </div>
  199. <div class="publishing-actions">
  200. <div id="save-action">
  201. <?php if ( 'publish' != $post->post_status && 'future' != $post->post_status && 'pending' != $post->post_status ) : ?>
  202. <input <?php if ( 'private' == $post->post_status ) { ?>style="display:none"<?php } ?> type="submit" name="save" id="save-post" value="<?php esc_attr_e( 'Save Draft' ); ?>" class="button button-large" />
  203. <?php elseif ( 'pending' == $post->post_status && $can_publish ) : ?>
  204. <input type="submit" name="save" id="save-post" value="<?php esc_attr_e( 'Save as Pending' ); ?>" class="button button-large" />
  205. <?php endif; ?>
  206. <span class="spinner"></span>
  207. </div>
  208. <?php if ( $post_type_object->public ) : ?>
  209. <div id="preview-action">
  210. <?php
  211. if ( 'publish' == $post->post_status ) {
  212. $preview_link = esc_url( apply_filters( 'it_exchange_view_product_button_link', get_permalink( $post->ID ), $post ) );
  213. $preview_button = apply_filters( 'it_exchange_view_product_button_label', __( 'View Product', 'it-l10n-ithemes-exchange' ), $post );
  214. $preview_id = 'post-view';
  215. } else {
  216. $preview_link = set_url_scheme( get_permalink( $post->ID ) );
  217. $preview_link = esc_url( apply_filters( 'it_exchange_preview_product_button_link', apply_filters( 'preview_post_link', add_query_arg( 'preview', 'true', $preview_link ) ), $post ) );
  218. $preview_button = apply_filters( 'it_exchange_preview_product_button_label', __( 'Preview Product', 'it-l10n-ithemes-exchange' ), $post );
  219. $preview_id = 'post-preview';
  220. }
  221. ?>
  222. <a class="preview button button-large" href="<?php echo $preview_link; ?>" target="wp-preview" id="<?php echo $preview_id; ?>"><?php echo $preview_button; ?></a>
  223. <input type="hidden" name="wp-preview" id="wp-preview" value="" />
  224. </div>
  225. <?php endif; ?>
  226. <div id="publishing-action">
  227. <span class="spinner"></span>
  228. <?php if ( ! in_array( $post->post_status, array( 'publish', 'future', 'private' ) ) || 0 == $post->ID ) : ?>
  229. <?php if ( $can_publish ) : ?>
  230. <?php if ( !empty($post->post_date_gmt) && time() < strtotime( $post->post_date_gmt . ' +0000' ) ) : ?>
  231. <input name="original_publish" type="hidden" id="original_publish" value="<?php esc_attr_e( 'Schedule' ) ?>" />
  232. <?php submit_button( __( 'Schedule' ), 'primary button-large', 'publish', false, array( 'accesskey' => 'p' ) ); ?>
  233. <?php else : ?>
  234. <input name="original_publish" type="hidden" id="original_publish" value="<?php esc_attr_e('Publish') ?>" />
  235. <?php submit_button( __( 'Publish' ), 'primary button-large', 'publish', false, array( 'accesskey' => 'p' ) ); ?>
  236. <?php endif; ?>
  237. <?php else : ?>
  238. <input name="original_publish" type="hidden" id="original_publish" value="<?php esc_attr_e('Submit for Review') ?>" />
  239. <?php submit_button( __( 'Submit for Review' ), 'primary button-large', 'publish', false, array( 'accesskey' => 'p' ) ); ?>
  240. <?php endif; ?>
  241. <?php else : ?>
  242. <input name="original_publish" type="hidden" id="original_publish" value="<?php esc_attr_e( 'Update' ) ?>" />
  243. <input name="save" type="submit" class="button button-primary button-large" id="publish" accesskey="p" value="<?php esc_attr_e( 'Update' ) ?>" />
  244. <?php endif; ?>
  245. </div>
  246. </div>
  247. <div class="modifying-actions">
  248. <div id="advanced-action">
  249. <a class="advanced-status-option-link advanced-hidden" href data-hidden="<?php _e( 'Show Advanced', 'it-l10n-ithemes-exchange' ); ?>" data-visible="<?php _e( 'Hide Advanced', 'it-l10n-ithemes-exchange' ); ?>"><?php _e( 'Show Advanced', 'it-l10n-ithemes-exchange' ); ?></a>
  250. </div>
  251. <div id="delete-action">
  252. <?php if ( current_user_can( "delete_post", $post->ID ) ) : ?>
  253. <?php
  254. if ( ! EMPTY_TRASH_DAYS )
  255. $delete_text = __( 'Delete Permanently' );
  256. else
  257. $delete_text = __('Move to Trash');
  258. ?>
  259. <a class="submitdelete deletion" href="<?php echo get_delete_post_link( $post->ID ); ?>"><?php echo $delete_text; ?></a>
  260. <?php endif; ?>
  261. </div>
  262. </div>
  263. <div class="advanced-actions hide-if-js">
  264. <div id="misc-publishing-actions">
  265. <div class="misc-pub-section">
  266. <label for="post_status"><?php _e( 'Status:' ) ?></label>
  267. <span id="post-status-display">
  268. <?php
  269. switch ( $post->post_status ) {
  270. case 'private':
  271. _e('Privately Published');
  272. break;
  273. case 'publish':
  274. _e('Published');
  275. break;
  276. case 'future':
  277. _e('Scheduled');
  278. break;
  279. case 'pending':
  280. _e('Pending Review');
  281. break;
  282. case 'draft':
  283. case 'auto-draft':
  284. _e('Draft');
  285. break;
  286. }
  287. ?>
  288. </span>
  289. <?php if ( 'publish' == $post->post_status || 'private' == $post->post_status || $can_publish ) : ?>
  290. <a href="#post_status" <?php if ( 'private' == $post->post_status ) { ?>style="display:none;" <?php } ?>class="edit-post-status hide-if-no-js"><?php _e( 'Edit', 'it-l10n-ithemes-exchange' ) ?></a>
  291. <div id="post-status-select" class="hide-if-js">
  292. <input type="hidden" name="hidden_post_status" id="hidden_post_status" value="<?php echo esc_attr( ('auto-draft' == $post->post_status ) ? 'draft' : $post->post_status); ?>" />
  293. <select name='post_status' id='post_status'>
  294. <?php if ( 'publish' == $post->post_status ) : ?>
  295. <option<?php selected( $post->post_status, 'publish' ); ?> value='publish'><?php _e( 'Published', 'it-l10n-ithemes-exchange' ); ?></option>
  296. <?php endif; ?>
  297. <option<?php selected( $post->post_status, 'pending' ); ?> value='pending'><?php _e( 'Pending Review', 'it-l10n-ithemes-exchange' ); ?></option>
  298. <?php if ( 'auto-draft' == $post->post_status ) : ?>
  299. <option<?php selected( $post->post_status, 'auto-draft' ); ?> value='draft'><?php _e( 'Draft', 'it-l10n-ithemes-exchange' ); ?></option>
  300. <?php else : ?>
  301. <option<?php selected( $post->post_status, 'draft' ); ?> value='draft'><?php _e('Draft') ?></option>
  302. <?php endif; ?>
  303. </select>
  304. <a href="#post_status" class="save-post-status hide-if-no-js button"><?php _e('OK'); ?></a>
  305. <a href="#post_status" class="cancel-post-status hide-if-no-js"><?php _e('Cancel'); ?></a>
  306. </div>
  307. <?php endif; ?>
  308. </div>
  309. <div class="misc-pub-section">
  310. <label for="visibility"><?php _e( 'Visibility:', 'it-l10n-ithemes-exchange' ) ?></label>
  311. <span id="product-visibility-display">
  312. <?php
  313. switch ( $product_visibility ) {
  314. case 'hidden':
  315. _e( 'Hide from Store', 'it-l10n-ithemes-exchange' );
  316. break;
  317. case 'visible':
  318. default:
  319. _e( 'Show in Store', 'it-l10n-ithemes-exchange' );
  320. break;
  321. }
  322. ?>
  323. </span>
  324. <?php if ( 'visible' == $product_visibility || 'hidden' == $product_visibility || $can_publish ) : ?>
  325. <a href="#product_visibility" class="edit-product-visibility hide-if-no-js"><?php _e('Edit') ?></a>
  326. <div id="product-visibility-select" class="hide-if-js">
  327. <input type="hidden" name="hidden_it-exchange-visibility" id="hidden_it-exchange-visibility" value="<?php echo esc_attr( ('hidden' == $post->post_status ) ? 'hidden' : $product_visibility); ?>" />
  328. <select name='it-exchange-visibility' id='it-exchange-visibility'>
  329. <option<?php selected( $product_visibility, 'visible' ); ?> value='visible'><?php _e( 'Show in Store', 'it-l10n-ithemes-exchange' ) ?></option>
  330. <option<?php selected( $product_visibility, 'hidden' ); ?> value='hidden'><?php _e( 'Hide from Store', 'it-l10n-ithemes-exchange' ) ?></option>
  331. </select>
  332. <a href="#product_visibility" class="save-product_visibility hide-if-no-js button"><?php _e('OK'); ?></a>
  333. <a href="#product_visibility" class="cancel-product_visibility hide-if-no-js"><?php _e('Cancel'); ?></a>
  334. </div>
  335. <?php endif; ?>
  336. </div>
  337. <?php
  338. if ( 'private' == $post->post_status ) {
  339. $post->post_password = '';
  340. $visibility = 'private';
  341. $visibility_trans = __( 'Private' );
  342. } elseif ( !empty( $post->post_password ) ) {
  343. $visibility = 'password';
  344. $visibility_trans = __('Password protected');
  345. } elseif ( $post_type == 'post' && is_sticky( $post->ID ) ) {
  346. $visibility = 'public';
  347. $visibility_trans = __('Public, Sticky');
  348. } else {
  349. $visibility = 'public';
  350. $visibility_trans = __('Public');
  351. }
  352. ?>
  353. <input type="hidden" name="hidden_post_visibility" id="hidden-post-visibility" value="<?php echo esc_attr( $visibility ); ?>" />
  354. <?php do_action('post_submitbox_misc_actions'); ?>
  355. </div>
  356. </div>
  357. </div>
  358. <?php
  359. }
  360. /**
  361. * Generates the Add New Product Label for a new Product
  362. *
  363. * @since 0.3.0
  364. * @return string $label Label for add new product page.
  365. */
  366. function set_add_new_item_label() {
  367. global $pagenow, $wp_post_types;
  368. if ( $pagenow != 'post-new.php' || empty( $_GET['post_type'] ) || 'it_exchange_prod' != $_GET['post_type'] )
  369. return apply_filters( 'it_exchange_add_new_product_label', __( 'Add New Product', 'it-l10n-ithemes-exchange' ) );
  370. if ( empty( $wp_post_types['it_exchange_prod'] ) )
  371. return;
  372. $product_add_ons = it_exchange_get_enabled_addons( array( 'category' => array( 'product-type' ) ) );
  373. $product = array();
  374. // Isolate the product type
  375. if ( 1 == count( $product_add_ons ) ) {
  376. $product = reset( $product_add_ons );
  377. } else {
  378. $product_type = it_exchange_get_product_type();
  379. if ( ! empty( $product_type ) && ! empty( $product_add_ons[$product_type] ) )
  380. $product = $product_add_ons[$product_type];
  381. else
  382. $product['options']['labels']['singular_name'] = 'Product';
  383. }
  384. $singular = empty( $product['options']['labels']['singular_name'] ) ? $product['name'] : $product['options']['labels']['singular_name'];
  385. $label = apply_filters( 'it_exchange_add_new_product_label_' . $product['slug'], __( 'Add New ', 'it-l10n-ithemes-exchange' ) . $singular );
  386. $wp_post_types['it_exchange_prod']->labels->add_new_item = $label;
  387. }
  388. /**
  389. * Generates the Edit Product Label for a new Product
  390. *
  391. * Post types have to be registered earlier than we know that type of post is being edited
  392. * so this function inserts the correct label into the $wp_post_types global after post type is registered
  393. *
  394. * @since 0.3.1
  395. * @return string $label Label for edit product page.
  396. */
  397. function set_edit_item_label() {
  398. global $pagenow, $wp_post_types;
  399. $post = empty( $_GET['post'] ) ? false : get_post( $_GET['post'] );
  400. if ( ! is_admin() || $pagenow != 'post.php' || ! $post )
  401. return;
  402. if ( empty( $wp_post_types['it_exchange_prod'] ) )
  403. return;
  404. if ( 'it_exchange_prod' != get_post_type( $post ) )
  405. return;
  406. $product_type = it_exchange_get_product_type( $post );
  407. $product_add_ons = it_exchange_get_enabled_addons( array( 'category' => array( 'product-type' ) ) );
  408. $product = array();
  409. if ( 1 == count( $product_add_ons ) ) {
  410. $product = reset( $product_add_ons );
  411. } else {
  412. if ( ! empty( $product_type ) && ! empty( $product_add_ons[$product_type] ) ) {
  413. $product = $product_add_ons[$product_type];
  414. } else {
  415. $product['slug'] = '';
  416. $product['options']['labels']['singular_name'] = 'Product';
  417. }
  418. }
  419. $singular = empty( $product['options']['labels']['singular_name'] ) ? $product['name'] : $product['options']['labels']['singular_name'];
  420. $label = apply_filters( 'it_exchange_edit_product_label_' . $product['slug'], __( 'Edit ', 'it-l10n-ithemes-exchange' ) . $singular );
  421. $wp_post_types['it_exchange_prod']->labels->edit_item = $label;
  422. }
  423. /**
  424. * Provides specific hooks for when iThemes Exchange products are saved.
  425. *
  426. * This method is hooked to save_post. It provides hooks for add-on developers
  427. * that will only be called when the post being saved is an iThemes Exchange product.
  428. * It provides the following 4 hooks:
  429. * - it_exchange_save_product_unvalidated // Runs every time an iThemes Exchange product is saved.
  430. * - it_exchange_save_product_unavalidate-[product-type] // Runs every time a specific iThemes Exchange product type is saved.
  431. * - it_exchange_save_product // Runs every time an iThemes Exchange product is saved if not an autosave and if user has permission to save post
  432. * - it_exchange_save_product-[product-type] // Runs every time a specific iThemes Exchange product-type is saved if not an autosave and if user has permission to save post
  433. *
  434. * @since 0.3.1
  435. * @param int $post_id WordPress Post ID
  436. * @return void
  437. */
  438. function save_product( $post_id ) {
  439. // Exit if not it_exchange_prod post_type
  440. if ( ! 'it_exchange_prod' === get_post_type( $post_id ) )
  441. return;
  442. // Fire off actions with validations that most instances need to use.
  443. if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
  444. return;
  445. if ( ! current_user_can( 'edit_post', $post_id ) )
  446. return;
  447. if ( isset( $_POST['it-exchange-visibility'] ) )
  448. update_post_meta( $post_id, '_it-exchange-visibility', $_POST['it-exchange-visibility'] );
  449. // Grab enabled product add-ons
  450. $product_type_addons = it_exchange_get_enabled_addons( array( 'category' => 'product-type' ) );
  451. // Grab current post's product_type
  452. $product_type = it_exchange_get_product_type();
  453. // These hooks fire off any time a it_exchange_prod post is saved w/o validations
  454. do_action( 'it_exchange_save_product_unvalidated', $post_id );
  455. foreach( (array) $product_type_addons as $slug => $params ) {
  456. if ( $slug == $product_type ) {
  457. do_action( 'it_exchange_save_product_unvalidated_' . $slug, $post_id );
  458. }
  459. }
  460. // This is called any time save_post hook
  461. do_action( 'it_exchange_save_product', $post_id );
  462. foreach( (array) $product_type_addons as $slug => $params ) {
  463. if ( $slug == $product_type ) {
  464. do_action( 'it_exchange_save_product_' . $slug, $post_id );
  465. }
  466. }
  467. }
  468. /**
  469. * Sets the post product_type on post creation
  470. *
  471. * @since 0.3.3
  472. * @return void
  473. */
  474. function set_initial_post_product_type( $post ) {
  475. global $pagenow;
  476. if ( $product = it_exchange_get_product( $post ) ) {
  477. if ( ! empty( $product->product_type ) && ! get_post_meta( $product->ID, '_it_exchange_product_type', true ) )
  478. update_post_meta( $product->ID, '_it_exchange_product_type', $product->product_type );
  479. }
  480. }
  481. /**
  482. * Modifies the value of $post_new_file to change the link attached to the Add New button next to the H2 on all / edit products
  483. *
  484. * I'm not proud of this. Don't copy it. ^gta
  485. *
  486. * @since 0.3.10
  487. * @return void
  488. */
  489. function modify_post_new_file() {
  490. global $current_screen, $post_new_file;
  491. if ( 'edit-it_exchange_prod' == $current_screen->id || 'it_exchange_prod' == $current_screen->id ) {
  492. $product_type = it_exchange_get_product_type();
  493. // Hackery. The 'Add New button in the H2 isn't going to work if we have multiple product types
  494. $product_addons = it_exchange_get_enabled_addons( array( 'category' => 'product-type' ) );
  495. $hide_it = '<style type="text/css">.add-new-h2 { display:none; }</style>';
  496. if ( empty( $product_type ) && ( count( $product_addons ) > 1 ) ) {
  497. echo $hide_it;
  498. } else if ( empty( $product_type ) && ! it_exchange_get_products() ) {
  499. // If we made it here, we only have one product type, but there are no products. Won't happen that often.
  500. $product_addon = array_keys( $product_addons );
  501. $product_addon = $product_addon[0];
  502. $product_type = empty( $product_addon ) ? false : $product_addon;
  503. }
  504. if ( ! empty( $post_new_file) && ! empty( $product_type ) )
  505. $post_new_file = add_query_arg( array( 'it-exchange-product-type' => $product_type ), $post_new_file );
  506. }
  507. }
  508. /**
  509. * Adds the product type column to the View All products table
  510. *
  511. * @since 0.3.3
  512. * @param array $existing exisiting columns array
  513. * @return array modified columns array
  514. */
  515. function it_exchange_product_columns( $existing ) {
  516. add_filter( 'the_excerpt', array( $this, 'replace_excerpt_in_products_table_with_description' ) );
  517. $columns['cb'] = '<input type="checkbox" />';
  518. $columns['title'] = __( 'Title', 'it-l10n-ithemes-exchange' );
  519. $columns['it_exchange_product_price'] = __( 'Price', 'it-l10n-ithemes-exchange' );
  520. $columns['it_exchange_product_show_in_store'] = __( 'Show in Store', 'it-l10n-ithemes-exchange' );
  521. $columns['it_exchange_product_inventory'] = __( 'Inventory', 'it-l10n-ithemes-exchange' );
  522. $columns['it_exchange_product_purchases'] = __( 'Purchases', 'it-l10n-ithemes-exchange' );
  523. if ( 1 < count( it_exchange_get_enabled_addons( array( 'category' => 'product-type' ) ) ) )
  524. $columns['it_exchange_product_type'] = __( 'Product Type', 'it-l10n-ithemes-exchange' );
  525. return $columns;
  526. }
  527. /**
  528. * Replace the excerpt with the product description (our version of excerpt) in the admin All Products table when mode is 'excerpt'
  529. *
  530. * @since 0.4.0
  531. *
  532. * @param string $excerpt existing excerpt passed in by WP filter
  533. * @return string
  534. */
  535. function replace_excerpt_in_products_table_with_description( $excerpt ) {
  536. global $post;
  537. if ( it_exchange_product_has_feature( $post->ID, 'description' ) )
  538. $excerpt = it_exchange_get_product_feature( $post->ID, 'description' );
  539. else
  540. $excerpt = '';
  541. return $excerpt;
  542. }
  543. /**
  544. * Makes the product_type column added above sortable
  545. *
  546. * @since 0.3.3
  547. * @param array $sortables existing sortable columns
  548. * @return array modified sortable columnns
  549. */
  550. function it_exchange_product_sortable_columns( $sortables ) {
  551. $sortables['it_exchange_product_price'] = 'it-exchange-product-price';
  552. $sortables['it_exchange_product_show_in_store'] = 'it-exchange-product-show-in-store';
  553. $sortables['it_exchange_product_inventory'] = 'it-exchange-product-inventory';
  554. //This will only show up if there are multiple product-type addons
  555. $sortables['it_exchange_product_type'] = 'it-exchange-product-type';
  556. return $sortables;
  557. }
  558. /**
  559. * Adds the product_type of a product to each row of the column added above
  560. *
  561. * @since 0.3.3
  562. * @param string $column column title
  563. * @param integer $post post ID
  564. * @return void
  565. */
  566. function it_exchange_prod_posts_custom_column_info( $column ) {
  567. global $post;
  568. $product = it_exchange_get_product( $post );
  569. switch( $column ) {
  570. case 'it_exchange_product_price':
  571. esc_attr_e( it_exchange_format_price( it_exchange_get_product_feature( $post->ID, 'base-price' ) ) );
  572. break;
  573. case 'it_exchange_product_show_in_store':
  574. $product_visibility = get_post_meta( $post->ID, '_it-exchange-visibility', true );
  575. echo ucwords( $product_visibility );
  576. break;
  577. case 'it_exchange_product_inventory':
  578. esc_attr_e( it_exchange_get_product_feature( $post->ID, 'inventory' ) );
  579. break;
  580. case 'it_exchange_product_purchases':
  581. esc_attr_e( count( it_exchange_get_transactions_for_product( $post->ID, 'ids' ) ) );
  582. break;
  583. case 'it_exchange_product_type':
  584. esc_attr_e( it_exchange_get_product_type_name( it_exchange_get_product_type( $post ) ) );
  585. break;
  586. }
  587. }
  588. /**
  589. * Modify sort of products in edit.php for custom columns
  590. *
  591. * @since 0.4.0
  592. *
  593. * @param string $request original request
  594. */
  595. function modify_wp_query_request_on_edit_php( $request ) {
  596. global $hook_suffix;
  597. if ( 'edit.php' === $hook_suffix ) {
  598. if ( 'it_exchange_prod' === $request['post_type'] && isset( $request['orderby'] ) ) {
  599. switch( $request['orderby'] ) {
  600. case 'it-exchange-product-price':
  601. $request['orderby'] = 'meta_value_num';
  602. $request['meta_key'] = '_it-exchange-base-price';
  603. break;
  604. case 'it-exchange-product-show-in-store':
  605. $request['orderby'] = 'meta_value';
  606. $request['meta_key'] = '_it-exchange-visibility';
  607. break;
  608. case 'it-exchange-product-type':
  609. $request['orderby'] = 'meta_value';
  610. $request['meta_key'] = '_it_exchange_product_type';
  611. break;
  612. }
  613. }
  614. }
  615. return $request;
  616. }
  617. /**
  618. * Modify the product updated messages
  619. *
  620. * @since 0.4.9
  621. *
  622. * @param array $messages existing messages
  623. * @return array
  624. */
  625. function product_updated_messages( $messages ) {
  626. global $post;
  627. $post_ID = $post->ID;
  628. $messages['it_exchange_prod'] = array(
  629. 1 => sprintf( __('Product updated. <a href="%s">View product</a>'), esc_url( get_permalink($post_ID) ) ),
  630. 2 => __('Custom field updated.'),
  631. 3 => __('Custom field deleted.'),
  632. 4 => __('Product updated.'),
  633. /* translators: %s: date and time of the revision */
  634. 5 => isset($_GET['revision']) ? sprintf( __('Product restored to revision from %s'), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
  635. 6 => sprintf( __('Product published. <a href="%s">View product</a>'), esc_url( get_permalink($post_ID) ) ),
  636. 7 => __('Product saved.'),
  637. 8 => sprintf( __('Product submitted. <a target="_blank" href="%s">Preview product</a>'), esc_url( add_query_arg( 'preview', 'true', get_permalink($post_ID) ) ) ),
  638. 9 => sprintf( __('Product scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview product</a>'),
  639. // translators: Publish box date format, see http://php.net/date
  640. date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) ), esc_url( get_permalink($post_ID) ) ),
  641. 10 => sprintf( __('Product draft updated. <a target="_blank" href="%s">Preview product</a>'), esc_url( add_query_arg( 'preview', 'true', get_permalink($post_ID) ) ) )
  642. );
  643. return $messages;
  644. }
  645. /**
  646. * Unregisters core slug metabox and registers ours
  647. *
  648. * @since 0.4.13
  649. * @return void
  650. */
  651. function replace_core_slug_metabox() {
  652. remove_meta_box( 'slugdiv', 'it_exchange_prod', 'it_exchange_advanced', 'low' );
  653. add_meta_box( 'slugdiv', __( 'Product Slug', 'it-l10n-ithemes-exchange' ), array( $this, 'post_slug_meta_box' ), 'it_exchange_prod', 'it_exchange_advanced', 'low' );
  654. }
  655. /**
  656. * Modifed version of slugmetabox with description
  657. *
  658. * @since 0.4.13
  659. *
  660. * @return void
  661. */
  662. function post_slug_meta_box( $post ) {
  663. ?>
  664. <label class="" for="post_name">
  665. <?php _e( 'Product Slug', 'it-l10n-ithemes-exchange' ); ?> <span class="tip" title="<?php _e( 'This is the final part of the product\'s URL. WordPress will auto-create it for you.', 'it-l10n-ithemes-exchange' ); ?>">i</span>
  666. </label>
  667. <input name="post_name" type="text" size="13" id="post_name" value="<?php echo esc_attr( apply_filters('editable_slug', $post->post_name) ); ?>" />
  668. <?php
  669. }
  670. /**
  671. * Creates a sample product when the wizard is saved.
  672. *
  673. * @since 0.1.15
  674. *
  675. * @return void
  676. */
  677. function create_sample_product() {
  678. $settings = it_exchange_get_option( 'settings_general', true );
  679. $sample_id = empty( $settings['sample-product-id'] ) ? false : $settings['sample-product-id'];
  680. // Abort if product already exists.
  681. if ( it_exchange_get_product( $sample_id ) )
  682. return;
  683. // Set sample product Type
  684. $product_types = it_exchange_get_enabled_addons( array( 'category' => 'product-type' ) );
  685. $product_type = current( $product_types );
  686. $sample_product_type = empty( $product_type['slug'] ) ? 'digital-downloads-product-type' : $product_type['slug'];
  687. $title = __( 'My Sample Product', 'it-l10n-ithemes-exchange' );
  688. $price = '1';
  689. $description = __( 'A great product description includes the primary benefits, not just features or technical specs to your target market and core audience. It\'s probably about 3-4 sentences, if that, selling your product as the solution for your prospective customers. To help you, answer these questions: What problem does it solve? Who does it solve it for? And how is it different than other products out there?', 'it-l10n-ithemes-exchange' );
  690. $extended = __( '
  691. This is your extended description. Use this area for a variety of information, like:
  692. <ul>
  693. <li>FAQs</li>
  694. <li>Table of contents (for books) or track listings (for albums)</li>
  695. <li>Samples files</li>
  696. <li>Additional yet educational sales information</li>
  697. <li>And don\'t forget you could put all those other features and technical specs here!</li>
  698. </ul>
  699. You can change this on the fly too!
  700. <strong>Photos and Images</strong>
  701. You\'ll want to create bigger images, perhaps even at a 1x1 ratio and 1000pixel wide.
  702. Then let WordPress resize them for output on your page. It\'s best to have a featured image (one big one that really displays your product) then have supplement images (if available) that buyers can click on to see more what you offer.
  703. JPGs are typically best for photos. PNGs for other types of artwork.'
  704. , 'it-l10n-ithemes-exchange' );
  705. $args = array(
  706. 'type' => $sample_product_type,
  707. 'status' => 'draft',
  708. 'show_in_store' => true,
  709. 'description' => $description,
  710. 'title' => $title,
  711. 'base-price' => $price,
  712. 'extended-description' => $extended,
  713. 'images-from-urls' => array(
  714. ITUtility::get_url_from_file( dirname( dirname( __FILE__ ) ) . '/admin/images/sample-product-image-1.png' ) => __( 'Sample Image One', 'it-l10n-ithemes-exchange' ),
  715. ITUtility::get_url_from_file( dirname( dirname( __FILE__ ) ) . '/admin/images/sample-product-image-2.png' ) => __( 'Sample Image Two', 'it-l10n-ithemes-exchange' ),
  716. ITUtility::get_url_from_file( dirname( dirname( __FILE__ ) ) . '/admin/images/sample-product-image-3.png' ) => __( 'Sample Image Three', 'it-l10n-ithemes-exchange' ),
  717. ),
  718. );
  719. // The it_exchange_add_product API method is a work in progress. We don't suggest that you use it yet.
  720. if ( $product_id = it_exchange_add_product( $args ) ) {
  721. $settings['sample-product-id'] = $product_id;
  722. it_exchange_save_option( 'settings_general', $settings );
  723. }
  724. }
  725. }
  726. $IT_Exchange_Product_Post_Type = new IT_Exchange_Product_Post_Type();