Advertisement
Guest User

Untitled

a guest
Oct 15th, 2019
161
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.91 KB | None | 0 0
  1. <?php
  2.  
  3. namespace MyListing\Src;
  4.  
  5. use \MyListing\Src\Conditions;
  6. use \MyListing\Src\User as User;
  7. use \MyListing\Src\Schema as Schema;
  8.  
  9. class Listing {
  10.  
  11. public static $instances = [];
  12.  
  13. private
  14. $data,
  15. $categories,
  16. $field_cache = [],
  17. $special_keys = [];
  18.  
  19. public
  20. $schedule,
  21. $schema,
  22. $type = null,
  23. $author = null;
  24.  
  25. public static $aliases = [
  26. 'title' => 'job_title',
  27. 'tagline' => 'job_tagline',
  28. 'location' => 'job_location',
  29. 'category' => 'job_category',
  30. 'tags' => 'job_tags',
  31. 'description' => 'job_description',
  32. 'email' => 'job_email',
  33. 'logo' => 'job_logo',
  34. 'cover' => 'job_cover',
  35. 'gallery' => 'job_gallery',
  36. 'website' => 'job_website',
  37. 'phone' => 'job_phone',
  38. 'video_url' => 'job_video_url',
  39. 'date' => 'job_date',
  40. ];
  41.  
  42. /**
  43. * Get a new listing instance (Multiton pattern).
  44. * When called the first time, listing will be fetched from database.
  45. * Otherwise, it will return the previous instance.
  46. *
  47. * @since 1.6.0
  48. * @param $listing int or \WP_Post
  49. */
  50. public static function get( $listing ) {
  51. if ( is_numeric( $listing ) ) {
  52. $listing = get_post( $listing );
  53. }
  54.  
  55. if ( ! $listing instanceof \WP_Post ) {
  56. return false;
  57. }
  58.  
  59. if ( $listing->post_type !== 'job_listing' ) {
  60. return false;
  61. }
  62.  
  63. if ( ! array_key_exists( $listing->ID, self::$instances ) ) {
  64. self::$instances[ $listing->ID ] = new self( $listing );
  65. }
  66.  
  67. return self::$instances[ $listing->ID ];
  68. }
  69.  
  70. /**
  71. * Ignore cache and retrieve listing information from db.
  72. *
  73. * @since 2.1
  74. */
  75. public static function force_get( $listing_id ) {
  76. clean_post_cache( $listing_id );
  77. unset( self::$instances[ $listing_id ] );
  78. return self::get( $listing_id );
  79. }
  80.  
  81. public function __construct( \WP_Post $post ) {
  82. self::$instances[ $post->ID ] = $this;
  83. $this->data = $post;
  84. $this->schedule = new \MyListing\Src\Work_Hours( (array) get_post_meta( $this->data->ID, '_work_hours', true ) );
  85. $this->author = new User( $this->data->post_author );
  86.  
  87. $this->type();
  88. $this->setup_special_keys();
  89. $this->schema = new Schema( $this );
  90. }
  91.  
  92. public function get_id() {
  93. return $this->data->ID;
  94. }
  95.  
  96. public function get_name() {
  97. return $this->data->post_title;
  98. }
  99.  
  100. public function get_slug() {
  101. return $this->data->post_name;
  102. }
  103.  
  104. public function get_status() {
  105. return $this->data->post_status;
  106. }
  107.  
  108. /**
  109. * Get the label for the current listing status.
  110. *
  111. * @since 2.1
  112. */
  113. public function get_status_label() {
  114. $statuses = self::get_post_statuses();
  115. return isset( $statuses[ $this->get_status() ] )
  116. ? $statuses[ $this->get_status() ]
  117. : _x( 'Inactive', 'post status', 'my-listing' );
  118. }
  119.  
  120. public function get_logo( $size = 'thumbnail' ) {
  121. if ( $this->has_field( 'logo' ) ) {
  122. return c27()->get_resized_image( $this->get_field( 'logo' ), $size );
  123. }
  124.  
  125. if ( $this->type && ( $default_logo = $this->type->get_default_logo( $size ) ) ) {
  126. return apply_filters( 'mylisting\listing\get_logo\default', $default_logo, $this );
  127. }
  128.  
  129. return apply_filters( 'mylisting\listing\get_logo\default', '', $this );
  130. }
  131.  
  132. public function get_cover_image( $size = 'large' ) {
  133. if ( $this->has_field( 'cover' ) ) {
  134. return c27()->get_resized_image( $this->get_field( 'cover' ), $size );
  135. }
  136.  
  137. if ( $this->type && ( $default_cover = $this->type->get_default_cover( $size ) ) ) {
  138. return apply_filters( 'mylisting\listing\get_cover_image\default', $default_cover, $this );
  139. }
  140.  
  141. return apply_filters( 'mylisting\listing\get_cover_image\default', '', $this );
  142. }
  143.  
  144. public function get_data( $key = null ) {
  145. if ( $key ) {
  146. if ( isset( $this->data->$key ) ) {
  147. return $this->data->$key;
  148. }
  149.  
  150. return null;
  151. }
  152.  
  153. return $this->data;
  154. }
  155.  
  156. public function get_link() {
  157. return get_permalink( $this->data );
  158. }
  159.  
  160. public function get_schedule() {
  161. return $this->schedule;
  162. }
  163.  
  164. /**
  165. * Get the listing type this listing belongs to.
  166. *
  167. * @since 1.0
  168. * @return Listing_Type|false
  169. */
  170. public function type() {
  171. if ( $this->type ) {
  172. return $this->type;
  173. }
  174.  
  175. // Get listing type based on listing type id (slug).
  176. $type_id = get_post_meta( $this->get_id(), '_case27_listing_type', true );
  177. if ( $type_id && ( $type = ( get_page_by_path( $type_id, OBJECT, 'case27_listing_type' ) ) ) ) {
  178. $this->type = \MyListing\Ext\Listing_Types\Listing_Type::get( $type );
  179. return $this->type;
  180. }
  181.  
  182. // If not available, set to null.
  183. $this->type = null;
  184. return $this->type;
  185. }
  186.  
  187. public function get_author() {
  188. return $this->author;
  189. }
  190.  
  191. public function get_author_id() {
  192. return absint( $this->get_data('post_author') );
  193. }
  194.  
  195. public function get_rating() {
  196. return \MyListing\Ext\Reviews\Reviews::get_listing_rating_optimized( $this->get_id() );
  197. }
  198.  
  199. /**
  200. * Retrieve listing priority.
  201. *
  202. * @since 1.7.0
  203. */
  204. public function get_priority() {
  205. return absint( $this->get_data( '_featured' ) );
  206. }
  207.  
  208. /**
  209. * Get the amount of listing reviews (first level comments).
  210. * If it's not stored in listing meta, then count them again and store the result.
  211. *
  212. * @since 1.6.3
  213. */
  214. public function get_review_count() {
  215. if ( ( $count = $this->get_data( '_case27_review_count' ) ) !== null ) {
  216. return (int) $count;
  217. }
  218.  
  219. return \MyListing\Ext\Reviews\Reviews::count_reviews( $this->get_id() );
  220. }
  221.  
  222. /**
  223. * Determine if the requested field has a value that should be displayed,
  224. * including values that are considered falsy but should still be shown,
  225. * such as 0 and '0'.
  226. *
  227. * @since 1.7.2
  228. */
  229. public function has_field( $key ) {
  230. return ( $field = $this->get_field( $key, true ) ) && $field->valid();
  231. }
  232.  
  233. public function get_field( $key, $object = false ) {
  234. if ( empty( $this->field_cache[ $key ] ) ) {
  235. $this->field_cache[ $key ] = $this->get_field_object( $key );
  236. }
  237.  
  238. return $object === true ? $this->field_cache[$key] : $this->field_cache[$key]->value;
  239. }
  240.  
  241. public function get_field_object( $key ) {
  242. $response = new \MyListing\Src\Field;
  243.  
  244. if ( ! $this->type ) {
  245. return $response;
  246. }
  247.  
  248. if ( array_key_exists( $key, $this->special_keys ) ) {
  249. $response->value = $this->special_keys[ $key ];
  250. return $response;
  251. }
  252.  
  253. if ( array_key_exists( $key, self::$aliases ) ) {
  254. return $this->get_field( self::$aliases[ $key ], true );
  255. }
  256.  
  257. if ( ! ( $field = $this->type->get_field( $key ) ) ) {
  258. return $response;
  259. }
  260.  
  261. $response->options = $field;
  262. $conditions = new Conditions( $field, $this );
  263. if ( ! $conditions->passes() ) {
  264. return $response;
  265. }
  266.  
  267. if ( in_array( $field['type'], [ 'term-checklist', 'term-select', 'term-multiselect' ] ) ) {
  268. $value = array_filter( (array) wp_get_object_terms(
  269. $this->get_id(), $field['taxonomy'],
  270. [ 'orderby' => 'term_order', 'order' => 'ASC' ])
  271. );
  272.  
  273. if ( is_wp_error( $value ) ) {
  274. $value = [];
  275. }
  276. } elseif ( isset( $this->data->{$field['slug']} ) ) {
  277. $value = $this->data->{$field['slug']};
  278. } elseif ( isset( $this->data->{'_' . $field['slug']} ) ) {
  279. $value = $this->data->{'_' . $field['slug']};
  280. } else {
  281. $value = '';
  282. }
  283.  
  284. if ( is_serialized( $value ) ) {
  285. $value = unserialize( $value );
  286. }
  287.  
  288. $response->value = $value;
  289. return $response;
  290. }
  291.  
  292. public function get_social_networks() {
  293. if ( ! $this->has_field( 'links' ) ) {
  294. return [];
  295. }
  296.  
  297. $networks = [];
  298. $allowed_networks = (array) mylisting()->schemes()->get('social-networks');
  299.  
  300. foreach ( (array) $this->get_field( 'links' ) as $link ) {
  301. if ( ! is_array( $link ) || empty( $link['network'] ) ) {
  302. continue;
  303. }
  304.  
  305. if ( empty( $link['url'] ) || ! isset( $allowed_networks[ $link['network'] ] ) ) {
  306. continue;
  307. }
  308.  
  309. $network = $allowed_networks[ $link['network'] ];
  310. $network['link'] = $link['url'];
  311.  
  312. $networks[] = $network;
  313. }
  314.  
  315. return array_filter( $networks );
  316. }
  317.  
  318. /**
  319. * Get the text to be used when listing is shared on social networks.
  320. *
  321. * @since 1.6.3
  322. * @return string $description
  323. */
  324. public function get_share_description() {
  325. $description = wp_kses( $this->get_field( 'description' ), [] );
  326.  
  327. if ( $this->has_field( 'tagline' ) ) {
  328. $description = $this->get_field( 'tagline' );
  329. }
  330.  
  331. return apply_filters( 'mylisting\listing\share\description', $description, $this );
  332. }
  333.  
  334. /**
  335. * Get the image to be used when listing is shared on social networks.
  336. *
  337. * @since 1.6.3
  338. * @return string $image
  339. */
  340. public function get_share_image() {
  341. $field = apply_filters( 'mylisting\single\og:image', 'logo' );
  342. $image = '';
  343.  
  344. if ( $field == 'logo' ) {
  345. $image = $this->get_logo( 'large' );
  346. } elseif ( $field == 'cover' ) {
  347. $image = $this->get_cover_image( 'large' );
  348. } elseif ( $this->has_field( $field ) ) {
  349. $image = c27()->get_resized_image( $this->get_field( $field ), 'large' );
  350. }
  351.  
  352. if ( $image && filter_var( $image, FILTER_VALIDATE_URL ) !== false ) {
  353. $image = esc_url( $image );
  354. }
  355.  
  356. return apply_filters( 'mylisting\listing\share\image', $image, $this );
  357. }
  358.  
  359. /**
  360. * Get the WooCommerce Product ID assigned to this listing.
  361. * Product type can be Listing Package or Listing Subscription.
  362. *
  363. * @since 2.1
  364. * @return int|null $product_id
  365. */
  366. public function get_product_id() {
  367. return get_post_meta( $this->get_id(), '_package_id', true );
  368. }
  369.  
  370. /**
  371. * Get the WooCommerce Product assigned to this listing.
  372. *
  373. * @since 2.1
  374. * @return \WC_Product|false $product
  375. */
  376. public function get_product() {
  377. $package_id = $this->get_product_id();
  378. if ( ! ( $package_id && function_exists( 'wc_get_product' ) ) ) {
  379. return false;
  380. }
  381.  
  382. return wc_get_product( $package_id );
  383. }
  384.  
  385. /**
  386. * Get the payment package ID assigned to this listing.
  387. *
  388. * @since 2.1.6
  389. * @return int|null $package_id
  390. */
  391. public function get_package_id() {
  392. return get_post_meta( $this->get_id(), '_user_package_id', true );
  393. }
  394.  
  395. /**
  396. * Get the payment package assigned to this listing.
  397. *
  398. * @since 2.1.6
  399. * @return \MyListing\Src\Package|false $package
  400. */
  401. public function get_package() {
  402. return \MyListing\Src\Package::get( $this->get_package_id() );
  403. }
  404.  
  405. /**
  406. * Get the listing expiry date in Y-m-d format.
  407. *
  408. * @since 2.1.6
  409. * @return \DateTime|false
  410. */
  411. public function get_expiry_date() {
  412. $date = get_post_meta( $this->get_id(), '_job_expires', true );
  413. $timestamp = strtotime( $date );
  414. if ( $timestamp === false ) {
  415. return false;
  416. }
  417.  
  418. $date = new \DateTime;
  419. $date->setTimestamp( $timestamp );
  420. return $date;
  421. }
  422.  
  423. /**
  424. * Replace field tags with the actual field value.
  425. * Example items to be replaced: [[tagline]] [[description]] [[twitter-id]]
  426. *
  427. * @since 1.5.0
  428. */
  429. public function compile_string( $string ) {
  430. preg_match_all('/\[\[+(?P<fields>.*?)\]\]/', $string, $matches);
  431.  
  432. if ( empty( $matches['fields'] ) ) {
  433. return $string;
  434. }
  435.  
  436. // Get all field values.
  437. foreach ( array_unique( $matches['fields'] ) as $slug ) {
  438. // If any of the used fields are empty, return false.
  439. // if ( ! $this->has_field( $slug ) ) {
  440. // return false;
  441. // }
  442.  
  443. $field = $this->get_field( $slug );
  444. $value = apply_filters( 'mylisting\listing\compile_string\field', $field, $slug, $this );
  445. if ( is_array( $value ) ) {
  446. $value = join( ', ', $value );
  447. }
  448.  
  449. // Escape square brackets so any shortcode added by the listing owner won't be run.
  450. $value = str_replace( [ "[" , "]" ] , [ "&#91;" , "&#93;" ] , $value );
  451. $string = str_replace( "[[$slug]]", esc_attr( $value ), $string );
  452. }
  453.  
  454. // Preserve line breaks.
  455. return $string;
  456. }
  457.  
  458. /**
  459. * Replace [[field]] with the field value in a string.
  460. *
  461. * @since 1.5.1
  462. * @param string $string to replace [[field]] from.
  463. * @param string $value that will replace [[field]].
  464. * @return string
  465. */
  466. public function compile_field_string( $string, $value ) {
  467. $string = str_replace( '[[field]]', c27()->esc_shortcodes( esc_attr( $value ) ), $string );
  468.  
  469. return do_shortcode( $string );
  470. }
  471.  
  472. public function get_preview_options() {
  473. // Get the preview template options for the listing type of the current listing.
  474. $options = $this->type ? $this->type->get_preview_options() : [];
  475.  
  476. // Merge with the default options, in case the listing type options meta returns null.
  477. return c27()->merge_options( mylisting()->schemes()->get('result'), $options );
  478. }
  479.  
  480. public function setup_special_keys() {
  481. $this->special_keys = [
  482. ':id' => $this->get_id(),
  483. ':url' => $this->get_link(),
  484. ':reviews-average' => $this->get_rating(),
  485. ':reviews-mode' => $this->type ? $this->type->get_review_mode() : 10,
  486. ':reviews-count' => $this->get_review_count(),
  487. ':lat' => $this->get_data('geolocation_lat'),
  488. ':lng' => $this->get_data('geolocation_long'),
  489. ':date' => date_i18n( get_option( 'date_format' ), strtotime( $this->get_data('post_date') ) ),
  490. ':rawdate' => $this->get_data('post_date'),
  491. ':authid' => $this->get_data('post_author'),
  492. ':authname' => get_the_author_meta( 'display_name', $this->get_data('post_author') ),
  493. ':authlogin' => get_the_author_meta( 'user_login', $this->get_data('post_author') ),
  494. ':currentuserid' => get_current_user_id(),
  495. ':currentusername' => get_the_author_meta( 'display_name', get_current_user_id() ),
  496. ':currentuserlogin' => get_the_author_meta( 'user_login', get_current_user_id() ),
  497. ];
  498. }
  499.  
  500. /**
  501. * Get preview card info fields, and validate them.
  502. *
  503. * @since 1.6.3
  504. * @return array $fields
  505. */
  506. public function get_info_fields() {
  507. $fields = [];
  508. $preview = $this->get_preview_options();
  509.  
  510. if ( empty( $preview['info_fields'] ) ) {
  511. return $fields;
  512. }
  513.  
  514. foreach ( (array) $preview['info_fields'] as $field ) {
  515. if ( empty( $field['icon'] ) ) {
  516. $field['icon'] = '';
  517. }
  518.  
  519. if ( ! $this->has_field( $field['show_field'] ) ) {
  520. continue;
  521. }
  522.  
  523. $field_value = apply_filters( 'case27\listing\preview\info_field\\' . $field['show_field'], $this->get_field( $field['show_field'] ), $field, $this );
  524. if ( is_array( $field_value ) ) {
  525. $field_value = join( ', ', $field_value );
  526. }
  527.  
  528. $GLOBALS['c27_active_shortcode_content'] = $field_value;
  529. $field_content = str_replace( '[[field]]', $field_value, do_shortcode( $field['label'] ) );
  530.  
  531. if ( ! strlen( $field_content ) ) {
  532. continue;
  533. }
  534.  
  535. $fields[] = [
  536. 'icon' => $field['icon'],
  537. 'field' => $field,
  538. 'content' => $field_content,
  539. ];
  540. }
  541.  
  542. return $fields;
  543. }
  544.  
  545. public function editable_by_current_user() {
  546. return (
  547. current_user_can( 'edit_others_posts', $this->get_id() ) ||
  548. absint( $this->get_data( 'post_author' ) ) === absint( get_current_user_id() )
  549. );
  550. }
  551.  
  552. public static function user_can_edit( $listing_id ) {
  553. if ( ! ( $listing = self::get( $listing_id ) ) ) {
  554. return false;
  555. }
  556.  
  557. return $listing->editable_by_current_user();
  558. }
  559.  
  560. /**
  561. * Check if listing has been verified. Previous to v2.1.6, this served to
  562. * identify claimed listings, but that's no longer necessary. The `_claimed`
  563. * meta key is kept to maintain backwards compatibility for versions pre v2.1.6.
  564. *
  565. * @since 1.6
  566. */
  567. public function is_verified() {
  568. return (bool) $this->get_data( '_claimed' );
  569. }
  570.  
  571. /**
  572. * Determine whether this listing can be claimed by other users.
  573. *
  574. * @since 2.1.6
  575. */
  576. public function is_claimable() {
  577. // claims must be enabled
  578. if ( ! mylisting_get_setting( 'claims_enabled' ) ) {
  579. return false;
  580. }
  581.  
  582. // author can't claim their own listing
  583. if ( absint( get_current_user_id() ) === absint( $this->get_author_id() ) ) {
  584. return false;
  585. }
  586.  
  587. // only published listings can be claimed
  588. if ( $this->get_status() !== 'publish' ) {
  589. return false;
  590. }
  591.  
  592. // if a listing already has a package, it cannot be claimed, unless the
  593. // package has been specially configured by the admin to still allow claims.
  594. $package = $this->get_package();
  595. if ( $package ) {
  596. return $package->is_claimable();
  597. }
  598.  
  599. // listing doesn't have a package, it should be claimable
  600. return true;
  601. }
  602.  
  603. /**
  604. * Get list of available listing post statuses.
  605. *
  606. * @since 2.1
  607. */
  608. public static function get_post_statuses() {
  609. return [
  610. 'draft' => _x( 'Draft', 'post status', 'my-listing' ),
  611. 'expired' => _x( 'Expired', 'post status', 'my-listing' ),
  612. 'preview' => _x( 'Preview', 'post status', 'my-listing' ),
  613. 'pending' => _x( 'Pending approval', 'post status', 'my-listing' ),
  614. 'pending_payment' => _x( 'Pending payment', 'post status', 'my-listing' ),
  615. 'publish' => _x( 'Active', 'post status', 'my-listing' ),
  616. ];
  617. }
  618.  
  619. /**
  620. * Calculates the expiry date for the given listing.
  621. *
  622. * @since 2.1
  623. */
  624. public static function calculate_expiry( $listing_id ) {
  625. // Get duration from the listing if set...
  626. $duration = get_post_meta( $listing_id, '_job_duration', true );
  627.  
  628. // ...otherwise use the global option.
  629. if ( ! metadata_exists( 'post', $listing_id, '_job_duration' ) ) {
  630. $duration = absint( mylisting_get_setting( 'submission_default_duration' ) );
  631. }
  632.  
  633. if ( $duration ) {
  634. return date( 'Y-m-d', strtotime( "+{$duration} days", current_time( 'timestamp' ) ) );
  635. }
  636.  
  637. return '';
  638. }
  639. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement