* @package WB */ WBClass::load('WBEvent'); /** * Generic Dictionary * * Store and access lists of somethings * * @version 0.2.0 * @package WB */ abstract class WBDictionary extends WBStdClass { /** * current word * @var string */ protected $word = null; /** * current data * @var array */ protected $data = null; /** * current id * @var string */ protected $id = null; /** * string name of actual dictionary * @var string */ protected $dictionary; /** * additional data to populate record * @var array */ protected $mergeFields = array(); /** * constructor * * */ final public function __construct() { $dict = get_class($this); $this->dictionary = substr($dict, strlen(__CLASS__) + 1); $this->init(); } /** * 2nd constructor * * Do initial stuff in derived classes */ protected function init() { } /** * add word to dictionary * * See whether word already exists in dictionary, otherwise add id. * Beware, because some dictionaries don't allow to add records. * * @param string $word */ final public function addWord($word) { $data = $this->explode($word); $old = $this->find($data); $this->word = $word; if (!empty($old)) { $this->data = $old; $this->id = $old['id']; return; } $this->id = $this->insert($data); if (!$this->id) { $this->word = null; return; } $this->data = $data; $this->data['id'] = $this->id; // trigger event $eData = $this->data; $eData['word'] = $word; $eData['dictionary']= $this->dictionary; WBEvent::trigger('dictionary:addword:' . strtolower($this->dictionary), 'Added word {WORD} to dictionary {DICT}.', $eData); } /** * extract dictionary data from word * * * * @param string $word * @return array */ abstract protected function explode($word); /** * find data in dictionary * * Search for record in dictionary and load it. * * @param array $data * @return array */ abstract protected function find($data); /** * save new dictionary record * * Store in dictionary as new record. * * @see addWord() * @param array $data * @return string id */ abstract protected function insert($data); /** * lookup word in dictionary * * @param string $word * @return bool true if found */ final public function lookupWord($word) { if ($word == $this->word) { return true; } $data = $this->explode($word); $old = $this->find($data); if (empty($old)) { $this->word = null; $this->id = null; $this->data = null; return false; } $this->word = $word; $this->data = $old; $this->id = $old['id']; return true; } /** * populate dictionary record * * * @param array $data */ final public function populate($data) { if (!$this->id) { WBClass::load('WBException_Call'); throw new WBException_Call('Cannot call isPopulate before word was looked up or added!', 1, __CLASS__); } $save = array(); $save['populated'] = gmdate('Y-m-d H:i:s'); foreach ($this->mergeFields as $f) { $save[$f] = null; if (isset($data[$f])) { $save[$f] = $data[$f]; } } $merge = $this->merge($save); $this->data = array_merge($this->data, $merge); $this->data['populated'] = $save['populated']; // trigger event $eData = $this->data; $eData['word'] = $this->word; $eData['dictionary'] = $this->dictionary; WBEvent::trigger('dictionary:populated:' . $this->dictionary, 'Populated word {WORD} in dictionary {DICT}.', $data); } /** * populate automaically * * Find additional data to populate dictionary record. E.g. by crawling Wikipedia * or looking up IMDB * * @param string $id */ abstract public function autoPopulate($id = null); /** * save additional data to dictionary record * * This is used to populate the dictionary record * * @see populate * @param array $save * @return array */ abstract protected function merge($save); /** * load record by id * * Restore dictionary object from storage * * @param string $id */ abstract public function load($id); /** * get dictionary id * * Fetch id of current word * * @return string|null */ final public function getId() { return $this->id; } /** * get word * * Fetch word currently looked up * * @return string|null */ final public function getWord() { return $this->word; } /** * get record * * Fetch current dictionary record * * @return array|null */ final public function get() { if (!$this->id) { return null; } return $this->data; } /** * Get Simple List of Dictionary Records as Key-Value-Pairs * * This is used to fetch the whole dictionary as list of ids pointing to * words. Some dictionaries are reasonable small and may provide a complete * list (like Language or Country), others are just to big or grow (URL) * and simply cannot provide complete lists without exceeding memory limit. * * Therefore it's the concrete dictionary's choice whether to provider * complete list, partual lists or throw an exception (default). * * In case there is a list to return, it will be a simple associative array * of key => value pairs. * * @throws WBException_Call if there is no list * @return array $list */ public function getList() { WBClass::load('WBException_Call'); throw new WBException_Call('getList() is not imeplemented in this dictionary!', 2, __CLASS__); } /** * Get List of Dictionary Records Like Database Records * * @throws WBException_Call if there is no list * @return array $list */ public function getExtendedList() { $list = $this->getList(); $rec = array(); foreach ($list as $k => $v) { $rec[] = array( 'id' => $k, 'word' => $v ); } return $rec; } /** * check whether record is populated yet * * See whether dictionary data have been populated * * @throws WBException_Call in case there is no current dictionary record * @return bool */ final public function isPopulated() { if (!$this->id) { WBClass::load('WBException_Call'); throw new WBException_Call('Cannot call isPopulate before word was looked up or added!', 1, __CLASS__); } if ($this->data['populated']) { return true; } return false; } } ?>