public function isObjectClosed( $obj, $text, $offset ) {
		if ( strlen( $text ) == $offset ) return 0;

		$parentClose = WOMProcessor::getObjectParser( $obj->getParent() )
			->isObjectClosed( $obj->getParent(), $text, $offset );
		if ( $parentClose !== false ) return 0;

		return false;
	}
	public function isObjectClosed( $obj, $text, $offset ) {
		if ( !( $obj instanceof WOMParamValueModel ) )
			return false;

		$parentClose = WOMProcessor::getObjectParser( $obj->getParent() )
			->isObjectClosed( $obj->getParent(), $text, $offset );
		if ( $parentClose !== false ) return 0;

		return false;
	}
	private static function setupParsers() {
		if ( self::$isParsersRegistered ) return;

		global $wgOMParsers;
		foreach ( $wgOMParsers as $p ) {
			$parser = new $p();
			self::$parsers[$parser->getParserID()] = $parser;
		}
		self::$base_parser = self::$parsers[WOM_PARSER_ID_TEXT];

		self::$isParsersRegistered = true;
	}
	public function isObjectClosed( $obj, $text, $offset ) {
		if ( !( $obj instanceof WOMNestPropertyValueModel ) )
			return false;

		if ( ( strlen( $text ) >= $offset + 1 ) && $text { $offset } == '|' ) {
			return 1;
		}
		$parentClose = WOMProcessor::getObjectParser( $obj->getParent() )
			->isObjectClosed( $obj->getParent(), $text, $offset );
		if ( $parentClose !== false ) return 0;

		return false;
	}
	static function getOutputData( $title, $rid = 0 ) {
		// normal page
		global $wgTitle, $wgUser;
		$wgTitle = $title;
		$revision = Revision::newFromTitle( $title, $rid );
		if ( $revision === NULL ) {
			throw new MWException( __METHOD__ . ": Page not exist '{$page_name} ({$rid})'" );
		}
		$text = $revision->getText();
		$wom = WOMProcessor::parseToWOM( $text );

		global $wgOMOutputHookedParserFunctions;
		$pfs = $wom->getObjectsByTypeID( WOM_TYPE_PARSERFUNCTION );
		foreach ( $pfs as $id => $obj ) {
			self::removeSubWOMIds( $obj );
			foreach ( $wgOMOutputHookedParserFunctions as $function_key ) {
				if ( $obj->getFunctionKey() == $function_key ) {
					// add wom id to parser function, with specified parameter 'wom_id'
					$param = new WOMParameterModel( 'wom_id' );
					$pv = new WOMParamValueModel();
					$param->insertObject( $pv );
					$pv->insertObject( new WOMTextModel( $id ) );
					$obj->insertObject( $param );
				}
			}
		}
		// FIXME: template values may have object ids
		$tmpls = $wom->getObjectsByTypeID( WOM_TYPE_TEMPLATE );
		foreach ( $tmpls as $id => $obj ) {
			self::removeSubWOMIds( $obj );
		}

		global $wgParser, $wgOut, $wgWOMOutputHooked;
		$wgWOMOutputHooked = true;
		$options = ParserOptions::newFromUser( $wgUser );

		self::$queryProps = array();
		self::$queryId = 1;
		$wgParser->parse( $wom->getWikiText(), $title, $options );

		$output = SMWParseData::getSMWdata( $wgParser );

		if ( !isset( $output ) ) {
			$semdata = smwfGetStore()->getSemanticData( $title );
		} else {
			$semdata = $output;
		}

		$tmp_id = 0;
		// fill in semantic properties
		$properties = array();
		foreach ( $semdata->getProperties() as $property ) {
			$label = '';
			if ( !$property->isShown() ) { // showing this is not desired, hide
				continue;
			} elseif ( $property->isUserDefined() ) { // user defined property
				if ( version_compare ( SMW_VERSION, '1.6', '>=' ) ) {
					$label = $property->getLabel();
				} else {
					$property->setCaption( preg_replace( '/[ ]/u', ' ', $property->getWikiValue(), 2 ) );
					// / NOTE: the preg_replace is a slight hack to ensure that the left column does not get too narrow
					$label = $property->getWikiValue();
				}
			} else {
				if ( version_compare ( SMW_VERSION, '1.6', '>=' ) ) {
					$label = $property->getLabel();
				} else {
					if ( $property->isVisible() ) { // predefined property
						$label = $property->getWikiValue();
					} else { // predefined, internal property
						continue;
					}
				}
			}
			$properties[$label] = array();

			$propvalues = $semdata->getPropertyValues( $property );
			foreach ( $propvalues as $propvalue ) {
				if ( version_compare ( SMW_VERSION, '1.6', '>=' ) ) {
					if ( $propvalue->getDIType() == SMWDataItem::TYPE_ERROR ) continue;
					$properties[$label][$propvalue->getSerialization()] = false;
				} else {
					$properties[$label][$propvalue->getWikiValue()] = false;
				}
			}
		}
		$props = $wom->getObjectsByTypeID( WOM_TYPE_PROPERTY );
		foreach ( $props as $prop ) {
			$id = $prop->getObjectID();
			if ( $id == '' ) continue;
			$name = $prop->getPropertyName();
			$value = $prop->getPropertyValue();
			if ( !isset( $properties[$name][$value] ) ) {
				// remove category not match to output
				$wom->removePageObject( $id );
			} else {
				$properties[$name][$value] = true;
			}
		}
		foreach ( $properties as $name => $values ) {
			foreach ( $values as $val => $flag ) {
				if ( $flag !== true ) {
					$p = new WOMPropertyModel( $name, $val );
					$p->setObjectID( 'output' . ( $tmp_id ++ ) );
					$wom->insertObject( $p );
					$wom->addToPageObjectSet( $p );
				}
			}
		}

		// fill in ask query results
		foreach ( self::$queryProps as $wom_id => $queries ) {
			$query_res = new WOMQueryResult();
			if ( $wom_id != '' ) {
				$parent = $wom->getObject( $wom_id );
			} else {
				$parent = new WOMParserFunctionModel( 'ask' );
				$parent->setObjectID( 'output' . ( $tmp_id ++ ) );
				$wom->insertObject( $parent );
				$wom->addToPageObjectSet( $parent );
			}
			$parent->insertObject( $query_res );
			$query_res->setObjectID( 'output' . ( $tmp_id ++ ) );
			$wom->addToPageObjectSet( $query_res );
			foreach ( $queries as $label => $vals ) {
				$vals = array_unique( $vals );
				foreach ( $vals as $val ) {
					$query_res->insertObject( new WOMPropertyModel( $label, $val ) );
				}
			}
		}

		// fill in categories
		$categories = $title->getParentCategories();
		$cates = $wom->getObjectsByTypeID( WOM_TYPE_CATEGORY );
		foreach ( $cates as $cate ) {
			$id = $cate->getObjectID();
			if ( $id == '' ) continue;
			$name = Title::newFromText( $cate->getName(), NS_CATEGORY )->getFullText();
			if ( !isset( $categories[$name] ) ) {
				// remove category not match to output
				$wom->removePageObject( $id );
			} else {
				$categories[$name] = true;
			}
		}
		foreach ( $categories as $cate => $flag ) {
			if ( $flag !== true ) {
				$c = new WOMCategoryModel( Title::newFromText( $cate )->getText() );
				$c->setObjectID( 'output' . ( $tmp_id ++ ) );
				$wom->insertObject( $c );
				$wom->addToPageObjectSet( $c );
			}
		}

		return $wom;
	}
	public function execute() {
		global $wgUser;

		$params = $this->extractRequestParams();
		if ( is_null( $params['title'] ) )
			$this->dieUsage( 'Must specify page title', 0 );
		if ( is_null( $params['xpath'] ) )
			$this->dieUsage( 'Must specify xpath', 1 );

		$page_name = $params['title'];
		$xpath = $params['xpath'];
		$type = $params['type'];
		$rid = $params['rid'];


		$articleTitle = Title::newFromText( $page_name );
		if ( !$articleTitle )
			$this->dieUsage( "Can't create title object ($page_name)", 2 );

		$article = new Article( $articleTitle );
		if ( !$article->exists() )
			$this->dieUsage( "Article doesn't exist ($page_name)", 3 );

		try {
			$objs = WOMProcessor::getObjIdByXPath( $articleTitle, $xpath, $rid );
		} catch ( Exception $e ) {
			$err = $e->getMessage();
		}

		$result = array();

		if ( isset( $err ) ) {
			$result = array(
				'result' => 'Failure',
				'message' => array(),
			);
			$this->getResult()->setContent( $result['message'], $err );
		} else {
			$result['result'] = 'Success';

			// pay attention to special xml tag, e.g., <property><value>...</value></property>
			$result['return'] = array();
			if ( $type == 'count' ) {
				$count = 0;
				foreach ( $objs as $id ) {
					if ( $id == '' ) continue;
					++ $count;
				}
				$this->getResult()->setContent( $result['return'], $count );
			} else {
				$xml = '';
				$page_obj = WOMProcessor::getPageObject( $articleTitle, $rid );
				foreach ( $objs as $id ) {
					if ( $id == '' ) continue;
					$wobj = $page_obj->getObject( $id );
					$result['return'][$id] = array();
					if ( $type == 'xml' ) {
						$xml .= "<{$id} xml:space=\"preserve\">{$wobj->toXML()}</{$id}>";
//						$this->getResult()->setContent( $result['return'][$id], $wobj->toXML() );
					} else {
						$this->getResult()->setContent( $result['return'][$id], $wobj->getWikiText() );
					}
				}
				if ( $type == 'xml' ) {
					header ( "Content-Type: application/rdf+xml" );
					echo <<<OUTPUT
<?xml version="1.0" encoding="UTF-8" ?>
<api><womget result="Success"><return>
{$xml}
</return></womget></api>
OUTPUT;
					exit( 1 );
				}
			}
		}
		$this->getResult()->addValue( null, $this->getModuleName(), $result );
	}
	public function isObjectClosed( $obj, $text, $offset ) {
		if ( !( ( $obj instanceof WOMTemplateFieldModel )
			|| ( $obj instanceof WOMParameterModel )
			|| ( $obj instanceof WOMQuerystringModel )
			|| ( $obj instanceof WOMQueryPrintoutModel ) ) )
				return false;

		if ( ( strlen( $text ) >= $offset + 1 ) && $text { $offset } == '|' ) {
			return 1;
		}
		$parentClose = WOMProcessor::getObjectParser( $obj->getParent() )
			->isObjectClosed( $obj->getParent(), $text, $offset );
		if ( $parentClose !== false ) return 0;

		return false;
	}
