xref: /plugin/amazonlight/syntax.php (revision 1c1d842e729f74d02e36e6f50a061ad4642316f6)
1*1c1d842eSAndreas Gohr<?php
2*1c1d842eSAndreas Gohr/**
3*1c1d842eSAndreas Gohr * DokuWiki Plugin amazonlight (Syntax Component)
4*1c1d842eSAndreas Gohr *
5*1c1d842eSAndreas Gohr * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6*1c1d842eSAndreas Gohr * @author  Andreas Gohr <andi@splitbrain.org>
7*1c1d842eSAndreas Gohr */
8*1c1d842eSAndreas Gohr
9*1c1d842eSAndreas Gohr// must be run within Dokuwiki
10*1c1d842eSAndreas Gohrif (!defined('DOKU_INC')) {
11*1c1d842eSAndreas Gohr    die();
12*1c1d842eSAndreas Gohr}
13*1c1d842eSAndreas Gohr
14*1c1d842eSAndreas Gohrclass syntax_plugin_amazonlight extends DokuWiki_Syntax_Plugin
15*1c1d842eSAndreas Gohr{
16*1c1d842eSAndreas Gohr
17*1c1d842eSAndreas Gohr    /** @var array what regions to use for the different countries */
18*1c1d842eSAndreas Gohr    const REGIONS = [
19*1c1d842eSAndreas Gohr        'us' => 'ws-na',
20*1c1d842eSAndreas Gohr        'ca' => 'ws-na',
21*1c1d842eSAndreas Gohr        'de' => 'ws-eu',
22*1c1d842eSAndreas Gohr        'gb' => 'ws-eu',
23*1c1d842eSAndreas Gohr        'fr' => 'ws-eu',
24*1c1d842eSAndreas Gohr        'jp' => 'ws-fe',
25*1c1d842eSAndreas Gohr    ];
26*1c1d842eSAndreas Gohr
27*1c1d842eSAndreas Gohr    /** @inheritDoc */
28*1c1d842eSAndreas Gohr    public function getType()
29*1c1d842eSAndreas Gohr    {
30*1c1d842eSAndreas Gohr        return 'substition';
31*1c1d842eSAndreas Gohr    }
32*1c1d842eSAndreas Gohr
33*1c1d842eSAndreas Gohr    /** @inheritDoc */
34*1c1d842eSAndreas Gohr    public function getPType()
35*1c1d842eSAndreas Gohr    {
36*1c1d842eSAndreas Gohr        return 'block';
37*1c1d842eSAndreas Gohr    }
38*1c1d842eSAndreas Gohr
39*1c1d842eSAndreas Gohr    /** @inheritDoc */
40*1c1d842eSAndreas Gohr    public function getSort()
41*1c1d842eSAndreas Gohr    {
42*1c1d842eSAndreas Gohr        return 160;
43*1c1d842eSAndreas Gohr    }
44*1c1d842eSAndreas Gohr
45*1c1d842eSAndreas Gohr    /**
46*1c1d842eSAndreas Gohr     * Connect lookup pattern to lexer.
47*1c1d842eSAndreas Gohr     *
48*1c1d842eSAndreas Gohr     * @param string $mode Parser mode
49*1c1d842eSAndreas Gohr     */
50*1c1d842eSAndreas Gohr    public function connectTo($mode)
51*1c1d842eSAndreas Gohr    {
52*1c1d842eSAndreas Gohr        $this->Lexer->addSpecialPattern('\{\{amazon>[\w:\\- =]+\}\}', $mode, 'plugin_amazonlight');
53*1c1d842eSAndreas Gohr    }
54*1c1d842eSAndreas Gohr
55*1c1d842eSAndreas Gohr    /** @inheritDoc */
56*1c1d842eSAndreas Gohr    public function handle($match, $state, $pos, Doku_Handler $handler)
57*1c1d842eSAndreas Gohr    {
58*1c1d842eSAndreas Gohr        $match = substr($match, 9, -2);
59*1c1d842eSAndreas Gohr        list($ctry, $asin) = explode(':', $match, 2);
60*1c1d842eSAndreas Gohr
61*1c1d842eSAndreas Gohr        // no country given?
62*1c1d842eSAndreas Gohr        if (empty($asin)) {
63*1c1d842eSAndreas Gohr            $asin = $ctry;
64*1c1d842eSAndreas Gohr            $ctry = 'us';
65*1c1d842eSAndreas Gohr        }
66*1c1d842eSAndreas Gohr
67*1c1d842eSAndreas Gohr        // default parameters...
68*1c1d842eSAndreas Gohr        $params = array(
69*1c1d842eSAndreas Gohr            'imgw' => $this->getConf('imgw'),
70*1c1d842eSAndreas Gohr            'imgh' => $this->getConf('imgh'),
71*1c1d842eSAndreas Gohr            'price' => $this->getConf('showprice'),
72*1c1d842eSAndreas Gohr        );
73*1c1d842eSAndreas Gohr        // ...can be overridden
74*1c1d842eSAndreas Gohr        list($asin, $more) = explode(' ', $asin, 2);
75*1c1d842eSAndreas Gohr        $params['asin'] = $asin;
76*1c1d842eSAndreas Gohr
77*1c1d842eSAndreas Gohr        if (preg_match('/(\d+)x(\d+)/i', $more, $match)) {
78*1c1d842eSAndreas Gohr            $params['imgw'] = $match[1];
79*1c1d842eSAndreas Gohr            $params['imgh'] = $match[2];
80*1c1d842eSAndreas Gohr        }
81*1c1d842eSAndreas Gohr        if (preg_match('/noprice/i', $more, $match)) {
82*1c1d842eSAndreas Gohr            $params['price'] = false;
83*1c1d842eSAndreas Gohr        } elseif (preg_match('/(show)?price/i', $more, $match)) {
84*1c1d842eSAndreas Gohr            $params['price'] = true;
85*1c1d842eSAndreas Gohr        }
86*1c1d842eSAndreas Gohr
87*1c1d842eSAndreas Gohr        // correct country given?
88*1c1d842eSAndreas Gohr        if ($ctry === 'uk') $ctry = 'gb';
89*1c1d842eSAndreas Gohr        if (!preg_match('/^(us|gb|jp|de|fr|ca)$/', $ctry)) {
90*1c1d842eSAndreas Gohr            $ctry = 'us';
91*1c1d842eSAndreas Gohr        }
92*1c1d842eSAndreas Gohr        $params['country'] = $ctry;
93*1c1d842eSAndreas Gohr
94*1c1d842eSAndreas Gohr        return $params;
95*1c1d842eSAndreas Gohr    }
96*1c1d842eSAndreas Gohr
97*1c1d842eSAndreas Gohr    /** @inheritDoc */
98*1c1d842eSAndreas Gohr    public function render($mode, Doku_Renderer $renderer, $data)
99*1c1d842eSAndreas Gohr    {
100*1c1d842eSAndreas Gohr        if ($mode !== 'xhtml') {
101*1c1d842eSAndreas Gohr            return false;
102*1c1d842eSAndreas Gohr        }
103*1c1d842eSAndreas Gohr
104*1c1d842eSAndreas Gohr        $html = $this->output($data);
105*1c1d842eSAndreas Gohr        $renderer->doc .= $html;
106*1c1d842eSAndreas Gohr
107*1c1d842eSAndreas Gohr        return true;
108*1c1d842eSAndreas Gohr    }
109*1c1d842eSAndreas Gohr
110*1c1d842eSAndreas Gohr    /**
111*1c1d842eSAndreas Gohr     * @param array $param
112*1c1d842eSAndreas Gohr     * @return string
113*1c1d842eSAndreas Gohr     */
114*1c1d842eSAndreas Gohr    protected function output($param)
115*1c1d842eSAndreas Gohr    {
116*1c1d842eSAndreas Gohr        global $conf;
117*1c1d842eSAndreas Gohr
118*1c1d842eSAndreas Gohr        try {
119*1c1d842eSAndreas Gohr            $data = $this->fetchData($param['asin'], $param['country']);
120*1c1d842eSAndreas Gohr        } catch (\Exception $e) {
121*1c1d842eSAndreas Gohr            msg(hsc($e->getMessage()), -1);
122*1c1d842eSAndreas Gohr            return false;
123*1c1d842eSAndreas Gohr        }
124*1c1d842eSAndreas Gohr
125*1c1d842eSAndreas Gohr        $img = ml($data['img'], array('w' => $param['imgw'], 'h' => $param['imgh']));
126*1c1d842eSAndreas Gohr
127*1c1d842eSAndreas Gohr        ob_start();
128*1c1d842eSAndreas Gohr        echo '<div class="amazon">';
129*1c1d842eSAndreas Gohr        echo '<a href="' . $data['url'] . '"';
130*1c1d842eSAndreas Gohr        if ($conf['target']['extern']) echo ' target="' . $conf['target']['extern'] . '"';
131*1c1d842eSAndreas Gohr        echo '>';
132*1c1d842eSAndreas Gohr        echo '<img src="' . $img . '" width="' . $param['imgw'] . '" height="' . $param['imgh'] . '" alt="" />';
133*1c1d842eSAndreas Gohr        echo '</a>';
134*1c1d842eSAndreas Gohr
135*1c1d842eSAndreas Gohr        echo '<div class="amazon_title">';
136*1c1d842eSAndreas Gohr        echo '<a href="' . $data['url'] . '"';
137*1c1d842eSAndreas Gohr        if ($conf['target']['extern']) echo ' target="' . $conf['target']['extern'] . '"';
138*1c1d842eSAndreas Gohr        echo '>';
139*1c1d842eSAndreas Gohr        echo hsc($data['title']);
140*1c1d842eSAndreas Gohr        echo '</a>';
141*1c1d842eSAndreas Gohr        echo '</div>';
142*1c1d842eSAndreas Gohr
143*1c1d842eSAndreas Gohr        if ($param['price'] && $data['price']) {
144*1c1d842eSAndreas Gohr            echo '<div class="amazon_price">' . hsc($data['price']) . '</div>';
145*1c1d842eSAndreas Gohr        }
146*1c1d842eSAndreas Gohr        echo '</div>';
147*1c1d842eSAndreas Gohr
148*1c1d842eSAndreas Gohr        return ob_get_clean();
149*1c1d842eSAndreas Gohr    }
150*1c1d842eSAndreas Gohr
151*1c1d842eSAndreas Gohr    /**
152*1c1d842eSAndreas Gohr     * Fetch the meta data
153*1c1d842eSAndreas Gohr     *
154*1c1d842eSAndreas Gohr     * @param string $asin
155*1c1d842eSAndreas Gohr     * @param string $country
156*1c1d842eSAndreas Gohr     * @return array
157*1c1d842eSAndreas Gohr     * @throws Exception
158*1c1d842eSAndreas Gohr     */
159*1c1d842eSAndreas Gohr    protected function fetchData($asin, $country)
160*1c1d842eSAndreas Gohr    {
161*1c1d842eSAndreas Gohr        $partner = $this->getConf('partner_' . $country);
162*1c1d842eSAndreas Gohr        if (!$partner) $partner = 'none';
163*1c1d842eSAndreas Gohr        $region = self::REGIONS[$country];
164*1c1d842eSAndreas Gohr
165*1c1d842eSAndreas Gohr        $attr = [
166*1c1d842eSAndreas Gohr            'ServiceVersion' => '20070822',
167*1c1d842eSAndreas Gohr            'OneJS' => '1',
168*1c1d842eSAndreas Gohr            'Operation' => 'GetAdHtml',
169*1c1d842eSAndreas Gohr            'MarketPlace' => strtoupper($country),
170*1c1d842eSAndreas Gohr            'source' => 'ss',
171*1c1d842eSAndreas Gohr            'ref' => 'as_ss_li_til',
172*1c1d842eSAndreas Gohr            'ad_type' => 'product_link',
173*1c1d842eSAndreas Gohr            'tracking_id' => $partner,
174*1c1d842eSAndreas Gohr            'marketplace' => 'amazon',
175*1c1d842eSAndreas Gohr            'region' => strtoupper($country),
176*1c1d842eSAndreas Gohr            'placement' => '0670022411',
177*1c1d842eSAndreas Gohr            'asins' => $asin,
178*1c1d842eSAndreas Gohr            'show_border' => 'true',
179*1c1d842eSAndreas Gohr            'link_opens_in_new_window' => 'true',
180*1c1d842eSAndreas Gohr        ];
181*1c1d842eSAndreas Gohr        $url = 'http://' . $region . '.amazon-adsystem.com/widgets/q?' . buildURLparams($attr, '&');
182*1c1d842eSAndreas Gohr
183*1c1d842eSAndreas Gohr        $http = new DokuHTTPClient();
184*1c1d842eSAndreas Gohr        $html = $http->get($url);
185*1c1d842eSAndreas Gohr        if (!$html) {
186*1c1d842eSAndreas Gohr            throw new \Exception('Failed to fetch data. Status ' . $http->status);
187*1c1d842eSAndreas Gohr        }
188*1c1d842eSAndreas Gohr
189*1c1d842eSAndreas Gohr        $result = [];
190*1c1d842eSAndreas Gohr
191*1c1d842eSAndreas Gohr        if (preg_match('/class="price".*?>(.*?)<\/span>/s', $html, $m)) {
192*1c1d842eSAndreas Gohr            $result['price'] = $m[1];
193*1c1d842eSAndreas Gohr        }
194*1c1d842eSAndreas Gohr
195*1c1d842eSAndreas Gohr        if (preg_match('/<a .* id="titlehref" [^>]*?>([^<]*?)<\/a>/s', $html, $m)) {
196*1c1d842eSAndreas Gohr            $result['title'] = $m[1];
197*1c1d842eSAndreas Gohr        }
198*1c1d842eSAndreas Gohr
199*1c1d842eSAndreas Gohr        if (preg_match('/<a .* id="titlehref" href=(.*?) /s', $html, $m)) {
200*1c1d842eSAndreas Gohr            $result['url'] = trim($m[1], '\'"');
201*1c1d842eSAndreas Gohr        }
202*1c1d842eSAndreas Gohr
203*1c1d842eSAndreas Gohr        $result['img'] = $this->getImageURL($asin, $country);
204*1c1d842eSAndreas Gohr
205*1c1d842eSAndreas Gohr        return $result;
206*1c1d842eSAndreas Gohr    }
207*1c1d842eSAndreas Gohr
208*1c1d842eSAndreas Gohr    /**
209*1c1d842eSAndreas Gohr     * @param $asin
210*1c1d842eSAndreas Gohr     * @param $country
211*1c1d842eSAndreas Gohr     * @return string
212*1c1d842eSAndreas Gohr     */
213*1c1d842eSAndreas Gohr    protected function getImageURL($asin, $country)
214*1c1d842eSAndreas Gohr    {
215*1c1d842eSAndreas Gohr        $partner = $this->getConf('partner_' . $country);
216*1c1d842eSAndreas Gohr        if (!$partner) $partner = 'none';
217*1c1d842eSAndreas Gohr        $region = self::REGIONS[$country];
218*1c1d842eSAndreas Gohr
219*1c1d842eSAndreas Gohr        $attr = [
220*1c1d842eSAndreas Gohr            '_encoding' => 'UTF8',
221*1c1d842eSAndreas Gohr            'ASIN' => $asin,
222*1c1d842eSAndreas Gohr            'Format' => '_SL250_',
223*1c1d842eSAndreas Gohr            'ID' => 'AsinImage',
224*1c1d842eSAndreas Gohr            'MarketPlace' => strtoupper($country),
225*1c1d842eSAndreas Gohr            'ServiceVersion' => '20070822',
226*1c1d842eSAndreas Gohr            'WS' => '1',
227*1c1d842eSAndreas Gohr            'tag' => $partner,
228*1c1d842eSAndreas Gohr        ];
229*1c1d842eSAndreas Gohr        $url = 'http://' . $region . '.amazon-adsystem.com/widgets/q?' . buildURLparams($attr, '&');
230*1c1d842eSAndreas Gohr
231*1c1d842eSAndreas Gohr        return $url;
232*1c1d842eSAndreas Gohr    }
233*1c1d842eSAndreas Gohr
234*1c1d842eSAndreas Gohr}
235*1c1d842eSAndreas Gohr
236