function getDefs() { return IACLDefinition::select(array('pe' => $this->pe_ids)); }
/** * This method returns HTML code for the IntraACL toolbar, * for the $title editing mode. * * Looks like the following: * Page protection: <selectbox>. [Additional ACL ↓] [Used content ↓] [Edit ACL] ... [Manage Quick ACL] * * Options for selectbox: * - [no custom rights] - use only category/namespace rights * - [ACL:Page/XXX] - use custom ACL * - [Right 1] - use ACL template 1 * - [Right 2] - use ACL template 2 * - ... * ACL templates are detected using HACLSecurityDescriptor::isSinglePredefinedRightInclusion() * So if ACL:Page/XXX is really the inclusion of a single right template, it will be detected. */ static function get($title, $nonreadable) { global $wgUser, $wgRequest, $haclgContLang, $wgContLang, $haclgHaloScriptPath, $wgScriptPath, $wgOut, $haclgOpenWikiAccess; self::addToolbarLinks($wgOut); $ns = $wgContLang->getNsText(HACL_NS_ACL); $canModify = true; $options = array(array('value' => 'unprotected', 'name' => wfMsg('hacl_toolbar_unprotected'), 'title' => wfMsg('hacl_toolbar_unprotected'))); if (!is_object($title)) { $title = Title::newFromText($title); } if ($title->getNamespace() == HACL_NS_ACL) { return ''; } // $found = "is current page SD in the list?" $found = false; // The list of ACLs which have effect on $title, but are not ACL:Page/$title by themselves // I.e. category and namespace ACLs $globalACL = array(); $pageSDId = NULL; if ($title->exists()) { // Check SD modification rights $pageSDTitle = Title::newFromText(IACLDefinition::nameOfSD(IACL::PE_PAGE, $title)); $pageSD = IACLDefinition::getSDForPE(IACL::PE_PAGE, $title->getArticleId()); if ($pageSD) { $realPageSDId = $pageSDId = array($pageSD['pe_type'], $pageSD['pe_id']); $canModify = $pageSDTitle->userCan('edit'); // Check if page SD is a single predefined right inclusion if ($pageSD['single_child']) { $pageSDId = $pageSD['single_child']; // But don't change $realPageSDId } else { $found = true; $options[] = array('current' => true, 'value' => implode('-', $pageSDId), 'name' => $pageSDTitle->getFullText(), 'title' => $pageSDTitle->getFullText()); } } else { // Get protected categories this article belongs to (for hint) $categories = IACLStorage::get('Util')->getParentCategoryIDs($title->getArticleId()); foreach ($categories as &$cat) { $cat = array(IACL::PE_CATEGORY, $cat); } unset($cat); // prevent reference bugs $defs = IACLDefinition::select(array('pe' => $categories)); foreach ($defs as $def) { $globalACL[] = $def['def_title']; } } } // Add Quick ACLs $quickacl = IACLQuickacl::newForUserId($wgUser->getId()); $default = $quickacl->default_pe_id; $hasQuickACL = false; foreach ($quickacl->getPEIds() as $def) { $hasQuickACL = true; $sdTitle = IACLDefinition::getSDTitle($def); if (!$sdTitle) { continue; } $option = array('value' => implode('-', $def), 'current' => $def == $pageSDId, 'name' => $sdTitle->getPrefixedText(), 'title' => $sdTitle->getPrefixedText()); $found = $found || $option['current']; if ($default == $def) { if (!$title->exists()) { // Select default option for new articles $option['current'] = true; } // Always insert default SD as the second option array_splice($options, 1, 0, array($option)); } else { $options[] = $option; } } // If page SD is not yet in the list, insert it as the second option if ($pageSDId && !$found) { $sdTitle = IACLDefinition::getSDTitle($pageSDId); array_splice($options, 1, 0, array(array('name' => $sdTitle->getPrefixedText(), 'value' => implode('-', $pageSDId), 'current' => true, 'title' => $sdTitle->getPrefixedText()))); } // Alter selection using request data (hacl_protected_with) if ($canModify && ($st = $wgRequest->getVal('hacl_protected_with'))) { foreach ($options as &$o) { $o['current'] = $o['value'] == $st; } unset($o); // prevent reference bugs } $selectedIndex = false; foreach ($options as $i => $o) { if (!empty($o['current'])) { $selectedIndex = $i; } } // Check if page namespace has an ACL (for hint) if (!$pageSDId && !$globalACL) { $sdTitle = IACLDefinition::getSDTitle(array(IACL::PE_NAMESPACE, $title->getNamespace())); if ($sdTitle->exists()) { $globalACL[] = $sdTitle; } } if ($globalACL) { foreach ($globalACL as &$t) { if ($haclgOpenWikiAccess || $t->userCan('read')) { $t = Xml::element('a', array('href' => $t->getLocalUrl(), 'target' => '_blank'), $t->getText()); } } unset($t); // prevent reference bugs $globalACL = implode(', ', $globalACL); } // Check if the article does include any content $anyLinks = $embeddedToolbar = false; if ($title->exists()) { if (!$pageSDId) { $pageSDId = ''; } $c = false; foreach ($wgRequest->getValues() as $k => $v) { if (substr($k, 0, 7) == 'sd_emb_' && $v !== "") { $c = true; break; } } if ($c) { // If there were any changes in the embedded content // toolbar, display it initially $embeddedToolbar = self::getEmbeddedHtml($title->getArticleId(), $realPageSDId[0], $realPageSDId[1]); } else { // Else only check for imagelinks/templatelinks existence $dbr = wfGetDB(DB_SLAVE); $res = $dbr->query($dbr->selectSQLText('imagelinks', '1', array('il_from' => $title->getArticleId()), __METHOD__, array('GROUP BY' => 'il_from')) . ' UNION ' . $dbr->selectSQLText('templatelinks', '1', array('tl_from' => $title->getArticleId()), __METHOD__, array('GROUP BY' => 'tl_from')), __METHOD__); $res = $res->fetchObject(); if ($res) { $anyLinks = true; } } } // Link to Quick ACL manage page $quick_acl_link = Title::newFromText('Special:IntraACL')->getLocalUrl(array('action' => 'quickaccess')); // Run template ob_start(); require dirname(__FILE__) . '/../templates/HACL_Toolbar.tpl.php'; $html = ob_get_contents(); ob_end_clean(); return $html; }
/** * Displays full graph of IntraACL rights using Graphviz, in SVG format. * Does not reflect the right override method - just displays which rights apply * to different protected elements. * * SD -> (namespace = page cluster) * SD -> page * SD -> category -> each subcategory -> subcluster of a namespace * Included SD -> SD */ public function html_rightgraph(&$q) { global $wgOut, $wgContLang; $patch = haclfDisableTitlePatch(); // FIXME Special pages? // Select ALL SDs $titles = array(); $defs = IACLDefinition::select(array('pe_type != ' . IACL::PE_GROUP)); $cats = array(); foreach ($defs as $def) { $titles[$def['key']] = $def['def_title']; if ($def['pe_type'] == IACL::PE_CATEGORY) { $cats[] = $def['pe_title']; } if ($def['pe_type'] == IACL::PE_CATEGORY || $def['pe_type'] == IACL::PE_PAGE) { $titles[$def['pe_id']] = $def['pe_title']; } } $cattitles = IACLStorage::get('Util')->getAllChildrenCategories($cats); $catkeys = array(); // Fetch article IDs massively using LinkBatch $batch = new LinkBatch(); foreach ($cattitles as $t) { $batch->addObj($t); } $batch->execute(); foreach ($cattitles as $t) { $titles[$t->getArticleId()] = $t; $catkeys[$t->getDBkey()] = $t->getArticleId(); } $catlinks = IACLStorage::get('Util')->getCategoryLinks(array_keys($catkeys)); // Draw security descriptors $nodes = array(); $edges = array(); $ns_first = array(); $cluster = array(); foreach ($defs as $def) { if ($def['pe_type'] != IACL::PE_PAGE) { $nodes['sd' . $def['key']] = $def; if ($def['pe_type'] == IACL::PE_CATEGORY) { $edges['sd' . $def['key']]['cat' . $def['pe_id']] = true; $nodes['cat' . $def['pe_id']] = true; $cluster['sd' . $def['key']] = "clusterns" . NS_CATEGORY; } } else { $nodes['pg' . $def['pe_id']] = true; $edges['sd' . $def['key']]['pg' . $def['pe_id']] = true; if (!isset($ns_first[$titles[$def['pe_id']]->getNamespace()])) { $ns_first[$titles[$def['pe_id']]->getNamespace()] = 'pg' . $def['pe_id']; } } } // Group pages in category clusters within namespaces $cat_cluster = array(); $cat_cluster[NS_CATEGORY][''] = array(); foreach ($catlinks as $catkey => $cattitles) { $cattitle = $titles[$catkeys[$catkey]]; $catid = $cattitle->getArticleId(); foreach ($cattitles as $t) { $tns = $t->getNamespace(); $tid = $t->getArticleId(); if ($tns == NS_CATEGORY) { $edges["cat{$catid}"]["cat{$tid}"] = true; if (!isset($nodes["cat{$tid}"])) { $nodes["cat{$tid}"] = true; } } elseif (isset($nodes["pg{$tid}"])) { if (!isset($cluster["pg{$tid}"])) { $cluster["pg{$tid}"] = 'clustercat' . $tns . '_' . $catid; if (!isset($cat_cluster[$tns][$catid])) { $cat_cluster[$tns][$catid] = array(); $edges["cat{$catid}"]["pg{$tid}"] = 'lhead=clustercat' . $tns . '_' . $catid; } } else { $edges["cat{$catid}"]["pg{$tid}"] = true; } } } } // Set namespace clusters for non-grouped nodes foreach ($nodes as $n => &$attr) { if (substr($n, 0, 2) == 'pg' && !isset($cluster[$n])) { $cluster[$n] = 'clusterns' . $titles[substr($n, 2)]->getNamespace(); } elseif (substr($n, 0, 3) == 'cat') { $cluster[$n] = 'clusterns' . NS_CATEGORY; if (!isset($ns_first[NS_CATEGORY])) { $ns_first[NS_CATEGORY] = $n; } } } unset($attr); // prevent reference bugs // Group SDs in the same clusters as their PEs and draw namespace SD edges $sdbyid = array(); foreach ($defs as $def) { if ($def['pe_type'] == IACL::PE_PAGE) { $cluster['sd' . $def['key']] = $cluster['pg' . $def['pe_id']]; $sdbyid[$def['key']] = $def; } elseif ($def['pe_type'] == IACL::PE_NAMESPACE) { $cluster['sd' . $def['key']] = ''; if (isset($ns_first[$def['pe_id']])) { $k = $ns_first[$def['pe_id']]; } else { $k = 'etc' . $def['pe_id']; $nodes[$k] = array('label' => '...', 'shape' => 'circle', 'href' => Title::newFromText('Special:Allpages')->getFullUrl(array('namespace' => $def['pe_id'])), 'tooltip' => "Click to see all pages in namespace " . $wgContLang->getNsText($def['pe_id'])); $cluster[$k] = "clusterns" . $def['pe_id']; $ns_first[$def['pe_id']] = $k; } $edges['sd' . $def['key']][$k] = "lhead=clusterns" . $def['pe_id']; } elseif ($def['pe_type'] == IACL::PE_RIGHT) { $cluster['sd' . $def['key']] = ''; } } // Draw right hierarchy $hier = array(); foreach ($defs as $def) { foreach ($def['rules'] as $rules) { foreach ($rules as $rule) { if ($rule['child_type'] != IACL::PE_USER && $rule['child_type'] != IACL::PE_GROUP && $rule['child_type'] != IACL::PE_ALL_USERS && $rule['child_type'] != IACL::PE_REG_USERS && $rule['actions'] & IACL::ACTION_INCLUDE_SD) { $parent = $rule['pe_type'] . '-' . $rule['pe_id']; // get_key $child = $rule['child_type'] . '-' . $rule['child_id']; // get_key if (isset($sdbyid[$child]) && $sdbyid[$child]['pe_type'] == IACL::PE_PAGE) { $nodes['sd' . $child] = $sdbyid[$child]; } if (isset($sdbyid[$parent]) && $sdbyid[$parent]['pe_type'] == IACL::PE_PAGE) { $nodes['sd' . $parent] = $sdbyid[$parent]; } if (isset($nodes['sd' . $child]) && isset($nodes['sd' . $parent])) { $edges['sd' . $child]['sd' . $parent] = true; } } } } } foreach ($cluster as $k => $cl) { if (isset($nodes[$k])) { if (preg_match('/clustercat(\\d+)_(\\d+)/', $cl, $m)) { $cat_cluster[$m[1]][$m[2]][] = $k; } elseif (preg_match('/clusterns(\\d+)/', $cl, $m)) { $cat_cluster[$m[1]][''][] = $k; } elseif ($cl === '') { $cat_cluster[''][''][] = $k; } } } // Set node attributes $shapes = array('sd' => 'note', 'pg' => 'ellipse', 'cat' => 'folder'); $colors = array('sd' . IACL::PE_PAGE => '#ffd0d0', 'sd' . IACL::PE_CATEGORY => '#ffff80', 'sd' . IACL::PE_RIGHT => '#90ff90', 'sd' . IACL::PE_NAMESPACE => '#c0c0ff', 'cat' => '#ffe0c0'); foreach ($nodes as $n => $r) { if (is_array($r)) { continue; } preg_match('/([a-z]+)(\\d+(?:-\\d+)?)/', $n, $m); $type = $m[1]; $id = $m[2]; $nodes[$n] = array('shape' => $shapes[$type], 'label' => $titles[$id]->getPrefixedText(), 'href' => $titles[$id]->getFullUrl()); if ($type != 'pg') { $type2 = $type; if ($type2 == 'sd') { $type2 .= $r['pe_type']; } if (isset($colors[$type2])) { $nodes[$n]['fillcolor'] = $colors[$type2]; } $nodes[$n]['style'] = 'filled'; } } if ($nodes) { // Draw clusters $graph = ''; $ns_first[''] = ''; foreach ($ns_first as $ns => $first) { if ($ns !== '') { $graph .= "subgraph clusterns{$ns} {\n"; $graph .= "graph [label=\"Namespace " . ($ns ? $wgContLang->getNsText($ns) : 'Main') . "\", href=\"" . Title::newFromText('Special:Allpages')->getFullUrl(array('namespace' => $ns)) . "\"];\n"; } if (isset($cat_cluster[$ns])) { foreach ($cat_cluster[$ns] as $cat => $ks) { if ($cat !== '') { $graph .= "subgraph clustercat{$ns}_{$cat} {\n"; $graph .= 'graph [label="' . $titles[$cat]->getPrefixedText() . '", href="' . $titles[$cat]->getFullUrl() . '"];' . "\n"; } foreach ($ks as $nodename) { $graph .= "\"{$nodename}\" [" . self::attrstring($nodes[$nodename]) . "];\n"; } if ($cat !== '') { $graph .= "}\n"; } } } if ($ns !== '') { $graph .= "}\n"; } } // Draw edges foreach ($edges as $from => $to) { if (isset($nodes[$from])) { foreach ($to as $id => $attr) { if ($attr !== true) { $attr .= ', '; } else { $attr = ''; } $attr .= self::attrstring(array('href' => $nodes[$from]['href'], 'tooltip' => $nodes[$from]['label'])); $graph .= "\"{$from}\" -> \"{$id}\" [{$attr}];\n"; } } } // Render the graph $graph = "<graphviz>\ndigraph G {\nedge [penwidth=2 color=blue];\nsplines=polyline;\n" . "overlap=false;\nranksep=2;\nrankdir=LR;\ncompound=true;\n{$graph}\n}\n</graphviz>\n"; $wgOut->addWikiText($graph); $wgOut->addHTML("<pre>{$graph}</pre>"); } else { $wgOut->addWikiText(wfMsg('hacl_acllist_empty')); } haclfRestoreTitlePatch($patch); }