1: <?php
2:
3: namespace Alpha\Model;
4:
5: use Alpha\Model\Type\String;
6: use Alpha\Model\Type\Integer;
7: use Alpha\Exception\AlphaException;
8: use Alpha\Exception\IllegalArguementException;
9: use Alpha\Exception\CustomQueryException;
10: use Alpha\Util\Config\ConfigProvider;
11: use Alpha\Util\Cache\CacheProviderFactory;
12: use Alpha\Util\Helper\Validator;
13: use Alpha\Util\Logging\Logger;
14:
15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56:
57: class Tag extends ActiveRecord
58: {
59: 60: 61: 62: 63: 64: 65:
66: protected $taggedClass;
67:
68: 69: 70: 71: 72: 73: 74:
75: protected $taggedOID;
76:
77: 78: 79: 80: 81: 82: 83:
84: protected $content;
85:
86: 87: 88: 89: 90: 91: 92:
93: protected $dataLabels = array('OID' => 'Tag ID#', 'taggedClass' => 'Class Name', 'taggedOID' => 'Tagged Object ID#', 'content' => 'Tag');
94:
95: 96: 97: 98: 99: 100: 101:
102: const TABLE_NAME = 'Tag';
103:
104: 105: 106: 107: 108: 109: 110:
111: private static $logger = null;
112:
113: 114: 115: 116: 117:
118: public function __construct()
119: {
120: self::$logger = new Logger('Tag');
121:
122:
123: parent::__construct();
124: $this->taggedClass = new String();
125: $this->taggedOID = new Integer();
126: $this->content = new String();
127:
128: $this->markUnique('taggedClass', 'taggedOID', 'content');
129: }
130:
131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143:
144: public function loadTags($taggedClass, $taggedOID)
145: {
146: $config = ConfigProvider::getInstance();
147:
148: if ($taggedClass == '' || $taggedOID == '') {
149: throw new IllegalArguementException('The taggedClass or taggedOID provided are empty');
150: }
151:
152: $provider = ActiveRecordProviderFactory::getInstance($config->get('db.provider.name'), $this);
153:
154: try {
155: $tags = $provider->loadAllByAttributes(array('taggedOID', 'taggedClass'), array($taggedOID, $taggedClass));
156:
157: return $tags;
158: } catch (RecordNotFoundException $bonf) {
159: return array();
160: } catch (Exception $e) {
161: self::$logger->error($e->getMessage());
162: throw new AlphaException($e->getMessage());
163: }
164: }
165:
166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178:
179: public static function getPopularTagsArray($limit)
180: {
181: $config = ConfigProvider::getInstance();
182:
183: $provider = ActiveRecordProviderFactory::getInstance($config->get('db.provider.name'), new self());
184:
185: $sqlQuery = 'SELECT content, count(*) as count FROM '.self::TABLE_NAME." GROUP BY content ORDER BY count DESC LIMIT $limit";
186:
187: try {
188: $result = $provider->query($sqlQuery);
189: } catch (CustomQueryException $e) {
190: throw new AlphaException('Failed to query the tags table, error is ['.$e->getMessage().']');
191:
192: return array();
193: }
194:
195:
196: $popTags = array();
197:
198: foreach ($result as $row) {
199: $popTags[$row['content']] = $row['count'];
200: }
201:
202:
203: ksort($popTags);
204:
205: return $popTags;
206: }
207:
208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222:
223: public static function tokenize($content, $taggedClass = '', $taggedOID = '', $applyStopwords = true)
224: {
225: if (self::$logger == null) {
226: self::$logger = new Logger('Tag');
227: }
228:
229: $config = ConfigProvider::getInstance();
230:
231:
232: $lowerWords = preg_split("/[\s,.:-]+/", $content);
233:
234: array_walk($lowerWords, 'Alpha\Model\Tag::lowercaseArrayElement');
235:
236: if ($applyStopwords) {
237: if (file_exists($config->get('app.root').'config/stopwords-'.$config->get('search.stop.words.size').'.ini')) {
238: $stopwords = file($config->get('app.root').'config/stopwords-'.$config->get('search.stop.words.size').'.ini', FILE_IGNORE_NEW_LINES);
239: } elseif (file_exists($config->get('app.root').'Alpha/stopwords-'.$config->get('search.stop.words.size').'.ini')) {
240: $stopwords = file($config->get('app.root').'Alpha/stopwords-'.$config->get('search.stop.words.size').'.ini', FILE_IGNORE_NEW_LINES);
241: } else {
242: throw new AlphaException('Unable to find a stopwords-'.$config->get('search.stop.words.size').'.ini file in the application!');
243: }
244:
245: array_walk($stopwords, 'Alpha\Model\Tag::lowercaseArrayElement');
246:
247: $filtered = array_diff($lowerWords, $stopwords);
248: } else {
249: $filtered = $lowerWords;
250: }
251:
252: $tagObjects = array();
253: $tagContents = array();
254: foreach ($filtered as $tagContent) {
255:
256: if (Validator::isAlpha($tagContent)) {
257:
258: if (!in_array($tagContent, $tagContents) && !empty($tagContent)) {
259: $tag = new self();
260: $tag->set('content', trim(mb_strtolower($tagContent)));
261: if (!empty($taggedClass)) {
262: $tag->set('taggedClass', $taggedClass);
263: }
264: if (!empty($taggedOID)) {
265: $tag->set('taggedOID', $taggedOID);
266: }
267:
268: array_push($tagObjects, $tag);
269: array_push($tagContents, $tagContent);
270: }
271: }
272: }
273:
274: self::$logger->debug('Tags generated: ['.var_export($tagContents, true).']');
275:
276: return $tagObjects;
277: }
278:
279: 280: 281: 282: 283: 284:
285: private static function lowercaseArrayElement(&$element, $key)
286: {
287: $element = trim(mb_strtolower($element));
288: }
289:
290: 291: 292: 293: 294: 295: 296:
297: public static function cleanTagContent($content)
298: {
299: return trim(mb_strtolower(str_replace(' ', '', $content)));
300: }
301:
302: 303: 304: 305: 306:
307: protected function after_save_callback()
308: {
309: $config = ConfigProvider::getInstance();
310:
311: if ($config->get('cache.provider.name') != '') {
312: try {
313: $cache = CacheProviderFactory::getInstance($config->get('cache.provider.name'));
314: $cache->delete($this->get('content'));
315: } catch (\Exception $e) {
316: self::$logger->error('Error while attempting to remove search matches array from the ['.$config->get('cache.provider.name').']
317: instance: ['.$e->getMessage().']');
318: }
319: }
320: }
321:
322: 323: 324: 325: 326:
327: protected function before_delete_callback()
328: {
329: $this->after_save_callback();
330: }
331: }
332: