| Total Complexity | 87 |
| Total Lines | 389 |
| Duplicated Lines | 0 % |
| Changes | 5 | ||
| Bugs | 0 | Features | 0 |
Complex classes like FeedHandler often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use FeedHandler, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 33 | class FeedHandler |
||
| 34 | { |
||
| 35 | public $rssmod; |
||
| 36 | public $pluginHandler; |
||
| 37 | public $miscHandler; |
||
| 38 | public $helper; |
||
| 39 | public $channelreq; |
||
| 40 | public $subHandler; |
||
| 41 | public $pluginObject; |
||
| 42 | public $myts; |
||
| 43 | public $modConfig; |
||
| 44 | public $xoopsConfig; |
||
| 45 | public $cached = ''; |
||
| 46 | public $charset = _CHARSET; |
||
| 47 | public $feedkey = 'feed'; |
||
| 48 | public $pluginFile = '%s.php'; |
||
| 49 | public $substrRemove = [',', '/', ';', ':', '(', '{', '[', ' ']; |
||
| 50 | public $substrAdd = ['.', '!', '?', '}', ']', ')', '%']; |
||
| 51 | public $substrEndwith = '...'; |
||
| 52 | public $specUrl = 'http://blogs.law.harvard.edu/tech/rss'; |
||
| 53 | public $specs = [ |
||
| 54 | 'req' => 'requiredChannelElements', |
||
| 55 | 'opt' => 'optionalChannelElements', |
||
| 56 | 'cloud' => 'ltcloudgtSubelementOfLtchannelgt', |
||
| 57 | 'img' => 'ltimagegtSubelementOfLtchannelgt', |
||
| 58 | ]; |
||
| 59 | public $escaped = [ |
||
| 60 | 128 => '€', |
||
| 61 | 130 => '‚', |
||
| 62 | 131 => 'ƒ', |
||
| 63 | 132 => '„', |
||
| 64 | 133 => '…', |
||
| 65 | 134 => '†', |
||
| 66 | 135 => '‡', |
||
| 67 | 136 => 'ˆ', |
||
| 68 | 137 => '‰', |
||
| 69 | 138 => 'Š', |
||
| 70 | 139 => '‹', |
||
| 71 | 140 => 'Œ', |
||
| 72 | 142 => 'Ž', |
||
| 73 | 145 => '‘', |
||
| 74 | 146 => '’', |
||
| 75 | 147 => '“', |
||
| 76 | 148 => '”', |
||
| 77 | 149 => '•', |
||
| 78 | 150 => '–', |
||
| 79 | 151 => '—', |
||
| 80 | 152 => '˜', |
||
| 81 | 153 => '™', |
||
| 82 | 154 => 'š', |
||
| 83 | 155 => '›', |
||
| 84 | 156 => 'œ', |
||
| 85 | 158 => 'ž', |
||
| 86 | 159 => 'Ÿ', |
||
| 87 | ]; |
||
| 88 | |||
| 89 | /** |
||
| 90 | * FeedHandler constructor. |
||
| 91 | */ |
||
| 92 | public function __construct(array $modConfig, array $xoopsConfig, \XoopsModule $xoopsModule) |
||
| 93 | { |
||
| 94 | $this->myts = \MyTextSanitizer::getInstance(); |
||
| 95 | $this->rssmod = $xoopsModule; |
||
| 96 | $this->helper = Helper::getInstance(); |
||
| 97 | $this->pluginHandler = Helper::getInstance()->getHandler('Plugin'); |
||
| 98 | $this->miscHandler = Helper::getInstance()->getHandler('Misc'); |
||
| 99 | $this->modConfig = $modConfig; |
||
| 100 | $this->xoopsConfig = $xoopsConfig; |
||
| 101 | $this->channelreq = [ |
||
| 102 | 'title' => $this->xoopsConfig['sitename'], |
||
| 103 | 'link' => XOOPS_URL, |
||
| 104 | 'description' => $this->xoopsConfig['slogan'], |
||
| 105 | ]; |
||
| 106 | } |
||
| 107 | |||
| 108 | public function getChannel(array &$feed): void |
||
| 109 | { |
||
| 110 | $channel = []; |
||
| 111 | $elements = $this->miscHandler->getObjects2(new \Criteria('misc_category', 'channel')); |
||
| 112 | if (\is_array($elements) && !empty($elements)) { |
||
| 113 | foreach ($elements as $e) { |
||
| 114 | if ('' !== $e->getVar('misc_content')) { |
||
| 115 | $channel[$e->getVar('misc_title')] = $e->getVar('misc_content', 'n'); |
||
| 116 | } |
||
| 117 | } |
||
| 118 | $channel['language'] = _LANGCODE; |
||
| 119 | $channel['lastBuildDate'] = $this->rssTimeStamp(\time()); |
||
| 120 | if ($this->modConfig['cache']) { |
||
| 121 | $channel['ttl'] = (string)$this->modConfig['cache']; |
||
| 122 | } |
||
| 123 | } |
||
| 124 | if (!empty($feed['plugin'])) { |
||
| 125 | if (\is_object($this->pluginObject) && \is_object($this->subHandler)) { |
||
| 126 | $channel['title'] = $this->pluginObject->getVar('sub_title', 'n'); |
||
| 127 | $channel['link'] = $this->pluginObject->getVar('sub_link', 'n'); |
||
| 128 | $channel['description'] = $this->pluginObject->getVar('sub_desc', 'n'); |
||
| 129 | $image = [ |
||
| 130 | 'url' => $this->pluginObject->getVar('img_url', 'n'), |
||
| 131 | 'title' => $this->pluginObject->getVar('img_title', 'n'), |
||
| 132 | 'link' => $this->pluginObject->getVar('img_link', 'n'), |
||
| 133 | ]; |
||
| 134 | } |
||
| 135 | } else { |
||
| 136 | $img = $this->miscHandler->getObjects2(new \Criteria('misc_category', 'channelimg'), '*', 'title'); |
||
| 137 | if ($img) { |
||
| 138 | $image = [ |
||
| 139 | 'url' => $img['url']->getVar('misc_content', 'n'), |
||
| 140 | 'title' => $img['title']->getVar('misc_content', 'n'), |
||
| 141 | 'link' => $img['link']->getVar('misc_content', 'n'), |
||
| 142 | ]; |
||
| 143 | } |
||
| 144 | } |
||
| 145 | if (empty($channel['title']) || empty($channel['link']) || empty($channel['description'])) { |
||
| 146 | $channel = \array_merge($channel, $this->channelreq); |
||
| 147 | } |
||
| 148 | foreach ($channel as $k => $v) { |
||
| 149 | |||
| 150 | $this->cleanupChars($channel[$k]); |
||
| 151 | } |
||
| 152 | if (!empty($image)) { |
||
| 153 | foreach ($image as $k => $v) { |
||
| 154 | $this->cleanupChars($image[$k]); |
||
| 155 | } |
||
| 156 | $feed['image'] = &$image; |
||
| 157 | } |
||
| 158 | $feed['channel'] = &$channel; |
||
| 159 | } |
||
| 160 | |||
| 161 | public function getSticky(array &$feed): bool |
||
| 162 | { |
||
| 163 | if (!$intr = $this->miscHandler->getObjects2(new \Criteria('misc_category', 'sticky'))) { |
||
| 164 | return false; |
||
| 165 | } |
||
| 166 | $sticky = &$intr[0]; |
||
| 167 | unset($intr); |
||
| 168 | $setting = $sticky->getVar('misc_setting'); |
||
| 169 | if (\in_array(0, $setting['feeds']) || '' === $sticky->getVar('misc_title') || '' === $sticky->getVar('misc_content')) { |
||
| 170 | return false; |
||
| 171 | } |
||
| 172 | if ((\in_array(-1, $setting['feeds']) && empty($feed['plugin'])) |
||
| 173 | || (!empty($feed['plugin']) && \in_array($this->pluginObject->getVar('rssf_conf_id'), $setting['feeds']))) { |
||
| 174 | $feed['sticky']['title'] = $sticky->getVar('misc_title', 'n'); |
||
| 175 | $feed['sticky']['link'] = $setting['link']; |
||
| 176 | $sticky->setDoHtml((bool)$setting['dohtml']); |
||
| 177 | $sticky->setDoBr((bool)$setting['dobr']); |
||
| 178 | $feed['sticky']['description'] = $sticky->getVar('misc_content'); |
||
| 179 | $this->cleanupChars($feed['sticky']['title']); |
||
| 180 | $this->cleanupChars($feed['sticky']['link']); |
||
| 181 | $this->cleanupChars($feed['sticky']['description'], !$setting['dohtml'], false); |
||
| 182 | $this->wrapCdata($feed['sticky']['description']); |
||
| 183 | $feed['sticky']['pubdate'] = $this->rssTimeStamp(\time()); |
||
| 184 | } |
||
| 185 | |||
| 186 | return true; |
||
| 187 | } |
||
| 188 | |||
| 189 | public function getItems(array &$feed): void |
||
| 190 | { |
||
| 191 | $entries = []; |
||
| 192 | $db = \XoopsDatabaseFactory::getDatabaseConnection(); |
||
| 193 | if (!empty($feed['plugin'])) { |
||
| 194 | $this->pluginObject->setVar('rssf_grab', $this->pluginObject->getVar('sub_entries')); |
||
| 195 | $this->subHandler->grab = $this->pluginObject->getVar('sub_entries'); |
||
| 196 | $grab = $this->subHandler->grabEntries($db); |
||
| 197 | if (null !== $grab && \count($grab) > 0) { |
||
| 198 | foreach ($grab as $g) { |
||
| 199 | $entries[] = $g; |
||
| 200 | } |
||
| 201 | } |
||
| 202 | } elseif ($plugins = $this->pluginHandler->getObjects2(new \Criteria('rssf_activated', '1'))) { |
||
| 203 | foreach ($plugins as $p) { |
||
| 204 | $handler = $this->pluginHandler->checkPlugin($p); |
||
| 205 | if ($handler) { |
||
| 206 | $handler->grab = $p->getVar('rssf_grab'); |
||
| 207 | $grab = $handler->grabEntries($db); |
||
| 208 | if (null !== $grab && \count($grab) > 0) { |
||
| 209 | foreach ($grab as $g) { |
||
| 210 | $entries[] = $g; |
||
| 211 | } |
||
| 212 | } |
||
| 213 | } |
||
| 214 | } |
||
| 215 | } |
||
| 216 | if (\count($entries) > 0) { |
||
| 217 | foreach ($entries as $i => &$iValue) { |
||
| 218 | $this->cleanupChars($iValue['title']); |
||
| 219 | $strip = (bool)$this->modConfig['strip_html']; |
||
| 220 | $this->cleanupChars($iValue['description'], $strip, false, true); |
||
| 221 | $this->wrapCdata($iValue['description']); |
||
| 222 | $entries[$i]['category'] = $this->myts->undoHtmlSpecialChars($iValue['category']); |
||
| 223 | $this->cleanupChars($iValue['category']); |
||
| 224 | if (!isset($iValue['timestamp'])) { |
||
| 225 | $entries[$i]['timestamp'] = $this->rssmod->getVar('last_update'); |
||
| 226 | } |
||
| 227 | $entries[$i]['pubdate'] = $this->rssTimeStamp((int)$iValue['timestamp']); |
||
| 228 | } |
||
| 229 | unset($iValue); |
||
| 230 | |||
| 231 | if (empty($feed['plugin']) && 'd' === $this->modConfig['sort']) { |
||
| 232 | \uasort($entries, [$this, 'sortTimestamp']); |
||
| 233 | } |
||
| 234 | if (empty($feed['plugin']) && \count($entries) > $this->modConfig['overall_entries']) { |
||
| 235 | $entries = \array_slice($entries, 0, $this->modConfig['overall_entries']); |
||
| 236 | } |
||
| 237 | } |
||
| 238 | |||
| 239 | $feed['items'] = &$entries; |
||
| 240 | } |
||
| 241 | |||
| 242 | public function doSubstr(string $text): string |
||
| 243 | { |
||
| 244 | $ret = $text; |
||
| 245 | $len = \function_exists('mb_strlen') ? mb_strlen($ret, $this->charset) : mb_strlen($ret); |
||
| 246 | $maxChars = $this->helper->getConfig('max_char'); |
||
| 247 | if ($len > $maxChars && $maxChars > 0) { |
||
| 248 | $ret = $this->substrDetect($ret, 0, $maxChars - 1); |
||
| 249 | if (false === $this->strrposDetect($ret, ' ')) { |
||
| 250 | if (false !== $this->strrposDetect($text, ' ')) { |
||
| 251 | $ret = $this->substrDetect($text, 0, (int)mb_strpos($text, ' ')); |
||
| 252 | } |
||
| 253 | } |
||
| 254 | if (\in_array($this->substrDetect($text, $maxChars - 1, 1), $this->substrAdd)) { |
||
| 255 | $ret .= $this->substrDetect($text, $maxChars - 1, 1); |
||
| 256 | } else { |
||
| 257 | if (false !== $this->strrposDetect($ret, ' ')) { |
||
| 258 | $ret = $this->substrDetect($ret, 0, $this->strrposDetect($ret, ' ')); |
||
| 259 | } |
||
| 260 | if (\in_array($this->substrDetect($ret, -1, 1), $this->substrRemove)) { |
||
| 261 | $ret = $this->substrDetect($ret, 0, -1); |
||
| 262 | } |
||
| 263 | } |
||
| 264 | $ret .= $this->substrEndwith; |
||
| 265 | } |
||
| 266 | |||
| 267 | return $ret; |
||
| 268 | } |
||
| 269 | |||
| 270 | public function substrDetect(string $text, int $start, int $len): string |
||
| 271 | { |
||
| 272 | if (\function_exists('mb_strcut')) { |
||
| 273 | return mb_strcut($text, $start, $len, _CHARSET); |
||
| 274 | } |
||
| 275 | |||
| 276 | return mb_substr($text, $start, $len); |
||
| 277 | } |
||
| 278 | |||
| 279 | /** |
||
| 280 | * @return false|int |
||
| 281 | */ |
||
| 282 | public function strrposDetect(string $text, string $find) |
||
| 283 | { |
||
| 284 | if (\function_exists('mb_strrpos')) { |
||
| 285 | return mb_strrpos($text, $find, 0, _CHARSET); |
||
| 286 | } |
||
| 287 | |||
| 288 | return mb_strrpos($text, $find); |
||
| 289 | } |
||
| 290 | |||
| 291 | public function rssTimeStamp(int $time): ?string |
||
| 292 | { |
||
| 293 | return \date('D, j M Y H:i:s O', $time); |
||
| 294 | } |
||
| 295 | |||
| 296 | public function sortTimestamp(array $a, array $b): int |
||
| 297 | { |
||
| 298 | if ($a['timestamp'] === $b['timestamp']) { |
||
| 299 | return 0; |
||
| 300 | } |
||
| 301 | |||
| 302 | return ($a['timestamp'] > $b['timestamp']) ? -1 : 1; |
||
| 303 | } |
||
| 304 | |||
| 305 | public function cleanupChars(string &$text, bool $strip = true, bool $dospec = true, bool $dosub = false): void |
||
| 306 | { |
||
| 307 | if ($strip) { |
||
| 308 | $text = \strip_tags($text); |
||
| 309 | } |
||
| 310 | if ($dosub) { |
||
| 311 | $text = $this->doSubstr($text); |
||
| 312 | } |
||
| 313 | if ($dospec) { |
||
| 314 | $text = \htmlspecialchars($text, \ENT_QUOTES, $this->charset); |
||
| 315 | $text = \preg_replace('/&(#\d+);/i', '&$1;', $text); |
||
| 316 | } |
||
| 317 | if (XOOPS_USE_MULTIBYTES !== 1 || false === stripos($this->charset, "utf-8")) { |
||
|
|
|||
| 318 | $text = \str_replace(\array_map('\chr', \array_keys($this->escaped)), $this->escaped, $text); |
||
| 319 | } |
||
| 320 | } |
||
| 321 | |||
| 322 | public function wrapCdata(string &$text): void |
||
| 323 | { |
||
| 324 | $text = '<![CDATA[' . \str_replace(['<![CDATA[', ']]>'], ['<![CDATA[', ']]>'], $text) . ']]>'; |
||
| 325 | } |
||
| 326 | |||
| 327 | public function &getActivatedSubfeeds(string $fields = '', string $type = ''): ?array |
||
| 328 | { |
||
| 329 | $ret = null; |
||
| 330 | $subs = $this->pluginHandler->getObjects2(new \Criteria('subfeed', '1'), $fields); |
||
| 331 | if (\is_array($subs) && !empty($subs)) { |
||
| 332 | $ret = []; |
||
| 333 | switch ($type) { |
||
| 334 | default: |
||
| 335 | $ret = &$subs; |
||
| 336 | break; |
||
| 337 | case 'list': |
||
| 338 | foreach ($subs as $s) { |
||
| 339 | $ret[$s->getVar('rssf_conf_id')] = $s->getVar('sub_title'); |
||
| 340 | } |
||
| 341 | break; |
||
| 342 | } |
||
| 343 | } |
||
| 344 | |||
| 345 | return $ret; |
||
| 346 | } |
||
| 347 | |||
| 348 | /** |
||
| 349 | * @param null|string|array $selected |
||
| 350 | */ |
||
| 351 | public function feedSelectBox(string $caption = '', $selected = null, int $size = 1, bool $multi = true, bool $none = true, bool $main = true, string $name = 'feeds', string $type = 'id'): \XoopsFormSelect |
||
| 368 | } |
||
| 369 | |||
| 370 | /** |
||
| 371 | * @return string |
||
| 372 | */ |
||
| 373 | public function specUrl(string $key = '0'): ?string |
||
| 374 | { |
||
| 375 | if (isset($this->specs[$key])) { |
||
| 376 | return $this->specUrl . '#' . $this->specs[$key]; |
||
| 377 | } |
||
| 378 | |||
| 379 | return null; |
||
| 380 | } |
||
| 381 | |||
| 382 | /** |
||
| 383 | * @return string |
||
| 384 | */ |
||
| 385 | public function subFeedUrl(string $filename = ''): ?string |
||
| 394 | } |
||
| 395 | |||
| 396 | public function checkSubFeed(array &$feed): void |
||
| 397 | { |
||
| 398 | if (!empty($feed['plugin'])) { |
||
| 399 | $criteria = new \CriteriaCompo(); |
||
| 400 | $criteria->add(new \Criteria('rssf_filename', \sprintf($this->pluginFile, $feed['plugin']))); |
||
| 401 | $criteria->add(new \Criteria('subfeed', '1')); |
||
| 402 | $sub = $this->pluginHandler->getObjects2($criteria); |
||
| 403 | $handler = null; |
||
| 404 | if (isset($sub[0])) { |
||
| 405 | $handler = $this->pluginHandler->checkPlugin($sub[0]); |
||
| 406 | } |
||
| 407 | if ($handler) { |
||
| 408 | $this->pluginObject = $sub[0]; |
||
| 409 | $this->subHandler = $handler; |
||
| 410 | $this->cached = 'mod_' . $this->rssmod->getVar('dirname') . '|' . \md5(\str_replace(XOOPS_URL, '', $GLOBALS['xoopsRequestUri'])); |
||
| 411 | } else { |
||
| 412 | $feed['plugin'] = ''; |
||
| 413 | } |
||
| 414 | } |
||
| 415 | } |
||
| 416 | |||
| 417 | public function buildFeed(array &$feed): void |
||
| 422 | } |
||
| 423 | } |
||
| 424 |