+ /**
+ * Determine whether the block allows the user to edit their own
+ * user talk page. This is done separately from Block::appliesToRight
+ * because there is no right for editing one's own user talk page
+ * and because the user's talk page needs to be passed into the
+ * Block object, which is unaware of the user.
+ *
+ * The ipb_allow_usertalk flag (which corresponds to the property
+ * allowUsertalk) is used on sitewide blocks and partial blocks
+ * that contain a namespace restriction on the user talk namespace,
+ * but do not contain a page restriction on the user's talk page.
+ * For all other (i.e. most) partial blocks, the flag is ignored,
+ * and the user can always edit their user talk page unless there
+ * is a page restriction on their user talk page, in which case
+ * they can never edit it. (Ideally the flag would be stored as
+ * null in these cases, but the database field isn't nullable.)
+ *
+ * @since 1.33
+ * @param Title|null $usertalk The user's user talk page. If null,
+ * and if the target is a User, the target's userpage is used
+ * @return bool The user can edit their talk page
+ */
+ public function appliesToUsertalk( Title $usertalk = null ) {
+ $target = $this->target;
+ $targetIsUser = $target instanceof User;
+ $targetName = $targetIsUser ? $target->getName() : $target;
+
+ if ( !$usertalk ) {
+ if ( $targetIsUser ) {
+ $usertalk = $this->target->getTalkPage();
+ } else {
+ throw new InvalidArgumentException(
+ '$usertalk must be provided if block target is not a user/IP'
+ );
+ }
+ }
+
+ if ( $usertalk->getNamespace() !== NS_USER_TALK ) {
+ throw new InvalidArgumentException(
+ '$usertalk must be a user talk page'
+ );
+ }
+
+ switch ( $this->type ) {
+ case self::TYPE_USER:
+ case self::TYPE_IP:
+ if ( $usertalk->getText() !== $targetName ) {
+ throw new InvalidArgumentException(
+ '$usertalk must be a talk page for the block target'
+ );
+ }
+ break;
+ case self::TYPE_RANGE:
+ if ( !IP::isInRange( $usertalk->getText(), $target ) ) {
+ throw new InvalidArgumentException(
+ '$usertalk must be a talk page for an IP within the block target range'
+ );
+ }
+ break;
+ default:
+ throw new LogicException(
+ 'Cannot determine validity of $usertalk for this type of block'
+ );
+ }
+
+ if ( !$this->isSitewide() ) {
+ if ( $this->appliesToPage( $usertalk->getArticleID() ) ) {
+ return true;
+ }
+ if ( !$this->appliesToNamespace( NS_USER_TALK ) ) {
+ return false;
+ }
+ }
+
+ // This is a type of block which uses the ipb_allow_usertalk
+ // flag. The flag can still be overridden by global configs.
+ $config = RequestContext::getMain()->getConfig();
+ if ( !$config->get( 'BlockAllowsUTEdit' ) ) {
+ return true;
+ }
+ return !$this->isUsertalkEditAllowed();
+ }
+