// Creates an overview table of all sledruns specified (one per line) in the tag. // // // Like but includes all sledruns that are in the region of the current page // or in the region specified by one of the following parameters: // (refers to region represented by the MediaWiki Title name) // (refers to id in the wrregion table) // (refers to name in the wrregion table) // This tag does not accept any contents. // // // Shows an overview of the sledrun reports of the current page. // // // Creates the form that is used to enter sledrun reports. // // // Generates a list of sledrun entries in a flexible way. // Each line (entry) either add sledruns or removes sledruns. // Without entries, the table contains no sledruns. // // Examples: // Empty list: // // // Sledrun "Rumer Alm" and sledrun "Juifenalm" // // Juifenalm // Rumer Alm // // // All sledruns in region Innsbruck thats entries are not "under construction". // The name of the region has to correspond to a name (column name) // in the table wrregion. // // Innsbruck // // // Same as above but excluding the sledrun "Rumer Alm": // // Innsbruck // Rumer Alm // // // All sledruns thats entries are "under construction" // // // // // Attributes: // * in_arbeit: values "ja", "nein" (default for and ), "*" (default for ) // Just include the sledrun(s) if the condition is fulfilled. // * operation: values "+" (add the sledrun(s) to the set, default), "-" (subtract the sledrun(s) from the set) // Attributes that may be implemented later // * beleuchtungstage: values "0", "unknown" (is null), ">0" (excludes null), "7", "*" (includes null) // Just include the sledrun(s) if the condition is fulfilled. // // Constants // --------- // Constants for wrReportTableRender define('WRREPORT_COMPACT_PAGE', 1); ///< includes the page name define('WRREPORT_COMPACT', 2); ///< shown on a single page define('WRREPORT_DETAIL', 3); ///< more columns // DOM helper classes // ------------------ class WrDOMDocument extends DOMDocument { function __construct() { parent::__construct('1.0', 'utf-8'); $this->registerNodeClass('DOMElement', 'WrDOMElement'); } /// Creates and adds the element with the given tag name and returns it. /// Additionally, it calls setAttribute($key, $value) for every entry /// in $attributes. function appendElement($tagName, $attributes=array()) { $child = $this->appendChild($this->createElement($tagName)); foreach ($attributes as $key => $value) $child->setAttribute($key, $value); return $child; } } class WrDOMElement extends DOMElement { /// Creates and adds the element with the given tag name and returns it /// Additionally, it calls setAttribute($key, $value) for every entry /// in $attributes. function appendElement($tagName, $attributes=array()) { $child = $this->appendChild($this->ownerDocument->createElement($tagName)); foreach ($attributes as $key => $value) $child->setAttribute($key, $value); return $child; } /// Adds any UTF-8 string as content of the element - it will be escaped. function appendText($text) { return $this->appendChild($this->ownerDocument->createTextNode($text)); } // Appends a CDATASections to the element. This can be used to include // raw (unparsed) HTML to the DOM tree as it is necessary because // $parser->recursiveTagParse does not always escape & characters. // (see https://bugzilla.wikimedia.org/show_bug.cgi?id=55526 ) // Workaround: Use a CDATA section. When serializing with $doc->saveHTML, // the is returned as ... . // However, we end up having unescaped & in the output due to this bug in recursiveTagParse. function appendCDATA($data) { return $this->appendChild($this->ownerDocument->createCDATASection($data)); } } // WrReportException // ----------------- /// Exception type that is used internally by WrReport class WrReportException extends Exception {} // Fast version of Services_Libravatar // ----------------------------------- /// This is a fast version of Services_Libravatar by omitting the DNS /// lookup and always falling back to libravatar.org class WrServicesLibravatar extends Services_Libravatar { function __construct() { $this->setSize(32); $this->setDefault('monsterid'); $this->setHttps(true); } protected function srvGet($domain, $https = false) { if ($https === true) return 'seccdn.libravatar.org'; return 'cdn.libravatar.org'; } public function getSize() { return $this->size; } } // Tool functions // -------------- /// Forces a regeneration of region overview pages ('Tirol', 'Vorarlberg', ...) function wrRecacheRegions() { $dbr = wfGetDB(DB_SLAVE); // SELECT cl_from FROM categorylinks where cl_to = 'Region' $res = $dbr->select('categorylinks', 'cl_from', array('cl_to' => 'Region')); $page_ids = array(); while ($row = $dbr->fetchObject($res)) $page_ids[] = $row->cl_from; $dbr->freeResult($res); $titles = Title::newFromIDs($page_ids); foreach ($titles as $title) $title->invalidateCache(); } /// Returns the tuple ($report_id, $sledrun_condition, $date_report) /// $date_report is NULL or a time as returned by strtotime /// Expects a database connection ($dbr = wfGetDB(DB_SLAVE);) /// and a page_id describung the page where the condition should be returned. /// If no condition is found, (NULL, NULL, NULL) is returned. function wrGetSledrunCondition($dbr, $page_id) { // select wrreport.id as report_id, `condition`, date_report from wrreport where page_title='Axamer Lizum' and `condition` is not null and date_invalid > now() and delete_date is null order by date_report desc, date_entry desc limit 1; $cres = $dbr->select( 'wrreport', array('wrreport.id as report_id', '`condition`', 'date_report'), array('page_id' => $page_id, '`condition` is not null', 'date_invalid > now()', 'delete_date is null'), 'wrReportConditionRender', array('ORDER BY' => 'date_report desc, date_entry desc', 'LIMIT' => '1') ); if ($cres->numRows() <= 0) { $report_id = NULL; $condition = NULL; $date_report = NULL; } else { $crow = $dbr->fetchObject($cres); $report_id = $crow->report_id; $condition = $crow->condition; $date_report = strtotime($crow->date_report); } $dbr->freeResult($cres); return array($report_id, $condition, $date_report); } /// Updates the line of the wrreportcache table that corresponds to the $page_id parameter function wrUpdateWrReportCacheTable($page_id) { // Determine the new content for the row that should be updated $dbr = wfGetDB(DB_SLAVE); list($report_id, $condition, $date_report) = wrGetSledrunCondition($dbr, $page_id); $rows = wrReportGetReports(array('id' => $report_id), 1); // Delete the old content (if any) $dbw = wfGetDB(DB_MASTER); $dbw->begin(); $dbw->delete('wrreportcache', array('page_id' => $page_id)); // Insert the updated row if (count($rows) == 1) { $row = $rows[0]; $dbw->insert('wrreportcache', array( 'page_id' => $row['page_id'], 'page_title' => $row['page_title'], 'report_id' => $row['id'], 'date_report' => $row['date_report'], '`condition`' => $row['condition'], 'description' => $row['description'], 'author_name' => $row['author_name'], 'author_username' => (is_null($row['author_userid']) ? NULL : $row['author_username']))); } $dbw->commit(); } // Render Functions // ---------------- /// \brief Returns a form to enter a report (string containing HTML). /// /// All parameters have to be UTF-8 encoded. /// \param $page_title Name of the sledrun. /// \param $condition 1 to 5 for normal condition, 0 or NULL for missing condition and -1 for intentionally no condition. /// \return UTF-8 encoded HTML form function wrReportFormRender($hide_save_button = TRUE, $page_title = NULL, $date_report = NULL, $time_report = NULL, $condition = NULL, $description = NULL, $author_name = NULL, $page_title_list = NULL) { $doc = new WrDOMDocument(); $rownum = 0; // Info about special page $specialPageName = wfMessage('wrreport')->text(); // 'Bahnberichte' $title = Title::newFromText($specialPageName, NS_SPECIAL); $specialPageUrl = $title->getLocalURL(); // e.g. '/wiki/Spezial:Bahnberichte' // form $form = $doc->appendElement('form', array('action' => $specialPageUrl, 'method' => 'post')); // table (for layout of form elements) $table = $form->appendElement('table', array('class' => 'wrreportform')); // sledrun name $tr = $table->appendElement('tr'); $tr->appendElement('th')->appendText(wfMessage('wrreport-sledrun')->text()); $td = $tr->appendElement('td'); $td->appendText($page_title); $td->appendElement('input', array('type' => 'hidden', 'name' => 'page_title', 'value' => $page_title)); // report date $tr = $table->appendElement('tr'); $tr->appendElement('th')->appendText(wfMessage('wrreport-newreport-date')->text()); $td = $tr->appendElement('td'); $select = $td->appendElement('select', array('name' => 'date_report')); $daynames = array( wfMessage('wrreport-date-today')->text(), wfMessage('wrreport-date-yesterday')->text(), wfMessage('wrreport-date-2daysbefore')->text(), wfMessage('wrreport-date-3daysbefore')->text(), wfMessage('wrreport-date-4daysbefore')->text()); $date_selected = false; $time = time(); // number of seconds since the Unix Epoch (January 1 1970 00:00:00 GMT) for ($day=0; $day!=5; ++$day) { $date = strtotime("-$day days", $time); $date_f = strftime("%Y-%m-%d", $date); // Formats it according to locale, that is set to CET. $option = $select->appendElement('option', array('value' => $date_f)); if ((is_null($date_report) && $day == 0) || (!is_null($date_report) && $date_report == $date_f)) { $option->setAttribute('selected', 'selected'); $date_selected = true; } $option->appendText($daynames[$day] . ' (' . strftime('%d.%m.', $date) . ')'); } if (!$date_selected) { // note: if $date_report is null $date_selected is true here $option = $select->appendElement('option', array('value' => $date_report, 'selected' => 'selected')); $option->appendText($date_report); } // report time $tr = $table->appendElement('tr'); $tr->appendElement('th')->appendText(wfMessage('wrreport-newreport-time')->text()); $td = $tr->appendElement('td'); $td->appendElement('input', array('name' => 'time_report', 'maxlength' => '5', 'size' => '5', 'value' => $time_report)); $td->appendText(' '); $td->appendText('Uhr'); $td->appendText(' '); $td->appendElement('span', array('class' => 'wrcomment'))->appendText("(z.B. '14', '1400' oder '14:00'. Optional.)"); // condition $tr = $table->appendElement('tr'); $tr->appendElement('th')->appendText(wfMessage('wrreport-newreport-condition')->text()); $td = $tr->appendElement('td'); $select = $td->appendElement('select', array('name' => 'condition', 'required' => 'required')); $option = $select->appendElement('option', array('value' => '0')); $option->appendText(wfMessage('wrreport-condition-select')->text()); foreach (WrReport::$wrConditions as $condition_num => $condition_text) { $option = $select->appendElement('option', array('value' => (string) $condition_num)); if ($condition == $condition_num) $option->setAttribute('selected', 'selected'); $option->appendText($condition_text); } $option = $select->appendElement('option', array('value' => '-1')); if ($condition == -1) $option->setAttribute('selected', 'selected'); $option->appendText(wfMessage('wrreport-condition-no')->text()); // description $tr = $table->appendElement('tr'); $tr->appendElement('th')->appendText(wfMessage('wrreport-newreport-description')->text()); $tr->appendElement('td')->appendElement('textarea', array('name' => 'description', 'class' => 'fullwidth', 'rows' => '7', 'required' => 'required'))->appendText($description); // author $tr = $table->appendElement('tr'); $tr->appendElement('th')->appendText(wfMessage('wrreport-newreport-author')->text()); $tr->appendElement('td')->appendElement('input', array('name' => 'author_name', 'class' => 'fullwidth', 'maxlength' => '30', 'value' => $author_name)); // Buttons // I would like to do it this way, but due to a bug of internet explorer, the '; // if (!$hide_save_button) $buttons .= ''; // Workaround: User $tr = $table->appendElement('tr'); $tr->appendElement('th')->appendText(wfMessage('wrreport-newreport-submit')->text()); $td = $tr->appendElement('td'); $input = $td->appendElement('input', array('name' => 'preview', 'type' => 'submit')); if ($hide_save_button) $input->setAttribute('value', wfMessage('wrreport-newreport-next')->text()); else { $input->setAttribute('value', wfMessage('wrreport-newreport-preview')->text()); $td->appendElement('input', array('name' => 'store', 'type' => 'submit', 'value' => wfMessage('wrreport-newreport-save')->text())); } return $doc->saveHTML($form); } /// \brief Renders the form to delete a report /// /// All in and output strings should be/are UTF-8 encoded. /// \param $reportid the id of the report that is going to be deleted /// \param $delete_person_name name of the person that wants to delete the report (form field) /// \param $delete_reason_public publically visible reason for deleting the entry. /// \param $delete_invisible don't show the report as being deleted /// \return UTF-8 encoded HTML form function wrDeleteReportFormRender($reportid, $delete_person_name, $delete_reason_public, $delete_invisible) { $doc = new WrDOMDocument(); $rownum = 0; // Info about special page $specialPageName = wfMessage('wrreport')->text(); // 'Bahnberichte' $title = Title::newFromText($specialPageName, NS_SPECIAL); $specialPageUrl = $title->getLocalURL(); // e.g. '/wiki/Spezial:Bahnberichte' // form $form = $doc->appendElement('form', array('action' => $specialPageUrl, 'method' => 'post')); // table (for layout of form elements) $table = $form->appendElement('table', array('class' => 'wrreportform', 'summary' => wfMessage('wrreport-deletereport-tablesummary')->text())); // delete_reason_public $tr = $table->appendElement('tr'); $tr->appendElement('th')->appendText(wfMessage('wrreport-deletereport-reason')->text()); $tr->appendElement('td')->appendElement('textarea', array('name' => 'delete_reason_public', 'cols' => '50', 'rows' => '7'))->appendText($delete_reason_public); // delete_person_name $tr = $table->appendElement('tr'); $tr->appendElement('th')->appendText(wfMessage('wrreport-deletereport-name')->text()); $tr->appendElement('td')->appendElement('input', array('name' => 'delete_person_name', 'maxlength' => '30', 'size' => '30', 'value' => $delete_person_name)); // buttons $tr = $table->appendElement('tr'); $tr->appendElement('th')->appendText(wfMessage('wrreport-reports-action')->text()); $td = $tr->appendElement('td'); $td->appendElement('input', array('name' => 'deletepreview', 'type' => 'submit', 'value' => wfMessage('wrreport-newreport-preview')->text())); $td->appendElement('input', array('name' => 'delete', 'type' => 'submit', 'value' => wfMessage('wrreport-deletereport-delete')->text())); // hidden field $input = $td->appendElement('input', array('name' => 'reportid', 'type' => 'hidden', 'value' => (string) $reportid)); // delete_invisible - who is allowed to do so? // $td->appendElement('input', array('name' => 'delete_invisible', 'type' => 'hidden', 'value' => (string) $delete_invisible)); return $doc->saveHTML($form); } /// \brief Generates the DOM of the table header ("private" sub-function of wrReportTableRender) /// /// \param $table table WrDOMElement where the header should be appended /// \param $format row format like WRREPORT_COMPACT /// \param $showActions boolean to indicate whether an actions column should be created /// \return WrDOMElement of the HTML table header function wrReportTableTitleRender($table, $format, $showActions) { $tr = $table->appendElement('tr'); $tr->appendElement('th')->appendText(wfMessage('wrreport-reports-date-trip')->text()); if ($format != WRREPORT_COMPACT) $tr->appendElement('th')->appendText(wfMessage('wrreport-sledrun')->text()); $tr->appendElement('th')->appendText(wfMessage('wrreport-newreport-condition')->text()); $tr->appendElement('th')->appendText(wfMessage('wrreport-newreport-description')->text()); $tr->appendElement('th')->appendText(wfMessage('wrreport-newreport-author')->text()); if ($format == WRREPORT_DETAIL) $tr->appendElement('th')->appendText(wfMessage('wrreport-reports-date-entry')->text()); if ($showActions) $tr->appendElement('th')->appendText(wfMessage('wrreport-reports-action')->text()); return $tr; } /// \brief Generates the DOM of a table row ("private" sub-function of wrReportTableRender) /// /// \param $table table WrDOMElement where the row should be appended /// \param $row associative array of table columns like one row in the wrreport table /// \param $format row format like WRREPORT_COMPACT /// \param $showActions boolean to indicate whether an actions column should be created /// \param $parser Parser instance of a Parser class that can be used to parse the condition /// \return WrDOMElement of the HTML table row function wrReportTableRowRender($table, $row, $format, $showActions, $parser) { $tr = $table->appendElement('tr'); // $row['date_report'] and $row['time_report'] $date_report = strtotime($row['date_report']); $date_report = wfMessage(Language::$mWeekdayAbbrevMsgs[(int) date('w', $date_report)])->text() . strftime(', %d.%m.', $date_report); $td = $tr->appendElement('td'); $td->appendText($date_report); if ($row['time_report']) { $td->appendText(' '); $td->appendElement('span', array('class' => 'wrcomment'))->appendText(date('H:i', strtotime($row['time_report']))); } // $row['page_title'] if ($format != WRREPORT_COMPACT) { $title = Title::newFromText($row['page_title']); $tr->appendElement('td')->appendCDATA(Linker::link($title)); } // $row['condition'] $condition_text = '---'; if (isset(WrReport::$wrConditions[$row['condition']])) $condition_text = WrReport::$wrConditions[$row['condition']]; $td = $tr->appendElement('td'); if ($row['delete_date']) $td->appendElement('em')->appendText(wfMessage('wrreport-deletereport-deleted')->text()); else $td->appendText($condition_text); // $row['description'] $td = $tr->appendElement('td', array('class' => 'wrreportdescription')); if ($row['delete_date']) $td->appendElement('em')->appendText(wfMessage('wrreport-deletereport-deleted')->text()); else { // for registered users, use wikitext formatting if (is_null($row['author_userid'])) $td->appendText($row['description']); else { $html = $parser->recursiveTagParse($row['description']); $td->appendCDATA($html); } } // $row['author_name'] $td = $tr->appendElement('td'); if ($row['delete_date']) $td->appendElement('em')->appendText(wfMessage('wrreport-deletereport-deleted')->text()); else { if (!is_null($row['author_userid'])) { // find user's email ($user->getEmail()) $user = User::newFromId($row['author_userid']); // create avatar (using the Services_Libravatar library to get avatar URL) $sla = new WrServicesLibravatar(); $url = $sla->getUrl($user->getEmail()); // create img tag for the avatar $td->appendElement('img', array('src' => $url, 'alt' => $row['author_name'], 'width' => $sla->getSize(), 'height' => $sla->getSize())); $td->appendText(' '); // get user page $title = $user->getUserPage(); if ($title->exists()) { $td->appendCDATA(Linker::link($title, $row['author_name'])); } else { $td->appendText($row['author_name']); } $td->appendText(' '); // get number of sledrun reports $td->appendElement('span', array('class' => 'wrreportcount')) ->appendText((string) WrReport::getUserSeldrunReportCount($user->getId())); } else { $td->appendText($row['author_name']); } } // $row['date_entry'] if ($format == WRREPORT_DETAIL) { $td = $tr->appendElement('td'); $td->appendText(date('d.m. ', strtotime($row['date_entry']))); $td->appendElement('span', array('class' => 'wrcomment'))->appendText(date('H:i', strtotime($row['date_entry']))); } // actions // wiki/Spezial:Bahnberichte?action=deletepreview&reportid=42 if ($showActions) { $td = $tr->appendElement('td'); if (!isset($row['delete_date'])) { $specialPageName = wfMessage('wrreport')->text(); // 'Bahnberichte' $title = Title::newFromText($specialPageName, NS_SPECIAL); $specialPageUrl = $title->getLocalURL(); // e.g. '/wiki/Spezial:Bahnberichte' $td->appendElement('a', array('href' => $specialPageUrl . '?action=deletepreview&reportid=' . $row['id'])) ->appendText(wfMessage('wrreport-deletereport-delete')->text() . '...'); } } return $tr; } /// \brief Renders the report table. Call wrReportGetReports for the $rows parameter. /// /// \param $rows array of associative row arrays /// \param $format row format like WRREPORT_TABLE_SHORT function wrReportTableRender($rows, $format, $showActions, $parser) { $doc = new WrDOMDocument(); $table = $doc->appendElement('table', array('class' => 'wrreporttable')); wrReportTableTitleRender($table, $format, $showActions); foreach ($rows as $key => $row) wrReportTableRowRender($table, $row, $format, $showActions, $parser); return $doc->saveHTML($table); } /// Returns an array with column names function wrReportGetColumnNames() { return array('id', 'page_id', 'page_title', 'date_report', 'time_report', 'date_entry', 'date_invalid', 'condition', 'description', 'author_name', 'author_userid', 'author_username', 'delete_date', 'delete_person_name', 'delete_person_ip', 'delete_person_userid', 'delete_person_username', 'delete_reason_public', 'delete_invisible'); } /// \brief Returns reports as associative array. /// /// Examples: /// $conditions = array('page_title' => 'Birgitzer Alm', 'date_invalid > now()'); /// $limit = 1; // or NULL for no limit function wrReportGetReports($conditions, $limit=NULL) { $dbr = wfGetDB(DB_SLAVE); $columns = wrReportGetColumnNames(); global $wgDBtype; if ($wgDBtype == "mysql") // "condition" is a reserved word in mysql for ($i = 0; $i != count($columns); ++$i) $columns[$i] = sprintf('`%s`', $columns[$i]); $options = array('ORDER BY' => 'date_report desc, date_entry desc'); if (!is_null($limit)) $options['LIMIT'] = $limit; $res = $dbr->select('wrreport', $columns, $conditions, 'wrReportGetReports', $options); $result = array(); while ($row = $dbr->fetchRow($res)) $result[] = $row; $dbr->freeResult($res); return $result; } /// \brief It returns an array of the "condition" (as number) and the date of the "most recent" report of the specified page (to decode as list($condition, $date)); /// /// If no condition is present, array(NULL, NULL) is returned function wrReportConditionRender($page_title) { $dbr = wfGetDB(DB_SLAVE); $cond = 'condition'; global $wgDBtype; // select wrreport.id as report_id, `condition`, date_report from wrreport where page_title='Axamer Lizum' and `condition` is not null and date_invalid > now() and delete_date is null order by date_report desc, date_entry desc limit 1; if ($wgDBtype == "mysql") $cond = "`$cond`"; // "condition" is a reserved word in mysql $res = $dbr->select( 'wrreport', array('wrreport.id as report_id', $cond, 'date_report'), array('page_title' => $page_title, "$cond is not null", 'date_invalid > now()', 'delete_date is null'), 'wrReportConditionRender', array('ORDER BY' => 'date_report desc, date_entry desc', 'LIMIT' => '1') ); if ($res->numRows() <= 0) { $dbr->freeResult($res); return array(NULL, NULL); } $row = $dbr->fetchObject($res); $date = $row->date_report; if ($date) $date = strtotime($date); $dbr->freeResult($res); return array($row->condition, $date); } /// \brief Returns true if the user is allowed to delete reports (in general) function wrReportUserMayDelete() { global $wgUser; global $wgWrReportDeleteMode; return $wgWrReportDeleteMode == 'allow' || ($wgWrReportDeleteMode == 'loggedin' && $wgUser->isLoggedIn()); } // tag extension hooks // ------------------- class WrReport { // Conditions: array(1 => 'Sehr gut', 2 => 'Gut', 3 => 'Mittelmäßig', 4 => 'Schlecht', 5 => 'Geht nicht'); public static $wrConditions; public static function initWrConditions() { WrReport::$wrConditions = array(); for ($i = 1; $i != 6; ++$i) WrReport::$wrConditions[$i] = wfMessage('wrreport-condition-' . $i)->text(); } /// Returns the number of sledrun reports issued by a user with the given id. public static function getUserSeldrunReportCount($user_id) { $dbr = wfGetDB(DB_SLAVE); // select count(*) from wrreport where author_userid = 1 and delete_date is null and `condition` is not null; $res = $dbr->select('wrreport', 'count(*)', array('author_userid' => $user_id, 'delete_date' => null, '`condition` is not null')); $row = $res->fetchRow(); $count = $row[0]; $dbr->freeResult($res); return $count; } // Parser Hook Functions // --------------------- public static function ParserFirstCallInitHook(&$parser) { $parser->setHook('bahnberichtformular', 'WrReport::bahnberichtformularParserHook'); $parser->setHook('bahnberichte', 'WrReport::bahnberichteParserHook'); $parser->setHook('bahnentabelle', 'WrReport::bahnentabelleParserHook'); $parser->setHook('bahnenregiontabelle', 'WrReport::bahnenregiontabelleParserHook'); $parser->setHook('rodelbahntabelle', 'WrReport::rodelbahntabelleParserHook'); $parser->setHook('avatar', 'WrReport::avatarParserHook'); return true; } /// \brief Is called when the tag is encountered. /// /// The current page name is taken. public static function bahnberichtformularParserHook($input, $args, $parser) { // Username $wgUser = $parser->getUser(); $author_name = NULL; if ($wgUser->isLoggedIn()) { $author_name = $wgUser->getRealName(); if (!$author_name) $author_name = $wgUser->getName(); } global $wgWrReportMode; global $wgWrReportBlackListAll; global $wgWrReportBlackListStrangers; // is the form allowed to be shown? $error_key = null; if ($wgWrReportMode == 'summer') $error_key = 'wrreport-newreport-summer'; elseif ($wgWrReportMode == 'deny') $error_key = 'wrreport-newreport-deny'; elseif ($wgWrReportMode == 'loggedin' && !$wgUser->isLoggedIn()) $error_key = 'wrreport-newreport-loggedin'; elseif (in_array($parser->getTitle()->getText(), $wgWrReportBlackListAll)) $error_key = 'wrreport-newreport-blacklist'; elseif (!$wgUser->isLoggedIn() && in_array($parser->getTitle()->getText(), $wgWrReportBlackListStrangers)) $error_key = 'wrreport-newreport-blackliststrangers'; // report error if (!is_null($error_key)) { $doc = new WrDOMDocument(); $p = $doc->appendElement('p')->appendElement('em')->appendText(wfMessage($error_key)->text()); return $doc->saveHTML($p); } // Calling "$title = $parser->getTitle(); $title->invalidateCache();" doesn't help here to force regeneration // However, this would not be the best solution because the page has to be re-rendered only at midnight // In the following line, $author_name was replaced by NULL to prevent a bug, where the wrong author_name // is shown due to caching (see ticket #35). return array(wrReportFormRender(TRUE, $parser->getTitle()->getText(), NULL, NULL, NULL, NULL, NULL), 'markerType' => 'nowiki'); } /// \brief Is called when the tag is encountered. /// /// The current page name is taken. public static function bahnberichteParserHook($input, $args, $parser) { $parser->getOutput()->addModules('ext.wrreport'); // getOutput() returns class ParserOutput $title = $parser->getTitle(); $page_id = $title->getArticleID(); $rows = array(); if ($page_id > 0) { global $wgOut; // class OutputPage global $wgWrReportFeedRoot; $wgOut->addFeedLink('atom', $wgWrReportFeedRoot . '/berichte/bahn/' . strtolower($title->getPartialURL())); $conditions = array('page_id' => $page_id, 'date_invalid > now()'); $rows = wrReportGetReports($conditions); } if (count($rows) == 0) return wfMessage('wrreport-reports-none')->text(); return array(wrReportTableRender($rows, WRREPORT_COMPACT, wrReportUserMayDelete(), $parser), 'markerType' => 'nowiki'); } /// Returns the region details of the region specifed in $conditions. /// region_id (as in the database), region name (as in the database), and region border (as WKB). /// conditions is an array that's given to the where clause private static function getRegionDetails($conditions) { // Example: SELECT name FROM wrregion WHERE page_id = 882; $dbr = wfGetDB(DB_SLAVE); $res = $dbr->select('wrregion', array('id', 'name', 'aswkb(border)'), $conditions); if ($dbr->numRows($res) == 1) { $row = $dbr->fetchRow($res); return array($row[0], $row[1], $row[2]); // region_id, region_name, region_border_wkb } $dbr->freeResult($res); return array(null, null, null); } /// Returns the region details if the specified title is one. /// region_id (as in the database), region name (as in the database), and region border (as WKB). private static function getPageRegion($title) { $categories = $title->getParentCategories(); // e.g. array('Kategorie:Region' => 'Osttirol') global $wgContLang; $key_region = $wgContLang->getNSText(NS_CATEGORY) . ':Region'; if (array_key_exists($key_region, $categories)) { return WrReport::getRegionDetails(array('page_id' => $title->getArticleID())); } return array(null, null, null); } /// Adds a region feed to the current page private static function addRegionFeedLink($title) { list($region_id, $region_name, $region_border_wkb) = WrReport::getPageRegion($title); if (is_null($region_name)) return; global $wgWrReportFeedRoot; global $wgOut; // class OutputPage $wgOut->addFeedLink('atom', $wgWrReportFeedRoot . '/berichte/region/' . strtolower($region_name)); } /// Creates the HTML of the , and tags. private static function createBahnentabelle($page_titles) { $dbr = wfGetDB(DB_SLAVE); // SELECT p.page_id,p.page_title, c.length, c.walkup_time, c.top_elevation, c.bottom_elevation, c.walkup_separate, c.lift, c.night_light, c.public_transport, c.sled_rental, c.information_phone FROM `page` p, wrsledruncache c WHERE (p.page_title in ('Birgitzer_Alm_(vom_Adelshof)', 'Kemater_Alm', 'Axamer_Lizum') and p.page_id=c.page_id) ORDER BY page_title $where_array = array('page.page_id = wrsledruncache.page_id'); if (count($page_titles) > 0) { $mysql_page_ids = array(); foreach ($page_titles as $page_title) $mysql_page_ids[] = $page_title->getArticleID(); $where_array[] = 'page.page_id in (' . implode(', ', $mysql_page_ids) . ')'; } else $where_array[] = 'false'; $res = $dbr->select(array('page', 'wrsledruncache'), array('page.page_id', 'page.page_title', 'page_namespace', 'length', 'walkup_time', 'top_elevation', 'bottom_elevation', 'walkup_possible', 'walkup_separate', 'lift', 'night_light', 'public_transport', 'sled_rental', 'information_phone', 'information_web'), $where_array, 'bahnentabelleParserHook', array('ORDER BY' => 'page.page_title')); global $wgUser; global $wgWrReportMode; // e.g. 'summer' global $wgWrReportBlackListAll; global $wgWrReportBlackListStrangers; global $wgDBtype; // Determine, whether the user is allowed to make a new report $userMayReport = ($wgWrReportMode == 'allow' || ($wgWrReportMode == 'loggedin' && $wgUser->isLoggedIn())); // Generate DOM for HTML $doc = new WrDOMDocument(); $table = $doc->appendElement('table', array('class' => 'wikitable')); // Title $tr = $table->appendElement('tr'); $tr->appendElement('th')->appendElement('img', array('src' => '/vorlagen/s_rental.png', 'alt' => wfMessage('wrreport-icon-sledrental')->text(), 'title' => wfMessage('wrreport-icon-sledrental')->text())); $tr->appendElement('th')->appendElement('img', array('src' => '/vorlagen/s_light.png', 'alt' => wfMessage('wrreport-icon-nightlight')->text(), 'title' => wfMessage('wrreport-icon-nightlight')->text())); $tr->appendElement('th')->appendElement('img', array('src' => '/vorlagen/s_lift.png', 'alt' => wfMessage('wrreport-icon-lift')->text(), 'title' => wfMessage('wrreport-icon-lift')->text())); $tr->appendElement('th')->appendElement('img', array('src' => '/vorlagen/s_walk.png', 'alt' => wfMessage('wrreport-icon-walkupseparate')->text(), 'title' => wfMessage('wrreport-icon-walkupseparate')->text())); $tr->appendElement('th')->appendElement('img', array('src' => '/vorlagen/s_bus.png', 'alt' => wfMessage('wrreport-icon-publictransport')->text(), 'title' => wfMessage('wrreport-icon-publictransport')->text())); $tr->appendElement('th')->appendText(wfMessage('wrreport-sledrun')->text()); if ($wgWrReportMode != 'summer') $tr->appendElement('th')->appendText(wfMessage('wrreport-newreport-condition')->text()); $tr->appendElement('th')->appendText(wfMessage('wrreport-sledrun-information')->text()); $tr->appendElement('th')->appendText(wfMessage('wrreport-sledrun-walkuptime')->text()); $tr->appendElement('th')->appendText(wfMessage('wrreport-sledrun-height')->text()); $tr->appendElement('th')->appendText(wfMessage('wrreport-sledrun-length')->text()); // Rows while ($row = $dbr->fetchObject($res)) { $title = Title::newFromRow($row); $tr = $table->appendElement('tr'); $td = $tr->appendElement('td'); if ($row->sled_rental) $td->appendElement('img', array('src' => '/vorlagen/s_rental.png', 'alt' => wfMessage('wrreport-icon-sledrental')->text(), 'title' => wfMessage('wrreport-icon-sledrental')->text())); $td = $tr->appendElement('td'); if ($row->night_light) $td->appendElement('img', array('src' => '/vorlagen/s_light.png', 'alt' => wfMessage('wrreport-icon-nightlight')->text(), 'title' => wfMessage('wrreport-icon-nightlight')->text())); $td = $tr->appendElement('td'); if ($row->lift) $td->appendElement('img', array('src' => '/vorlagen/s_lift.png', 'alt' => wfMessage('wrreport-icon-lift')->text(), 'title' => wfMessage('wrreport-icon-lift')->text())); $td = $tr->appendElement('td'); if (!is_null($row->walkup_possible)) { if ($row->walkup_possible) { if ($row->walkup_separate) $td->appendElement('img', array('src' => '/vorlagen/s_walk.png', 'alt' => wfMessage('wrreport-icon-walkupseparate')->text(), 'title' => wfMessage('wrreport-icon-walkupseparate')->text())); } else $td->appendElement('img', array('src' => '/vorlagen/s_nowalk.png', 'alt' => wfMessage('wrreport-icon-walkupnotpossible')->text(), 'title' => wfMessage('wrreport-icon-walkupnotpossible')->text())); } $td = $tr->appendElement('td'); if ($row->public_transport and $row->public_transport != 5) $td->appendElement('img', array('src' => '/vorlagen/s_bus.png', 'alt' => wfMessage('wrreport-icon-publictransport')->text(), 'title' => wfMessage('wrreport-icon-publictransport')->text())); $tr->appendElement('td')->appendElement('a', array('href' => $title->getLocalURL()))->appendText($title->getPrefixedText()); if ($wgWrReportMode != 'summer') { // Check rights $userMayReportThis = $userMayReport; if ($userMayReportThis) { if (in_array($title->getText(), $wgWrReportBlackListAll)) $userMayReportThis = FALSE; if (!$wgUser->isLoggedIn() && in_array($title->getText(), $wgWrReportBlackListStrangers)) $userMayReportThis = FALSE; // Title::getText() uses spaces instead of underscores } // Select condition list($report_id, $condition, $date_report) = wrGetSledrunCondition($dbr, $row->page_id); if (is_null($report_id)) $date = ''; else $date = strftime('%d.%m.', $date_report); $td = $tr->appendElement('td'); if (isset(WrReport::$wrConditions[$condition])) { $td->appendElement('a', array('href' => $title->getLocalURL() . '#' . Title::escapeFragmentForURL(wfMessage('wrreport-reports-sectionname')->text())))->appendText(WrReport::$wrConditions[$condition]); $td->appendText(' '); $small = $td->appendElement('small'); $small->appendText($date); if ($userMayReportThis) { $small->appendText(' '); $small->appendElement('em')->appendElement('a', array('href' =>$title->getLocalURL() . '#' . Title::escapeFragmentForURL(wfMessage('wrreport-newreport-sectionname')->text())))->appendText(wfMessage('wrreport-newreport-new')->text()); } } else { if ($userMayReportThis) $td->appendElement('small')->appendElement('em')->appendElement('a', array('href' =>$title->getLocalURL() . '#' . Title::escapeFragmentForURL(wfMessage('wrreport-newreport-sectionname')->text())))->appendText(wfMessage('wrreport-newreport-please')->text()); else $td->appendText('--'); } } $td = $tr->appendElement('td'); $info_phone = $row->information_phone; if ($info_phone) { $info_parts = explode(';', $info_phone); $info_parts = explode('(', $info_parts[0], 2); if (count($info_parts) == 2 && substr($info_parts[1], -1) == ')') { $td->appendText($info_parts[0]); $td->appendElement('span', array('class' => 'wrtelinfo'))->appendText(substr($info_parts[1], 0, -1)); } else $td->appendText($info_phone); } $info_web = $row->information_web; if ($info_web === 'Nein') $info_web = null; if ($info_phone && $info_web) $td->appendText('; '); if ($info_web) { $td->appendElement('a', array('href' => $info_web))->appendText('web'); } $tr->appendElement('td')->appendText($row->walkup_time ? $row->walkup_time . ' min' : ''); $tr->appendElement('td')->appendText( ($row->bottom_elevation ? $row->bottom_elevation : '') . ($row->bottom_elevation && $row->top_elevation ? ' - ' : '') . ($row->top_elevation ? $row->top_elevation : '') . ($row->bottom_elevation || $row->top_elevation ? ' m' : '')); $tr->appendElement('td')->appendText($row->length ? $row->length . ' m' : ''); } $dbr->freeResult($res); return $doc->saveHTML(); } /// \brief Is called when the tag is encountered. /// /// Example: /// /// Birgitzer Alm (vom Adelshof) /// Kemater Alm /// Axamer Lizum /// public static function bahnentabelleParserHook($input, $args, $parser) { $parser->getOutput()->addModules('ext.wrreport'); // Add feed // Note: As (of MediaWiki 1.19), only one feed can be added and each feed added replaces the previous one, the following is possible without risk of having duplicated feed entries. WrReport::addRegionFeedLink($parser->getTitle()); // Add each page title that has been found $page_titles = array(); // array of Title objects foreach (explode("\n", $input) as $page_title) { $page_title = Title::newFromText(trim($page_title)); if (!$page_title || !$page_title->exists()) continue; $page_titles[] = $page_title; } // Create bahnentabelle $html = WrReport::createBahnentabelle($page_titles); return array($html, 'markerType' => 'nowiki'); } /// \brief Is called when the tag is encountered. /// /// Example 1: /// /// /// Example 2: /// (refers to region represented by the MediaWiki Title name) /// (refers to id in the wrregion table) /// (refers to name in the wrregion table) public static function bahnenregiontabelleParserHook($input, $args, $parser) { $parser->getOutput()->addModules('ext.wrreport'); try { // we accept 0 or 1 parameters if (count($args) > 1) throw new WrReportException(wfMessage('wrreport-bahnenregiontabelle-toomanyarguments')->text()); if (count($args) == 0) { // current page represents a region $title = $parser->getTitle(); // default title: current page list($region_id, $region_name, $region_border_wkb) = WrReport::getPageRegion($title); if (is_null($region_id)) throw new WrReportException(wfMessage('wrreport-bahnenregiontabelle-thispagenoregion')->text()); } elseif (isset($args['wiki'])) { // other page represents a region $title = Title::newFromText($args['wiki']); list($region_id, $region_name, $region_border_wkb) = WrReport::getPageRegion($title); if (is_null($region_id)) throw new WrReportException(wfMessage('wrreport-bahnenregiontabelle-pagenoregion')->text()); } elseif (isset($args['region_id'])) { list($region_id, $region_name, $region_border_wkb) = WrReport::getRegionDetails(array('id' => $args['region_id'])); if (is_null($region_id)) throw new WrReportException(wfMessage('wrreport-bahnenregiontabelle-noregionid')->text()); } elseif (isset($args['region_name'])) { list($region_id, $region_name, $region_border_wkb) = WrReport::getRegionDetails(array('name' => $args['region_name'])); if (is_null($region_id)) throw new WrReportException(wfMessage('wrreport-bahnenregiontabelle-noregionname')->text()); } else { throw new WrReportException(wfMessage('wrreport-bahnenregiontabelle-invalidargument', array_keys($args)[0])->text()); } // get titles that are in the region $page_titles = array(); $dbr = wfGetDB(DB_SLAVE); // the following line would work if MySQL 5.5 would implement a real geospatial version of CONTAINS. // $res = $dbr->select('wrsledruncache', 'page_id', array('CONTAINS(GEOMFROMWKB(' . $dbr->addQuotes($region_border_wkb) . '), POINT(position_longitude, position_latitude))', 'NOT under_construction'), __METHOD__, 'page_title'); $res = $dbr->select(array('wrsledruncache', 'wrregioncache'), array('page_id' => 'wrregioncache.page_id'), array('wrregioncache.region_id' => $region_id, 'wrregioncache.page_id=wrsledruncache.page_id', 'NOT under_construction'), __METHOD__, 'page_title'); foreach ($res as $row) { $page_titles[] = Title::newFromId($row->page_id); } $dbr->freeResult($res); $html = WrReport::createBahnentabelle($page_titles); } catch (WrReportException $e) { $doc = new WrDOMDocument(); $doc->appendElement('span', array('class' => 'error'))->appendText(wfMessage('wrreport-bahnenregiontabelle-error', $e->getMessage())->text()); $html = $doc->saveHTML($doc->firstChild); } return array($html, 'markerType' => 'nowiki'); } /// \brief Is called when the tag is encountered. /// /// Description: See description of wrreport.php public static function rodelbahntabelleParserHook($input, $args, $parser) { $parser->getOutput()->addModules('ext.wrreport'); // Add feed // Note: As (of MediaWiki 1.19), only one feed can be added and each feed added replaces the previous one, the following is possible without risk of having duplicated feed entries. WrReport::addRegionFeedLink($parser->getTitle()); $dbr = wfGetDB(DB_SLAVE); try { libxml_use_internal_errors(true); // without that, we get PHP Warnings if the $input is not well-formed try { $xml_input = '' . $input . ''; $xml = new SimpleXMLElement($xml_input); // input } catch (Exception $e) { throw new WrReportException(wfMessage('wrreport-rodelbahntabelle-invalid-xml', $xml_input)->text()); } $whitespace = (string) $xml; // everything between and that's not a sub-element if (strlen($whitespace) > 0 && !ctype_space($whitespace)) // there must not be anythin except sub-elements or whitespace throw new WrReportException(wfMessage('wrreport-rodelbahntabelle-textbetweenelements', trim($xml))->text()); // page_ids of sledrun titles that that are going to be returned $page_ids = array(); foreach ($xml as $entry) { // entry is , or $entry_page_ids = array(); // page_ids selected (or un-selected) for this entry. $tagname = $entry->getName(); $attributes = array(); foreach ($entry->attributes() as $key => $value) $attributes[(string) $key] = (string) $value; // is the tagname valid? if (!in_array($tagname, array('rodelbahn', 'rodelbahnen', 'region'))) throw new WrReportException(wfMessage('wrreport-rodelbahntabelle-invalid-element', $tagname)->text()); // parse operation attribute $operation = '+'; // '+' (append) or '-' (subtract) if (array_key_exists('operation', $attributes)) { $operation = $attributes['operation']; if (!in_array($operation, array('+', '-'))) throw new WrReportException(wfMessage('wrreport-rodelbahntabelle-invalid-attribute-value', $tagname, 'operation', $operation)->text()); unset($attributes['operation']); } // parse in_arbeit attribute $under_construction = false; // false (only sledruns that are not under construction), true (only sledruns under construction) or null (doen't matter) if ($tagname === 'rodelbahn') $under_construction = null; // different default value for tag . if (array_key_exists('in_arbeit', $attributes)) { if ($attributes['in_arbeit'] === 'nein') $under_construction = false; elseif ($attributes['in_arbeit'] === 'ja') $under_construction = true; elseif ($attributes['in_arbeit'] === '*') $under_construction = null; else throw new WrReportException(wfMessage('wrreport-rodelbahntabelle-invalid-attribute-value', $tagname, 'in_arbeit', $attributes['in_arbeit'])->text()); unset($attributes['in_arbeit']); } // any attributes left that are not handled yet? if (count($attributes) > 0) throw new WrReportException(wfMessage('wrreport-rodelbahntabelle-invalid-attribute-name', $tagname, array_keys($attributes)[0])->text()); // build SQL query $tables = array('wrsledruncache'); $where = array(); // if ($tagname === 'region') { // the following line would work if MySQL 5.5 would implement a real geospatial version of CONTAINS. // $where[] = 'CONTAINS(GEOMFROMWKB(' . $dbr->addQuotes($region_border_wkb) . '), POINT(position_longitude, position_latitude))' $tables[] = 'wrregion'; $tables[] = 'wrregioncache'; $where[] = 'wrregioncache.region_id=wrregion.id'; $where[] = 'wrregioncache.page_id=wrsledruncache.page_id'; $where['wrregion.name'] = $entry; } // if ($tagname == 'rodelbahn') { $page_title = Title::newFromText(trim($entry)); $where['page_title'] = $page_title->getDBkey(); } // under contruction if ($under_construction === true) $where[] = 'wrsledruncache.under_construction'; if ($under_construction === false) $where[] = 'not wrsledruncache.under_construction'; // query $res = $dbr->select($tables, array('page_id' => 'wrsledruncache.page_id'), $where, __METHOD__, 'page_id'); foreach ($res as $row) { $entry_page_ids[] = $row->page_id; } $dbr->freeResult($res); // merge the entry page_ids with the page_ids if ($operation == '+') $page_ids = array_merge($page_ids, $entry_page_ids); elseif ($operation == '-') $page_ids = array_diff($page_ids, $entry_page_ids); } // page_titles that are going to be returned $page_titles = Title::newFromIDs($page_ids); $html = WrReport::createBahnentabelle($page_titles); } catch (WrReportException $e) { $doc = new WrDOMDocument(); $doc->appendElement('span', array('class' => 'error'))->appendText(wfMessage('wrreport-rodelbahntabelle-error', $e->getMessage())->text()); $html = $doc->saveHTML($doc->firstChild); } return array($html, 'markerType' => 'nowiki'); } /// \brief Is called when the tag username is encountered. public static function avatarParserHook($input, $args, $parser, $frame) { $doc = new WrDOMDocument(); $sla = new WrServicesLibravatar(); try { // check user name if (is_null($input)) throw new WrReportException(wfMessage('wrreport-avatar-nousername')->text()); $username = $parser->recursiveTagParse($input, $frame); $user = User::newFromName($username); if ($user === false) throw new WrReportException(wfMessage('wrreport-avatar-invalidusername', $username)->text()); if ($user->getId() == 0) throw new WrReportException(wfMessage('wrreport-avatar-userunknown', $username)->text()); // size attribute (optional) if (isset($args['size'])) $sla->setSize((int) $parser->recursiveTagParse($args['size'], $frame)); // alt attribute (optional) $alt = wfMessage('wrreport-avatar-of', $username)->text(); // create avatar (using the Services_Libravatar library to get avatar URL) $url = $sla->getUrl($user->getEmail()); $doc->appendElement('img', array('src' => $url, 'alt' => $username, 'width' => $sla->getSize(), 'height' => $sla->getSize())); } catch (WrReportException $e) { $doc->appendElement('span', array('class' => 'error'))->appendText(wfMessage('wrreport-avatar-error', $e->getMessage())->text()); } // return result (markerType => nowiki prevents wiki formatting of the result) $html = $doc->saveHTML($doc->firstChild); return array($html, 'markerType' => 'nowiki'); } } WrReport::initWrConditions(); // Special page // ------------ /// Specal Page to show reports class SpecialWrReport extends SpecialPage { function __construct() { parent::__construct('wrreport'); } static function LanguageGetSpecialPageAliasesHook(&$specialPageArray, $languageCode) { $text = wfMessage('wrreport')->text(); // 'Bahnberichte' $title = Title::newFromText($text); // 'Bahnberichte' $specialPageArray['wrreport'][] = $title->getDBKey(); // 'Bahnberichte' return true; } /// \param $par Possibilities: /// - action == 'view' (default) /// - action == 'preview': Preview new report /// - action == 'store': Store new report /// - action == 'deletepreview': Preview the deleted record /// - action == 'delete': Delete an existing report /// - action == 'showerror': Shows the error and exits /// \param $override_action If not NULL (default), it overrides the action in $par /// \param $errorMsg UFT-8 encoded error message (in WikiText) to show on top of the page or NULL (default): function execute($par, $override_action = NULL, $errorMsg = NULL) { $request = $this->getRequest(); $output = $this->getOutput(); global $wgParser; $output->addModules('ext.wrreport'); $this->setHeaders(); // Get request data $action = $request->getText('action'); if (!$action) { if ($request->getVal('preview')) $action = 'preview'; elseif ($request->getVal('store')) $action = 'store'; elseif ($request->getVal('deletepreview')) $action = 'deletepreview'; elseif ($request->getVal('delete')) $action = 'delete'; else $action = 'view'; } if ($override_action) $action = $override_action; // Show error message if ($errorMsg || $action == 'showerror') { $output->addWikiText('
' . $errorMsg . "
\n"); if ($action == 'showerror') return; } // Action view if ($action == 'view') { global $wgWrReportFeedRoot; $output->addFeedLink('atom', $wgWrReportFeedRoot . '/berichte/alle'); $conditions = array('date_invalid > now()'); $rows = wrReportGetReports($conditions); if (count($rows) == 0) $output->addHTML(wfMessage('wrreport-reports-none')->text()); else { $output->addWikiText(''); // this is necessary because otherwise $wgParser is not properly initialized but $wgParser is needed in the next line $output->addHTML(wrReportTableRender($rows, WRREPORT_DETAIL, wrReportUserMayDelete(), $wgParser)); } } // Action deletepreview or delete elseif ($action == 'deletepreview' || $action == 'delete') { $reportid = (int) $request->getText('reportid'); if ($reportid == 0) { $this->execute($par, 'showerror', wfMessage('wrreport-deletereport-noreport')->text()); return; } $rows = wrReportGetReports(array('id' => $reportid)); if (count($rows) != 1) { $this->execute($par, 'showerror', wfMessage('wrreport-deletereport-invalid')->text()); return; } $row = $rows[0]; if (!is_null($row['delete_date'])) { $this->execute($par, 'showerror', wfMessage('wrreport-deletereport-alreadydeleted')->text()); return; } $delete_reason_public = $request->getText('delete_reason_public'); $delete_person_name = $request->getText('delete_person_name'); $delete_invisible = $request->getText('delete_invisible') ? TRUE : FALSE; if ($action == 'delete') { // page $title = Title::newFromId($row['page_id']); // user global $wgUser; $delete_person_userid = $wgUser->getId(); if ($delete_person_userid == 0) $delete_person_userid = NULL; // to store a NULL value in the database if no user is logged in instead of 0. $delete_person_username = $wgUser->getName(); // Check permissions - see also function wrReportUserMayDelete, that does also check permissions but does not return an error message. $errorMsg = NULL; global $wgWrReportDeleteMode; if ($wgWrReportDeleteMode == 'deny') $errorMsg = wfMessage('wrreport-deletereport-deny')->text(); elseif ($wgWrReportDeleteMode == 'loggedin' && !$wgUser->isLoggedIn()) $errorMsg = wfMessage('wrreport-deletereport-loggedin')->text(); elseif (!$delete_person_name || !$delete_reason_public) $errorMsg = wfMessage('wrreport-deletereport-incomplete')->text(); if ($errorMsg) { $this->execute($par, 'deletepreview', $errorMsg); return; } // "Delete" (update) entry $dbr = wfGetDB(DB_MASTER); $dbr->update( 'wrreport', array( 'delete_date' => date('c'), 'delete_person_name' => $delete_person_name, 'delete_person_ip' => $_SERVER['REMOTE_ADDR'], 'delete_person_userid' => $delete_person_userid, 'delete_person_username' => $delete_person_username, 'delete_reason_public' => $delete_reason_public, 'delete_invisible' => $delete_invisible ? 't' : 'f' ), array('id' => $reportid) ); // Purge cache $title->invalidateCache(); wrRecacheRegions(); // Show success message $output->addWikiText(wfMessage('wrreport-deletereport-success', '[[' . $row['page_title'] . '#' . wfMessage('wrreport-reports-sectionname')->text() . '|' . $row['page_title'] . ']]')->text()); } if ($action == 'deletepreview') { $output->addWikiText(wfMessage('wrreport-deletereport-preview-before')->text()); $format = WRREPORT_COMPACT_PAGE; $output->addHTML(wrReportTableRender(array($row), $format, FALSE, $wgParser)); $output->addWikiText(wfMessage('wrreport-deletereport-preview-after')->text()); $row['delete_date'] = date('c'); $row['delete_reason_public'] = $delete_reason_public; $row['delete_person_name'] = $delete_person_name; $row['delete_invisible'] = $delete_invisible; $output->addHTML(wrReportTableRender(array($row), $format, FALSE, $wgParser)); $output->addWikiText(wfMessage('wrreport-deletereport-preview-form')->text()); $output->addHTML(wrDeleteReportFormRender($reportid, $delete_person_name, $delete_reason_public, $delete_invisible)); $output->addWikiText(wfMessage('wrreport-deletereport-preview-bottom')->text()); } } // Action preview or store elseif ($action == 'preview' || $action == 'store') { $page_title = $request->getText('page_title'); $date_report = $request->getText('date_report'); $time_report = $request->getText('time_report'); $condition = $request->getText('condition'); $description = $request->getText('description'); $author_name = $request->getText('author_name'); // time_report $time_report = trim($time_report); // strip whitespace $matches = array(); $hour = NULL; $minute = NULL; if (preg_match('/^[0-2]?[0-9]$/', $time_report)) { // $time_report has 1 or 2 digits, e.g. 'h', or 'hh'. $hour = intval($time_report); $minute = 0; } elseif (preg_match('/^([0-2]?[0-9]):?([0-9]{2})$/', $time_report, $matches)) { // $time_report has 3 or 4 digits, e.g. 'hmm' or 'hhmm' or 'h:mm' or 'hh:mm'. $hour = intval($matches[1]); $minute = intval($matches[2]); } if (!is_null($hour) && $hour >= 0 && $hour < 24 && $minute >= 0 && $minute < 60) $time_report = sprintf('%02d:%02d', $hour, $minute); else $time_report = NULL; // condition $condition = (int) $condition; // force to be nummeric. -1 ... "keine Bewertung", 0 ... "Bitte eingeben", 1 to 5 ... "Sehr gut" to "Geht nicht" if ($condition < -1 or $condition > 5) $condition = 0; // invalid condition: Tread like 0. $condition_sql = NULL; if ($condition >= 1 and $condition <= 5) $condition_sql = $condition; // author_name $author_name = trim($author_name); // page_id $title = Title::newFromText($page_title); $page_id = $title->getArticleID(); if ($page_id == 0) $page_id = NULL; // user_id global $wgUser; $author_userid = $wgUser->getId(); if ($author_userid == 0) $author_userid = NULL; // to store a NULL value in the database if no user is logged in instead of 0. $author_username = $wgUser->getName(); if ($action == 'store') { // check conditions/permissions $errorMsg = NULL; global $wgWrReportMode; global $wgWrReportBlackListAll; global $wgWrReportBlackListStrangers; if ($wgWrReportMode == 'summer') $errorMsg = htmlspecialchars(wfMessage('wrreport-newreport-summer')->text()); elseif ($wgWrReportMode == 'deny') $errorMsg = htmlspecialchars(wfMessage('wrreport-newreport-deny')->text()); elseif ($wgWrReportMode == 'loggedin' && !$wgUser->isLoggedIn()) $errorMsg = htmlspecialchars(wfMessage('wrreport-newreport-loggedin')->text()); elseif (!$page_id) $errorMsg = htmlspecialchars(wfMessage('wrreport-newreport-pagenotfound')->text()); elseif (in_array($page_title, $wgWrReportBlackListAll)) $errorMsg = htmlspecialchars(wfMessage('wrreport-newreport-blacklist')->text()); elseif (!$wgUser->isLoggedIn() && in_array($page_title, $wgWrReportBlackListStrangers)) $errorMsg = htmlspecialchars(wfMessage('wrreport-newreport-blackliststrangers')->text()); elseif ($condition == 0) $errorMsg = htmlspecialchars(wfMessage('wrreport-newreport-choosecondition')->text()); elseif (!$wgUser->isLoggedIn()) { if (!$description) $errorMsg = htmlspecialchars(wfMessage('wrreport-newreport-enterdescription')->text()); elseif (!(stripos($description, 'http') === FALSE)) $errorMsg = htmlspecialchars(wfMessage('wrreport-newreport-nohttp')->text()); elseif (!$author_name) $errorMsg = htmlspecialchars(wfMessage('wrreport-newreport-enterauthor')->text()); } // check author name if (!$errorMsg) { $author_name_id = $wgUser->idFromName(strtolower($author_name)); if ($wgUser->isLoggedIn()) { if ($author_name_id != 0 && $author_name_id != $wgUser->getId()) $errorMsg = htmlspecialchars(wfMessage('wrreport-newreport-authorused')->text()); } else { if ($author_name_id != 0) $errorMsg = htmlspecialchars(wfMessage('wrreport-newreport-authorlogin')->text()); } } // Chech whether identical reports are present if (!$errorMsg) { $dbr = wfGetDB(DB_SLAVE); $cond = 'condition'; global $wgDBtype; if ($wgDBtype == "mysql") $cond = "`$cond`"; // "condition" is a reserved word in mysql $sqlConditions = array('page_id' => $page_id, 'date_report' => $date_report, 'time_report' => $time_report, $cond => $condition_sql, 'description' => $description, 'author_name' => $author_name); $res = $dbr->select('wrreport', 'id', $sqlConditions); if ($res->numRows() == 1) $errorMsg = htmlspecialchars(wfMessage('wrreport-newreport-alreadysaved')->text()); $dbr->freeResult($res); } // Show error if any if ($errorMsg) { $this->execute($par, 'preview', $errorMsg); return; } // Save entry $dbr = wfGetDB(DB_MASTER); $dbr->insert( 'wrreport', array( 'page_id' => $page_id, 'page_title' => $page_title, 'date_report' => $date_report, 'time_report' => $time_report, 'date_entry' => date('c'), 'date_invalid' => date('c', strtotime('+9 days')), $cond => $condition_sql, 'description' => $description, 'author_name' => $author_name, 'author_ip' => $_SERVER['REMOTE_ADDR'], 'author_userid' => $author_userid, 'author_username' => $author_username // 'delete_*' => // use database defaults (NULL) ) ); // Purge cache $title->invalidateCache(); wrRecacheRegions(); wrUpdateWrReportCacheTable($page_id); // Show success message $output->addWikiText(wfMessage('wrreport-newreport-success', '[[' . $page_title . '#' . wfMessage('wrreport-reports-sectionname')->text() . '|' . $page_title . ']]')->text()); // We could redirect to result with the following line but we don't want to. // $output->redirect($title->getFullURL() . '#' . wfMessage('wrreport-reports-sectionname')->text()); } if ($action == 'preview') { $output->addWikiText(wfMessage('wrreport-newreport-preview-top')->text()); $format = WRREPORT_COMPACT_PAGE; $row = array_fill_keys(wrReportGetColumnNames(), NULL); $row['page_id'] = $page_id; $row['page_title'] = $page_title; $row['date_report'] = $date_report; $row['time_report'] = $time_report; $row['condition'] = $condition_sql; $row['description'] = $description; $row['author_name'] = $author_name; $row['author_userid'] = $author_userid; $row['author_username'] = $author_username; $output->addHTML(wrReportTableRender(array($row), $format, FALSE, $wgParser)); $output->addWikiText(wfMessage('wrreport-newreport-preview-middle')->text()); $output->addHTML(wrReportFormRender(FALSE, $page_title, $date_report, $time_report, $condition, $description, $author_name)); $output->addWikiText(wfMessage('wrreport-newreport-preview-bottom')->text()); if ($wgUser->isLoggedIn()) $output->addWikiText(wfMessage('wrreport-newreport-preview-bottom-loggedin')->text()); else $output->addWikiText(wfMessage('wrreport-newreport-preview-bottom-anonymous')->text()); } } else die('Wrong action'); } } ?>