<?php class DribbbleBridge extends BridgeAbstract { const MAINTAINER = 'quentinus95'; const NAME = 'Dribbble popular shots'; const URI = 'https://dribbble.com'; const CACHE_TIMEOUT = 1800; const DESCRIPTION = 'Returns the newest popular shots from Dribbble.'; public function getIcon() { return 'https://cdn.dribbble.com/assets/ favicon-63b2904a073c89b52b19aa08cebc16a154bcf83fee8ecc6439968b1e6db569c7.ico'; } public function collectData() { $html = getSimpleHTMLDOM(self::URI); $data = $this->fetchData($html); foreach ($html->find('li[id^="screenshot-"]') as $shot) { $item = []; $additional_data = $this->findJsonForShot($shot, $data); if ($additional_data === null) { $item['uri'] = self::URI . $shot->find('a', 0)->href; $item['title'] = $shot->find('.shot-title', 0)->plaintext; } else { $item['timestamp'] = strtotime($additional_data['published_at']); $item['uri'] = self::URI . $additional_data['path']; $item['title'] = $additional_data['title']; } $item['author'] = trim($shot->find('.user-information .display-name', 0)->plaintext); $description = $shot->find('.comment', 0); $item['content'] = $description === null ? '' : $description->plaintext; $preview_path = $shot->find('figure img', 1)->attr['data-srcset']; $item['content'] .= $this->getImageTag($preview_path, $item['title']); $item['enclosures'] = [$this->getFullSizeImagePath($preview_path)]; $this->items[] = $item; } } private function fetchData($html) { $scripts = $html->find('script'); foreach ($scripts as $script) { if (strpos($script->innertext, 'newestShots') !== false) { // fix single quotes $script->innertext = preg_replace('/\'(.*)\'(,?)$/im', '"\1"\2', $script->innertext); // fix JavaScript JSON (why do they not adhere to the standard?) $script->innertext = preg_replace('/^(\s*)(\w+):/im', '\1"\2":', $script->innertext); // fix relative dates, so they are recognized by strtotime $script->innertext = preg_replace('/"about ([0-9]+ hours? ago)"(,?)$/im', '"\1"\2', $script->innertext); // find beginning of JSON array $start = strpos($script->innertext, '['); // find end of JSON array, compensate for missing character! $end = strpos($script->innertext, '];') + 1; // convert JSON to PHP array $json = substr($script->innertext, $start, $end - $start); try { // TODO: fix broken json return Json::decode($json); } catch (\JsonException $e) { return []; } } } return []; } private function findJsonForShot($shot, $json) { foreach ($json as $element) { if (strpos($shot->getAttribute('id'), (string)$element['id']) !== false) { return $element; } } return null; } private function getImageTag($preview_path, $title) { return sprintf( '<br /> <a href="%s"><img srcset="%s" alt="%s" /></a>', $this->getFullSizeImagePath($preview_path), $preview_path, $title ); } private function getFullSizeImagePath($preview_path) { // Get last image from srcset $src_set_urls = explode(',', $preview_path); $url = end($src_set_urls); $url = explode(' ', $url)[1]; return htmlspecialchars_decode($url); } }