1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 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: class SearchProviderTags implements SearchProviderInterface {
50:
51: 52: 53: 54: 55: 56:
57: private static $logger;
58:
59: 60: 61: 62: 63: 64:
65: private $numberFound = 0;
66:
67: 68: 69: 70: 71:
72: public function __construct() {
73: self::$logger = new Logger('SearchProviderTags');
74: }
75:
76: 77: 78:
79: public function search($query, $returnType = 'all', $start = 0, $limit = 10) {
80: global $config;
81:
82:
83: $queryTags = TagObject::tokenize($query, '', '', false);
84: $matchingTags = array();
85:
86:
87: foreach($queryTags as $queryTag) {
88: $tags = $queryTag->loadAllByAttribute('content', $queryTag->get('content'));
89: $matchingTags = array_merge($matchingTags, $tags);
90: }
91:
92:
93: $results = array();
94:
95: $matches = array();
96:
97: if ($config->get('cache.provider.name') != '' && count($queryTags) == 1) {
98: $key = $queryTags[0]->get('content');
99: $matches = $this->loadFromCache($key);
100: }
101:
102: if (count($matches) == 0) {
103: 104: 105: 106: 107:
108: foreach($matchingTags as $tag) {
109: if ($returnType == 'all' || $tag->get('taggedClass') == $returnType) {
110:
111: $key = $tag->get('taggedClass').'-'.$tag->get('taggedOID');
112:
113: if(isset($matches[$key])) {
114:
115: $weight = intval($matches[$key]) + 1;
116: $matches[$key] = $weight;
117: }else{
118: $matches[$key] = 1;
119: }
120: }
121: }
122:
123: if ($config->get('cache.provider.name') != '' && count($queryTags) == 1) {
124: $key = $queryTags[0]->get('content');
125: $this->addToCache($key, $matches);
126: }
127: }
128:
129:
130: arsort($matches);
131:
132: $this->numberFound = count($matches);
133:
134:
135: $matches = array_slice($matches, $start, $limit+5);
136:
137:
138: foreach ($matches as $key => $weight) {
139: if(count($results) < $limit) {
140: $parts = explode('-', $key);
141:
142: try {
143:
144: $BO = new $parts[0];
145: $BO->load($parts[1]);
146:
147: $results[] = $BO;
148:
149: }catch(BONotFoundException $e) {
150: self::$logger->warn('Orpaned TagObject detected pointing to a non-existant BO of OID ['.$parts[1].'] and type ['.$parts[0].'].');
151: }
152: }
153: }
154:
155: return $results;
156: }
157:
158: 159: 160:
161: public function getRelated(AlphaDAO $sourceObject, $returnType = 'all', $start = 0, $limit = 10, $distinct = '') {
162:
163: global $config;
164:
165:
166: $results = array();
167:
168: $matches = array();
169:
170: $distinctValues = array();
171:
172: if ($config->get('cache.provider.name') != '') {
173: $key = get_class($sourceObject).'-'.$sourceObject->getOID().'-related'.($distinct == '' ? '' : '-distinct');
174: $matches = $this->loadFromCache($key);
175: }
176:
177: if (count($matches) == 0) {
178:
179: $tags = $sourceObject->getPropObject('tags')->getRelatedObjects();
180:
181: foreach($tags as $tag) {
182: $tagObject = new TagObject();
183:
184: if ($distinct == '') {
185: $matchingTags = $tagObject->query("SELECT * FROM ".$tagObject->getTableName()." WHERE
186: content='".$tag->get('content')."' AND NOT
187: (taggedOID = '".$sourceObject->getOID()."' AND taggedClass = '".get_class($sourceObject)."');");
188: }else{
189:
190: $matchingTags = $tagObject->query("SELECT * FROM ".$tagObject->getTableName()." WHERE
191: content='".$tag->get('content')."' AND NOT
192: (taggedOID = '".$sourceObject->getOID()."' AND taggedClass = '".get_class($sourceObject)."')
193: AND taggedOID IN (SELECT OID FROM ".$sourceObject->getTableName()." WHERE ".$distinct." != '".addslashes($sourceObject->get($distinct))."');");
194: }
195:
196: foreach($matchingTags as $matchingTag) {
197: if ($returnType == 'all' || $tag->get('taggedClass') == $returnType) {
198:
199: $key = $matchingTag['taggedClass'].'-'.$matchingTag['taggedOID'];
200:
201:
202: if ($distinct != '') {
203: try {
204:
205: $BO = new $matchingTag['taggedClass'];
206: $BO->load($matchingTag['taggedOID']);
207:
208:
209: if ($sourceObject->get($distinct) == $BO->get($distinct))
210: continue;
211:
212: if(!in_array($BO->get($distinct), $distinctValues)) {
213: $distinctValues[] = $BO->get($distinct);
214: }else{
215: continue;
216: }
217: }catch (BONotFoundException $e) {
218: self::$logger->warn('Error loading object ['.$matchingTag['taggedOID'].'] of type ['.$matchingTag['taggedClass'].'], probable orphan');
219: }
220: }
221:
222: if(isset($matches[$key])) {
223:
224: $weight = intval($matches[$key]) + 1;
225: $matches[$key] = $weight;
226: }else{
227: $matches[$key] = 1;
228: }
229: }
230: }
231:
232: if ($config->get('cache.provider.name') != '') {
233: $key = get_class($sourceObject).'-'.$sourceObject->getOID().'-related'.($distinct == '' ? '' : '-distinct');
234: $this->addToCache($key, $matches);
235: }
236: }
237: }
238:
239:
240: arsort($matches);
241:
242: $this->numberFound = count($matches);
243:
244:
245: $matches = array_slice($matches, $start, $limit);
246:
247:
248: foreach ($matches as $key => $weight) {
249: $parts = explode('-', $key);
250:
251: $BO = new $parts[0];
252: $BO->load($parts[1]);
253:
254: $results[] = $BO;
255: }
256:
257: return $results;
258: }
259:
260: 261: 262:
263: public function index(AlphaDAO $sourceObject) {
264: $taggedAttributes = $sourceObject->getTaggedAttributes();
265:
266: foreach($taggedAttributes as $tagged) {
267: $tags = TagObject::tokenize($sourceObject->get($tagged), get_class($sourceObject), $sourceObject->getOID());
268:
269: foreach($tags as $tag) {
270: try {
271: $tag->save();
272: }catch(ValidationException $e){
273: 274: 275: 276:
277: }
278: }
279: }
280: }
281:
282: 283: 284:
285: public function delete(AlphaDAO $sourceObject) {
286: $tags = $sourceObject->getPropObject('tags')->getRelatedObjects();
287:
288: foreach ($tags as $tag)
289: $tag->delete();
290: }
291:
292: 293: 294:
295: public function getNumberFound() {
296: return $this->numberFound;
297: }
298:
299: 300: 301: 302: 303:
304: private function loadFromCache($key) {
305: global $config;
306:
307: try {
308: $cache = AlphaCacheProviderFactory::getInstance($config->get('cache.provider.name'));
309: $matches = $cache->get($key);
310:
311: if(!$matches) {
312: self::$logger->debug('Cache miss on key ['.$key.']');
313: return array();
314: }else{
315: self::$logger->debug('Cache hit on key ['.$key.']');
316: return $matches;
317: }
318: }catch(Exception $e) {
319: self::$logger->error('Error while attempting to load a search result from ['.$config->get('cache.provider.name').']
320: instance: ['.$e->getMessage().']');
321:
322: return array();
323: }
324: }
325:
326: 327: 328: 329: 330:
331: public function addToCache($key, $matches) {
332: global $config;
333:
334: try {
335: $cache = AlphaCacheProviderFactory::getInstance($config->get('cache.provider.name'));
336: $cache->set($key, $matches, 86400);
337:
338: }catch(Exception $e) {
339: self::$logger->error('Error while attempting to store a search matches array to the ['.$config->get('cache.provider.name').']
340: instance: ['.$e->getMessage().']');
341: }
342: }
343: }
344:
345: ?>