user = &$user; $this->type_id = $type['type_id']; $this->name = $type['name']; $this->weight = $type['weight']; $this->remind_delay_yes = $type['remind_delay_yes']; $this->remind_delay_no = $type['remind_delay_no']; $this->remind_delay_dismiss = $type['remind_delay_dismiss']; if (isset($type['status'])) { $this->current_status = $type['status']; } if (isset($type['remind_last'])) { $this->last_ask = $type['remind_last']; } } // Updates (or creates) the reminder line for the pair (|user|, |reminder_id|) // using the |status| as status, and the |next_ask| as the delay between now // and the next ask (if any). private function UpdateStatus($status, $next_ask) { XDB::execute('REPLACE INTO reminder SET uid = {?}, type_id = {?}, status = {?}, remind_last = NOW(), remind_next = FROM_UNIXTIME({?})', $this->user->id(), $this->type_id, $status, ($next_ask > 0 ? time() + $next_ask * 24 * 60 * 60 : null)); } // Updates the status of the reminder for the current user. protected function UpdateOnYes() { $this->UpdateStatus('yes', $this->remind_delay_yes); } protected function UpdateOnNo() { $this->UpdateStatus('no', $this->remind_delay_no); } protected function UpdateOnDismiss() { $this->UpdateStatus('dismiss', $this->remind_delay_dismiss); } // Display and http handling helpers -------------------------------------- // Handles a hit on the reminder onebox (for links made using the GetBaseUrl // method below). abstract public function HandleAction($action); // Returns the content of the onebox reminder. Default implementation displays // a text and three links (yes, no, dismiss); it uses the text from method // GetDisplayText. public function Display(&$page) { header('Content-Type: text/html; charset=utf-8'); $page->changeTpl('reminder/default.tpl', NO_SKIN); $page->assign('text', $this->GetDisplayText()); $page->assign('baseurl', $this->GetBaseUrl()); } // Helper for returning the content as a string, instead of using the existing // globale XorgPage instance. public function GetDisplayAsString() { $page = new XorgPage(); $this->Display($page); return $page->raw(); } // Returns the text to display in the onebox. abstract protected function GetDisplayText(); // Returns the base url for the reminder module. protected function GetBaseUrl() { return 'ajax/reminder/' . $this->name; } // Static factories ------------------------------------------------------- // Returns a chosen class using the user data from |user|, and from the database. public static function GetCandidateReminder(User &$user) { $res = XDB::query('SELECT rt.*, r.status, r.remind_last FROM reminder_type AS rt LEFT JOIN reminder AS r ON (rt.type_id = r.type_id AND r.uid = {?}) WHERE r.uid IS NULL OR r.remind_next < NOW()', $user->id()); $candidates = $res->fetchAllAssoc(); $weight_map = create_function('$a', 'return $a["weight"];'); while (count($candidates) > 0) { $position = rand(1, array_sum(array_map($weight_map, $candidates))); foreach ($candidates as $key => $candidate) { $position -= $candidate['weight']; if ($position <= 0) { $class = self::GetClassName($candidate['name']); if ($class && call_user_func(array($class, 'IsCandidate'), $user)) { return new $class($user, $candidate); } unset($candidates[$key]); } } } return null; } // Returns an instantiation of the reminder class which name is |name|, using // user data from |user|, and from the database. public static function GetByName(User &$user, $name) { if (!($class = self::GetClassName($name))) { return null; } $res = XDB::query('SELECT rt.*, r.status, r.remind_last FROM reminder_type AS rt LEFT JOIN reminder AS r ON (rt.type_id = r.type_id AND r.uid = {?}) WHERE rt.name = {?}', $user->id(), $name); if ($res->numRows() > 0) { return new $class($user, $res->fetchOneAssoc()); } return null; } // Computes the name of the class for reminder named |name|, and preloads // the class. private static function GetClassName($name) { @include_once "reminder/$name.inc.php"; $class = 'Reminder' . str_replace(' ', '', ucwords(str_replace('_', ' ', $name))); return (class_exists($class) ? $class : null); } } // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: ?>