/**
  * Returns the ID of a protected object that is given by its name.
  * The ID depends on the type.
  *
  * @param  string $peName   Object name
  * @param  int $peType      Object type (IACL::PE_*)
  * @return int/bool         Object id or <false> if it does not exist
  */
 public static function peIDforName($peType, $peName)
 {
     $ns = NS_MAIN;
     $force = true;
     switch ($peType) {
         case IACL::PE_PAGE:
             // Page ACLs allow any namespace except NS_SPECIAL
             $force = false;
             break;
         case IACL::PE_NAMESPACE:
             // $peName is a namespace => get its ID
             global $wgContLang;
             $peName = str_replace(' ', '_', trim($peName, " _\t\n\r"));
             $idx = $wgContLang->getNsIndex($peName);
             if ($idx == false) {
                 return strtolower($peName) == 'main' ? 0 : false;
             }
             return $idx;
         case IACL::PE_CATEGORY:
             $ns = NS_CATEGORY;
             break;
         case IACL::PE_USER:
             $user = User::newFromName($peName);
             return $user->getId();
         case IACL::PE_SPECIAL:
             $ns = NS_SPECIAL;
             break;
             // Groups and rights are in ACL namespace
         // Groups and rights are in ACL namespace
         case IACL::PE_GROUP:
             global $haclgContLang;
             $peName = $haclgContLang->getPetPrefix(IACL::PE_GROUP) . '/' . $peName;
         case IACL::PE_RIGHT:
             $ns = HACL_NS_ACL;
             break;
     }
     // Return the page id
     // TODO add caching here
     $id = haclfArticleID($peName, $ns, $force);
     if ($id < 0) {
         if ($peType != IACL::PE_SPECIAL) {
             throw new Exception(__METHOD__ . ': BUG: Special page title passed, but PE type = ' . $peType . ' (not PE_SPECIAL)');
         }
         return -$id;
     }
     return $id ? $id : NULL;
 }
 /**
  * Returns array(final log message, access granted?, continue hook processing?)
  */
 public static function userCan_Switches($title, $user, $action)
 {
     global $haclgContLang, $haclgSuperGroups;
     if (!$title) {
         return array('Title is <null>', 1);
     }
     if ($title->getInterwiki() !== '') {
         // Do not check interwiki links
         return array('Interwiki title', 1);
     }
     $groups = $user->getGroups();
     if ($groups && array_intersect($groups, $haclgSuperGroups)) {
         return array('User is a superuser and can do anything.', 1);
     }
     if ($title->getPrefixedText() == $haclgContLang->getPermissionDeniedPage()) {
         // no access to the page "Permission denied" emitted by TitlePatch is allowed
         return array('Special handling of "Permission denied" page', 0);
     }
     // Check action
     $actionID = IACL::getActionID($action);
     if (!$actionID) {
         // Unknown action => nothing can be said about this
         return array('Unknown action', 1);
     }
     // Check rights for managing ACLs
     if ($title->getNamespace() == HACL_NS_ACL) {
         return array('Checked ACL modification rights', self::checkACLManager($title, $user, $actionID));
     }
     // If there is a whitelist, then allow user to read the page
     if ($actionID == IACL::ACTION_READ && self::isWhitelisted($title)) {
         return array('Page is in MediaWiki whitelist', 1);
     }
     // haclfArticleID also returns IDs for special pages
     $articleID = haclfArticleID($title);
     $userID = $user->getId();
     if ($articleID && $actionID == IACL::ACTION_CREATE) {
         // create=edit for existing articles
         $actionID = IACL::ACTION_EDIT;
     } elseif (!$articleID) {
         if ($actionID == IACL::ACTION_EDIT) {
             // edit=create for non-existing articles
             self::log('Article does not exist yet. Checking right to create.');
             $actionID = IACL::ACTION_CREATE;
         } elseif ($actionID == IACL::ACTION_DELETE || $actionID == IACL::ACTION_MOVE) {
             return array('Moving/deleting non-existing article is pointless', 1);
         }
         $r = IACLDefinition::userCan($userID, IACL::PE_NAMESPACE, $title->getNamespace(), $actionID);
         if ($r <= 0 && $actionID == IACL::ACTION_READ) {
             // Read right is needed to show edit form
             $r = IACLDefinition::userCan($userID, IACL::PE_NAMESPACE, $title->getNamespace(), IACL::ACTION_CREATE);
         }
         return array('Checked namespace access right', $r);
     }
     if ($articleID && $title->isRedirect()) {
         // Redirects are treated like symlinks in Unix: their permissions are always equal to target
         // (at least if target exists...)
         $dbr = wfGetDB(DB_SLAVE);
         $id = $articleID;
         $seen = array();
         do {
             $seen[$id] = true;
             $row = $dbr->selectRow(array('page', 'redirect'), 'page.*', array('rd_from' => $id, 'page_namespace=rd_namespace', 'page_title=rd_title'), __METHOD__);
             $id = $row ? $row->page_id : NULL;
         } while ($row && $row->page_is_redirect && !$seen[$row->page_id]);
         if ($row) {
             $title = Title::newFromRow($row);
             $articleID = $row->page_id;
             self::log("Page is a live redirect to " . $title->getFullText() . ", checking permissions for target");
         }
     }
     return self::hasSD($title, $articleID, $userID, $actionID);
 }