1: <?php
2:
3: namespace Alpha\View\Widget;
4:
5: use Alpha\Util\Logging\Logger;
6: use Alpha\Util\Config\ConfigProvider;
7: use Alpha\Util\Cache\CacheProviderFactory;
8: use Alpha\Model\Tag;
9:
10: /**
11: * A widget for rendering a tag cloud, based off the Tag instances in the
12: * database.
13: *
14: * @since 1.0
15: *
16: * @author John Collins <dev@alphaframework.org>
17: * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
18: * @copyright Copyright (c) 2015, John Collins (founder of Alpha Framework).
19: * All rights reserved.
20: *
21: * <pre>
22: * Redistribution and use in source and binary forms, with or
23: * without modification, are permitted provided that the
24: * following conditions are met:
25: *
26: * * Redistributions of source code must retain the above
27: * copyright notice, this list of conditions and the
28: * following disclaimer.
29: * * Redistributions in binary form must reproduce the above
30: * copyright notice, this list of conditions and the
31: * following disclaimer in the documentation and/or other
32: * materials provided with the distribution.
33: * * Neither the name of the Alpha Framework nor the names
34: * of its contributors may be used to endorse or promote
35: * products derived from this software without specific
36: * prior written permission.
37: *
38: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
39: * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
40: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
41: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
42: * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
43: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
48: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
49: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
50: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51: * </pre>
52: */
53: class TagCloud
54: {
55: /**
56: * Trace logger.
57: *
58: * @var Alpha\Util\Logging\Logger
59: *
60: * @since 1.0
61: */
62: private static $logger = null;
63:
64: /**
65: * A hash array of popular tags.
66: *
67: * @var array
68: *
69: * @since 1.0
70: */
71: private $popTags = array();
72:
73: /**
74: * Constructor.
75: *
76: * @param $limit The maximum amount of tags to include in the cloud.
77: * @param $cacheKey Set this optional value to attempt to store the tag cloud array in the available cache for 24hrs (cache.provider.name).
78: *
79: * @since 1.0
80: */
81: public function __construct($limit, $cacheKey = '')
82: {
83: $config = ConfigProvider::getInstance();
84:
85: self::$logger = new Logger('TagCloud');
86:
87: if ($cacheKey != '' && $config->get('cache.provider.name') != '') {
88: $cache = CacheProviderFactory::getInstance($config->get('cache.provider.name'));
89: $this->popTags = $cache->get($cacheKey);
90:
91: // cache look-up failed, so add it for the next time
92: if (!$this->popTags) {
93: self::$logger->debug('Cache lookup on the key ['.$cacheKey.'] failed, regenerating popular tags...');
94:
95: $this->popTags = Tag::getPopularTagsArray($limit);
96:
97: $cache->set($cacheKey, $this->popTags, 86400);
98: } else {
99: $this->popTags = array_slice($this->popTags, 0, $limit);
100: self::$logger->debug('Cache lookup on the key ['.$cacheKey.'] succeeded');
101: }
102: } else {
103: $this->popTags = Tag::getPopularTagsArray($limit);
104: }
105: }
106:
107: /**
108: * Render the tag cloud and return all of the HTML links in a single paragraph.
109: *
110: * @param $minLinkSize The minimum font size for any tag link, in points.
111: * @param $maxLinkSize The maximum font size for any tag link, in points.
112: * @param $target The target attribute for the links
113: *
114: * @return string
115: *
116: * @since 1.0
117: */
118: public function render($minLinkSize = 8, $maxLinkSize = 20, $target = '')
119: {
120: $config = ConfigProvider::getInstance();
121: $html = '<p>';
122:
123: foreach (array_keys($this->popTags) as $key) {
124: $linkSize = $this->popTags[$key];
125: if ($linkSize < $minLinkSize) {
126: $linkSize = $minLinkSize;
127: }
128: if ($linkSize > $maxLinkSize) {
129: $linkSize = $maxLinkSize;
130: }
131: $html .= '<a href="'.$config->get('app.url').'/search/'.$key.'" style="font-size:'.$linkSize.'pt;"'.(empty($target) ? '' : ' target="'.$target.'"').' rel="tag">'.$key.'</a> ';
132: }
133:
134: return $html.'</p>';
135: }
136:
137: /**
138: * Get the array of popular tags.
139: *
140: * @return array
141: *
142: * @since 2.0.1
143: */
144: public function getPopTags()
145: {
146: return $this->popTags;
147: }
148: }
149: