[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/includes/ -> MWNamespace.php (source)

   1  <?php
   2  /**
   3   * Provide things related to namespaces.
   4   *
   5   * This program is free software; you can redistribute it and/or modify
   6   * it under the terms of the GNU General Public License as published by
   7   * the Free Software Foundation; either version 2 of the License, or
   8   * (at your option) any later version.
   9   *
  10   * This program is distributed in the hope that it will be useful,
  11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13   * GNU General Public License for more details.
  14   *
  15   * You should have received a copy of the GNU General Public License along
  16   * with this program; if not, write to the Free Software Foundation, Inc.,
  17   * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18   * http://www.gnu.org/copyleft/gpl.html
  19   *
  20   * @file
  21   */
  22  
  23  /**
  24   * This is a utility class with only static functions
  25   * for dealing with namespaces that encodes all the
  26   * "magic" behaviors of them based on index.  The textual
  27   * names of the namespaces are handled by Language.php.
  28   *
  29   * These are synonyms for the names given in the language file
  30   * Users and translators should not change them
  31   *
  32   */
  33  class MWNamespace {
  34  
  35      /**
  36       * These namespaces should always be first-letter capitalized, now and
  37       * forevermore. Historically, they could've probably been lowercased too,
  38       * but some things are just too ingrained now. :)
  39       */
  40      private static $alwaysCapitalizedNamespaces = array( NS_SPECIAL, NS_USER, NS_MEDIAWIKI );
  41  
  42      /**
  43       * Throw an exception when trying to get the subject or talk page
  44       * for a given namespace where it does not make sense.
  45       * Special namespaces are defined in includes/Defines.php and have
  46       * a value below 0 (ex: NS_SPECIAL = -1 , NS_MEDIA = -2)
  47       *
  48       * @param int $index
  49       * @param string $method
  50       *
  51       * @throws MWException
  52       * @return bool
  53       */
  54  	private static function isMethodValidFor( $index, $method ) {
  55          if ( $index < NS_MAIN ) {
  56              throw new MWException( "$method does not make any sense for given namespace $index" );
  57          }
  58          return true;
  59      }
  60  
  61      /**
  62       * Can pages in the given namespace be moved?
  63       *
  64       * @param int $index Namespace index
  65       * @return bool
  66       */
  67  	public static function isMovable( $index ) {
  68          global $wgAllowImageMoving;
  69  
  70          $result = !( $index < NS_MAIN || ( $index == NS_FILE && !$wgAllowImageMoving ) );
  71  
  72          /**
  73           * @since 1.20
  74           */
  75          wfRunHooks( 'NamespaceIsMovable', array( $index, &$result ) );
  76  
  77          return $result;
  78      }
  79  
  80      /**
  81       * Is the given namespace is a subject (non-talk) namespace?
  82       *
  83       * @param int $index Namespace index
  84       * @return bool
  85       * @since 1.19
  86       */
  87  	public static function isSubject( $index ) {
  88          return !self::isTalk( $index );
  89      }
  90  
  91      /**
  92       * Is the given namespace a talk namespace?
  93       *
  94       * @param int $index Namespace index
  95       * @return bool
  96       */
  97  	public static function isTalk( $index ) {
  98          return $index > NS_MAIN
  99              && $index % 2;
 100      }
 101  
 102      /**
 103       * Get the talk namespace index for a given namespace
 104       *
 105       * @param int $index Namespace index
 106       * @return int
 107       */
 108  	public static function getTalk( $index ) {
 109          self::isMethodValidFor( $index, __METHOD__ );
 110          return self::isTalk( $index )
 111              ? $index
 112              : $index + 1;
 113      }
 114  
 115      /**
 116       * Get the subject namespace index for a given namespace
 117       * Special namespaces (NS_MEDIA, NS_SPECIAL) are always the subject.
 118       *
 119       * @param int $index Namespace index
 120       * @return int
 121       */
 122  	public static function getSubject( $index ) {
 123          # Handle special namespaces
 124          if ( $index < NS_MAIN ) {
 125              return $index;
 126          }
 127  
 128          return self::isTalk( $index )
 129              ? $index - 1
 130              : $index;
 131      }
 132  
 133      /**
 134       * Get the associated namespace.
 135       * For talk namespaces, returns the subject (non-talk) namespace
 136       * For subject (non-talk) namespaces, returns the talk namespace
 137       *
 138       * @param int $index Namespace index
 139       * @return int|null If no associated namespace could be found
 140       */
 141  	public static function getAssociated( $index ) {
 142          self::isMethodValidFor( $index, __METHOD__ );
 143  
 144          if ( self::isSubject( $index ) ) {
 145              return self::getTalk( $index );
 146          } elseif ( self::isTalk( $index ) ) {
 147              return self::getSubject( $index );
 148          } else {
 149              return null;
 150          }
 151      }
 152  
 153      /**
 154       * Returns whether the specified namespace exists
 155       *
 156       * @param int $index
 157       *
 158       * @return bool
 159       * @since 1.19
 160       */
 161  	public static function exists( $index ) {
 162          $nslist = self::getCanonicalNamespaces();
 163          return isset( $nslist[$index] );
 164      }
 165  
 166      /**
 167       * Returns whether the specified namespaces are the same namespace
 168       *
 169       * @note It's possible that in the future we may start using something
 170       * other than just namespace indexes. Under that circumstance making use
 171       * of this function rather than directly doing comparison will make
 172       * sure that code will not potentially break.
 173       *
 174       * @param int $ns1 The first namespace index
 175       * @param int $ns2 The second namespace index
 176       *
 177       * @return bool
 178       * @since 1.19
 179       */
 180  	public static function equals( $ns1, $ns2 ) {
 181          return $ns1 == $ns2;
 182      }
 183  
 184      /**
 185       * Returns whether the specified namespaces share the same subject.
 186       * eg: NS_USER and NS_USER wil return true, as well
 187       *     NS_USER and NS_USER_TALK will return true.
 188       *
 189       * @param int $ns1 The first namespace index
 190       * @param int $ns2 The second namespace index
 191       *
 192       * @return bool
 193       * @since 1.19
 194       */
 195  	public static function subjectEquals( $ns1, $ns2 ) {
 196          return self::getSubject( $ns1 ) == self::getSubject( $ns2 );
 197      }
 198  
 199      /**
 200       * Returns array of all defined namespaces with their canonical
 201       * (English) names.
 202       *
 203       * @param bool $rebuild Rebuild namespace list (default = false). Used for testing.
 204       *
 205       * @return array
 206       * @since 1.17
 207       */
 208  	public static function getCanonicalNamespaces( $rebuild = false ) {
 209          static $namespaces = null;
 210          if ( $namespaces === null || $rebuild ) {
 211              global $wgExtraNamespaces, $wgCanonicalNamespaceNames;
 212              $namespaces = array( NS_MAIN => '' ) + $wgCanonicalNamespaceNames;
 213              if ( is_array( $wgExtraNamespaces ) ) {
 214                  $namespaces += $wgExtraNamespaces;
 215              }
 216              wfRunHooks( 'CanonicalNamespaces', array( &$namespaces ) );
 217          }
 218          return $namespaces;
 219      }
 220  
 221      /**
 222       * Returns the canonical (English) name for a given index
 223       *
 224       * @param int $index Namespace index
 225       * @return string|bool If no canonical definition.
 226       */
 227  	public static function getCanonicalName( $index ) {
 228          $nslist = self::getCanonicalNamespaces();
 229          if ( isset( $nslist[$index] ) ) {
 230              return $nslist[$index];
 231          } else {
 232              return false;
 233          }
 234      }
 235  
 236      /**
 237       * Returns the index for a given canonical name, or NULL
 238       * The input *must* be converted to lower case first
 239       *
 240       * @param string $name Namespace name
 241       * @return int
 242       */
 243  	public static function getCanonicalIndex( $name ) {
 244          static $xNamespaces = false;
 245          if ( $xNamespaces === false ) {
 246              $xNamespaces = array();
 247              foreach ( self::getCanonicalNamespaces() as $i => $text ) {
 248                  $xNamespaces[strtolower( $text )] = $i;
 249              }
 250          }
 251          if ( array_key_exists( $name, $xNamespaces ) ) {
 252              return $xNamespaces[$name];
 253          } else {
 254              return null;
 255          }
 256      }
 257  
 258      /**
 259       * Returns an array of the namespaces (by integer id) that exist on the
 260       * wiki. Used primarily by the api in help documentation.
 261       * @return array
 262       */
 263  	public static function getValidNamespaces() {
 264          static $mValidNamespaces = null;
 265  
 266          if ( is_null( $mValidNamespaces ) ) {
 267              foreach ( array_keys( self::getCanonicalNamespaces() ) as $ns ) {
 268                  if ( $ns >= 0 ) {
 269                      $mValidNamespaces[] = $ns;
 270                  }
 271              }
 272          }
 273  
 274          return $mValidNamespaces;
 275      }
 276  
 277      /**
 278       * Can this namespace ever have a talk namespace?
 279       *
 280       * @param int $index Namespace index
 281       * @return bool
 282       */
 283  	public static function canTalk( $index ) {
 284          return $index >= NS_MAIN;
 285      }
 286  
 287      /**
 288       * Does this namespace contain content, for the purposes of calculating
 289       * statistics, etc?
 290       *
 291       * @param int $index Index to check
 292       * @return bool
 293       */
 294  	public static function isContent( $index ) {
 295          global $wgContentNamespaces;
 296          return $index == NS_MAIN || in_array( $index, $wgContentNamespaces );
 297      }
 298  
 299      /**
 300       * Can pages in a namespace be watched?
 301       *
 302       * @param int $index
 303       * @return bool
 304       */
 305  	public static function isWatchable( $index ) {
 306          return $index >= NS_MAIN;
 307      }
 308  
 309      /**
 310       * Does the namespace allow subpages?
 311       *
 312       * @param int $index Index to check
 313       * @return bool
 314       */
 315  	public static function hasSubpages( $index ) {
 316          global $wgNamespacesWithSubpages;
 317          return !empty( $wgNamespacesWithSubpages[$index] );
 318      }
 319  
 320      /**
 321       * Get a list of all namespace indices which are considered to contain content
 322       * @return array Array of namespace indices
 323       */
 324  	public static function getContentNamespaces() {
 325          global $wgContentNamespaces;
 326          if ( !is_array( $wgContentNamespaces ) || $wgContentNamespaces === array() ) {
 327              return array( NS_MAIN );
 328          } elseif ( !in_array( NS_MAIN, $wgContentNamespaces ) ) {
 329              // always force NS_MAIN to be part of array (to match the algorithm used by isContent)
 330              return array_merge( array( NS_MAIN ), $wgContentNamespaces );
 331          } else {
 332              return $wgContentNamespaces;
 333          }
 334      }
 335  
 336      /**
 337       * List all namespace indices which are considered subject, aka not a talk
 338       * or special namespace. See also MWNamespace::isSubject
 339       *
 340       * @return array Array of namespace indices
 341       */
 342  	public static function getSubjectNamespaces() {
 343          return array_filter(
 344              MWNamespace::getValidNamespaces(),
 345              'MWNamespace::isSubject'
 346          );
 347      }
 348  
 349      /**
 350       * List all namespace indices which are considered talks, aka not a subject
 351       * or special namespace. See also MWNamespace::isTalk
 352       *
 353       * @return array Array of namespace indices
 354       */
 355  	public static function getTalkNamespaces() {
 356          return array_filter(
 357              MWNamespace::getValidNamespaces(),
 358              'MWNamespace::isTalk'
 359          );
 360      }
 361  
 362      /**
 363       * Is the namespace first-letter capitalized?
 364       *
 365       * @param int $index Index to check
 366       * @return bool
 367       */
 368  	public static function isCapitalized( $index ) {
 369          global $wgCapitalLinks, $wgCapitalLinkOverrides;
 370          // Turn NS_MEDIA into NS_FILE
 371          $index = $index === NS_MEDIA ? NS_FILE : $index;
 372  
 373          // Make sure to get the subject of our namespace
 374          $index = self::getSubject( $index );
 375  
 376          // Some namespaces are special and should always be upper case
 377          if ( in_array( $index, self::$alwaysCapitalizedNamespaces ) ) {
 378              return true;
 379          }
 380          if ( isset( $wgCapitalLinkOverrides[$index] ) ) {
 381              // $wgCapitalLinkOverrides is explicitly set
 382              return $wgCapitalLinkOverrides[$index];
 383          }
 384          // Default to the global setting
 385          return $wgCapitalLinks;
 386      }
 387  
 388      /**
 389       * Does the namespace (potentially) have different aliases for different
 390       * genders. Not all languages make a distinction here.
 391       *
 392       * @since 1.18
 393       * @param int $index Index to check
 394       * @return bool
 395       */
 396  	public static function hasGenderDistinction( $index ) {
 397          return $index == NS_USER || $index == NS_USER_TALK;
 398      }
 399  
 400      /**
 401       * It is not possible to use pages from this namespace as template?
 402       *
 403       * @since 1.20
 404       * @param int $index Index to check
 405       * @return bool
 406       */
 407  	public static function isNonincludable( $index ) {
 408          global $wgNonincludableNamespaces;
 409          return $wgNonincludableNamespaces && in_array( $index, $wgNonincludableNamespaces );
 410      }
 411  
 412      /**
 413       * Get the default content model for a namespace
 414       * This does not mean that all pages in that namespace have the model
 415       *
 416       * @since 1.21
 417       * @param int $index Index to check
 418       * @return null|string Default model name for the given namespace, if set
 419       */
 420  	public static function getNamespaceContentModel( $index ) {
 421          global $wgNamespaceContentModels;
 422          return isset( $wgNamespaceContentModels[$index] )
 423              ? $wgNamespaceContentModels[$index]
 424              : null;
 425      }
 426  
 427      /**
 428       * Determine which restriction levels it makes sense to use in a namespace,
 429       * optionally filtered by a user's rights.
 430       *
 431       * @since 1.23
 432       * @param int $index Index to check
 433       * @param User $user User to check
 434       * @return array
 435       */
 436  	public static function getRestrictionLevels( $index, User $user = null ) {
 437          global $wgNamespaceProtection, $wgRestrictionLevels;
 438  
 439          if ( !isset( $wgNamespaceProtection[$index] ) ) {
 440              // All levels are valid if there's no namespace restriction.
 441              // But still filter by user, if necessary
 442              $levels = $wgRestrictionLevels;
 443              if ( $user ) {
 444                  $levels = array_values( array_filter( $levels, function ( $level ) use ( $user ) {
 445                      $right = $level;
 446                      if ( $right == 'sysop' ) {
 447                          $right = 'editprotected'; // BC
 448                      }
 449                      if ( $right == 'autoconfirmed' ) {
 450                          $right = 'editsemiprotected'; // BC
 451                      }
 452                      return ( $right == '' || $user->isAllowed( $right ) );
 453                  } ) );
 454              }
 455              return $levels;
 456          }
 457  
 458          // First, get the list of groups that can edit this namespace.
 459          $namespaceGroups = array();
 460          $combine = 'array_merge';
 461          foreach ( (array)$wgNamespaceProtection[$index] as $right ) {
 462              if ( $right == 'sysop' ) {
 463                  $right = 'editprotected'; // BC
 464              }
 465              if ( $right == 'autoconfirmed' ) {
 466                  $right = 'editsemiprotected'; // BC
 467              }
 468              if ( $right != '' ) {
 469                  $namespaceGroups = call_user_func( $combine, $namespaceGroups,
 470                      User::getGroupsWithPermission( $right ) );
 471                  $combine = 'array_intersect';
 472              }
 473          }
 474  
 475          // Now, keep only those restriction levels where there is at least one
 476          // group that can edit the namespace but would be blocked by the
 477          // restriction.
 478          $usableLevels = array( '' );
 479          foreach ( $wgRestrictionLevels as $level ) {
 480              $right = $level;
 481              if ( $right == 'sysop' ) {
 482                  $right = 'editprotected'; // BC
 483              }
 484              if ( $right == 'autoconfirmed' ) {
 485                  $right = 'editsemiprotected'; // BC
 486              }
 487              if ( $right != '' && ( !$user || $user->isAllowed( $right ) ) &&
 488                  array_diff( $namespaceGroups, User::getGroupsWithPermission( $right ) )
 489              ) {
 490                  $usableLevels[] = $level;
 491              }
 492          }
 493  
 494          return $usableLevels;
 495      }
 496  }


Generated: Fri Nov 28 14:03:12 2014 Cross-referenced by PHPXref 0.7.1