PageRenderTime 50ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/plugins/seo-ultimate/modules/autolinks/content-autolinks.php

https://github.com/sharpmachine/wakeupmedia.com
PHP | 495 lines | 365 code | 121 blank | 9 comment | 103 complexity | 1cf5dd64ad222f2b8249a6d210bfa17e MD5 | raw file
  1. <?php
  2. /**
  3. * Content Deeplink Juggernaut Module
  4. *
  5. * @since 2.2
  6. */
  7. if (class_exists('SU_Module')) {
  8. class SU_ContentAutolinks extends SU_Module {
  9. function get_parent_module() { return 'autolinks'; }
  10. function get_child_order() { return 10; }
  11. function is_independent_module() { return false; }
  12. function get_module_title() { return __('Content Deeplink Juggernaut', 'seo-ultimate'); }
  13. function get_module_subtitle() { return __('Content Links', 'seo-ultimate'); }
  14. function init() {
  15. add_filter('the_content', array(&$this, 'autolink_content'));
  16. add_filter('su_postmeta_help', array(&$this, 'postmeta_help'), 35);
  17. add_filter('su_get_postmeta-autolinks', array(&$this, 'get_post_autolinks'), 10, 3);
  18. add_filter('su_custom_update_postmeta-autolinks', array(&$this, 'save_post_autolinks'), 10, 4);
  19. if ($this->is_action('update'))
  20. add_action('admin_footer', array(&$this, 'outdate_max_post_dates'));
  21. add_action('save_post', array(&$this, 'outdate_max_post_dates'));
  22. $this->cron('update_max_post_dates', 'hourly');
  23. add_filter('su_get_setting-autolinks-linkfree_tags', array(&$this, 'filter_linkfree_tags'));
  24. }
  25. function filter_linkfree_tags($tags) {
  26. return sustr::preg_filter('a-z0-9,', strtolower($tags));
  27. }
  28. function autolink_content($content) {
  29. $links = $this->get_setting('links', array());
  30. if (!count($links)) return $content;
  31. suarr::vklrsort($links, 'anchor');
  32. $links = array_values($links);
  33. //Dummy vars; needed for PHP4 compat
  34. $count = 0;
  35. $link_count = array();
  36. $content = $this->_autolink_content(suwp::get_post_id(), $content, $links, $this->get_setting('limit_lpp_value', 5), $count, $link_count);
  37. return $content;
  38. }
  39. function _autolink_content($id, $content, $links, $limit, &$count, &$link_count, $round=1, $linked_urls=array(), $context='the_content') {
  40. $links = array_values($links);
  41. $count = 0;
  42. if (!is_array($link_count)) $link_count = array();
  43. $i=0; foreach ($links as $data) {
  44. if (!isset($link_count[$i]))
  45. $link_count[$i] = 0;
  46. $i++;
  47. }
  48. if (!$this->get_setting('autolink_posttype_' . get_post_type($id)))
  49. return $content;
  50. if ($this->get_postmeta('disable_autolinks', $id))
  51. return $content;
  52. $limit_enabled = $this->get_setting('limit_lpp', false);
  53. if ($limit_enabled && $limit < 1)
  54. return $content;
  55. $oldlimit = $limit;
  56. $lpa_limit_enabled = $this->get_setting('limit_lpa', false);
  57. $lpa_limit = $lpa_limit_enabled ? $this->get_setting('limit_lpa_value', 5) : -1;
  58. $lpu_limit_enabled = $this->get_setting('limit_lpu', false);
  59. $lpu_limit = $lpu_limit_enabled ? $this->get_setting('limit_lpu_value', 1) : -1;
  60. $from_post_type = get_post_type();
  61. $dest_limit = $from_post_type ? (bool)$this->get_setting('dest_limit_' . $from_post_type, false) : false;
  62. $dest_limit_taxonomies = array();
  63. if ($dest_limit) {
  64. $from_post_type_taxonomies = suwp::get_object_taxonomy_names($from_post_type);
  65. foreach ($from_post_type_taxonomies as $from_post_type_taxonomy) {
  66. if ($this->get_setting('dest_limit_' . $from_post_type . '_within_' . $from_post_type_taxonomy, false))
  67. $dest_limit_taxonomies[] = $from_post_type_taxonomy;
  68. }
  69. }
  70. $autolink_class = $this->get_setting('autolink_class', '');
  71. $post = get_post($id);
  72. $i=0;
  73. foreach ($links as $data) {
  74. $anchor = $data['anchor'];
  75. $to_id = su_esc_attr($data['to_id']);
  76. if (strlen(trim($anchor)) && $to_id !== 0 && $to_id != 'http://') {
  77. if ($context == 'the_content' && ($this->get_setting('limit_sitewide_lpa', false) || ($this->get_setting('enable_link_limits', false) && $data['sitewide_lpa'] !== false)) && isset($data['max_post_date']) && $data['max_post_date'] !== false && $post && sudate::gmt_to_unix($post->post_date_gmt) > sudate::gmt_to_unix($data['max_post_date']))
  78. continue;
  79. $type = $data['to_type'];
  80. if (sustr::startswith($type, 'posttype_')) {
  81. $to_id = intval($to_id);
  82. $to_post = get_post($to_id);
  83. if (get_post_status($to_id) != 'publish') continue;
  84. if (count($dest_limit_taxonomies)) {
  85. $shares_term = false;
  86. foreach ($dest_limit_taxonomies as $dest_limit_taxonomy) {
  87. $from_terms = suarr::flatten_values(get_the_terms(null, $dest_limit_taxonomy), 'term_id');
  88. if (is_object_in_taxonomy($to_post, $dest_limit_taxonomy))
  89. $to_terms = suarr::flatten_values(get_the_terms($to_id, $dest_limit_taxonomy), 'term_id');
  90. else
  91. $to_terms = array();
  92. if (count(array_intersect($from_terms, $to_terms))) {
  93. $shares_term = true;
  94. break;
  95. }
  96. }
  97. if (!$shares_term)
  98. continue;
  99. }
  100. $url = get_permalink($to_id);
  101. } elseif ($type == 'url')
  102. $url = $to_id;
  103. else
  104. $url = $this->jlsuggest_value_to_url($to_id ? "obj_$type/$to_id" : "obj_$type");
  105. if (!is_string($url))
  106. continue;
  107. if (!$this->get_setting('enable_current_url_links', false) && suurl::equal($url, suurl::current()))
  108. continue;
  109. if (!$this->get_setting('enable_self_links', false) && is_singular() && suurl::equal($url, get_permalink()))
  110. continue;
  111. if ($lpu_limit_enabled && isset($linked_urls[$url]) && $linked_urls[$url] >= $lpu_limit)
  112. continue;
  113. $rel = $data['nofollow'] ? ' rel="nofollow"' : '';
  114. $target = ($data['target'] == 'blank') ? ' target="_blank"' : '';
  115. $title = strlen($titletext = su_esc_attr($data['title'])) ? " title=\"$titletext\"" : '';
  116. $class = $autolink_class ? ' class="' . su_esc_attr($autolink_class) . '"' : '';
  117. $a_url = su_esc_attr($url);
  118. $h_anchor = esc_html($anchor);
  119. $link = "<a href=\"$a_url\"$title$rel$target$class>$1</a>";
  120. $lpa_lpu_limits = array();
  121. if ($lpa_limit_enabled) $lpa_lpu_limits[] = $lpa_limit;
  122. if ($lpu_limit_enabled) $lpa_lpu_limits[] = $lpu_limit;
  123. $lpa_lpu_limits = count($lpa_lpu_limits) ? sunum::lowest($lpa_lpu_limits) : -1;
  124. $content = sustr::htmlsafe_str_replace($h_anchor, $link, $content, $limit_enabled ? 1 : $lpa_lpu_limits, $new_count, $this->get_linkfree_tags());
  125. $link_count[$i] += $new_count;
  126. $count += $new_count;
  127. if ($lpu_limit_enabled) {
  128. if (isset($linked_urls[$url]))
  129. $linked_urls[$url] += $new_count;
  130. else
  131. $linked_urls[$url] = $new_count;
  132. }
  133. if ($limit_enabled) {
  134. $limit -= $new_count;
  135. if ($limit < 1) return $content;
  136. }
  137. }
  138. $i++;
  139. }
  140. if ($limit_enabled && $limit < $oldlimit && $round < $lpa_limit)
  141. $content = $this->_autolink_content($id, $content, $links, $limit, $count, $link_count, $round+1, $linked_urls, $context);
  142. return $content;
  143. }
  144. function get_linkfree_tags() {
  145. if ($linkfree_tags = $this->get_setting('linkfree_tags')) {
  146. $linkfree_tags = explode(',', $linkfree_tags);
  147. array_unshift($linkfree_tags, 'a');
  148. } else {
  149. $linkfree_tags = array('a');
  150. }
  151. return $linkfree_tags;
  152. }
  153. function outdate_max_post_dates() {
  154. $links = $this->get_setting('links', array());
  155. $new_links = array();
  156. foreach ($links as $link_data) {
  157. $link_data['max_post_date_outdated'] = true;
  158. $new_links[] = $link_data;
  159. }
  160. $this->update_setting('links', $new_links);
  161. }
  162. function update_max_post_dates() {
  163. $processing_limit = 1;
  164. $sitewide_lpa_enabled = $this->get_setting('limit_sitewide_lpa', false);
  165. $sitewide_lpa = intval($this->get_setting('limit_sitewide_lpa_value', false));
  166. $lpp = $this->get_setting('limit_lpp_value', 5); //No need to check limit_lpp, as _autolink_content already does this
  167. global $wpdb;
  168. $links = $this->get_setting('links', array());
  169. suarr::vklrsort($links, 'anchor');
  170. $links = array_values($links);
  171. $new_links = array();
  172. $i=0;
  173. foreach ($links as $link_data) {
  174. if ($link_data['max_post_date_outdated'] && $processing_limit > 0) {
  175. $link_data['max_post_date_outdated'] = false;
  176. if ($this->get_setting('enable_link_limits', false) && isset($link_data['sitewide_lpa']) && $link_data['sitewide_lpa'] !== false)
  177. $link_sitewide_lpa = intval($link_data['sitewide_lpa']);
  178. elseif ($sitewide_lpa_enabled)
  179. $link_sitewide_lpa = $sitewide_lpa;
  180. else
  181. $link_sitewide_lpa = false;
  182. if ($link_sitewide_lpa !== false) {
  183. $link_data['max_post_date'] = false;
  184. $posts_with_anchor = $wpdb->get_results( $wpdb->prepare(
  185. "SELECT ID, post_content, post_date_gmt FROM $wpdb->posts WHERE post_status = 'publish' AND LOWER(post_content) LIKE %s ORDER BY post_date_gmt ASC"
  186. , '%' . like_escape(strtolower($link_data['anchor'])) . '%'
  187. ));
  188. $count = 0;
  189. foreach ($posts_with_anchor as $post_with_anchor) {
  190. $total_count = 0; //Not used
  191. $link_count = array();
  192. $this->_autolink_content($post_with_anchor->ID, $post_with_anchor->post_content, $links, $lpp, $total_count, $link_count, 1, array(), 'update_max_post_dates');
  193. $count += $link_count[$i];
  194. if ($count >= $link_sitewide_lpa) {
  195. $link_data['max_post_date'] = $post_with_anchor->post_date_gmt;
  196. break;
  197. }
  198. }
  199. $processing_limit--;
  200. }
  201. }
  202. $new_links[] = $link_data;
  203. $i++;
  204. }
  205. $this->update_setting('links', $new_links);
  206. }
  207. function admin_page_init() {
  208. $this->jlsuggest_init();
  209. }
  210. function admin_page_contents() {
  211. echo "\n<p>";
  212. _e('The Content Links section of Deeplink Juggernaut lets you automatically link a certain word or phrase in your post/page content to a URL you specify.', 'seo-ultimate');
  213. echo "</p>\n";
  214. $links = $this->get_setting('links', array());
  215. $num_links = count($links);
  216. if ($this->is_action('update')) {
  217. $links = array();
  218. $guid = stripslashes($_POST['_link_guid']);
  219. for ($i=0; $i <= $num_links; $i++) {
  220. $anchor = stripslashes($_POST["link_{$i}_anchor"]);
  221. $to = stripslashes($_POST["link_{$i}_to"]);
  222. if (sustr::startswith($to, 'obj_')) {
  223. $to = sustr::ltrim_str($to, 'obj_');
  224. $to = explode('/', $to);
  225. if (count($to) == 2) {
  226. $to_type = $to[0];
  227. $to_id = $to[1];
  228. } else {
  229. $to_type = $to[0];
  230. $to_id = null;
  231. }
  232. } else {
  233. $to_type = 'url';
  234. $to_id = $to;
  235. }
  236. $title = stripslashes($_POST["link_{$i}_title"]);
  237. $sitewide_lpa = sustr::preg_filter('0-9', strval($_POST["link_{$i}_sitewide_lpa"]));
  238. $sitewide_lpa = ($sitewide_lpa === '') ? false : intval($sitewide_lpa);
  239. $max_post_date = sustr::preg_filter('0-9-: ', strval($_POST["link_{$i}_max_post_date"]));
  240. $target = empty($_POST["link_{$i}_target"]) ? 'self' : 'blank';
  241. $nofollow = isset($_POST["link_{$i}_nofollow"]) ? (intval($_POST["link_{$i}_nofollow"]) == 1) : false;
  242. $delete = isset($_POST["link_{$i}_delete"]) ? (intval($_POST["link_{$i}_delete"]) == 1) : false;
  243. if (!$delete && (strlen($anchor) || $to_id))
  244. $links[] = compact('anchor', 'to_type', 'to_id', 'title', 'sitewide_lpa', 'nofollow', 'target', 'max_post_date');
  245. }
  246. $this->update_setting('links', $links);
  247. $num_links = count($links);
  248. }
  249. $guid = substr(md5(time()), 0, 10);
  250. if ($num_links > 0) {
  251. $this->admin_subheader(__('Edit Existing Links', 'seo-ultimate'));
  252. $this->content_links_form($guid, 0, $links);
  253. }
  254. $this->admin_subheader(__('Add a New Link', 'seo-ultimate'));
  255. $this->content_links_form($guid, $num_links, array(array()), false);
  256. }
  257. function content_links_form($guid, $start_id = 0, $links, $delete_option = true) {
  258. $link_limits_enabled = $this->get_setting('enable_link_limits', false, null, true);
  259. $global_sitewide_lpa = $this->get_setting('limit_sitewide_lpa', false, null, true) ? $this->get_setting('limit_sitewide_lpa_value', 50, null, true) : null;
  260. //Set headers
  261. $headers = array();
  262. $headers['link-anchor'] = __('Anchor Text', 'seo-ultimate');
  263. $headers['link-to'] = __('Destination', 'seo-ultimate');
  264. $headers['link-title'] = __('Title Attribute', 'seo-ultimate');
  265. if ($link_limits_enabled)
  266. $headers['link-sitewide-lpa'] = __('Site Cap', 'seo-ultimate');
  267. $headers['link-options'] = __('Options', 'seo-ultimate');
  268. if ($delete_option)
  269. $headers['link-delete'] = __('Delete', 'seo-ultimate');
  270. //Begin table; output headers
  271. $this->admin_wftable_start($headers);
  272. //Cycle through links
  273. $i = $start_id;
  274. foreach ($links as $link) {
  275. if (!isset($link['anchor'])) $link['anchor'] = '';
  276. if (!isset($link['to_id'])) $link['to_id'] = '';
  277. if (!isset($link['to_type'])) $link['to_type'] = 'url';
  278. if (!isset($link['title'])) $link['title'] = '';
  279. if (!isset($link['sitewide_lpa'])) $link['sitewide_lpa'] = '';
  280. if (!isset($link['max_post_date'])) $link['max_post_date'] = '';
  281. if (!isset($link['nofollow'])) $link['nofollow'] = false;
  282. if (!isset($link['target'])) $link['target'] = '';
  283. $to_type_arr = array_pad(explode('_', $link['to_type'], 2), 2, null);
  284. $jlsuggest_box_params = array($to_type_arr[0], $to_type_arr[1], $link['to_id']);
  285. $cells = array();
  286. $cells['link-anchor'] = $this->get_input_element('textbox', "link_{$i}_anchor", $link['anchor']);
  287. $cells['link-to'] = $this->get_jlsuggest_box("link_{$i}_to", $jlsuggest_box_params);
  288. $cells['link-title'] = $this->get_input_element('textbox', "link_{$i}_title", $link['title']);
  289. if ($link_limits_enabled) {
  290. $cells['link-sitewide-lpa'] = $this->get_input_element('textbox', "link_{$i}_sitewide_lpa", $link['sitewide_lpa'], $global_sitewide_lpa);
  291. $cells['link-options'] = '';
  292. } else
  293. $cells['link-options'] = $this->get_input_element('hidden', "link_{$i}_sitewide_lpa", $link['sitewide_lpa']);
  294. $cells['link-options'] .= $this->get_input_element('hidden', "link_{$i}_max_post_date", $link['max_post_date']);
  295. $cells['link-options'] .=
  296. $this->get_input_element('checkbox', "link_{$i}_nofollow", $link['nofollow'], str_replace(' ', '&nbsp;', __('Nofollow', 'seo-ultimate')))
  297. .'<br />'
  298. .$this->get_input_element('checkbox', "link_{$i}_target", $link['target'] == 'blank', str_replace(' ', '&nbsp;', __('New window', 'seo-ultimate')));
  299. if ($delete_option)
  300. $cells['link-delete'] = $this->get_input_element('checkbox', "link_{$i}_delete");
  301. $this->table_row($cells, $i, 'link');
  302. $i++;
  303. }
  304. $this->admin_wftable_end();
  305. echo $this->get_input_element('hidden', '_link_guid', $guid);
  306. }
  307. function get_post_autolinks($value, $key, $post) {
  308. $links = $this->get_setting('links', array());
  309. $postlinks = '';
  310. foreach ($links as $link_data) {
  311. if ($link_data['to_type'] == 'posttype_'.$post->post_type && $link_data['to_id'] == $post->ID)
  312. $postlinks .= $link_data['anchor']."\r\n";
  313. }
  314. return trim($postlinks);
  315. }
  316. function save_post_autolinks($false, $value, $metakey, $post) {
  317. if ($post->post_type == 'revision') return true;
  318. $links = $this->get_setting('links', array());
  319. $new_links = array();
  320. $keep_anchors = array();
  321. $others_anchors = array();
  322. $new_anchors = suarr::explode_lines($value);
  323. $new_anchors = array_map('trim', $new_anchors);
  324. array_filter($new_anchors);
  325. if (count($new_anchors)) {
  326. foreach ($links as $link_data) {
  327. if ($link_data['to_type'] == 'posttype_'.$post->post_type && $link_data['to_id'] == $post->ID) {
  328. if (in_array($link_data['anchor'], $new_anchors)) {
  329. $keep_anchors[] = $link_data['anchor'];
  330. $new_links[] = $link_data;
  331. }
  332. } else {
  333. $others_anchors[] = $link_data['anchor'];
  334. $new_links[] = $link_data;
  335. }
  336. }
  337. $anchors_to_add = array_diff($new_anchors, $keep_anchors, $others_anchors);
  338. if (count($anchors_to_add)) {
  339. foreach ($anchors_to_add as $anchor_to_add) {
  340. if (trim($anchor_to_add))
  341. $new_links[] = array(
  342. 'anchor' => $anchor_to_add
  343. , 'to_type' => 'posttype_'.$post->post_type
  344. , 'to_id' => $post->ID
  345. , 'title' => ''
  346. , 'nofollow' => false
  347. , 'target' => 'self'
  348. );
  349. }
  350. }
  351. $this->update_setting('links', $new_links);
  352. }
  353. return true;
  354. }
  355. function postmeta_fields($fields) {
  356. $id = suwp::get_post_id();
  357. if ($id)
  358. $type = get_post_type($id);
  359. elseif (!empty($_GET['post_type']))
  360. $type = $_GET['post_type'];
  361. else
  362. $type = 'post';
  363. $fields['links'][10]['autolinks'] = $this->get_postmeta_textarea('autolinks', __('Inbound Autolink Anchors:<br /><em>(one per line)</em>', 'seo-ultimate'));
  364. if ($this->get_setting("autolink_posttype_$type"))
  365. $fields['links'][15]['disable_autolinks'] = $this->get_postmeta_checkbox('disable_autolinks', __('Don&#8217;t add autolinks to anchor texts found in this post.', 'seo-ultimate'), __('Autolink Exclusion:', 'seo-ultimate'));
  366. return $fields;
  367. }
  368. function postmeta_help($help) {
  369. $help[] = __('<strong>Incoming Autolink Anchors</strong> &mdash; When you enter anchors into this box, Deeplink Juggernaut will search for that anchor in all your other posts and link it to this post. For example, if the post you&#8217;re editing is about &#8220;blue widgets,&#8221; you could type &#8220;blue widgets&#8221; into the &#8220;Incoming Autolink Anchors&#8221; box and Deeplink Juggernaut will automatically build internal links to this post with that anchor text (assuming other posts contain that text). If you&#8217;re working on a draft post or a scheduled post, don&#8217;t worry &mdash; SEO Ultimate won&#8217;t add autolinks to this post until it&#8217;s published.', 'seo-ultimate');
  370. return $help;
  371. }
  372. }
  373. }
  374. ?>