= 1; $length--) { for ($offset = 0; $offset <= $count - $length; $offset++) { $slice = array_slice($words, $offset, $length); $candidate = preg_replace('/[^\p{L}\p{N}\s&+-]/u', '', implode(' ', $slice)); $candidate = preg_replace('/\s+/', ' ', trim($candidate)); if (!$this->is_linkworthy_phrase($candidate)) { continue; } $candidates[strtolower($candidate)] = $candidate; } } return array_values($candidates); } /** * Determine whether a generated keyword phrase is specific enough for linking. * * @param string $phrase Candidate phrase. * @return bool */ public function is_linkworthy_phrase($phrase) { $phrase = preg_replace('/\s+/', ' ', trim(wp_strip_all_tags((string) $phrase))); $words = $this->get_normalized_phrase_words($phrase); $word_count = count($words); $meaningful_words = array(); if (strlen($phrase) < 4 || 0 === $word_count) { return false; } if (in_array($words[0], $this->get_stopwords(), true) || in_array($words[$word_count - 1], $this->get_stopwords(), true)) { return false; } foreach ($words as $word) { if (!in_array($word, $this->get_stopwords(), true) && strlen($word) > 2) { $meaningful_words[] = $word; } } if (empty($meaningful_words)) { return false; } if (1 === $word_count) { return strlen($meaningful_words[0]) >= 5 || preg_match('/\d/', $meaningful_words[0]); } return true; } /** * Count whole-phrase matches in plain editor text. * * @param string $text Plain text. * @param string $phrase Candidate phrase. * @return int */ public function count_phrase_matches($text, $phrase) { $pattern = '/(?stopwords) { $this->stopwords = require SKYINPO_PLUGIN_PATH . 'includes/data/skyinpo-stopwords.php'; } return $this->stopwords; } }