diff options
Diffstat (limited to 'bridges/DealabsBridge.php')
-rw-r--r-- | bridges/DealabsBridge.php | 339 |
1 files changed, 227 insertions, 112 deletions
diff --git a/bridges/DealabsBridge.php b/bridges/DealabsBridge.php index d2cab2f..fb88f37 100644 --- a/bridges/DealabsBridge.php +++ b/bridges/DealabsBridge.php @@ -1,8 +1,9 @@ <?php -class DealabsBridge extends BridgeAbstract { - const NAME = 'Dealabs search bridge'; +class DealabsBridge extends PepperBridgeAbstract { + + const NAME = 'Dealabs Bridge'; const URI = 'https://www.dealabs.com/'; - const DESCRIPTION = 'Return the Dealabs search result using keywords'; + const DESCRIPTION = 'Affiche les Deals de Dealabs'; const MAINTAINER = 'sysadminstory'; const PARAMETERS = array( 'Recherche par Mot(s) clé(s)' => array ( @@ -39,7 +40,7 @@ class DealabsBridge extends BridgeAbstract { ), 'Deals par groupe' => array( - 'groupe' => array( + 'group' => array( 'name' => 'Groupe', 'type' => 'list', 'required' => 'true', @@ -61,10 +62,10 @@ class DealabsBridge extends BridgeAbstract { 'Services divers' => 'services-divers', 'Sports & plein air' => 'sports-plein-air', 'Téléphonie' => 'telephonie', - 'Voyages & sorties' => 'voyages-sorties-restaurants' + 'Voyages & sorties' => 'voyages-sorties-restaurants', ) ), - 'ordre' => array( + 'order' => array( 'name' => 'Trier par', 'type' => 'list', 'required' => 'true', @@ -78,37 +79,99 @@ class DealabsBridge extends BridgeAbstract { ) ); + public $lang = array( + 'bridge-uri' => SELF::URI, + 'bridge-name' => SELF::NAME, + 'context-keyword' => 'Recherche par Mot(s) clé(s)', + 'context-group' => 'Deals par groupe', + 'uri-group' => '/groupe/', + 'request-error' => 'Could not request Dealabs', + 'no-results' => 'Il n'y a rien à afficher pour le moment :(', + 'relative-date-indicator' => array( + 'il y a', + ), + 'price' => 'Prix', + 'shipping' => 'Livraison', + 'origin' => 'Origine', + 'discount' => 'Réduction', + 'title-keyword' => 'Recherche', + 'title-group' => 'Groupe', + 'local-months' => array( + 'janvier', + 'février', + 'mars', + 'avril', + 'mai', + 'juin', + 'juillet', + 'août', + 'septembre', + 'octobre', + 'novembre', + 'décembre' + ), + 'local-time-relative' => array( + 'il y a ', + 'min', + 'h', + 'jour', + 'jours', + 'mois', + 'ans', + 'et ' + ), + 'date-prefixes' => array( + 'Actualisé ', + ), + 'relative-date-alt-prefixes' => array( + 'Actualisé ', + ), + 'relative-date-ignore-suffix' => array( + ), + + 'localdeal' => array( + 'Local', + 'Pays d\'expédition' + ), + ); + + + +} + +class PepperBridgeAbstract extends BridgeAbstract { + const CACHE_TIMEOUT = 3600; public function collectData(){ switch($this->queriedContext) { - case 'Recherche par Mot(s) clé(s)': - return $this->collectDataMotsCles(); + case $this->i8n('context-keyword'): + return $this->collectDataKeywords(); break; - case 'Deals par groupe': - return $this->collectDataGroupe(); + case $this->i8n('context-group'): + return $this->collectDataGroup(); break; } } /** - * Get the Deal data from the choosen groupe in the choose order + * Get the Deal data from the choosen group in the choosed order */ - public function collectDataGroupe() + public function collectDataGroup() { - $groupe = $this->getInput('groupe'); - $ordre = $this->getInput('ordre'); + $group = $this->getInput('group'); + $order = $this->getInput('order'); - $url = self::URI - . '/groupe/' . $groupe . $ordre; + $url = $this->i8n('bridge-uri') + . $this->i8n('uri-group') . $group . $order; $this->collectDeals($url); } /** * Get the Deal data from the choosen keywords and parameters */ - public function collectDataMotsCles() + public function collectDataKeywords() { $q = $this->getInput('q'); $hide_expired = $this->getInput('hide_expired'); @@ -117,7 +180,7 @@ class DealabsBridge extends BridgeAbstract { $priceTo = $this->getInput('priceFrom'); /* Even if the original website uses POST with the search page, GET works too */ - $url = self::URI + $url = $this->i8n('bridge-uri') . '/search/advanced?q=' . urlencode($q) . '&hide_expired='. $hide_expired @@ -138,8 +201,8 @@ class DealabsBridge extends BridgeAbstract { */ public function collectDeals($url){ $html = getSimpleHTMLDOM($url) - or returnServerError('Could not request Dealabs.'); - $list = $html->find('article'); + or returnServerError($this->i8n('request-error')); + $list = $html->find('article[id]'); // Deal Image Link CSS Selector $selectorImageLink = implode( @@ -148,7 +211,6 @@ class DealabsBridge extends BridgeAbstract { 'cept-thread-image-link', 'imgFrame', 'imgFrame--noBorder', - 'box--all-i', 'thread-listImgCell', ) ); @@ -160,9 +222,6 @@ class DealabsBridge extends BridgeAbstract { 'cept-tt', 'thread-link', 'linkPlain', - 'space--r-1', - 'size--all-s', - 'size--fromW3-m', ) ); @@ -184,7 +243,7 @@ class DealabsBridge extends BridgeAbstract { 'cept-description-container', 'overflow--wrap-break', 'size--all-s', - 'size--fromW3-m', + 'size--fromW3-m' ) ); @@ -194,7 +253,6 @@ class DealabsBridge extends BridgeAbstract { array( 'size--all-s', 'flex', - 'flex--wrap', 'flex--justify-e', 'flex--grow-1', ) @@ -202,40 +260,44 @@ class DealabsBridge extends BridgeAbstract { // If there is no results, we don't parse the content because it display some random deals $noresult = $html->find('h3[class=size--all-l size--fromW2-xl size--fromW3-xxl]', 0); - if($noresult != null && $noresult->plaintext == 'Il n'y a rien à afficher pour le moment :(') { + if ($noresult != null && strpos($noresult->plaintext, $this->i8n('no-results')) !== false) { $this->items = array(); } else { - foreach($list as $deal) { + foreach ($list as $deal) { $item = array(); $item['uri'] = $deal->find('div[class=threadGrid-title]', 0)->find('a', 0)->href; - $item['title'] = $deal->find('a[class='. $selectorLink .']', 0 - )->plaintext; + $item['title'] = $deal->find('a[class*='. $selectorLink .']', 0 + )->plaintext; $item['author'] = $deal->find('span.thread-username', 0)->plaintext; $item['content'] = '<table><tr><td><a href="' . $deal->find( 'a[class*='. $selectorImageLink .']', 0)->href - . '"><img src="' - . $this->getImage($deal) - . '"/></td><td><h2><a href="' - . $deal->find('a[class='. $selectorLink .']', 0)->href - . '">' - . $deal->find('a[class='. $selectorLink .']', 0)->innertext - . '</a></h2>' - . $this->getPrix($deal) - . $this->getReduction($deal) - . $this->getExpedition($deal) - . $this->getLivraison($deal) - . $this->getOrigine($deal) - . $deal->find('div[class='. $selectorDescription .']', 0)->innertext - . '</td><td>' - . $deal->find('div[class='. $selectorHot .']', 0)->children(0)->outertext - . '</td></table>'; - $dealDateDiv = $deal->find('div[class='. $selectorDate .']', 0) + . '"><img src="' + . $this->getImage($deal) + . '"/></td><td><h2><a href="' + . $deal->find('a[class*='. $selectorLink .']', 0)->href + . '">' + . $deal->find('a[class*='. $selectorLink .']', 0)->innertext + . '</a></h2>' + . $this->getPrice($deal) + . $this->getDiscount($deal) + . $this->getShipsFrom($deal) + . $this->getShippingCost($deal) + . $this->GetSource($deal) + . $deal->find('div[class*='. $selectorDescription .']', 0)->innertext + . '</td><td>' + . $deal->find('div[class='. $selectorHot .']', 0)->children(0)->outertext + . '</td></table>'; + $dealDateDiv = $deal->find('div[class*='. $selectorDate .']', 0) ->find('span[class=hide--toW3]'); $itemDate = end($dealDateDiv)->plaintext; - if(substr( $itemDate, 0, 6 ) === 'il y a') { + // In case of a Local deal, there is no date, but we can use + // this case for other reason (like date not in the last field) + if ($this->contains($itemDate, $this->i8n('localdeal'))) { + $item['timestamp'] = time(); + } else if ($this->contains($itemDate, $this->i8n('relative-date-indicator'))) { $item['timestamp'] = $this->relativeDateToTimestamp($itemDate); - } else { + } else { $item['timestamp'] = $this->parseDate($itemDate); } $this->items[] = $item; @@ -244,14 +306,28 @@ class DealabsBridge extends BridgeAbstract { } /** + * Check if the string $str contains any of the string of the array $arr + * @return boolean true if the string matched anything otherwise false + */ + private function contains($str, array $arr) + { + foreach ($arr as $a) { + if (stripos($str, $a) !== false) { + return true; + } + } + return false; + } + + /** * Get the Price from a Deal if it exists * @return string String of the deal price */ - private function getPrix($deal) + private function getPrice($deal) { - if($deal->find( + if ($deal->find( 'span[class*=thread-price]', 0) != null) { - return '<div>Prix : ' + return '<div>'.$this->i8n('price') .' : ' . $deal->find( 'span[class*=thread-price]', 0 )->plaintext @@ -266,17 +342,17 @@ class DealabsBridge extends BridgeAbstract { * Get the Shipping costs from a Deal if it exists * @return string String of the deal shipping Cost */ - private function getLivraison($deal) + private function getShippingCost($deal) { - if($deal->find('span[class*=cept-shipping-price]', 0) != null) { - if($deal->find('span[class*=cept-shipping-price]', 0)->children(0) != null) { - return '<div>Livraison : ' - . $deal->find('span[class*=cept-shipping-price]', 0)->children(0)->innertext - . '</div>'; + if ($deal->find('span[class*=cept-shipping-price]', 0) != null) { + if ($deal->find('span[class*=cept-shipping-price]', 0)->children(0) != null) { + return '<div>'. $this->i8n('shipping') .' : ' + . $deal->find('span[class*=cept-shipping-price]', 0)->children(0)->innertext + . '</div>'; } else { - return '<div>Livraison : ' - . $deal->find('span[class*=cept-shipping-price]', 0)->innertext - . '</div>'; + return '<div>'. $this->i8n('shipping') .' : ' + . $deal->find('span[class*=cept-shipping-price]', 0)->innertext + . '</div>'; } } else { return ''; @@ -287,10 +363,10 @@ class DealabsBridge extends BridgeAbstract { * Get the source of a Deal if it exists * @return string String of the deal source */ - private function getOrigine($deal) + private function GetSource($deal) { - if($deal->find('a[class=text--color-greyShade]', 0) != null) { - return '<div>Origine : ' + if ($deal->find('a[class=text--color-greyShade]', 0) != null) { + return '<div>'. $this->i8n('origin') .' : ' . $deal->find('a[class=text--color-greyShade]', 0)->outertext . '</div>'; } else { @@ -302,15 +378,21 @@ class DealabsBridge extends BridgeAbstract { * Get the original Price and discout from a Deal if it exists * @return string String of the deal original price and discount */ - private function getReduction($deal) + private function getDiscount($deal) { - if($deal->find('span[class*=mute--text text--lineThrough]', 0) != null) { - return '<div>Réduction : <span style="text-decoration: line-through;">' + if ($deal->find('span[class*=mute--text text--lineThrough]', 0) != null) { + $discountHtml = $deal->find('span[class=space--ml-1 size--all-l size--fromW3-xl]', 0); + if ($discountHtml != null) { + $discount = $discountHtml->plaintext; + } else { + $discount = ''; + } + return '<div>'. $this->i8n('discount') .' : <span style="text-decoration: line-through;">' . $deal->find( 'span[class*=mute--text text--lineThrough]', 0 - )->plaintext + )->plaintext . '</span> ' - . $deal->find('span[class=space--ml-1 size--all-l size--fromW3-xl]', 0)->plaintext + . $discount . '</div>'; } else { return ''; @@ -323,7 +405,6 @@ class DealabsBridge extends BridgeAbstract { */ private function getImage($deal) { - $selectorLazy = implode( ' ', /* Notice this is a space! */ array( @@ -337,7 +418,7 @@ class DealabsBridge extends BridgeAbstract { ) ); - $selectorPlain = implode( + $selectorPlain = implode( ' ', /* Notice this is a space! */ array( 'thread-image', @@ -347,21 +428,21 @@ class DealabsBridge extends BridgeAbstract { 'cept-thread-img' ) ); - if($deal->find('img[class='. $selectorLazy .']', 0) != null) { + if ($deal->find('img[class='. $selectorLazy .']', 0) != null) { return json_decode( html_entity_decode( $deal->find('img[class='. $selectorLazy .']', 0) - ->getAttribute('data-lazy-img')))->{'src'}; + ->getAttribute('data-lazy-img')))->{'src'}; } else { - return $deal->find('img[class='. $selectorPlain .']', 0 )->src; + return $deal->find('img[class*='. $selectorPlain .']', 0 )->src; } } /** - * Get the originating country from a Deal if it existsa + * Get the originating country from a Deal if it exists * @return string String of the deal originating country */ - private function getExpedition($deal) + private function getShipsFrom($deal) { $selector = implode( ' ', /* Notice this is a space! */ @@ -372,7 +453,7 @@ class DealabsBridge extends BridgeAbstract { 'text--color-greyShade' ) ); - if($deal->find('span[class='. $selector .']', 0) != null) { + if ($deal->find('span[class='. $selector .']', 0) != null) { return '<div>' . $deal->find('span[class='. $selector .']', 0)->children(2)->plaintext . '</div>'; @@ -382,25 +463,12 @@ class DealabsBridge extends BridgeAbstract { } /** - * Transforms a French date into a timestam + * Transforms a local date into a timestamp * @return int timestamp of the input date */ private function parseDate($string) { - $month_fr = array( - 'janvier', - 'février', - 'mars', - 'avril', - 'mai', - 'juin', - 'juillet', - 'août', - 'septembre', - 'octobre', - 'novembre', - 'décembre' - ); + $month_local = $this->i8n('local-months'); $month_en = array( 'January', 'February', @@ -415,11 +483,18 @@ class DealabsBridge extends BridgeAbstract { 'November', 'December' ); - $date_str = trim(str_replace($month_fr, $month_en, $string)); - if(!preg_match('/[0-9]{4}/', $string)) { + // A date can be prfixed with some words, we remove theme + $string = $this->removeDatePrefixes($string); + // We translate the local months name in the english one + $date_str = trim(str_replace($month_local, $month_en, $string)); + + // If the date does not contain any year, we add the current year + if (!preg_match('/[0-9]{4}/', $string)) { $date_str .= ' ' . date('Y'); } + + // Add the Hour and minutes $date_str .= ' 00:00'; $date = DateTime::createFromFormat('j F Y H:i', $date_str); @@ -427,21 +502,41 @@ class DealabsBridge extends BridgeAbstract { } /** - * Transforms a relate French date into a timestam + * Remove the prefix of a date if it has one + * @return the date without prefiux + */ + private function removeDatePrefixes($string) + { + $string = str_replace($this->i8n('date-prefixes'), array(), $string); + return $string; + } + + /** + * Remove the suffix of a relative date if it has one + * @return the relative date without suffixes + */ + private function removeRelativeDateSuffixes($string) + { + if (count($this->i8n('relative-date-ignore-suffix')) > 0) { + $string = preg_replace($this->i8n('relative-date-ignore-suffix'), '', $string); + } + return $string; + } + + /** + * Transforms a relative local date into a timestamp * @return int timestamp of the input date */ private function relativeDateToTimestamp($str) { $date = new DateTime(); - $search = array( - 'il y a ', - 'min', - 'h', - 'jour', - 'jours', - 'mois', - 'ans', - 'et ' - ); + + // In case of update date, replace it by the regular relative date first word + $str = str_replace($this->i8n('relative-date-alt-prefixes'), $this->i8n('local-time-relative')[0], $str); + + $str = $this->removeRelativeDateSuffixes($str); + + $search = $this->i8n('local-time-relative'); + $replace = array( '-', 'minute', @@ -456,18 +551,38 @@ class DealabsBridge extends BridgeAbstract { return $date->getTimestamp(); } + /** + * Returns the RSS Feed title according to the parameters + * @return string the RSS feed Tiyle + */ public function getName(){ switch($this->queriedContext) { - case 'Recherche par Mot(s) clé(s)': - return self::NAME . ' - Recherche : '. $this->getInput('q'); + case $this->i8n('context-keyword'): + return $this->i8n('bridge-name') . ' - '. $this->i8n('title-keyword') .' : '. $this->getInput('q'); break; - case 'Deals par groupe': - $values = self::PARAMETERS['Deals par groupe']['groupe']['values']; - $groupe = array_search($this->getInput('groupe'), $values); - return self::NAME . ' - Groupe : '. $groupe; + case $this->i8n('context-group'): + $values = $this->getParameters()[$this->i8n('context-group')]['group']['values']; + $group = array_search($this->getInput('group'), $values); + return $this->i8n('bridge-name') . ' - '. $this->i8n('title-group'). ' : '. $group; break; default: // Return default value - return self::NAME; + return static::NAME; + } + } + + + + /** + * This is some "localisation" function that returns the needed content using + * the "$lang" class variable in the local class + * @return various the local content needed + */ + public function i8n($key) + { + if (array_key_exists($key, $this->lang)) { + return $this->lang[$key]; + } else { + return null; } } |