API:Vnitřní volání

From mediawiki.org
This page is a translated version of the page API:Calling internally and the translation is 100% complete.

API lze volat interně z PHP, aniž by bylo nutné procházet HTTP požadavkem.

Aplikační logika by se tomu však měla vyhnout a místo toho, aby procházela rozhraním API, měla přímý přístup k třídám PHP, které jsou zodpovědné za příslušnou funkcionalitu.

Interní volání API by se obecně mělo používat pouze pro účely testování a rychlého prototypování.

Z kódu testovací sady

Chcete-li volat rozhraní API z testů, nejjednodušším způsobem je rozšířit třídu testu z ApiTestCase (spíše než MediaWikiTestCase). Poté můžete použít ApiTestCase::doApiRequest() následovně.

$result = $this->doApiRequest( [
	'action'     => 'edit',
	'title'      => 'Test_page',
	'appendtext' => 'Testing editing.',
	'token'      => $user->getEditToken(),
] );

Takto by se měly provádět testy API, ale někdy chcete, aby test použil API, abyste mohli nastavit další testy, které nejsou skutečnými testy API. V tomto případě pravděpodobně nebudete chtít dědit z ApiTestCase.

V této situaci musí být požadavek sestaven podrobněji, protože token pro úpravy musí být uložen v relaci. V tomto případě je globální $wgRequest FauxRequest, který je již nakonfigurován testovacím kabelem.

global $wgRequest;
$user = parent::getTestSysop()->getUser();
$this->assertTrue($user->isRegistered());
$apiParams = [
	'action'     => 'edit',
	'title'      => 'Test_page',
	'appendtext' => 'Testing editing.',
	'token'      => $user->getEditToken(),
];
$apiRequest = new FauxRequest( $apiParams, true, $wgRequest->getSessionArray() );
$context = new DerivativeContext( new RequestContext() );
$context->setRequest( $apiRequest );
$context->setUser( $user );
$api = new ApiMain( $context, true );
$result = $api->execute();


Z kódu aplikace

Interní volání API je často známkou toho, že některé funkce by měly být přepracovány do backendové třídy, kterou může používat váš kód i modul API. V novém výrobním kódu se to odrazuje a je považováno za technický dluh. Viz Architecture guidelines#Separation of concerns — UI and business logic. Existují však některé přijatelné případy, kdy je tato technika přijatelná: jednotkové a funkční testy.
Pokud váš kód provádí předem určené úpravy a nepotřebuje dezinfikovat uživatelský vstup, projít filtrem zneužití atd., zvažte použití WikiPage ::doUserEditContent() místo požadavku API.

Někdy si jiný PHP kód může přát použít funkci přístupu k datům a agregaci akčního API. Namísto odesílání síťového požadavku HTTP na stejný server můžete zavolat v rámci PHP.

Postup je následující:

1) Pokud provádíte v kontextu existujícího požadavku od uživatele, připravte parametry požadavku pomocí třídy DerivativeRequest.

  • Prvním parametrem jeho konstruktoru je požadavek, ze kterého se má odvodit.
  • Druhým parametrem jeho konstruktoru je pole parametrů API, které je stejné, jako když požadavek zadáváte přes web.
  • Třetí parametr jeho konstruktoru je volitelný, zadejte true, aby bylo volání API považováno za POST, když modul API, který vyvoláváte, vyžaduje požadavky POST.

Tento ukázkový kód vydá dotaz na seznam 'allpages' začínající písmenem 'M'. Toto je jednoduchý dotaz, který nevyžaduje uživatele ani POST.

$params = new DerivativeRequest(
	$this->getRequest(), // Fallback upon $wgRequest if you can't access context.
	array(
		'action' => 'query',
		'list' => 'allpages',
		'apnamespace' => 0,
		'aplimit' => 10, 
		'apprefix' => 'M'
	)
);

Pokud potřebujete poskytnout token pro úpravy jako parametr API při provádění úprav nebo jiných změn, můžete token pro úpravy získat takto:

$user = $this->getUser(); // Or User::newFromName, etc.
$token = $user->getEditToken();

2) Vytvořte instanci ApiMain. Poté spusťte požadavek API. Protože parametr je objekt DerivativeRequest, ApiMain nespustí žádné formátovací tiskárny ani nezpracuje žádné chyby. Chyba parametru nebo jakákoli jiná interní chyba způsobí výjimku, která může být zachycena ve volajícím kódu.

$api = new ApiMain( $params );
$api->execute();

Důležité: Pokud chcete vytvářet nebo upravovat stránky, musíte při vytváření ApiMain object předat true jako druhý parametr:

$api = new ApiMain( $params, true ); // default is false
$api->execute();

3) Získejte výsledné datové pole.

$data = $api->getResult()->getResultData();

Zde je úplný příklad převzatý z Extension:WikiLove (od r112758). Přidává text na stránku, takže se musí spustit při zpracování HTTP požadavku přihlášeného uživatele.

	$api = new ApiMain(
		new DerivativeRequest(
			$this->getRequest(), // Fallback upon $wgRequest if you can't access context
			array(
				'action'     => 'edit',
				'title'      => $talk->getFullText(),
				'appendtext' => ( $talk->exists() 
				                  ? "\n\n" 
				                  : '' ) .
					wfMsgForContent( 'newsectionheaderdefaultlevel', 
						$params['subject'] )
						"\n\n" . $params['text'],
				'token'      => $params['token'],
				'summary'    => wfMsgForContent( 'wikilove-summary',
					$wgParser->stripSectionName( $params['subject'] ) ),
				'notminor'   => true
			),
			true // treat this as a POST
		),
		true // Enable write.
	);

	$api->execute();

FauxRequest

Výše uvedený příklad vytvoří DerivativeRequest RequestContext . To "zdědí" část původního požadavku, jako je IP a hlavičky požadavků, které jsou nastaveny, když MediaWiki provádí akci jménem uživatele, obvykle při zpracování webového požadavku. Pokud neexistuje žádný kontext požadavku uživatele, například při vyvolání API akce ze systémového procesu, nebo pokud chcete vytvořit zcela samostatný interní požadavek, můžete místo toho použít FauxRequest.

Použití FauxRequest pro operace zápisu bez předání kontextu požadavku způsobí chybu T36838.

Zpracování chyb

Pokud jsou předány neplatné parametry, může API akce vyhodit UsageException. Pokud je možné, že váš kód odešle neplatný parametr, měli byste pravděpodobně zavolat API zevnitř bloku try/catch


Související odkazy