示例#8
0
 public function execute()
 {
     global $wgUser;
     $params = $this->extractRequestParams();
     if (is_null($params['title'])) {
         $this->dieUsageMsg(array('missingparam', 'title'));
     }
     if (is_null($params['xpath'])) {
         $this->dieUsage(array('missingparam', 'xpath'));
     }
     $titleObj = Title::newFromText($params['title']);
     if (!$titleObj || $titleObj->isExternal()) {
         $this->dieUsageMsg(array('invalidtitle', $params['title']));
     }
     // Some functions depend on $wgTitle == $ep->mTitle
     global $wgTitle;
     $wgTitle = $titleObj;
     if ($params['nocreate'] && !$titleObj->exists()) {
         $this->dieUsageMsg(array('nocreate-missing'));
     }
     // Now let's check whether we're even allowed to do this
     $errors = $titleObj->getUserPermissionsErrors('edit', $wgUser);
     if (!$titleObj->exists()) {
         $errors = array_merge($errors, $titleObj->getUserPermissionsErrors('create', $wgUser));
     }
     if (count($errors)) {
         $this->dieUsageMsg($errors[0]);
     }
     $articleObj = new Article($titleObj);
     if (!is_null($params['rid'])) {
         $revObj = Revision::newFromID($params['rid']);
         if (is_null($revObj) || $revObj->isDeleted(Revision::DELETED_TEXT)) {
             $this->dieUsageMsg(array('nosuchrevid', $params['rid']));
         }
         if ($revObj->getPage() != $articleObj->getID()) {
             $this->dieUsageMsg(array('revwrongpage', $revObj->getID(), $titleObj->getPrefixedText()));
         }
         if (!$params['force_update'] && !$revObj->isCurrent()) {
             $this->dieUsage("Page revision id is not current '{$titleObj->getPrefixedText()} ({$params['rid']})'", 'revnotcurrent');
         }
     } else {
         $params['rid'] = 0;
     }
     $verb = $params['verb'];
     $xpath = $params['xpath'];
     try {
         $wom = WOMProcessor::getPageObject($titleObj, $params['rid']);
         $obj_ids = WOMProcessor::getObjIdByXPath2($wom, $xpath);
         $obj_id = null;
         foreach ($obj_ids as $id) {
             if ($id != '') {
                 $obj_id = $id;
                 break;
             }
         }
         if ($obj_id == null) {
             throw new MWException(__METHOD__ . ": object does not found, xpath: {$xpath}");
         }
         if ($verb == 'remove') {
             $wom->removePageObject($obj_id);
         } elseif ($verb == 'removeall') {
             foreach ($obj_ids as $id) {
                 if ($id == '') {
                     continue;
                 }
                 $wom->removePageObject($id);
             }
         } else {
             if (is_null($params['text'])) {
                 $this->dieUsageMsg(array('missingparam', 'text'));
             }
             $toMD5 = $params['text'];
             // See if the MD5 hash checks out
             if (!is_null($params['md5']) && md5($toMD5) !== $params['md5']) {
                 $this->dieUsageMsg(array('hashcheckfailed'));
             }
             $text = $params['text'];
             if ($verb == 'insert') {
                 $text = WOMProcessor::getValidText($text, $wom->getObject($obj_id)->getParent(), $wom);
                 // no need to parse or merge object model but use text
                 $wom->insertPageObject(new WOMTextModel($text), $obj_id);
             } elseif ($verb == 'update') {
                 $text = WOMProcessor::getValidText($text, $wom->getObject($obj_id)->getParent(), $wom);
                 $wom->updatePageObject(new WOMTextModel($text), $obj_id);
             } elseif ($verb == 'append') {
                 $parent = $wom->getObject($obj_id);
                 if (!$parent instanceof WikiObjectModelCollection) {
                     throw new MWException(__METHOD__ . ": Object is not a collection object '{$title} ({$revision_id}) - {$obj_id}'");
                 }
                 $text = WOMProcessor::getValidText($text, $parent, $wom);
                 $wom->appendChildObject(new WOMTextModel($text), $obj_id);
             } elseif ($verb == 'attribute') {
                 $obj = $wom->getObject($obj_id);
                 $kv = explode('=', $text, 2);
                 if (count($kv) != 2) {
                     throw new MWException(__METHOD__ . ": value should be 'key=value' in attribute mode");
                 }
                 $obj->setXMLAttribute(trim($kv[0]), trim($kv[1]));
             }
         }
         $ep = new EditPage($articleObj);
         // EditPage wants to parse its stuff from a WebRequest
         // That interface kind of sucks, but it's workable
         $reqArr = array('wpTextbox1' => $wom->getWikiText(), 'wpEditToken' => $params['token'], 'wpIgnoreBlankSummary' => '', 'wpSection' => '');
         if (!is_null($params['summary'])) {
             $reqArr['wpSummary'] = $params['summary'];
         }
         // Watch out for basetimestamp == ''
         // wfTimestamp() treats it as NOW, almost certainly causing an edit conflict
         if (!is_null($params['basetimestamp']) && $params['basetimestamp'] != '') {
             $reqArr['wpEdittime'] = wfTimestamp(TS_MW, $params['basetimestamp']);
         } else {
             $reqArr['wpEdittime'] = $articleObj->getTimestamp();
         }
         if (!is_null($params['starttimestamp']) && $params['starttimestamp'] != '') {
             $reqArr['wpStarttime'] = wfTimestamp(TS_MW, $params['starttimestamp']);
         } else {
             $reqArr['wpStarttime'] = $reqArr['wpEdittime'];
         }
         // Fake wpStartime
         if ($params['minor'] || !$params['notminor'] && $wgUser->getOption('minordefault')) {
             $reqArr['wpMinoredit'] = '';
         }
         // Handle watchlist settings
         switch ($params['watchlist']) {
             case 'watch':
                 $watch = true;
                 break;
             case 'unwatch':
                 $watch = false;
                 break;
             case 'preferences':
                 if ($titleObj->exists()) {
                     $watch = $wgUser->getOption('watchdefault') || $titleObj->userIsWatching();
                 } else {
                     $watch = $wgUser->getOption('watchcreations');
                 }
                 break;
             case 'nochange':
             default:
                 $watch = $titleObj->userIsWatching();
         }
         // Deprecated parameters
         if ($params['watch']) {
             $watch = true;
         } elseif ($params['unwatch']) {
             $watch = false;
         }
         if ($watch) {
             $reqArr['wpWatchthis'] = '';
         }
         $req = new FauxRequest($reqArr, true);
         $ep->importFormData($req);
         // Run hooks
         // Handle CAPTCHA parameters
         global $wgRequest;
         if (!is_null($params['captchaid'])) {
             $wgRequest->setVal('wpCaptchaId', $params['captchaid']);
         }
         if (!is_null($params['captchaword'])) {
             $wgRequest->setVal('wpCaptchaWord', $params['captchaword']);
         }
         $r = array();
         if (!wfRunHooks('APIEditBeforeSave', array($ep, $ep->textbox1, &$r))) {
             if (count($r)) {
                 $r['result'] = "Failure";
                 $this->getResult()->addValue(null, $this->getModuleName(), $r);
                 return;
             } else {
                 $this->dieUsageMsg(array('hookaborted'));
             }
         }
         // Do the actual save
         $oldRevId = $articleObj->getRevIdFetched();
         $result = null;
         // Fake $wgRequest for some hooks inside EditPage
         // FIXME: This interface SUCKS
         $oldRequest = $wgRequest;
         $wgRequest = $req;
         $retval = $ep->internalAttemptSave($result, $wgUser->isAllowed('bot') && $params['bot']);
         $wgRequest = $oldRequest;
         switch ($retval) {
             case EditPage::AS_HOOK_ERROR:
             case EditPage::AS_HOOK_ERROR_EXPECTED:
                 $this->dieUsageMsg(array('hookaborted'));
             case EditPage::AS_IMAGE_REDIRECT_ANON:
                 $this->dieUsageMsg(array('noimageredirect-anon'));
             case EditPage::AS_IMAGE_REDIRECT_LOGGED:
                 $this->dieUsageMsg(array('noimageredirect-logged'));
             case EditPage::AS_SPAM_ERROR:
                 $this->dieUsageMsg(array('spamdetected', $result['spam']));
             case EditPage::AS_FILTERING:
                 $this->dieUsageMsg(array('filtered'));
             case EditPage::AS_BLOCKED_PAGE_FOR_USER:
                 $this->dieUsageMsg(array('blockedtext'));
             case EditPage::AS_MAX_ARTICLE_SIZE_EXCEEDED:
             case EditPage::AS_CONTENT_TOO_BIG:
                 global $wgMaxArticleSize;
                 $this->dieUsageMsg(array('contenttoobig', $wgMaxArticleSize));
             case EditPage::AS_READ_ONLY_PAGE_ANON:
                 $this->dieUsageMsg(array('noedit-anon'));
             case EditPage::AS_READ_ONLY_PAGE_LOGGED:
                 $this->dieUsageMsg(array('noedit'));
             case EditPage::AS_READ_ONLY_PAGE:
                 $this->dieReadOnly();
             case EditPage::AS_RATE_LIMITED:
                 $this->dieUsageMsg(array('actionthrottledtext'));
             case EditPage::AS_ARTICLE_WAS_DELETED:
                 $this->dieUsageMsg(array('wasdeleted'));
             case EditPage::AS_NO_CREATE_PERMISSION:
                 $this->dieUsageMsg(array('nocreate-loggedin'));
             case EditPage::AS_BLANK_ARTICLE:
                 $this->dieUsageMsg(array('blankpage'));
             case EditPage::AS_CONFLICT_DETECTED:
                 $this->dieUsageMsg(array('editconflict'));
                 // case EditPage::AS_SUMMARY_NEEDED: Can't happen since we set wpIgnoreBlankSummary
             // case EditPage::AS_SUMMARY_NEEDED: Can't happen since we set wpIgnoreBlankSummary
             case EditPage::AS_TEXTBOX_EMPTY:
                 $this->dieUsageMsg(array('emptynewsection'));
             case EditPage::AS_SUCCESS_NEW_ARTICLE:
                 $r['new'] = '';
             case EditPage::AS_SUCCESS_UPDATE:
                 $r['result'] = "Success";
                 $r['pageid'] = intval($titleObj->getArticleID());
                 $r['title'] = $titleObj->getPrefixedText();
                 // HACK: We create a new Article object here because getRevIdFetched()
                 // refuses to be run twice, and because Title::getLatestRevId()
                 // won't fetch from the master unless we select for update, which we
                 // don't want to do.
                 $newArticle = new Article($titleObj);
                 $newRevId = $newArticle->getRevIdFetched();
                 if ($newRevId == $oldRevId) {
                     $r['nochange'] = '';
                 } else {
                     $r['oldrevid'] = intval($oldRevId);
                     $r['newrevid'] = intval($newRevId);
                     $r['newtimestamp'] = wfTimestamp(TS_ISO_8601, $newArticle->getTimestamp());
                 }
                 break;
             case EditPage::AS_END:
                 // This usually means some kind of race condition
                 // or DB weirdness occurred. Fall through to throw an unknown
                 // error.
                 // This needs fixing higher up, as Article::doEdit should be
                 // used rather than Article::updateArticle, so that specific
                 // error conditions can be returned
             // This usually means some kind of race condition
             // or DB weirdness occurred. Fall through to throw an unknown
             // error.
             // This needs fixing higher up, as Article::doEdit should be
             // used rather than Article::updateArticle, so that specific
             // error conditions can be returned
             default:
                 $this->dieUsageMsg(array('unknownerror', $retval));
         }
         $this->getResult()->addValue(null, $this->getModuleName(), $r);
     } catch (Exception $e) {
         $this->dieUsage($e->getMessage(), 'WOM error');
     }
 }