function getDefs() { return IACLDefinition::select(array('pe' => $this->pe_ids)); }
static function getContentAction() { global $wgTitle, $haclgContLang, $haclgDisableACLTab, $wgUser; if ($wgUser->isAnon()) { return NULL; } if ($wgTitle->getNamespace() == HACL_NS_ACL) { // Display the link to article or category list($peType, $peName) = IACLDefinition::nameOfPE($wgTitle->getText()); if ($peType == IACL::PE_PAGE || $peType == IACL::PE_CATEGORY) { $title = $peType == IACL::PE_PAGE ? Title::newFromText($peName) : Title::makeTitleSafe(NS_CATEGORY, $peName); return array('class' => false, 'text' => wfMsg("hacl_tab_" . IACL::$typeToName[$peType]), 'href' => $title->getLocalUrl()); } } elseif ($wgTitle->exists()) { // Display the link to category or page SD if ($wgTitle->getNamespace() == NS_CATEGORY) { $sd = IACLDefinition::nameOfSD(IACL::PE_CATEGORY, $wgTitle); } else { $sd = IACLDefinition::nameOfSD(IACL::PE_PAGE, $wgTitle); } $etc = haclfDisableTitlePatch(); $sd = Title::newFromText($sd, HACL_NS_ACL); haclfRestoreTitlePatch($etc); // Hide ACL tab if SD does not exist and $haclgDisableACLTab is true if (!$sd || !empty($haclgDisableACLTab) && !$sd->exists() && !$wgUser->getOption('showacltab')) { return NULL; } return array('class' => $sd->exists() ? false : 'new', 'text' => wfMsg('hacl_tab_acl'), 'href' => $sd->getLocalUrl()); } return NULL; }
/** * Saves this definition into database */ public function save(&$preventLoop = array()) { // Load ID and parents before saving, as the definition may be deleted next $parents = $this['parents']; $peType = $this['pe_type']; $peID = $this['pe_id']; $key = $peType . '-' . $peID; $st = IACLStorage::get('SD'); if (!$this->data['rules']) { // Delete definition $clean = $this->clean(); $delRules = $clean['rules'] ? $clean['rules'] : array(); $addRules = array(); $st->deleteRules(array(array('pe_type' => $peType, 'pe_id' => $peID))); } else { // Update definition list($delRules, $addRules) = $this->diffRulesAssoc(); if ($delRules) { $st->deleteRules(self::expandRuleArray($delRules)); } if ($addRules) { $st->addRules(self::expandRuleArray($addRules)); } } // Invalidate userCan() cache (FIXME - in fact our parents don't need to do it...) if (isset($delRules[IACL::PE_ALL_USERS]) || isset($delRules[IACL::PE_REG_USERS]) || isset($addRules[IACL::PE_ALL_USERS]) || isset($addRules[IACL::PE_REG_USERS])) { self::$userCache = array(); self::$userCacheLoaded = array(); } else { if (isset($delRules[IACL::PE_USER])) { foreach ($delRules[IACL::PE_USER] as $userID => $rule) { unset(self::$userCache[$userID]); unset(self::$userCacheLoaded[$userID]); } } if (isset($addRules[IACL::PE_USER])) { foreach ($addRules[IACL::PE_USER] as $userID => $rule) { unset(self::$userCache[$userID]); unset(self::$userCacheLoaded[$userID]); } } } // Invalidate 'parents' field for children foreach ($delRules as $peType => $ids) { foreach ($ids as $peID => $rules) { if (!empty(self::$clean["{$peType}-{$peID}"])) { unset(self::$clean["{$peType}-{$peID}"]->data['parents']); } } } foreach ($addRules as $peType => $ids) { foreach ($ids as $peID => $rules) { if (!empty(self::$clean["{$peType}-{$peID}"])) { unset(self::$clean["{$peType}-{$peID}"]->data['parents']); } } } // Commit new state into the object cache (FIXME - is the object cache needed at all?) unset(self::$dirty[$key]); $this->rw = false; if ($this->data['rules']) { self::$clean[$key] = $this; } else { self::$clean[$key] = false; } // Invalidate parents - they will do the same recursively for their parents and so on $preventLoop[$key] = true; foreach ($parents as $p) { if (!isset($preventLoop[$p['key']])) { $p->save($preventLoop); } } }
/** * Retrieve the list of content used in article with page_id=$peID * from $linkstable = one of 'imagelinks', 'templatelinks', with following info: * - count of pages on which it is used * - its SD title * - modification timestamp its SD, if one does exist, for conflict detection * - is its SD a single inclusion of other SD with ID $sdID? * $sdID usually is SD ID for the page $peID as the protection of embedded * content is usually including page SD. * with their security descriptors' modification timestamps (if they exist), * and the status of these SDs - are they a single inclusion of $sdID ? * * This is a very high-level subroutine, for optimisation purposes. * This method does not return used content with recursion as it used to * determine embedded content of only ONE article. * * @param int $peID Page ID to retrieve the list of content used in. * @param int $incSDType (optional) SD type to to check if used content SDs are a single inclusion of this SD. * @param int $incSDId (optional) SD ID to check if used content SDs are a single inclusion of this SD. * @param $linkstable 'imagelinks' (retrieve used images) or 'templatelinks' (retrieve used templates). * @return array(array('title' => , 'sd_revid' => , 'single' => )) */ public function getEmbedded($peID, $incSDType, $incSDId, $linkstable) { global $haclgContLang; $dbr = wfGetDB(DB_SLAVE); if ($linkstable == 'imagelinks') { $linksjoin = "p1.page_title=il1.il_to AND p1.page_namespace=" . NS_FILE; $linksfield = "il_from"; } elseif ($linkstable == 'templatelinks') { $linksjoin = "p1.page_title=il1.tl_title AND p1.page_namespace=il1.tl_namespace"; $linksfield = "tl_from"; } else { die("Unknown \$linkstable='{$linkstable}' passed to " . __METHOD__); } $linksjoin2 = str_replace('il1.', 'il2.', $linksjoin); $il = $dbr->tableName($linkstable); $p = $dbr->tableName('page'); $rules = $dbr->tableName('intraacl_rules'); $rev = $dbr->tableName('revision'); // SQL subquery for single inclusion detection $sql_is_single = $incSDType && $incSDId ? "(SELECT 1=SUM(CASE WHEN child_type=" . $incSDType . " AND child_id=" . $incSDId . " AND (actions & " . ((1 << IACL::INDIRECT_OFFSET) - 1) . ") = " . IACL::ACTION_INCLUDE_SD . " THEN 1 WHEN !(actions & " . ((1 << IACL::INDIRECT_OFFSET) - 1) . ") THEN 0 ELSE 2 END) FROM {$rules} r" . " WHERE r.pe_type=" . IACL::PE_PAGE . " AND r.pe_id=p1.page_id)" : "0"; // Full SQL query $sql = "SELECT p1.*," . " {$sql_is_single} sd_inc_single," . " COUNT(il2.{$linksfield}) used_on_pages" . " FROM {$il} il1 INNER JOIN {$p} p1 ON {$linksjoin}" . " LEFT JOIN {$il} il2 ON {$linksjoin2}" . " WHERE il1.{$linksfield}={$peID}" . " GROUP BY p1.page_id" . " ORDER BY p1.page_namespace, p1.page_title"; $res = $dbr->query($sql, __METHOD__); $embedded = array(); $batch = new LinkBatch(); foreach ($res as $obj) { $title = Title::newFromRow($obj); $sd_title = Title::newFromText(IACLDefinition::nameOfSD(IACL::PE_PAGE, $title)); $batch->addObj($sd_title); $embedded[] = array('title' => $title, 'sd_title' => $sd_title, 'sd_revid' => NULL, 'sd_single' => $obj->sd_inc_single, 'used_on_pages' => $obj->used_on_pages); } $batch->execute(); foreach ($embedded as &$e) { if (!$e['sd_title']->exists()) { $e['sd_title'] = NULL; } else { // Add SD modification timestamp $e['sd_revid'] = $e['sd_title']->getLatestRevID(); } } return $embedded; }
function haclSDExists_GetEmbedded($type, $name) { if (!isset(IACL::$nameToType[$type])) { return 'null'; } $type = IACL::$nameToType[$type]; $data = array('exists' => false, 'embedded' => '', 'canon' => false); $sd = IACLDefinition::newFromName($type, $name); if ($sd) { $data['canon'] = $sd['def_title']->getPrefixedText(); if ($sd['rules']) { // FIXME Maybe check page for existence instead of SD rules? $data['exists'] = true; } if ($type == IACL::PE_PAGE) { // Build HTML code for embedded protection toolbar $data['embedded'] = IACLToolbar::getEmbeddedHtml(Title::newFromText($name)->getArticleId(), $sd['pe_type'], $sd['pe_id']); } } return json_encode($data); }
/** * "Real" ACL list, loaded using AJAX */ static function haclAcllist($t, $n, $offset = 0, $limit = 10) { global $wgScript, $wgTitle, $haclgHaloScriptPath, $haclgContLang, $wgUser; haclCheckScriptPath(); // Load data $spec = SpecialPage::getTitleFor('IntraACL'); $titles = IACLStorage::get('SD')->getSDPages($t, $n, NULL, $offset, $limit, $total); $defs = IACLDefinition::newFromTitles($titles); // Build SD data for template $lists = array(); foreach ($titles as $k => $sd) { $d = array('name' => $sd->getText(), 'real' => $sd->getText(), 'editlink' => $spec->getLocalUrl(array('action' => 'acl', 'sd' => $sd->getText())), 'viewlink' => $sd->getLocalUrl(), 'single' => NULL); $pe = IACLDefinition::nameOfPE($sd); $d['type'] = IACL::$typeToName[$pe[0]]; $d['real'] = $pe[1]; // Single SD inclusion if (isset($defs[$k]) && !empty($defs[$k]['single_child'])) { $s = $defs[$k]['single_child']; $name = IACLDefinition::peNameForID($s[0], $s[1]); $d['single'] = Title::newFromText(IACLDefinition::nameOfSD($s[0], $name)); $d['singletype'] = IACL::$typeToName[$s[0]]; $d['singlename'] = $name; $d['singlelink'] = $d['single']->getLocalUrl(); $d['singletip'] = wfMsg('hacl_acllist_hint_single', $d['real'], $d['single']->getPrefixedText()); } $lists[$d['type']][] = $d; } // Next and previous page links $pageurl = Title::makeTitleSafe(NS_SPECIAL, 'IntraACL')->getLocalUrl(array('types' => $t, 'filter' => $n, 'limit' => $limit)); $nextpage = $prevpage = false; if ($total > $limit + $offset) { $nextpage = $pageurl . '&offset=' . intval($offset + $limit); } if ($offset >= $limit) { $prevpage = $pageurl . '&offset=' . intval($offset - $limit); } // Run template ob_start(); require dirname(__FILE__) . '/../templates/HACL_ACLListContents.tpl.php'; $html = ob_get_contents(); ob_end_clean(); return $html; }
protected static function checkProtectPageRight($pageID, $userID) { $etc = haclfDisableTitlePatch(); $title = Title::newFromId($pageID); haclfRestoreTitlePatch($etc); return IACLDefinition::userCan($userID, IACL::PE_NAMESPACE, $title->getNamespace(), IACL::ACTION_PROTECT_PAGES) > 0 || IACLDefinition::userCan($userID, IACL::PE_CATEGORY, IACLStorage::get('Util')->getParentCategoryIDs($pageID), IACL::ACTION_PROTECT_PAGES) > 0; }