/app/rule/content/class-ms-rule-content-model.php

  1. <?php 
  2. /** 
  3. * Membership Comment Rule class. 
  4. * 
  5. * Persisted by Membership class. 
  6. * 
  7. * @since 1.0.0 
  8. * @package Membership2 
  9. * @subpackage Model 
  10. */ 
  11. class MS_Rule_Content_Model extends MS_Rule { 
  12.  
  13. /** 
  14. * Rule type. 
  15. * 
  16. * @since 1.0.0 
  17. * 
  18. * @var string $rule_type 
  19. */ 
  20. protected $rule_type = MS_Rule_Content::RULE_ID; 
  21.  
  22. /** 
  23. * Available special pages 
  24. * 
  25. * @since 1.0.0 
  26. * 
  27. * @var array 
  28. */ 
  29. protected $_content = null; 
  30.  
  31. /** 
  32. * Comment content ID. 
  33. * 
  34. * @since 1.0.0 
  35. * 
  36. * @var string $content_id 
  37. */ 
  38. const CONTENT_ID = 'content'; 
  39.  
  40. /** 
  41. * Rule value constants. 
  42. * 
  43. * @since 1.0.0 
  44. * 
  45. * @var int 
  46. */ 
  47. const COMMENT_NO_ACCESS = 'cmt_none'; 
  48. const COMMENT_READ = 'cmt_read'; 
  49. const COMMENT_WRITE = 'cmt_full'; 
  50. const MORE_LIMIT = 'no_more'; 
  51.  
  52. /** 
  53. * Flag of the final comment access level. 
  54. * When an user is member of multiple memberships with different 
  55. * comment-access-restrictions then the MOST GENEROUS access will be granted. 
  56. * 
  57. * @since 1.0.0 
  58. * 
  59. * @var string 
  60. */ 
  61. protected static $comment_access = self::COMMENT_NO_ACCESS; 
  62.  
  63. /** 
  64. * Set to true, if the user did not specify any comment protection. 
  65. * This means that the default logic should be used... 
  66. * 
  67. * @since 1.0.0 
  68. * 
  69. * @var bool 
  70. */ 
  71. protected static $comment_public = null; 
  72.  
  73. /** 
  74. * The message displayed below the "read more" mark. 
  75. * 
  76. * @since 1.0.0 
  77. * 
  78. * @var string 
  79. */ 
  80. protected $protection_message = ''; 
  81.  
  82. /** 
  83. * Verify access to the current content. 
  84. * 
  85. * This rule will return NULL (not relevant), because the comments are 
  86. * protected via WordPress hooks instead of protecting the whole page. 
  87. * 
  88. * @since 1.0.0 
  89. * 
  90. * @param string $id The content id to verify access. 
  91. * @return bool|null True if has access, false otherwise. 
  92. * Null means: Rule not relevant for current page. 
  93. */ 
  94. public function has_access( $id, $admin_has_access = true ) { 
  95. return null; 
  96.  
  97. /** 
  98. * Set initial protection. 
  99. * 
  100. * @since 1.0.0 
  101. */ 
  102. public function protect_content() { 
  103. parent::protect_content(); 
  104.  
  105. // ********* COMMENTS ********** 
  106.  
  107. // No comments on special pages (signup, account, ...) 
  108. $this->add_filter( 'the_content', 'check_special_page' ); 
  109.  
  110. /** 
  111. * We find the public comment access once. 
  112. * This is the access ganted to guests or memberships that do not define 
  113. * an explicit comment access rule. 
  114. */ 
  115. if ( null === self::$comment_public ) { 
  116. $base_rule = MS_Model_Membership::get_base()->get_rule( $this->rule_type ); 
  117. if ( null === $base_rule->get_rule_value( self::COMMENT_WRITE ) ) { 
  118. self::$comment_public = self::COMMENT_WRITE; 
  119. } elseif ( null === $base_rule->get_rule_value( self::COMMENT_READ ) ) { 
  120. self::$comment_public = self::COMMENT_READ; 
  121. } else { 
  122. self::$comment_public = self::COMMENT_NO_ACCESS; 
  123.  
  124. // Find the most generous comment access rule. 
  125. $has_full = is_user_logged_in() && $this->get_rule_value( self::COMMENT_WRITE ); 
  126. $has_read = is_user_logged_in() && $this->get_rule_value( self::COMMENT_READ ); 
  127. $has_none = $this->get_rule_value( self::COMMENT_NO_ACCESS ); 
  128.  
  129. if ( true === $has_full ) { 
  130. // Membership allows full comment access. 
  131. self::$comment_access = self::COMMENT_WRITE; 
  132. } elseif ( true === $has_read ) { 
  133. // Membership allows read-only access. 
  134. if ( self::$comment_access == self::COMMENT_NO_ACCESS ) { 
  135. self::$comment_access = self::COMMENT_READ; 
  136. } elseif ( true === $has_none ) { 
  137. // Membership does not allow any comment access. 
  138. // (no change, this is the default access level) 
  139. } else { 
  140. // This membership does not define a comment access: Use public access! 
  141. self::$comment_access = self::$comment_public; 
  142.  
  143. $this->add_action( 
  144. 'ms_setup_protection_done',  
  145. 'protect_comments' 
  146. ); 
  147.  
  148. // ********** READ MORE ********** 
  149.  
  150. if( defined( 'MS_PROTECTED_MESSAGE_REVERSE_RULE' ) && MS_PROTECTED_MESSAGE_REVERSE_RULE ) { 
  151.  
  152. $rule = MS_Factory::load( 'MS_Rule_Content_Model' ); 
  153. $allowed_memberships = $rule->get_memberships( self::MORE_LIMIT ); 
  154. if( ! is_array( $allowed_memberships ) ) $allowed_memberships = array(); 
  155.  
  156. $sorted_membership = array(); 
  157. foreach( $allowed_memberships as $allowed_membership_id => $allowed_membership_name ) { 
  158. $m_obj = MS_Factory::load( 'MS_Model_Membership', $allowed_membership_id ); 
  159. $key = $m_obj->priority; 
  160.  
  161. while( array_key_exists( $key, $sorted_membership ) ) { 
  162. $key++; 
  163.  
  164. $sorted_membership[$key] = $allowed_membership_id; 
  165. $protected_membership_id = reset( $sorted_membership ); 
  166.  
  167. }else{ 
  168. $protected_membership_id = $this->membership_id; 
  169.  
  170. $this->protection_message = MS_Plugin::instance()->settings->get_protection_message( 
  171. MS_Model_Settings::PROTECTION_MSG_MORE_TAG,  
  172. //$this->membership_id 
  173. $protected_membership_id 
  174. ); 
  175.  
  176. if ( ! parent::has_access( self::MORE_LIMIT ) ) { 
  177. $this->add_filter( 'the_content_more_link', 'show_moretag_protection', 99, 2 ); 
  178. $this->add_filter( 'the_content', 'replace_more_tag_content', 1 ); 
  179. $this->add_filter( 'the_content_feed', 'replace_more_tag_content', 1 ); 
  180.  
  181. // ********* COMMENTS ********** 
  182.  
  183. /** 
  184. * Setup the comment permissions after all membership rules were parsed. 
  185. * 
  186. * @since 1.0.0 
  187. */ 
  188. public function protect_comments() { 
  189. static $Done = false; 
  190.  
  191. if ( $Done ) { return; } 
  192. $Done = true; 
  193.  
  194. switch ( self::$comment_access ) { 
  195. case self::COMMENT_WRITE: 
  196. // Don't change the inherent comment status. 
  197. break; 
  198.  
  199. case self::COMMENT_READ: 
  200. $this->add_filter( 'comment_form_before', 'hide_form_start', 1 ); 
  201. $this->add_filter( 'comment_form_after', 'hide_form_end', 99 ); 
  202. add_filter( 'comment_reply_link', '__return_null', 99 ); 
  203. break; 
  204.  
  205. case self::COMMENT_NO_ACCESS: 
  206. add_filter( 'comments_open', '__return_false', 99 ); 
  207. add_filter( 'get_comments_number', '__return_zero', 99 ); 
  208. break; 
  209.  
  210. /** 
  211. * Before the comment form is output we start buffering. 
  212. * 
  213. * @since 1.0.0 
  214. */ 
  215. public function hide_form_start() { 
  216. ob_start(); 
  217.  
  218. /** 
  219. * At the end of the comment form we clear the buffer: The form is gone! 
  220. * 
  221. * @since 1.0.0 
  222. */ 
  223. public function hide_form_end() { 
  224. ob_end_clean(); 
  225.  
  226. /** 
  227. * Close comments for membership special pages. 
  228. * 
  229. * Related Action Hooks: 
  230. * - the_content 
  231. * 
  232. * @since 1.0.0 
  233. * 
  234. * @param string $content The content to filter. 
  235. */ 
  236. public function check_special_page( $content ) { 
  237. if ( MS_Model_Pages::is_membership_page() ) { 
  238. add_filter( 'comments_open', '__return_false', 100 ); 
  239.  
  240. return apply_filters( 
  241. 'ms_rule_content_model_check_special_page',  
  242. $content,  
  243. $this 
  244. ); 
  245.  
  246. // ********** READ MORE ********** 
  247.  
  248. /** 
  249. * Show more tag protection message. 
  250. * 
  251. * Related Action Hooks: 
  252. * - the_content_more_link 
  253. * 
  254. * @since 1.0.0 
  255. * 
  256. * @param string $more_tag_link the more tag link before filter. 
  257. * @param string $more_tag The more tag content before filter. 
  258. * @return string The protection message. 
  259. */ 
  260. public function show_moretag_protection( $more_tag_link, $more_tag ) { 
  261. $msg = stripslashes( $this->protection_message ); 
  262.  
  263. return apply_filters( 
  264. 'ms_rule_more_model_show_moretag_protection',  
  265. $msg,  
  266. $more_tag_link,  
  267. $more_tag,  
  268. $this 
  269. ); 
  270.  
  271. /** 
  272. * Replace more tag 
  273. * 
  274. * Related Action Hooks: 
  275. * - the_content 
  276. * - the_content_feed 
  277. * 
  278. * @since 1.0.0 
  279. * 
  280. * @param string $the_content The post content before filter. 
  281. * @return string The content replaced by more tag content. 
  282. */ 
  283. public function replace_more_tag_content( $the_content ) { 
  284. $more_starts_at = strpos( $the_content, '<span id="more-' ); 
  285.  
  286. if ( false !== $more_starts_at ) { 
  287. $the_content = substr( $the_content, 0, $more_starts_at ); 
  288. $the_content .= stripslashes( $this->protection_message ); 
  289.  
  290. return apply_filters( 
  291. 'ms_rule_more_model_replace_more_tag_content',  
  292. $the_content,  
  293. $this 
  294. ); 
  295.  
  296. // ********** ADMIN FUNCTIONS ********** 
  297.  
  298. /** 
  299. * Returns a list of special pages that can be configured by this rule. 
  300. * 
  301. * @since 1.0.0 
  302. * 
  303. * @param bool $flat If set to true then all pages are in the same 
  304. * hierarchy (no sub-arrays). 
  305. * @return array List of special pages. 
  306. */ 
  307. protected function get_rule_items() { 
  308. if ( ! is_array( $this->_content ) ) { 
  309. $this->_content = array(); 
  310.  
  311. $this->_content[self::COMMENT_NO_ACCESS] = (object) array( 
  312. 'label' => __( 'Comments: No Access', 'membership2' ),  
  313. ); 
  314. $this->_content[self::COMMENT_READ] = (object) array( 
  315. 'label' => __( 'Comments: Read Only Access', 'membership2' ),  
  316. ); 
  317. $this->_content[self::COMMENT_WRITE] = (object) array( 
  318. 'label' => __( 'Comments: Read and Write Access', 'membership2' ),  
  319. ); 
  320. $this->_content[self::MORE_LIMIT] = (object) array( 
  321. 'label' => __( 'Hide "read more" content', 'membership2' ),  
  322. ); 
  323.  
  324. return $this->_content; 
  325.  
  326. /** 
  327. * Count protection rules quantity. 
  328. * 
  329. * @since 1.0.0 
  330. * 
  331. * @return int $count The rule count result. 
  332. */ 
  333. public function count_rules( $args = null ) { 
  334. $count = count( $this->get_contents( $args ) ); 
  335.  
  336. return apply_filters( 
  337. 'ms_rule_content_model_count_rules',  
  338. $count,  
  339. $this 
  340. ); 
  341.  
  342. /** 
  343. * Get content to protect. 
  344. * 
  345. * @since 1.0.0 
  346. * 
  347. * @param $args Optional. Not used. 
  348. * @return array The content. 
  349. */ 
  350. public function get_contents( $args = null ) { 
  351. $items = $this->get_rule_items(); 
  352. $contents = array(); 
  353.  
  354. foreach ( $items as $key => $data ) { 
  355. $content = (object) array(); 
  356.  
  357. // Search the special page name... 
  358. if ( ! empty( $args['s'] ) ) { 
  359. if ( false === stripos( $data->label, $args['s'] ) ) { 
  360. continue; 
  361.  
  362. $content->id = $key; 
  363. $content->type = MS_Rule_Content::RULE_ID; 
  364. $content->name = $data->label; 
  365. $content->post_title = $data->label; 
  366. $content->access = $this->get_rule_value( $content->id ); 
  367.  
  368. $contents[ $content->id ] = $content; 
  369.  
  370. return apply_filters( 
  371. 'ms_rule_content_model_get_content',  
  372. $contents,  
  373. $args,  
  374. $this 
  375. ); 
  376.  
.