/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 = $this->get_rule_value( self::COMMENT_WRITE ); 
  126. $has_read = $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. $this->protection_message = MS_Plugin::instance()->settings->get_protection_message( 
  151. MS_Model_Settings::PROTECTION_MSG_MORE_TAG,  
  152. $this->membership_id 
  153. ); 
  154.  
  155. if ( ! parent::has_access( self::MORE_LIMIT ) ) { 
  156. $this->add_filter( 'the_content_more_link', 'show_moretag_protection', 99, 2 ); 
  157. $this->add_filter( 'the_content', 'replace_more_tag_content', 1 ); 
  158. $this->add_filter( 'the_content_feed', 'replace_more_tag_content', 1 ); 
  159.  
  160. // ********* COMMENTS ********** 
  161.  
  162. /** 
  163. * Setup the comment permissions after all membership rules were parsed. 
  164. * 
  165. * @since 1.0.0 
  166. */ 
  167. public function protect_comments() { 
  168. static $Done = false; 
  169.  
  170. if ( $Done ) { return; } 
  171. $Done = true; 
  172.  
  173. switch ( self::$comment_access ) { 
  174. case self::COMMENT_WRITE: 
  175. // Don't change the inherent comment status. 
  176. break; 
  177.  
  178. case self::COMMENT_READ: 
  179. $this->add_filter( 'comment_form_before', 'hide_form_start', 1 ); 
  180. $this->add_filter( 'comment_form_after', 'hide_form_end', 99 ); 
  181. add_filter( 'comment_reply_link', '__return_null', 99 ); 
  182. break; 
  183.  
  184. case self::COMMENT_NO_ACCESS: 
  185. add_filter( 'comments_open', '__return_false', 99 ); 
  186. add_filter( 'get_comments_number', '__return_zero', 99 ); 
  187. break; 
  188.  
  189. /** 
  190. * Before the comment form is output we start buffering. 
  191. * 
  192. * @since 1.0.0 
  193. */ 
  194. public function hide_form_start() { 
  195. ob_start(); 
  196.  
  197. /** 
  198. * At the end of the comment form we clear the buffer: The form is gone! 
  199. * 
  200. * @since 1.0.0 
  201. */ 
  202. public function hide_form_end() { 
  203. ob_end_clean(); 
  204.  
  205. /** 
  206. * Close comments for membership special pages. 
  207. * 
  208. * Related Action Hooks: 
  209. * - the_content 
  210. * 
  211. * @since 1.0.0 
  212. * 
  213. * @param string $content The content to filter. 
  214. */ 
  215. public function check_special_page( $content ) { 
  216. if ( MS_Model_Pages::is_membership_page() ) { 
  217. add_filter( 'comments_open', '__return_false', 100 ); 
  218.  
  219. return apply_filters( 
  220. 'ms_rule_content_model_check_special_page',  
  221. $content,  
  222. $this 
  223. ); 
  224.  
  225. // ********** READ MORE ********** 
  226.  
  227. /** 
  228. * Show more tag protection message. 
  229. * 
  230. * Related Action Hooks: 
  231. * - the_content_more_link 
  232. * 
  233. * @since 1.0.0 
  234. * 
  235. * @param string $more_tag_link the more tag link before filter. 
  236. * @param string $more_tag The more tag content before filter. 
  237. * @return string The protection message. 
  238. */ 
  239. public function show_moretag_protection( $more_tag_link, $more_tag ) { 
  240. $msg = stripslashes( $this->protection_message ); 
  241.  
  242. return apply_filters( 
  243. 'ms_rule_more_model_show_moretag_protection',  
  244. $msg,  
  245. $more_tag_link,  
  246. $more_tag,  
  247. $this 
  248. ); 
  249.  
  250. /** 
  251. * Replace more tag 
  252. * 
  253. * Related Action Hooks: 
  254. * - the_content 
  255. * - the_content_feed 
  256. * 
  257. * @since 1.0.0 
  258. * 
  259. * @param string $the_content The post content before filter. 
  260. * @return string The content replaced by more tag content. 
  261. */ 
  262. public function replace_more_tag_content( $the_content ) { 
  263. $more_starts_at = strpos( $the_content, '<span id="more-' ); 
  264.  
  265. if ( false !== $more_starts_at ) { 
  266. $the_content = substr( $the_content, 0, $more_starts_at ); 
  267. $the_content .= stripslashes( $this->protection_message ); 
  268.  
  269. return apply_filters( 
  270. 'ms_rule_more_model_replace_more_tag_content',  
  271. $the_content,  
  272. $this 
  273. ); 
  274.  
  275. // ********** ADMIN FUNCTIONS ********** 
  276.  
  277. /** 
  278. * Returns a list of special pages that can be configured by this rule. 
  279. * 
  280. * @since 1.0.0 
  281. * 
  282. * @param bool $flat If set to true then all pages are in the same 
  283. * hierarchy (no sub-arrays). 
  284. * @return array List of special pages. 
  285. */ 
  286. protected function get_rule_items() { 
  287. if ( ! is_array( $this->_content ) ) { 
  288. $this->_content = array(); 
  289.  
  290. $this->_content[self::COMMENT_NO_ACCESS] = (object) array( 
  291. 'label' => __( 'Comments: No Access', 'membership2' ),  
  292. ); 
  293. $this->_content[self::COMMENT_READ] = (object) array( 
  294. 'label' => __( 'Comments: Read Only Access', 'membership2' ),  
  295. ); 
  296. $this->_content[self::COMMENT_WRITE] = (object) array( 
  297. 'label' => __( 'Comments: Read and Write Access', 'membership2' ),  
  298. ); 
  299. $this->_content[self::MORE_LIMIT] = (object) array( 
  300. 'label' => __( 'Hide "read more" content', 'membership2' ),  
  301. ); 
  302.  
  303. return $this->_content; 
  304.  
  305. /** 
  306. * Count protection rules quantity. 
  307. * 
  308. * @since 1.0.0 
  309. * 
  310. * @return int $count The rule count result. 
  311. */ 
  312. public function count_rules( $args = null ) { 
  313. $count = count( $this->get_contents( $args ) ); 
  314.  
  315. return apply_filters( 
  316. 'ms_rule_content_model_count_rules',  
  317. $count,  
  318. $this 
  319. ); 
  320.  
  321. /** 
  322. * Get content to protect. 
  323. * 
  324. * @since 1.0.0 
  325. * 
  326. * @param $args Optional. Not used. 
  327. * @return array The content. 
  328. */ 
  329. public function get_contents( $args = null ) { 
  330. $items = $this->get_rule_items(); 
  331. $contents = array(); 
  332.  
  333. foreach ( $items as $key => $data ) { 
  334. $content = (object) array(); 
  335.  
  336. // Search the special page name... 
  337. if ( ! empty( $args['s'] ) ) { 
  338. if ( false === stripos( $data->label, $args['s'] ) ) { 
  339. continue; 
  340.  
  341. $content->id = $key; 
  342. $content->type = MS_Rule_Content::RULE_ID; 
  343. $content->name = $data->label; 
  344. $content->post_title = $data->label; 
  345. $content->access = $this->get_rule_value( $content->id ); 
  346.  
  347. $contents[ $content->id ] = $content; 
  348.  
  349. return apply_filters( 
  350. 'ms_rule_content_model_get_content',  
  351. $contents,  
  352. $args,  
  353. $this 
  354. ); 
  355.  
.