xref: /plugin/amazonlight/syntax.php (revision e20d6e78d70fbd01efc177563844e14e25061e16)
11c1d842eSAndreas Gohr<?php
21c1d842eSAndreas Gohr/**
31c1d842eSAndreas Gohr * DokuWiki Plugin amazonlight (Syntax Component)
41c1d842eSAndreas Gohr *
51c1d842eSAndreas Gohr * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
61c1d842eSAndreas Gohr * @author  Andreas Gohr <andi@splitbrain.org>
71c1d842eSAndreas Gohr */
81c1d842eSAndreas Gohr
91c1d842eSAndreas Gohr// must be run within Dokuwiki
101c1d842eSAndreas Gohrif (!defined('DOKU_INC')) {
111c1d842eSAndreas Gohr    die();
121c1d842eSAndreas Gohr}
131c1d842eSAndreas Gohr
141c1d842eSAndreas Gohrclass syntax_plugin_amazonlight extends DokuWiki_Syntax_Plugin
151c1d842eSAndreas Gohr{
161c1d842eSAndreas Gohr
171c1d842eSAndreas Gohr    /** @var array what regions to use for the different countries */
181c1d842eSAndreas Gohr    const REGIONS = [
191c1d842eSAndreas Gohr        'us' => 'ws-na',
201c1d842eSAndreas Gohr        'ca' => 'ws-na',
211c1d842eSAndreas Gohr        'de' => 'ws-eu',
221c1d842eSAndreas Gohr        'gb' => 'ws-eu',
231c1d842eSAndreas Gohr        'fr' => 'ws-eu',
241c1d842eSAndreas Gohr        'jp' => 'ws-fe',
251c1d842eSAndreas Gohr    ];
261c1d842eSAndreas Gohr
271c1d842eSAndreas Gohr    /** @inheritDoc */
281c1d842eSAndreas Gohr    public function getType()
291c1d842eSAndreas Gohr    {
301c1d842eSAndreas Gohr        return 'substition';
311c1d842eSAndreas Gohr    }
321c1d842eSAndreas Gohr
331c1d842eSAndreas Gohr    /** @inheritDoc */
341c1d842eSAndreas Gohr    public function getPType()
351c1d842eSAndreas Gohr    {
361c1d842eSAndreas Gohr        return 'block';
371c1d842eSAndreas Gohr    }
381c1d842eSAndreas Gohr
391c1d842eSAndreas Gohr    /** @inheritDoc */
401c1d842eSAndreas Gohr    public function getSort()
411c1d842eSAndreas Gohr    {
421c1d842eSAndreas Gohr        return 160;
431c1d842eSAndreas Gohr    }
441c1d842eSAndreas Gohr
451c1d842eSAndreas Gohr    /**
461c1d842eSAndreas Gohr     * Connect lookup pattern to lexer.
471c1d842eSAndreas Gohr     *
481c1d842eSAndreas Gohr     * @param string $mode Parser mode
491c1d842eSAndreas Gohr     */
501c1d842eSAndreas Gohr    public function connectTo($mode)
511c1d842eSAndreas Gohr    {
521c1d842eSAndreas Gohr        $this->Lexer->addSpecialPattern('\{\{amazon>[\w:\\- =]+\}\}', $mode, 'plugin_amazonlight');
531c1d842eSAndreas Gohr    }
541c1d842eSAndreas Gohr
551c1d842eSAndreas Gohr    /** @inheritDoc */
561c1d842eSAndreas Gohr    public function handle($match, $state, $pos, Doku_Handler $handler)
571c1d842eSAndreas Gohr    {
581c1d842eSAndreas Gohr        $match = substr($match, 9, -2);
591c1d842eSAndreas Gohr        list($ctry, $asin) = explode(':', $match, 2);
601c1d842eSAndreas Gohr
611c1d842eSAndreas Gohr        // no country given?
621c1d842eSAndreas Gohr        if (empty($asin)) {
631c1d842eSAndreas Gohr            $asin = $ctry;
641c1d842eSAndreas Gohr            $ctry = 'us';
651c1d842eSAndreas Gohr        }
661c1d842eSAndreas Gohr
671c1d842eSAndreas Gohr        // default parameters...
681c1d842eSAndreas Gohr        $params = array(
691c1d842eSAndreas Gohr            'imgw' => $this->getConf('imgw'),
701c1d842eSAndreas Gohr            'imgh' => $this->getConf('imgh'),
711c1d842eSAndreas Gohr            'price' => $this->getConf('showprice'),
721c1d842eSAndreas Gohr        );
731c1d842eSAndreas Gohr        // ...can be overridden
741c1d842eSAndreas Gohr        list($asin, $more) = explode(' ', $asin, 2);
751c1d842eSAndreas Gohr        $params['asin'] = $asin;
761c1d842eSAndreas Gohr
771c1d842eSAndreas Gohr        if (preg_match('/(\d+)x(\d+)/i', $more, $match)) {
781c1d842eSAndreas Gohr            $params['imgw'] = $match[1];
791c1d842eSAndreas Gohr            $params['imgh'] = $match[2];
801c1d842eSAndreas Gohr        }
811c1d842eSAndreas Gohr        if (preg_match('/noprice/i', $more, $match)) {
821c1d842eSAndreas Gohr            $params['price'] = false;
831c1d842eSAndreas Gohr        } elseif (preg_match('/(show)?price/i', $more, $match)) {
841c1d842eSAndreas Gohr            $params['price'] = true;
851c1d842eSAndreas Gohr        }
861c1d842eSAndreas Gohr
871c1d842eSAndreas Gohr        // correct country given?
881c1d842eSAndreas Gohr        if ($ctry === 'uk') $ctry = 'gb';
891c1d842eSAndreas Gohr        if (!preg_match('/^(us|gb|jp|de|fr|ca)$/', $ctry)) {
901c1d842eSAndreas Gohr            $ctry = 'us';
911c1d842eSAndreas Gohr        }
921c1d842eSAndreas Gohr        $params['country'] = $ctry;
931c1d842eSAndreas Gohr
941c1d842eSAndreas Gohr        return $params;
951c1d842eSAndreas Gohr    }
961c1d842eSAndreas Gohr
971c1d842eSAndreas Gohr    /** @inheritDoc */
981c1d842eSAndreas Gohr    public function render($mode, Doku_Renderer $renderer, $data)
991c1d842eSAndreas Gohr    {
1001c1d842eSAndreas Gohr        if ($mode !== 'xhtml') {
1011c1d842eSAndreas Gohr            return false;
1021c1d842eSAndreas Gohr        }
1031c1d842eSAndreas Gohr
1041c1d842eSAndreas Gohr        $html = $this->output($data);
1051c1d842eSAndreas Gohr        $renderer->doc .= $html;
1061c1d842eSAndreas Gohr
1071c1d842eSAndreas Gohr        return true;
1081c1d842eSAndreas Gohr    }
1091c1d842eSAndreas Gohr
1101c1d842eSAndreas Gohr    /**
1111c1d842eSAndreas Gohr     * @param array $param
1121c1d842eSAndreas Gohr     * @return string
1131c1d842eSAndreas Gohr     */
1141c1d842eSAndreas Gohr    protected function output($param)
1151c1d842eSAndreas Gohr    {
1161c1d842eSAndreas Gohr        global $conf;
1171c1d842eSAndreas Gohr
1181c1d842eSAndreas Gohr        try {
1191c1d842eSAndreas Gohr            $data = $this->fetchData($param['asin'], $param['country']);
1201c1d842eSAndreas Gohr        } catch (\Exception $e) {
1211c1d842eSAndreas Gohr            msg(hsc($e->getMessage()), -1);
1221c1d842eSAndreas Gohr            return false;
1231c1d842eSAndreas Gohr        }
1241c1d842eSAndreas Gohr
1251c1d842eSAndreas Gohr        $img = ml($data['img'], array('w' => $param['imgw'], 'h' => $param['imgh']));
1261c1d842eSAndreas Gohr
1271c1d842eSAndreas Gohr        ob_start();
1281c1d842eSAndreas Gohr        echo '<div class="amazon">';
1291c1d842eSAndreas Gohr        echo '<a href="' . $data['url'] . '"';
1301c1d842eSAndreas Gohr        if ($conf['target']['extern']) echo ' target="' . $conf['target']['extern'] . '"';
1311c1d842eSAndreas Gohr        echo '>';
1321c1d842eSAndreas Gohr        echo '<img src="' . $img . '" width="' . $param['imgw'] . '" height="' . $param['imgh'] . '" alt="" />';
1331c1d842eSAndreas Gohr        echo '</a>';
1341c1d842eSAndreas Gohr
1351c1d842eSAndreas Gohr        echo '<div class="amazon_title">';
1361c1d842eSAndreas Gohr        echo '<a href="' . $data['url'] . '"';
1371c1d842eSAndreas Gohr        if ($conf['target']['extern']) echo ' target="' . $conf['target']['extern'] . '"';
1381c1d842eSAndreas Gohr        echo '>';
1391c1d842eSAndreas Gohr        echo hsc($data['title']);
1401c1d842eSAndreas Gohr        echo '</a>';
1411c1d842eSAndreas Gohr        echo '</div>';
1421c1d842eSAndreas Gohr
143*e20d6e78SAndreas Gohr        echo '<div class="amazon_isbn">';
144*e20d6e78SAndreas Gohr        echo hsc($data['isbn']);
145*e20d6e78SAndreas Gohr        echo '</div>';
146*e20d6e78SAndreas Gohr
1471c1d842eSAndreas Gohr        if ($param['price'] && $data['price']) {
1481c1d842eSAndreas Gohr            echo '<div class="amazon_price">' . hsc($data['price']) . '</div>';
1491c1d842eSAndreas Gohr        }
1501c1d842eSAndreas Gohr        echo '</div>';
1511c1d842eSAndreas Gohr
1521c1d842eSAndreas Gohr        return ob_get_clean();
1531c1d842eSAndreas Gohr    }
1541c1d842eSAndreas Gohr
1551c1d842eSAndreas Gohr    /**
1561c1d842eSAndreas Gohr     * Fetch the meta data
1571c1d842eSAndreas Gohr     *
1581c1d842eSAndreas Gohr     * @param string $asin
1591c1d842eSAndreas Gohr     * @param string $country
1601c1d842eSAndreas Gohr     * @return array
1611c1d842eSAndreas Gohr     * @throws Exception
1621c1d842eSAndreas Gohr     */
1631c1d842eSAndreas Gohr    protected function fetchData($asin, $country)
1641c1d842eSAndreas Gohr    {
1651c1d842eSAndreas Gohr        $partner = $this->getConf('partner_' . $country);
1661c1d842eSAndreas Gohr        if (!$partner) $partner = 'none';
1671c1d842eSAndreas Gohr        $region = self::REGIONS[$country];
1681c1d842eSAndreas Gohr
1691c1d842eSAndreas Gohr        $attr = [
1701c1d842eSAndreas Gohr            'ServiceVersion' => '20070822',
1711c1d842eSAndreas Gohr            'OneJS' => '1',
1721c1d842eSAndreas Gohr            'Operation' => 'GetAdHtml',
1731c1d842eSAndreas Gohr            'MarketPlace' => strtoupper($country),
1741c1d842eSAndreas Gohr            'source' => 'ss',
1751c1d842eSAndreas Gohr            'ref' => 'as_ss_li_til',
1761c1d842eSAndreas Gohr            'ad_type' => 'product_link',
1771c1d842eSAndreas Gohr            'tracking_id' => $partner,
1781c1d842eSAndreas Gohr            'marketplace' => 'amazon',
1791c1d842eSAndreas Gohr            'region' => strtoupper($country),
1801c1d842eSAndreas Gohr            'placement' => '0670022411',
1811c1d842eSAndreas Gohr            'asins' => $asin,
1821c1d842eSAndreas Gohr            'show_border' => 'true',
1831c1d842eSAndreas Gohr            'link_opens_in_new_window' => 'true',
1841c1d842eSAndreas Gohr        ];
1851c1d842eSAndreas Gohr        $url = 'http://' . $region . '.amazon-adsystem.com/widgets/q?' . buildURLparams($attr, '&');
1861c1d842eSAndreas Gohr
1871c1d842eSAndreas Gohr        $http = new DokuHTTPClient();
1881c1d842eSAndreas Gohr        $html = $http->get($url);
1891c1d842eSAndreas Gohr        if (!$html) {
1901c1d842eSAndreas Gohr            throw new \Exception('Failed to fetch data. Status ' . $http->status);
1911c1d842eSAndreas Gohr        }
1921c1d842eSAndreas Gohr
1931c1d842eSAndreas Gohr        $result = [];
1941c1d842eSAndreas Gohr
1951c1d842eSAndreas Gohr        if (preg_match('/class="price".*?>(.*?)<\/span>/s', $html, $m)) {
1961c1d842eSAndreas Gohr            $result['price'] = $m[1];
1971c1d842eSAndreas Gohr        }
1981c1d842eSAndreas Gohr
1991c1d842eSAndreas Gohr        if (preg_match('/<a .* id="titlehref" [^>]*?>([^<]*?)<\/a>/s', $html, $m)) {
2001c1d842eSAndreas Gohr            $result['title'] = $m[1];
2011c1d842eSAndreas Gohr        }
2021c1d842eSAndreas Gohr
2031c1d842eSAndreas Gohr        if (preg_match('/<a .* id="titlehref" href=(.*?) /s', $html, $m)) {
2041c1d842eSAndreas Gohr            $result['url'] = trim($m[1], '\'"');
2051c1d842eSAndreas Gohr        }
2061c1d842eSAndreas Gohr
207*e20d6e78SAndreas Gohr        if (preg_match('/^\d{10}$/', $asin)) {
208*e20d6e78SAndreas Gohr            $result['isbn'] = 'ISBN ' . $asin;
209*e20d6e78SAndreas Gohr        }
210*e20d6e78SAndreas Gohr
2111c1d842eSAndreas Gohr        $result['img'] = $this->getImageURL($asin, $country);
2121c1d842eSAndreas Gohr
2131c1d842eSAndreas Gohr        return $result;
2141c1d842eSAndreas Gohr    }
2151c1d842eSAndreas Gohr
2161c1d842eSAndreas Gohr    /**
2171c1d842eSAndreas Gohr     * @param $asin
2181c1d842eSAndreas Gohr     * @param $country
2191c1d842eSAndreas Gohr     * @return string
2201c1d842eSAndreas Gohr     */
2211c1d842eSAndreas Gohr    protected function getImageURL($asin, $country)
2221c1d842eSAndreas Gohr    {
2231c1d842eSAndreas Gohr        $partner = $this->getConf('partner_' . $country);
2241c1d842eSAndreas Gohr        if (!$partner) $partner = 'none';
2251c1d842eSAndreas Gohr        $region = self::REGIONS[$country];
2261c1d842eSAndreas Gohr
2271c1d842eSAndreas Gohr        $attr = [
2281c1d842eSAndreas Gohr            '_encoding' => 'UTF8',
2291c1d842eSAndreas Gohr            'ASIN' => $asin,
2301c1d842eSAndreas Gohr            'Format' => '_SL250_',
2311c1d842eSAndreas Gohr            'ID' => 'AsinImage',
2321c1d842eSAndreas Gohr            'MarketPlace' => strtoupper($country),
2331c1d842eSAndreas Gohr            'ServiceVersion' => '20070822',
2341c1d842eSAndreas Gohr            'WS' => '1',
2351c1d842eSAndreas Gohr            'tag' => $partner,
2361c1d842eSAndreas Gohr        ];
2371c1d842eSAndreas Gohr        $url = 'http://' . $region . '.amazon-adsystem.com/widgets/q?' . buildURLparams($attr, '&');
2381c1d842eSAndreas Gohr
2391c1d842eSAndreas Gohr        return $url;
2401c1d842eSAndreas Gohr    }
2411c1d842eSAndreas Gohr
2421c1d842eSAndreas Gohr}
2431c1d842eSAndreas Gohr
244