CWIS Developer Documentation

- Home
- Main Page
- Classes
- Files

- File List
- File Members

Recommender.php
Go to the documentation of this file.
1 <?PHP
2
3 #
4 # FILE: SPT--Recommender.php
5 #
6 # Part of the Collection Workflow Integration System (CWIS)
7 # Copyright 2004-2013 Edward Almasy and Internet Scout Research Group
8 # http://scout.wisc.edu/cwis/
9 #
10
11 class Recommender {
12
13 # ---- PUBLIC INTERFACE --------------------------------------------------
14 # define content field types
15 const CONTENTFIELDTYPE_TEXT = 1;
16 const CONTENTFIELDTYPE_NUMERIC = 2;
17 const CONTENTFIELDTYPE_CONTROLLEDNAME = 3;
18 const CONTENTFIELDTYPE_DATE = 4;
19 const CONTENTFIELDTYPE_DATERAMGE = 5;
20
21 # object constructor
22 function Recommender(&$DB, $ItemTableName, $RatingTableName,
23 $ItemIdFieldName, $UserIdFieldName, $RatingFieldName,
24 $ContentFields)
25 {
26 # set default parameters
27 $this->ContentCorrelationThreshold = 1;
28
29 # save database object
30 $this->DB =& $DB;
31
32 # save new configuration values
33 $this->ItemTableName = $ItemTableName;
34 $this->RatingTableName = $RatingTableName;
35 $this->ItemIdFieldName = $ItemIdFieldName;
36 $this->UserIdFieldName = $UserIdFieldName;
37 $this->RatingFieldName = $RatingFieldName;
38 $this->ContentFields = $ContentFields;
39
40 # set default debug state
41 $this->DebugLevel = 0;
42 }
43
44 # set level for debugging output
45 function DebugLevel($Setting)
46 {
47 $this->DebugLevel = $Setting;
48 }
49
50
51 # ---- recommendation methods
52
53 # recommend items for specified user
54 function Recommend($UserId, $StartingResult = 0, $NumberOfResults = 10)
55 {
56 if ($this->DebugLevel > 0) { print("REC: Recommend(${UserId}, ${StartingResult}, ${NumberOfResults})<br>\n"); }
57
58 # load in user ratings
59 $Ratings = array();
60 $DB =& $this->DB;
61 $DB->Query("SELECT ".$this->ItemIdFieldName.", ".$this->RatingFieldName
62 ." FROM ".$this->RatingTableName
63 ." WHERE ".$this->UserIdFieldName." = ${UserId}");
64 while ($Row = $DB->FetchRow())
65 {
66 $Ratings[$Row[$this->ItemIdFieldName]] =
67 $Row[$this->RatingFieldName];
68 }
69 if ($this->DebugLevel > 1) { print("REC: user has rated ".count($Ratings)." items<br>\n"); }
70
71 # for each item that user has rated
72 $RecVals = array();
73 foreach ($Ratings as $ItemId => $ItemRating)
74 {
75 # for each content correlation available for that item
76 $DB->Query("SELECT Correlation, ItemIdB "
77 ."FROM RecContentCorrelations "
78 ."WHERE ItemIdA = ${ItemId}");
79 while ($Row = $DB->FetchRow())
80 {
81 # multiply that correlation by normalized rating and add
82 # resulting value to recommendation value for that item
83 if (isset($RecVals[$Row["ItemIdB"]]))
84 {
85 $RecVals[$Row["ItemIdB"]] +=
86 $Row["Correlation"] * ($ItemRating - 50);
87 }
88 else
89 {
90 $RecVals[$Row["ItemIdB"]] =
91 $Row["Correlation"] * ($ItemRating - 50);
92 }
93 if ($this->DebugLevel > 9) { print("REC: RecVal[".$Row["ItemIdB"]."] = ".$RecVals[$Row["ItemIdB"]]."<br>\n"); }
94 }
95 }
96 if ($this->DebugLevel > 1) { print("REC: found ".count($RecVals)." total recommendations<br>\n"); }
97
98 # calculate average correlation between items
99 $ResultThreshold = $DB->Query("SELECT AVG(Correlation) "
100 ."AS Average FROM RecContentCorrelations", "Average");
101 $ResultThreshold = round($ResultThreshold) * 2;
102
103 # for each recommended item
104 foreach ($RecVals as $ItemId => $RecVal)
105 {
106 # remove item from list if user already rated it
107 if (isset($Ratings[$ItemId]))
108 {
109 unset($RecVals[$ItemId]);
110 }
111 else
112 {
113 # scale recommendation value back to match thresholds
114 $RecVals[$ItemId] = round($RecVal / 50);
115
116 # remove item from recommendation list if value is below threshold
117 if ($RecVals[$ItemId] < $ResultThreshold)
118 {
119 unset($RecVals[$ItemId]);
120 }
121 }
122 }
123 if ($this->DebugLevel > 1) { print("REC: found ".count($RecVals)." positive recommendations<br>\n"); }
124
125 # sort recommendation list by value
126 if (isset($RecVals)) { arsort($RecVals, SORT_NUMERIC); }
127
128 # save total number of results available
129 $this->NumberOfResultsAvailable = count($RecVals);
130
131 # trim result list to match range requested by caller
132 $RecValKeys = array_slice(
133 array_keys($RecVals), $StartingResult, $NumberOfResults);
134 $RecValSegment = array();
135 foreach ($RecValKeys as $Key)
136 {
137 $RecValSegment[$Key] = $RecVals[$Key];
138 }
139
140 # return recommendation list to caller
141 return $RecValSegment;
142 }
143
144 # add function to be called to filter returned recommendation list
145 function AddResultFilterFunction($FunctionName)
146 {
147 # save filter function name
148 $this->FilterFuncs[] = $FunctionName;
149 }
150
151 # return number of recommendations generated
152 function NumberOfResults()
153 {
154 return $this->NumberOfResultsAvailable;
155 }
156
157 # return recommendation generation time
158 function SearchTime()
159 {
160 return $this->LastSearchTime;
161 }
162
163 # return list of items used to generate recommendation of specified item
164 function GetSourceList($UserId, $RecommendedItemId)
165 {
166 # pull list of correlations from DB
167 $this->DB->Query("SELECT * FROM RecContentCorrelations, ".$this->RatingTableName
168 ." WHERE (ItemIdA = ${RecommendedItemId}"
169 ." OR ItemIdB = ${RecommendedItemId})"
170 ." AND ".$this->UserIdFieldName." = ".$UserId
171 ." AND (RecContentCorrelations.ItemIdA = ".$this->RatingTableName.".".$this->ItemIdFieldName
172 ." OR RecContentCorrelations.ItemIdB = ".$this->RatingTableName.".".$this->ItemIdFieldName.")"
173 ." AND Rating >= 50 "
174 ." ORDER BY Correlation DESC");
175
176 # for each correlation
177 $SourceList = array();
178 while ($Row = $this->DB->FetchRow())
179 {
180 # pick out appropriate item ID
181 if ($Row["ItemIdA"] == $RecommendedItemId)
182 {
183 $ItemId = $Row["ItemIdB"];
184 }
185 else
186 {
187 $ItemId = $Row["ItemIdA"];
188 }
189
190 # add item to recommendation source list
191 $SourceList[$ItemId] = $Row["Correlation"];
192 }
193
194 # return recommendation source list to caller
195 return $SourceList;
196 }
197
198 # dynamically generate and return list of items similar to specified item
199 function FindSimilarItems($ItemId, $FieldList = NULL)
200 {
201 if ($this->DebugLevel > 1) { print("REC: searching for items similar to item \"".$ItemId."\"<br>\n"); }
202
203 # make sure we have item IDs available
204 $this->LoadItemIds();
205
206 # start with empty array
207 $SimilarItems = array();
208
209 # for every item
210 foreach ($this->ItemIds as $Id)
211 {
212 # if item is not specified item
213 if ($Id != $ItemId)
214 {
215 # calculate correlation of item to specified item
216 $Correlation = $this->CalculateContentCorrelation($ItemId, $Id, $FieldList);
217
218 # if correlation is above threshold
219 if ($Correlation > $this->ContentCorrelationThreshold)
220 {
221 # add item to list of similar items
222 $SimilarItems[$Id] = $Correlation;
223 }
224 }
225 }
226 if ($this->DebugLevel > 3) { print("REC: ".count($SimilarItems)." similar items to item \"".$ItemId."\" found<br>\n"); }
227
228 # filter list of similar items (if any)
229 if (count($SimilarItems) > 0)
230 {
231 $SimilarItems = $this->FilterOnSuppliedFunctions($SimilarItems);
232 if ($this->DebugLevel > 4) { print("REC: ".count($SimilarItems)." similar items to item \"".$ItemId."\" left after filtering<br>\n"); }
233 }
234
235 # if any similar items left
236 if (count($SimilarItems) > 0)
237 {
238 # sort list of similar items in order of most to least similar
239 arsort($SimilarItems, SORT_NUMERIC);
240 }
241
242 # return list of similar items to caller
243 return $SimilarItems;
244 }
245
246 # dynamically generate and return list of recommended field values for item
247 function RecommendFieldValues($ItemId, $FieldList = NULL)
248 {
249 if ($this->DebugLevel > 1) { print("REC: generating field value recommendations for item \"".$ItemId."\"<br>\n"); }
250
251 # start with empty array of values
252 $RecVals = array();
253
254 # generate list of similar items
255 $SimilarItems = $this->FindSimilarItems($ItemId, $FieldList);
256
257 # if similar items found
258 if (count($SimilarItems) > 0)
259 {
260 # prune list of similar items to only top third of better-than-average
261 $AverageCorr = intval(array_sum($SimilarItems) / count($SimilarItems));
262 reset($SimilarItems);
263 $HighestCorr = current($SimilarItems);
264 $CorrThreshold = intval($HighestCorr - (($HighestCorr - $AverageCorr) / 3));
265 if ($this->DebugLevel > 8) { print("REC: <i>Average Correlation: $AverageCorr &nbsp;&nbsp;&nbsp;&nbsp; Highest Correlation: $HighestCorr &nbsp;&nbsp;&nbsp;&nbsp; Correlation Threshold: $CorrThreshold </i><br>\n"); }
266 foreach ($SimilarItems as $ItemId => $ItemCorr)
267 {
268 if ($ItemCorr < $CorrThreshold)
269 {
270 unset($SimilarItems[$ItemId]);
271 }
272 }
273 if ($this->DebugLevel > 6) { print("REC: ".count($SimilarItems)." similar items left after threshold pruning<br>\n"); }
274
275 # for each item
276 foreach ($SimilarItems as $SimItemId => $SimItemCorr)
277 {
278 # for each field
279 foreach ($this->ContentFields as $FieldName => $FieldAttributes)
280 {
281 # load field data for this item
282 $FieldData = $this->GetFieldValue($SimItemId, $FieldName);
283
284 # if field data is array
285 if (is_array($FieldData))
286 {
287 # for each field data value
288 foreach ($FieldData as $FieldDataVal)
289 {
290 # if data value is not empty
291 $FieldDataVal = trim($FieldDataVal);
292 if (strlen($FieldDataVal) > 0)
293 {
294 # increment count for data value
295 $RecVals[$FieldName][$FieldDataVal]++;
296 }
297 }
298 }
299 else
300 {
301 # if data value is not empty
302 $FieldData = trim($FieldData);
303 if (strlen($FieldData) > 0)
304 {
305 # increment count for data value
306 $RecVals[$FieldName][$FieldData]++;
307 }
308 }
309 }
310 }
311
312 # for each field
313 $MatchingCountThreshold = 3;
314 foreach ($RecVals as $FieldName => $FieldVals)
315 {
316 # determine cutoff threshold
317 arsort($FieldVals, SORT_NUMERIC);
318 reset($FieldVals);
319 $HighestCount = current($FieldVals);
320 $AverageCount = intval(array_sum($FieldVals) / count($FieldVals));
321 $CountThreshold = intval($AverageCount + (($HighestCount - $AverageCount) / 2));
322 if ($CountThreshold < $MatchingCountThreshold) { $CountThreshold = $MatchingCountThreshold; }
323 if ($this->DebugLevel > 8) { print("REC: <i>Field: $FieldName &nbsp;&nbsp;&nbsp;&nbsp; Average Count: $AverageCount &nbsp;&nbsp;&nbsp;&nbsp; Highest Count: $HighestCount &nbsp;&nbsp;&nbsp;&nbsp; Count Threshold: $CountThreshold </i><br>\n"); }
324
325 # for each field data value
326 foreach ($FieldVals as $FieldVal => $FieldValCount)
327 {
328 # if value count is below threshold
329 if ($FieldValCount < $CountThreshold)
330 {
331 # unset value
332 unset($RecVals[$FieldName][$FieldVal]);
333 }
334 }
335
336 if ($this->DebugLevel > 3) { print("REC: found ".count($RecVals[$FieldName])." recommended values for field \"".$FieldName."\" after threshold pruning<br>\n"); }
337 }
338 }
339
340 # return recommended values to caller
341 return $RecVals;
342 }
343
344
345 # ---- database update methods
346
347 function UpdateForItems($StartingItemId, $NumberOfItems)
348 {
349 if ($this->DebugLevel > 0) { print("REC: UpdateForItems(${StartingItemId}, ${NumberOfItems})<br>\n"); }
350 # make sure we have item IDs available
351 $this->LoadItemIds();
352
353 # for every item
354 $ItemsUpdated = 0;
355 $ItemId = NULL;
356 foreach ($this->ItemIds as $ItemId)
357 {
358 # if item ID is within requested range
359 if ($ItemId >= $StartingItemId)
360 {
361 # update recommender info for item
362 if ($this->DebugLevel > 1) { print("REC: doing item ${ItemId}<br>\n"); }
363 $this->UpdateForItem($ItemId, TRUE);
364 $ItemsUpdated++;
365
366 # if we have done requested number of items
367 if ($ItemsUpdated >= $NumberOfItems)
368 {
369 # bail out
370 if ($this->DebugLevel > 1) { print("REC: bailing out with item ${ItemId}<br>\n"); }
371 return $ItemId;
372 }
373 }
374 }
375
376 # return ID of last resource updated to caller
377 return $ItemId;
378 }
379
380 function UpdateForItem($ItemId, $FullPass = FALSE)
381 {
382 if ($this->DebugLevel > 1) { print("REC: updating for item \"".$ItemId."\"<br>\n"); }
383
384 # make sure we have item IDs available
385 $this->LoadItemIds();
386
387 # clear existing correlations for this item
388 $this->DB->Query("DELETE FROM RecContentCorrelations "
389 ."WHERE ItemIdA = ${ItemId}");
390
391 # for every item
392 foreach ($this->ItemIds as $Id)
393 {
394 # if full pass and item is later in list than current item
395 if (($FullPass == FALSE) || ($Id > $ItemId))
396 {
397 # update correlation value for item and target item
398 $this->UpdateContentCorrelation($ItemId, $Id);
399 }
400 }
401 }
402
403 function DropItem($ItemId)
404 {
405 # drop all correlation entries referring to item
406 $this->DB->Query("DELETE FROM RecContentCorrelations "
407 ."WHERE ItemIdA = ".$ItemId." "
408 ."OR ItemIdB = ".$ItemId);
409 }
410
411 function PruneCorrelations()
412 {
413 # get average correlation
414 $AverageCorrelation = $this->DB->Query("SELECT AVG(Correlation) "
415 ."AS Average FROM RecContentCorrelations", "Average");
416
417 # dump all below-average correlations
418 if ($AverageCorrelation > 0)
419 {
420 $this->DB->Query("DELETE FROM RecContentCorrelations "
421 ."WHERE Correlation <= ${AverageCorrelation}");
422 }
423 }
424
429 function GetItemIds()
430 {
431 static $ItemIds;
432 if (!isset($ItemIds))
433 {
434 $this->DB->Query("SELECT ".$this->ItemIdFieldName." AS Id FROM "
435 .$this->ItemTableName." ORDER BY ".$this->ItemIdFieldName);
436 $ItemIds = $this->DB->FetchColumn("Id");
437 }
438 return $ItemIds;
439 }
440
441
442 # ---- PRIVATE INTERFACE -------------------------------------------------
443
444 var $ContentCorrelationThreshold;
445 var $ContentFields;
446 var $ItemTableName;
447 var $RatingTableName;
448 var $ItemIdFieldName;
449 var $UserIdFieldName;
450 var $RatingFieldName;
451 var $ItemIds;
452 var $DB;
453 var $FilterFuncs;
454 var $LastSearchTime;
455 var $NumberOfResultsAvailable;
456 var $DebugLevel;
457
458
459 function LoadItemIds()
460 {
461 # if item IDs not already loaded
462 if (!isset($this->ItemIds))
463 {
464 # load item IDs from DB
465 $this->DB->Query("SELECT ".$this->ItemIdFieldName." AS Id FROM "
466 .$this->ItemTableName." ORDER BY ".$this->ItemIdFieldName);
467 $this->ItemIds = array();
468 while ($Item = $this->DB->FetchRow())
469 {
470 $this->ItemIds[] = $Item["Id"];
471 }
472 }
473 }
474
475 function GetFieldData($ItemId, $FieldName)
476 {
477 static $ItemData;
478
479 # if data not already loaded
480 if (!isset($ItemData[$ItemId][$FieldName]))
481 {
482 # load field value from DB
483 $FieldValue = $this->GetFieldValue($ItemId, $FieldName);
484
485 # if field value is array
486 if (is_array($FieldValue))
487 {
488 # concatenate together text from array elements
489 $FieldValue = implode(" ", $FieldValue);
490 }
491
492 # normalize text and break into word array
493 $ItemData[$ItemId][$FieldName] = $this->NormalizeAndParseText($FieldValue);
494 }
495
496 # return cached data to caller
497 return $ItemData[$ItemId][$FieldName];
498 }
499
500 # calculate content correlation between two items and return value to caller
501 function CalculateContentCorrelation($ItemIdA, $ItemIdB, $FieldList = NULL)
502 {
503 static $CorrelationCache;
504
505 if ($this->DebugLevel > 10) { print("REC: calculating correlation"
506 ." between items $ItemIdA and $ItemIdB<br>\n"); }
507
508 # order item ID numbers
509 if ($ItemIdA > $ItemIdB)
510 {
511 $Temp = $ItemIdA;
512 $ItemIdA = $ItemIdB;
513 $ItemIdB = $Temp;
514 }
515
516 # if we already have the correlation
517 if (isset($CorrelationCache[$ItemIdA][$ItemIdB]))
518 {
519 # retrieve correlation from cache
520 $TotalCorrelation = $CorrelationCache[$ItemIdA][$ItemIdB];
521 }
522 else
523 {
524 # if list of fields to correlate specified
525 if ($FieldList != NULL)
526 {
527 # create list with only specified fields
528 foreach ($FieldList as $FieldName)
529 {
530 $ContentFields[$FieldName] = $this->ContentFields[$FieldName];
531 }
532 }
533 else
534 {
535 # use all fields
536 $ContentFields = $this->ContentFields;
537 }
538
539 # for each content field
540 $TotalCorrelation = 0;
541 foreach ($ContentFields as $FieldName => $FieldAttributes)
542 {
543 # if field is of a type that we use for correlation
544 $FieldType = intval($FieldAttributes["FieldType"]);
545 if (($FieldType == Recommender::CONTENTFIELDTYPE_TEXT)
546 || ($FieldType == Recommender::CONTENTFIELDTYPE_CONTROLLEDNAME))
547 {
548 # load data
549 $ItemAData = $this->GetFieldData($ItemIdA, $FieldName);
550 $ItemBData = $this->GetFieldData($ItemIdB, $FieldName);
551 if ($this->DebugLevel > 15) { print("REC: loaded ".count($ItemAData)." terms for item #".$ItemIdA." and ".count($ItemBData)." terms for item #".$ItemIdB." for field \"".$FieldName."\"<br>\n"); }
552
553 # call appropriate routine to get correlation
554 switch ($FieldType)
555 {
556 case Recommender::CONTENTFIELDTYPE_TEXT:
557 case Recommender::CONTENTFIELDTYPE_CONTROLLEDNAME:
558 $Correlation = $this->CalcTextCorrelation(
559 $ItemAData, $ItemBData);
560 break;
561 }
562
563 # add correlation multiplied by weight to total
564 $TotalCorrelation += $Correlation * $FieldAttributes["Weight"];
565 }
566 }
567
568 # store correlation to cache
569 $CorrelationCache[$ItemIdA][$ItemIdB] = $TotalCorrelation;
570 }
571
572 # return correlation value to caller
573 if ($this->DebugLevel > 9) { print("REC: correlation between items $ItemIdA and $ItemIdB found to be $TotalCorrelation<br>\n"); }
574 return $TotalCorrelation;
575 }
576
577 # calculate content correlation between two items and update in DB
578 function UpdateContentCorrelation($ItemIdA, $ItemIdB)
579 {
580 if ($this->DebugLevel > 6) { print("REC: updating correlation between items $ItemIdA and $ItemIdB<br>\n"); }
581
582 # bail out if two items are the same
583 if ($ItemIdA == $ItemIdB) { return; }
584
585 # calculate correlation
586 $Correlation = $this->CalculateContentCorrelation($ItemIdA, $ItemIdB);
587
588 # save new correlation
589 $this->ContentCorrelation($ItemIdA, $ItemIdB, $Correlation);
590 }
591
592 function NormalizeAndParseText($Text)
593 {
594 $StopWords = array(
595 "a",
596 "about",
597 "also",
598 "an",
599 "and",
600 "are",
601 "as",
602 "at",
603 "be",
604 "but",
605 "by",
606 "can",
607 "each",
608 "either",
609 "for",
610 "from",
611 "has",
612 "he",
613 "her",
614 "here",
615 "hers",
616 "him",
617 "his",
618 "how",
619 "i",
620 "if",
621 "in",
622 "include",
623 "into",
624 "is",
625 "it",
626 "its",
627 "me",
628 "neither",
629 "no",
630 "nor",
631 "not",
632 "of",
633 "on",
634 "or",
635 "so",
636 "she",
637 "than",
638 "that",
639 "the",
640 "their",
641 "them",
642 "then",
643 "there",
644 "these",
645 "they",
646 "this",
647 "those",
648 "through",
649 "to",
650 "too",
651 "very",
652 "what",
653 "when",
654 "where",
655 "while",
656 "who",
657 "why",
658 "will",
659 "you",
660 "");
661
662 # strip any HTML tags
663 $Text = strip_tags($Text);
664
665 # strip any punctuation
666 $Text = preg_replace("/,\\.\\?-\\(\\)\\[\\]\"/", " ", $Text); # "
667
668 # normalize whitespace
669 $Text = trim(preg_replace("/[\\s]+/", " ", $Text));
670
671 # convert to all lower case
672 $Text = strtolower($Text);
673
674 # split text into arrays of words
675 $Words = explode(" ", $Text);
676
677 # filter out all stop words
678 $Words = array_diff($Words, $StopWords);
679
680 # return word array to caller
681 return $Words;
682 }
683
684 function CalcTextCorrelation($WordsA, $WordsB)
685 {
686 # get array containing intersection of two word arrays
687 $IntersectWords = array_intersect($WordsA, $WordsB);
688
689 # return number of words remaining as score
690 return count($IntersectWords);
691 }
692
693 function ContentCorrelation($ItemIdA, $ItemIdB, $NewCorrelation = -1)
694 {
695 # if item ID A is greater than item ID B
696 if ($ItemIdA > $ItemIdB)
697 {
698 # swap item IDs
699 $Temp = $ItemIdA;
700 $ItemIdA = $ItemIdB;
701 $ItemIdB = $Temp;
702 }
703
704 # if new correlation value provided
705 if ($NewCorrelation != -1)
706 {
707 # if new value is above threshold
708 if ($NewCorrelation >= $this->ContentCorrelationThreshold)
709 {
710 # insert new correlation value in DB
711 $this->DB->Query("INSERT INTO RecContentCorrelations "
712 ."(ItemIdA, ItemIdB, Correlation) "
713 ."VALUES (${ItemIdA}, ${ItemIdB}, ${NewCorrelation})");
714
715 # return correlation value is new value
716 $Correlation = $NewCorrelation;
717 }
718 # else
719 else
720 {
721 # return value is zero
722 $Correlation = 0;
723 }
724 }
725 else
726 {
727 # retrieve correlation value from DB
728 $Correlation = $this->DB->Query(
729 "SELECT Correlation FROM RecContentCorrelations "
730 ."WHERE ItemIdA = ${ItemIdA} AND ItemIdB = ${ItemIdB}",
731 "Correlation");
732
733 # if no value found in DB
734 if ($Correlation == FALSE)
735 {
736 # return value is zero
737 $Correlation = 0;
738 }
739 }
740
741 # return correlation value to caller
742 return $Correlation;
743 }
744
745 function FilterOnSuppliedFunctions($Results)
746 {
747 # if filter functions have been set
748 if (count($this->FilterFuncs) > 0)
749 {
750 # for each result
751 foreach ($Results as $ResourceId => $Result)
752 {
753 # for each filter function
754 foreach ($this->FilterFuncs as $FuncName)
755 {
756 # if filter function return TRUE for result resource
757 if ($FuncName($ResourceId))
758 {
759 # discard result
760 if ($this->DebugLevel > 2) { print("REC: filter callback rejected resource ${ResourceId}<br>\n"); }
761 unset($Results[$ResourceId]);
762
763 # bail out of filter func loop
764 continue 2;
765 }
766 }
767 }
768 }
769
770 # return filtered list to caller
771 return $Results;
772 }
773 }
774
775 ?>
Recommender\DebugLevel
DebugLevel($Setting)
Definition: Recommender.php:45
Recommender\RecommendFieldValues
RecommendFieldValues($ItemId, $FieldList=NULL)
Definition: Recommender.php:247
Recommender\UpdateForItems
UpdateForItems($StartingItemId, $NumberOfItems)
Definition: Recommender.php:347
Recommender\GetSourceList
GetSourceList($UserId, $RecommendedItemId)
Definition: Recommender.php:164
Recommender\ContentCorrelation
ContentCorrelation($ItemIdA, $ItemIdB, $NewCorrelation=-1)
Definition: Recommender.php:693
Recommender\CONTENTFIELDTYPE_CONTROLLEDNAME
const CONTENTFIELDTYPE_CONTROLLEDNAME
Definition: Recommender.php:17
Recommender\$ItemIds
$ItemIds
Definition: Recommender.php:451
Recommender\$RatingTableName
$RatingTableName
Definition: Recommender.php:447
Recommender\AddResultFilterFunction
AddResultFilterFunction($FunctionName)
Definition: Recommender.php:145
Recommender\CONTENTFIELDTYPE_DATE
const CONTENTFIELDTYPE_DATE
Definition: Recommender.php:18
Recommender\$ItemIdFieldName
$ItemIdFieldName
Definition: Recommender.php:448
Recommender\$ItemTableName
$ItemTableName
Definition: Recommender.php:446
Recommender\FilterOnSuppliedFunctions
FilterOnSuppliedFunctions($Results)
Definition: Recommender.php:745
Recommender\$DebugLevel
$DebugLevel
Definition: Recommender.php:456
Recommender\SearchTime
SearchTime()
Definition: Recommender.php:158
Recommender\PruneCorrelations
PruneCorrelations()
Definition: Recommender.php:411
Recommender\$RatingFieldName
$RatingFieldName
Definition: Recommender.php:450
Recommender\GetItemIds
GetItemIds()
Retrieve all item IDs.
Definition: Recommender.php:429
Recommender\UpdateForItem
UpdateForItem($ItemId, $FullPass=FALSE)
Definition: Recommender.php:380
Recommender\NumberOfResults
NumberOfResults()
Definition: Recommender.php:152
Recommender\CONTENTFIELDTYPE_NUMERIC
const CONTENTFIELDTYPE_NUMERIC
Definition: Recommender.php:16
Recommender\GetFieldData
GetFieldData($ItemId, $FieldName)
Definition: Recommender.php:475
Recommender\UpdateContentCorrelation
UpdateContentCorrelation($ItemIdA, $ItemIdB)
Definition: Recommender.php:578
PHP
PHP
Definition: OAIClient.php:39
Recommender\Recommend
Recommend($UserId, $StartingResult=0, $NumberOfResults=10)
Definition: Recommender.php:54
Recommender\$FilterFuncs
$FilterFuncs
Definition: Recommender.php:453
Recommender\CalcTextCorrelation
CalcTextCorrelation($WordsA, $WordsB)
Definition: Recommender.php:684
Recommender\LoadItemIds
LoadItemIds()
Definition: Recommender.php:459
Recommender\CONTENTFIELDTYPE_TEXT
const CONTENTFIELDTYPE_TEXT
Definition: Recommender.php:15
Recommender\Recommender
Recommender(&$DB, $ItemTableName, $RatingTableName, $ItemIdFieldName, $UserIdFieldName, $RatingFieldName, $ContentFields)
Definition: Recommender.php:22
Recommender\FindSimilarItems
FindSimilarItems($ItemId, $FieldList=NULL)
Definition: Recommender.php:199
Recommender\CONTENTFIELDTYPE_DATERAMGE
const CONTENTFIELDTYPE_DATERAMGE
Definition: Recommender.php:19
Recommender\$NumberOfResultsAvailable
$NumberOfResultsAvailable
Definition: Recommender.php:455
Recommender\NormalizeAndParseText
NormalizeAndParseText($Text)
Definition: Recommender.php:592
Recommender\CalculateContentCorrelation
CalculateContentCorrelation($ItemIdA, $ItemIdB, $FieldList=NULL)
Definition: Recommender.php:501
Recommender
Definition: Recommender.php:11
Recommender\$ContentFields
$ContentFields
Definition: Recommender.php:445
Recommender\$DB
$DB
Definition: Recommender.php:452
Recommender\$ContentCorrelationThreshold
$ContentCorrelationThreshold
Definition: Recommender.php:444
Recommender\DropItem
DropItem($ItemId)
Definition: Recommender.php:403
Recommender\$LastSearchTime
$LastSearchTime
Definition: Recommender.php:454
Recommender\$UserIdFieldName
$UserIdFieldName
Definition: Recommender.php:449