1<?php
2/**
3 * Copyright 2011-2016 Horde LLC (http://www.horde.org/)
4 *
5 * See the enclosed file COPYING for license information (LGPL). If you
6 * did not receive this file, see http://www.horde.org/licenses/lgpl21.
7 *
8 * @category Horde
9 * @package  Service_Gravatar
10 * @author   Gunnar Wrobel <wrobel@pardus.de>
11 * @license  http://www.horde.org/licenses/lgpl21 LGPL 2.1
12 */
13
14/**
15 * Horde_Service_Gravatar abstracts communication with Services supporting the
16 * Gravatar API.
17 *
18 * @category Horde
19 * @package  Service_Gravatar
20 * @author   Gunnar Wrobel <wrobel@pardus.de>
21 * @license  http://www.horde.org/licenses/lgpl21 LGPL 2.1
22 * @link     http://www.gravatar.com/site/implement/
23 */
24class Horde_Service_Gravatar
25{
26    /** The default Gravatar base URL */
27    const STANDARD = 'http://www.gravatar.com';
28
29    /** The Gravatar base URL in SSL context */
30    const SECURE  = 'https://secure.gravatar.com';
31
32    /**
33     * The base Gravatar URL.
34     *
35     * @var string
36     */
37    private $_base;
38
39    /**
40     * The HTTP client to access the server.
41     *
42     * @var Horde_Http_Client
43     */
44    private $_client;
45
46    /**
47     * Constructor.
48     *
49     * The default Gravatar base URL is Horde_Service_Gravatar::STANDARD. If
50     * you need URLs in an HTTPS context you should provide the base URL
51     * parameter as Horde_Service_Gravatar::SECURE. In case you wish to access
52     * another URL offering the Gravatar API you can specify the base URL of
53     * this service as $base.
54     *
55     * @param string            $base    The base Gravatar URL.
56     * @param Horde_Http_Client $client  The HTTP client to access the server.
57     */
58    public function __construct(
59        $base = self::STANDARD,
60        Horde_Http_Client $client = null
61    )
62    {
63        $this->_base   = $base;
64        if ($client === null) {
65            $client = new Horde_Http_Client();
66        }
67        $this->_client = $client;
68    }
69
70    /**
71     * Return the Gravatar ID for the specified mail address.
72     *
73     * @param string $mail  The mail address.
74     *
75     * @return string  The Gravatar ID.
76     */
77    public function getId($mail)
78    {
79        if (!is_string($mail)) {
80            throw new InvalidArgumentException('The mail address must be a string!');
81        }
82        return md5(Horde_String::lower(trim($mail)));
83    }
84
85    /**
86     * Return the Gravatar image URL for the specified mail address. The
87     * returned URL can be directly used with an IMG tag e.g.:
88     * &lt;img src="http://www.gravatar.com/avatar/hash" /&gt;
89     *
90     * @param string $mail  The mail address.
91     * @param mixed $opts   Additional options. If an integer, treated as the
92     *                      'size' option.  If an array, the following options
93     *                      are available:
94     * <pre>
95     *   - default: (string) Default behavior. Valid values are '404', 'mm',
96     *              'identicon', 'monsterid', 'wavatar', 'retro', 'blank', or
97     *              a URL-encoded URL to use as the default image.
98     *   - rating: (string) Rating. Valid values are 'g', 'pg', 'r', and 'x'.
99     *   - size: (integer) Image size. Valid values are between 1 and 512.
100     * </pre>
101     *
102     * @return Horde_Url  The image URL.
103     */
104    public function getAvatarUrl($mail, $opts = array())
105    {
106        if (is_integer($opts)) {
107            $opts = array('size' => $opts);
108        }
109
110        if (!empty($opts['size']) &&
111            (($opts['size'] < 1) || ($opts['size'] > 512))) {
112            throw InvalidArgumentException('The size parameter is out of bounds');
113        }
114
115        $url = new Horde_Url($this->_base . '/avatar/' . $this->getId($mail));
116        if (!empty($opts['default'])) {
117            $url->add('d', $opts['default']);
118        }
119        if (!empty($opts['rating'])) {
120            $url->add('r', $opts['rating']);
121        }
122        if (!empty($opts['size'])) {
123            $url->add('s', $opts['size']);
124        }
125
126        return $url;
127    }
128
129    /**
130     * Return the Gravatar profile URL.
131     *
132     * @param string $mail  The mail address.
133     *
134     * @return string  The profile URL.
135     */
136    public function getProfileUrl($mail)
137    {
138        return $this->_base . '/' . $this->getId($mail);
139    }
140
141    /**
142     * Fetch the Gravatar profile information.
143     *
144     * @param string $mail  The mail address.
145     *
146     * @return string  The profile information.
147     */
148    public function fetchProfile($mail)
149    {
150        return $this->_client->get($this->getProfileUrl($mail) . '.json')
151            ->getBody();
152    }
153
154    /**
155     * Return the Gravatar profile information as an array.
156     *
157     * @param string $mail  The mail address.
158     *
159     * @return array  The profile information.
160     */
161    public function getProfile($mail)
162    {
163        return json_decode($this->fetchProfile($mail), true);
164    }
165
166    /**
167     * Fetch the avatar image.
168     *
169     * @param string $mail  The mail address.
170     * @param mixed $opts   Additional options. See getAvatarUrl().
171     *
172     * @return resource  The image as stream resource, or null if the server
173     *                   returned an error.
174     */
175    public function fetchAvatar($mail, $opts = array())
176    {
177        $get = $this->_client->get($this->getAvatarUrl($mail, $opts));
178        return ($get->code == 404)
179            ? null
180            : $get->getStream();
181    }
182
183}
184