PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 12.5.2
Jetpack – WP Security, Backup, Speed, & Growth v12.5.2
12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 13.9.2 14.0.1 14.1.1 14.2.2 14.3.1 14.4.2 All 500 releases
jetpack / vendor / nojimage / twitter-text-php / lib / Twitter / Text / Parser.php
Parser.php
191 lines 5.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * @author Takashi Nojima
5 * @copyright Copyright 2018, Takashi Nojima
6 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License v2.0
7 * @package Twitter.Text
8 */
9
10 namespace Twitter\Text;
11
12 /**
13 * Twitter Text Parser
14 *
15 * @author Takashi Nojima
16 * @copyright Copyright 2018, Takashi Nojima
17 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License v2.0
18 * @package Twitter.Text
19 */
20 class Parser
21 {
22 /**
23 * @var Configuration
24 */
25 private $config;
26
27 /**
28 * Create a Parser
29 *
30 * @param Configuration $config
31 * @return Parser
32 */
33 public static function create(Configuration $config = null)
34 {
35 return new self($config);
36 }
37
38 /**
39 * construct
40 *
41 * @param Configuration $config
42 */
43 public function __construct(Configuration $config = null)
44 {
45 if ($config === null) {
46 $config = new Configuration();
47 }
48
49 $this->config = $config;
50 }
51
52 /**
53 * Parses a given tweet text with the weighted character count configuration
54 *
55 * @param string $tweet which is to be parsed
56 * @return ParseResults
57 */
58 public function parseTweet($tweet)
59 {
60 if ($tweet === null || '' === $tweet) {
61 return new ParseResults();
62 }
63
64 $normalizedTweet = StringUtils::normalizeFromNFC($tweet);
65 $normalizedTweetLength = StringUtils::strlen($normalizedTweet);
66
67 $emojiParsingEnabled = $this->config->getEmojiParsingEnabled();
68 $maxWeightedTweetLength = $this->config->getScaledMaxWeightedTweetLength();
69 $transformedUrlWeight = $this->config->getScaledTransformedURLLength();
70
71 $extractor = new Extractor();
72 $urlEntitiesMap = $this->transformEntitiesToHash($extractor->extractURLsWithIndices($normalizedTweet));
73 $emojiEntitiesMap = $emojiParsingEnabled
74 ? $this->transformEntitiesToHash($extractor->extractEmojiWithIndices($normalizedTweet))
75 : array();
76
77 $hasInvalidCharacters = false;
78 $weightedCount = 0;
79 $offset = 0;
80 $displayOffset = 0;
81 $validOffset = 0;
82
83 while ($offset < $normalizedTweetLength) {
84 if (isset($urlEntitiesMap[$offset])) {
85 list($urlStart, $urlEnd) = $urlEntitiesMap[$offset]['indices'];
86 $urlLength = $urlEnd - $urlStart;
87
88 $weightedCount += $transformedUrlWeight;
89 $offset += $urlLength;
90 $displayOffset += $urlLength;
91 if ($weightedCount <= $maxWeightedTweetLength) {
92 $validOffset += $urlLength;
93 }
94 } elseif ($emojiParsingEnabled && isset($emojiEntitiesMap[$offset])) {
95 $emoji = $emojiEntitiesMap[$offset]['emoji'];
96 $emojiLength = StringUtils::strlen($emoji);
97 $charCount = StringUtils::charCount($emoji);
98
99 $weightedCount += $this->config->defaultWeight;
100 $offset += $emojiLength;
101 $displayOffset += $charCount;
102 if ($weightedCount <= $maxWeightedTweetLength) {
103 $validOffset += $charCount;
104 }
105 } else {
106 $char = StringUtils::substr($normalizedTweet, $offset, 1);
107
108 $hasInvalidCharacters = $hasInvalidCharacters || $this->hasInvalidCharacters($char);
109 $charCount = StringUtils::strlen($char);
110 $charWidth = StringUtils::isSurrogatePair($char) ? 2 : 1;
111
112 $weightedCount += $this->getCharacterWeight($char, $this->config);
113 $offset += $charCount;
114 $displayOffset += $charWidth;
115
116 if (!$hasInvalidCharacters && $weightedCount <= $maxWeightedTweetLength) {
117 $validOffset += $charWidth;
118 }
119 }
120 }
121
122 $scaledWeightedLength = $weightedCount / $this->config->scale;
123 $permillage = $scaledWeightedLength * 1000 / $this->config->maxWeightedTweetLength;
124 $isValid = !$hasInvalidCharacters && $weightedCount <= $maxWeightedTweetLength;
125
126 $normalizedTweetOffset = StringUtils::strlen($tweet) - $normalizedTweetLength;
127 $displayTextRange = array(0, $displayOffset + $normalizedTweetOffset - 1);
128 $validTextRange = array(0, $validOffset + $normalizedTweetOffset - 1);
129
130 return new ParseResults($scaledWeightedLength, $permillage, $isValid, $displayTextRange, $validTextRange);
131 }
132
133 /**
134 * Convert to Hash by indices start
135 *
136 * @param array $entities
137 * @return array
138 */
139 private function transformEntitiesToHash(array $entities)
140 {
141 return array_reduce($entities, function ($map, $entity) {
142 $map[$entity['indices'][0]] = $entity;
143
144 return $map;
145 }, array());
146 }
147
148 /**
149 * Get the character weight from ranges
150 *
151 * @param string $char the Character
152 * @param Configuration $config the parse configuration
153 * @return int
154 */
155 private function getCharacterWeight($char, Configuration $config)
156 {
157 $codePoint = StringUtils::ord($char);
158
159 foreach ($config->ranges as $range) {
160 if ($this->inRange($codePoint, $range)) {
161 return $range['weight'];
162 }
163 }
164
165 return $config->defaultWeight;
166 }
167
168 /**
169 * check codepoint in range
170 *
171 * @param int $codePoint
172 * @param array $range
173 * @return boolean
174 */
175 private function inRange($codePoint, array $range)
176 {
177 return ($codePoint >= $range['start'] && $codePoint <= $range['end']);
178 }
179
180 /**
181 * check has invalid characters
182 *
183 * @param string $char
184 * @return bool
185 */
186 private function hasInvalidCharacters($char)
187 {
188 return preg_match(Regex::getInvalidCharactersMatcher(), $char);
189 }
190 }
191