Skip to content

Commit

Permalink
Merge pull request #91 from JindrichPilar/3.x
Browse files Browse the repository at this point in the history
Fix parseOutput undefined property (closes #90)
  • Loading branch information
JindrichPilar authored Jun 21, 2020
2 parents 550ea03 + 4afaf1c commit 801b7bb
Show file tree
Hide file tree
Showing 10 changed files with 198 additions and 19 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
### v3.0.0
* Požadována verze PHP >=7.2
* Změna namespace ``\Skautis`` je nyní ``\Skaut\Skautis``
* Místo prázdného objektu typu ``\stdClass`` se nyní vrací null pro jeden výsledek, nebo prazdne pole pokud se jednalo o dotaz vracející kolekci.
* Odstranění podpory pro HHVM (HHVM dále [nedodržuje kompabilitu s PHP](https://hhvm.com/blog/2018/09/12/end-of-php-support-future-of-hack.html))
* Scalar typehints pro metody
* [Strict types](http://php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration.strict) - zpětně nekompatibilní
Expand Down
8 changes: 4 additions & 4 deletions src/Wsdl/Event/RequestPostEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ class RequestPostEvent implements Serializable
private $time;

/**
* @var array|stdClass[]
* @var array<int|string, mixed>|\stdClass|null
*/
private $result;

/**
* @param string $fname Nazev volane funkce
* @param array<int, mixed> $args Argumenty pozadavku
* @param array|StdClass[] $result
* @param array<int|string, mixed>|stdClass|null $result
*/
public function __construct(
string $fname,
Expand Down Expand Up @@ -94,9 +94,9 @@ public function getDuration(): float
}

/**
* @return array|StdClass[]
* @return array<int|string, mixed>|\stdClass|null
*/
public function getResult(): array
public function getResult()
{
return $this->result;
}
Expand Down
14 changes: 14 additions & 0 deletions src/Wsdl/ParsingFailedException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

declare(strict_types=1);


namespace Skaut\Skautis\Wsdl;

/**
* Thrown when parsing Skautis response fails
*/
class ParsingFailedException extends WsdlException
{

}
105 changes: 95 additions & 10 deletions src/Wsdl/WebService.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public function __call(string $functionName, array $arguments)
* @param array<string, mixed> $options Nastaveni
* @param array<int, string> $inputHeaders Hlavicky pouzite pri odesilani
* @param array<int, string> $outputHeaders Hlavicky ktere prijdou s odpovedi
* @return mixed
* @return array<int|string, mixed>|stdClass|null
*/
protected function soapCall(
string $functionName,
Expand Down Expand Up @@ -161,23 +161,108 @@ protected function prepareArgs(string $functionName, array $arguments): array
* @param string $fname Jméno funkce volané přes SOAP
* @param mixed $ret Odpoveď ze SoapClient::__soapCall
*
* @return array<int|string, mixed>
* @return array<int|string, mixed>|\stdClass|null
*/
protected function parseOutput(string $fname, $ret): array
protected function parseOutput(string $fname, $ret)
{
//pokud obsahuje Output tak vždy vrací pole i s jedním prvkem.
$result = $ret->{$fname . 'Result'};

/*
Pokud se jedna o request ktery ma vracet jednu hodnotu a ta existuje, skautis vraci primo objekt odpovedi
Napriklad:
<UnitDetailResponse xmlns="https://is.skaut.cz/">
<UnitDetailResult>
data jednoho objektu
</UnitDetailResult>
</UnitDetailResponse>
To SoapClient naparsuje jako:
class stdClass#25 (1) {
public $UnitDetailResult =>
class stdClass#26 (48) {
data objectu
}
}
Pokud se jedna o request ktery ma vracet jednu hodnotu a ta neexistuje, skautis vraci jeden self-closing tag
Napriklad:
<UnitDetailResponse xmlns="https://is.skaut.cz/" />
To SoapClient naparsuje jako:
class stdClass#25 (0) {
}
Pokud se jedna o request ktery ma vracet vice hodnot, vraci *Result/*Output
Napriklad:
<UnitAllResponse xmlns="https://is.skaut.cz/">
<UnitAllResult>
<UnitAllOutput>
data jednoho objektu
</UnitAllOutput>
<UnitAllOutput>
data dalsiho objektu
</UnitAllOutput>
</UnitAllResult>
</UnitAllResponse>
To SoapClient naparsuje jako:
class stdClass#25 (1) {
public $UnitAllResult =>
class stdClass#26 (1) {
public $UnitAllOutput =>
array(2) {
stdClass - data jednoho objektu,
stdClass - data dalsiho objektu,
}
}
}
}
Pokud se jedna o request ktery ma vracet vice hodnot, vraci klasickou dvojici tagu
Napriklad:
<UnitAllResponse xmlns="https://is.skaut.cz/">
<UnitAllResult />
</UnitAllResponse>
To SoapClient naparsuje jako:
class stdClass#25 (1) {
public $UnitAllResult =>
class stdClass#26 (0) {
}
}
*/

if (!$ret) {
throw new ParsingFailedException('Unexpected output from Skautis');
}

// Pokud byl vracen prazdny objekt predstavujici neexistujici vec
if ($ret instanceof stdClass && count((array) $ret) === 0) {
return null;
}

// Pokud obsahuje *Result pak se bud jedna o existujici jeden objekt, vice objektu nebo prazdny seznam objektu
$result = $ret->{$fname . 'Result'} ?? null;
if (!isset($result)) {
return $ret;
throw new ParsingFailedException('Unexpected output from Skautis');
}

$output = $result->{$fname . 'Output'};
$output = $result->{$fname . 'Output'} ?? null;
// Pokud obsahuje *Result, ale zadny *Output pak se jedna o jeden
if (!isset($output)) {
return $result; //neobsahuje $fname.Output
// Vraci prazdny object
if ($result instanceof stdClass && count((array) $result) === 0) {
return [];
}

return $result;
}

if ($output instanceof stdClass) { //vraci pouze jednu hodnotu misto pole?
return [$output]; //vraci pole se stdClass
// Vraci pouze jednu hodnotu misto pole?
if ($output instanceof stdClass) {
return [$output];
}

return $output; //vraci pole se stdClass
Expand Down
5 changes: 0 additions & 5 deletions tests/Unit/SkautisTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,4 @@ public function testGetRegisterURL(): void {
$this->assertEquals($urlEncodedAddress, $skautis->getRegisterUrl());
}

public function testEventSetter(): void
{
$this->markTestSkipped();
//@TODO
}
}
80 changes: 80 additions & 0 deletions tests/Unit/WebService/ParsingSOAPOutputTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php

declare(strict_types=1);


namespace Skaut\Skautis\Test\Unit\WebService;



use PHPUnit\Framework\TestCase;
use Skaut\Skautis\Wsdl\WebService;
use Skaut\Skautis\Wsdl\WebServiceInterface;

class ParsingSOAPOutputTest extends TestCase
{

protected function tearDown(): void
{
\Mockery::close();
}

private function loadData(string $methodName): \stdClass {
$filePath = __DIR__.'/resources/'.$methodName.'.txt';

if (!file_exists($filePath) || !is_readable($filePath)) {
throw new \RuntimeException("Cannot access file '$filePath'");
}

$text = file_get_contents($filePath);

return unserialize($text, ['allowed_classes' => [\stdClass::class]]);
}

private function createMockedWebService(\stdClass $data): WebServiceInterface {
$client = \Mockery::mock(\SoapClient::class);
$client->shouldReceive('__soapCall')->once()->andReturn($data);

return new WebService($client, [], null);
}

public function testObjectForExistentRecord(): void {
$service = $this->createMockedWebService($this->loadData(__FUNCTION__));

$result = $service->unitDetail(['ID' => 24404]);

$this->assertNotNull($result);
$this->assertInstanceOf(\stdClass::class, $result);
$this->assertSame('Středisko', $result->UnitType);
}

public function testNullForNonExistentRecord(): void {
$service = $this->createMockedWebService($this->loadData(__FUNCTION__));

$result = $service->unitDetail(['ID' => 999]);

$this->assertNull($result);
}

public function testArrayOfResults(): void {
$service = $this->createMockedWebService($this->loadData(__FUNCTION__));

$results = $service->unitAll(['ID_UnitParent' => 24404]);

$this->assertIsArray($results);
$this->assertCount(5, $results);

foreach ($results as $result) {
$this->assertInstanceOf(\stdClass::class, $result);
}
}

public function testEmptyArrayOfResults(): void {
$service = $this->createMockedWebService($this->loadData(__FUNCTION__));

$result = $service->unitAll(['ID_UnitParent' => 999]);

$this->assertIsArray($result);
$this->assertCount(0, $result);
}
}
1 change: 1 addition & 0 deletions tests/Unit/WebService/resources/testArrayOfResults.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
O:8:"stdClass":1:{s:13:"UnitAllResult";O:8:"stdClass":1:{s:13:"UnitAllOutput";a:5:{i:0;O:8:"stdClass":21:{s:2:"ID";i:24405;s:8:"ID_Group";i:762137;s:11:"ID_UnitType";s:5:"oddil";s:8:"UnitType";s:6:"Oddíl";s:11:"DisplayName";s:11:"Medvíďata";s:8:"SortName";s:26:"621.24.024-1 - Medvíďata";s:18:"RegistrationNumber";s:12:"621.24.024-1";s:23:"ShortRegistrationNumber";s:5:"024-1";s:8:"Location";s:7:"BLANSKO";s:2:"IC";s:0:"";s:6:"Street";s:16:"Pod Resslem 1978";s:11:"PostalState";s:0:"";s:4:"City";s:7:"BLANSKO";s:8:"Postcode";s:5:"67902";s:5:"State";s:17:"Česká republika";s:15:"PostalFirstLine";s:0:"";s:12:"PostalStreet";s:0:"";s:10:"PostalCity";s:0:"";s:14:"PostalPostcode";s:0:"";s:4:"Note";s:0:"";s:15:"FullDisplayName";s:11:"Medvíďata";}i:1;O:8:"stdClass":21:{s:2:"ID";i:24406;s:8:"ID_Group";i:762138;s:11:"ID_UnitType";s:5:"oddil";s:8:"UnitType";s:6:"Oddíl";s:11:"DisplayName";s:10:"Permoníci";s:8:"SortName";s:25:"621.24.024-2 - Permoníci";s:18:"RegistrationNumber";s:12:"621.24.024-2";s:23:"ShortRegistrationNumber";s:5:"024-2";s:8:"Location";s:7:"BLANSKO";s:2:"IC";s:0:"";s:6:"Street";s:18:"Na Drážkách 941";s:11:"PostalState";s:0:"";s:4:"City";s:7:"BLANSKO";s:8:"Postcode";s:5:"67902";s:5:"State";s:17:"Česká republika";s:15:"PostalFirstLine";s:0:"";s:12:"PostalStreet";s:0:"";s:10:"PostalCity";s:0:"";s:14:"PostalPostcode";s:0:"";s:4:"Note";s:0:"";s:15:"FullDisplayName";s:10:"Permoníci";}i:2;O:8:"stdClass":21:{s:2:"ID";i:24407;s:8:"ID_Group";i:762139;s:11:"ID_UnitType";s:5:"oddil";s:8:"UnitType";s:6:"Oddíl";s:11:"DisplayName";s:9:"3. oddíl";s:8:"SortName";s:24:"621.24.024-3 - 3. oddíl";s:18:"RegistrationNumber";s:12:"621.24.024-3";s:23:"ShortRegistrationNumber";s:5:"024-3";s:8:"Location";s:7:"BLANSKO";s:2:"IC";s:0:"";s:6:"Street";s:17:"Vrchlického 2535";s:11:"PostalState";s:0:"";s:4:"City";s:7:"BLANSKO";s:8:"Postcode";s:5:"67902";s:5:"State";s:17:"Česká republika";s:15:"PostalFirstLine";s:0:"";s:12:"PostalStreet";s:0:"";s:10:"PostalCity";s:0:"";s:14:"PostalPostcode";s:0:"";s:4:"Note";s:0:"";s:15:"FullDisplayName";s:9:"3. oddíl";}i:3;O:8:"stdClass":21:{s:2:"ID";i:24408;s:8:"ID_Group";i:762140;s:11:"ID_UnitType";s:5:"oddil";s:8:"UnitType";s:6:"Oddíl";s:11:"DisplayName";s:6:"Zámek";s:8:"SortName";s:21:"621.24.024-4 - Zámek";s:18:"RegistrationNumber";s:12:"621.24.024-4";s:23:"ShortRegistrationNumber";s:5:"024-4";s:8:"Location";s:7:"BLANSKO";s:2:"IC";s:0:"";s:6:"Street";s:16:"U včelína 1192";s:11:"PostalState";s:0:"";s:4:"City";s:7:"BLANSKO";s:8:"Postcode";s:5:"67902";s:5:"State";s:17:"Česká republika";s:15:"PostalFirstLine";s:0:"";s:12:"PostalStreet";s:0:"";s:10:"PostalCity";s:0:"";s:14:"PostalPostcode";s:0:"";s:4:"Note";s:0:"";s:15:"FullDisplayName";s:6:"Zámek";}i:4;O:8:"stdClass":21:{s:2:"ID";i:24409;s:8:"ID_Group";i:762141;s:11:"ID_UnitType";s:5:"oddil";s:8:"UnitType";s:6:"Oddíl";s:11:"DisplayName";s:9:"Jitřenky";s:8:"SortName";s:24:"621.24.024-5 - Jitřenky";s:18:"RegistrationNumber";s:12:"621.24.024-5";s:23:"ShortRegistrationNumber";s:5:"024-5";s:8:"Location";s:7:"BLANSKO";s:2:"IC";s:0:"";s:6:"Street";s:14:"Jarošova 1137";s:11:"PostalState";s:0:"";s:4:"City";s:7:"BLANSKO";s:8:"Postcode";s:5:"67902";s:5:"State";s:17:"Česká republika";s:15:"PostalFirstLine";s:0:"";s:12:"PostalStreet";s:0:"";s:10:"PostalCity";s:0:"";s:14:"PostalPostcode";s:0:"";s:4:"Note";s:0:"";s:15:"FullDisplayName";s:9:"Jitřenky";}}}}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
O:8:"stdClass":1:{s:13:"UnitAllResult";O:8:"stdClass":0:{}}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
O:8:"stdClass":0:{}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
O:8:"stdClass":1:{s:16:"UnitDetailResult";O:8:"stdClass":48:{s:8:"ID_Login";s:36:"00000000-0000-0000-0000-000000000000";s:2:"ID";i:24404;s:8:"ID_Group";i:762136;s:7:"ID_Unit";i:0;s:11:"ID_UnitType";s:9:"stredisko";s:8:"UnitType";s:10:"Středisko";s:15:"ContainsMembers";b:1;s:18:"CommissionDeadline";i:14;s:11:"DisplayName";s:15:"Žlutý kvítek";s:8:"SortName";s:24:"621.24 - Žlutý kvítek";s:18:"RegistrationNumber";s:6:"621.24";s:23:"ShortRegistrationNumber";s:6:"621.24";s:8:"Location";s:7:"BLANSKO";s:2:"IC";s:8:"11225073";s:10:"IsVatPayer";b:1;s:3:"DIC";s:10:"CZ11225073";s:6:"Street";s:14:"Bezručova 556";s:4:"City";s:7:"BLANSKO";s:8:"Postcode";s:5:"67902";s:5:"State";s:17:"Česká republika";s:15:"PostalFirstLine";s:0:"";s:12:"PostalStreet";s:0:"";s:10:"PostalCity";s:0:"";s:14:"PostalPostcode";s:0:"";s:11:"PostalState";s:0:"";s:4:"Note";s:0:"";s:11:"ID_TroopArt";N;s:27:"CanUpdateRegistrationNumber";b:0;s:12:"IsUnitCancel";b:1;s:13:"JournalParent";b:1;s:17:"ChangeFreeJournal";b:1;s:13:"ID_UnitParent";i:23506;s:12:"OnlyValidate";N;s:21:"IsPostalAuthenticated";N;s:22:"IsAddressAuthenticated";N;s:15:"AddressDistrict";s:7:"Blansko";s:14:"NewDisplayName";s:15:"Žlutý kvítek";s:19:"CompleteDisplayName";s:48:"Junák - český skaut, Žlutý kvítek, , z. s.";s:19:"ID_PersonChangeName";N;s:14:"DateChangeName";N;s:15:"IsPropertyOwner";b:0;s:28:"ID_TempFilePropertyAgreement";N;s:16:"ID_JournalNovice";s:3:"all";s:22:"ID_JournalDeliveryType";s:6:"single";s:15:"FullDisplayName";s:46:"Junák - český skaut, Žlutý kvítek, z. s.";s:19:"ID_DocumentDecision";N;s:28:"ID_DocumentPropertyAgreement";N;s:21:"ID_TempFileSeatChange";N;}}

0 comments on commit 801b7bb

Please sign in to comment.