migrate therinaldos.com data
Build & Deploy to DigitalOcean Space / build (push) Failing after 2m38s

This commit is contained in:
2024-05-05 15:50:45 -04:00
commit ef1ff240d4
23182 changed files with 3801898 additions and 0 deletions
@@ -0,0 +1,172 @@
<?php
declare(strict_types=1);
/**
* Circles - Bring cloud-users closer together.
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2022
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Circles\Tools\Model;
use OCP\Http\Client\IClient;
class NCRequest extends Request {
/** @var IClient */
private $client;
/** @var array */
private $clientOptions = [];
/** @var bool */
private $localAddressAllowed = false;
/** @var NCRequestResult */
private $result;
/** @var NCRequestResult[] */
private $previousResults = [];
/**
* @param IClient $client
*
* @return $this
*/
public function setClient(IClient $client): self {
$this->client = $client;
return $this;
}
/**
* @return IClient
*/
public function getClient(): IClient {
return $this->client;
}
/**
* @return array
*/
public function getClientOptions(): array {
return $this->clientOptions;
}
/**
* @param array $clientOptions
*
* @return self
*/
public function setClientOptions(array $clientOptions): self {
$this->clientOptions = $clientOptions;
return $this;
}
/**
* @return bool
*/
public function isLocalAddressAllowed(): bool {
return $this->localAddressAllowed;
}
/**
* @param bool $allowed
*
* @return self
*/
public function setLocalAddressAllowed(bool $allowed): self {
$this->localAddressAllowed = $allowed;
return $this;
}
/**
* @return bool
*/
public function hasResult(): bool {
return ($this->result !== null);
}
/**
* @return NCRequestResult
*/
public function getResult(): NCRequestResult {
return $this->result;
}
/**
* @param NCRequestResult $result
*
* @return self
*/
public function setResult(NCRequestResult $result): self {
if (!is_null($this->result)) {
$this->previousResults[] = $this->result;
}
$this->result = $result;
return $this;
}
/**
* @return NCRequestResult[]
*/
public function getPreviousResults(): array {
return $this->previousResults;
}
/**
* @return NCRequestResult[]
*/
public function getAllResults(): array {
return array_values(array_merge([$this->getResult()], $this->previousResults));
}
/**
* @return array
*/
public function jsonSerialize(): array {
$result = null;
if ($this->hasResult()) {
$result = $this->getResult();
}
return array_merge(
parent::jsonSerialize(),
[
'clientOptions' => $this->getClientOptions(),
'localAddressAllowed' => $this->isLocalAddressAllowed(),
'result' => $result
]
);
}
}
@@ -0,0 +1,321 @@
<?php
declare(strict_types=1);
/**
* Circles - Bring cloud-users closer together.
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2022
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Circles\Tools\Model;
use GuzzleHttp\Exception\BadResponseException;
use JsonSerializable;
use OCA\Circles\Tools\Exceptions\RequestContentException;
use OCA\Circles\Tools\Traits\TArrayTools;
use OCP\Http\Client\IResponse;
class NCRequestResult implements JsonSerializable {
use TArrayTools;
public const TYPE_STRING = 0;
public const TYPE_BINARY = 1;
public const TYPE_JSON = 2;
public const TYPE_XRD = 3;
/** @var int */
private $statusCode = 0;
/** @var array */
private $headers = [];
/** @var mixed */
private $content;
/** @var array */
private $contentAsArray = [];
/** @var int */
private $contentType = 0;
/** @var BadResponseException */
private $exception = null;
/**
* NCRequestResult constructor.
*
* @param IResponse|null $response
* @param BadResponseException|null $e
*/
public function __construct(?IResponse $response, ?BadResponseException $e = null) {
if (!is_null($response)) {
$this->setStatusCode($response->getStatusCode());
$this->setContent($response->getBody());
$this->setHeaders($response->getHeaders());
}
if (!is_null($e)) {
$this->setException($e);
}
$this->generateMeta();
}
/**
* @return int
*/
public function getStatusCode(): int {
return $this->statusCode;
}
/**
* @param int $statusCode
*
* @return self
*/
public function setStatusCode(int $statusCode): self {
$this->statusCode = $statusCode;
return $this;
}
/**
* @return array
*/
public function getHeaders(): array {
return $this->headers;
}
/**
* @param array $headers
*
* @return self
*/
public function setHeaders(array $headers): self {
$this->headers = $headers;
return $this;
}
/**
* @param string $key
*
* @return array
*/
public function getHeader(string $key): array {
return $this->getArray($key, $this->headers);
}
public function withinHeader(string $key, string $needle): bool {
foreach ($this->getHeader($key) as $header) {
if (strpos($header, $needle) !== false) {
return true;
}
}
return false;
}
/**
* @param string $content
*
* @return self
*/
public function setContent(string $content): self {
$this->content = $content;
return $this;
}
/**
* @return string
* @throws RequestContentException
*/
public function getContent(): string {
if (is_null($this->content) || !is_string($this->content)) {
throw new RequestContentException();
}
return $this->content;
}
/**
* @return array
*/
public function getAsArray(): array {
if (empty($this->contentAsArray)) {
$this->generateContentAsArray();
}
return $this->contentAsArray;
}
/**
* @return string
*/
public function getBinary() {
return $this->content;
}
/**
* @return int
*/
public function getContentType(): int {
return $this->contentType;
}
/**
* @param int $type
*
* @return $this
*/
public function setContentType(int $type): self {
$this->contentType = $type;
return $this;
}
/**
* @param int $type
*
* @return bool
*/
public function isContentType(int $type): bool {
return ($this->contentType === $type);
}
/**
*
*/
private function generateMeta(): void {
$this->setContentType($this->discoverContentType());
$this->generateContentAsArray();
}
/**
* @return int
*/
private function discoverContentType(): int {
if ($this->withinHeader('Content-Type', 'application/xrd')) {
return self::TYPE_XRD;
}
if ($this->withinHeader('Content-Type', 'application/json')
|| $this->withinHeader('Content-Type', 'application/jrd')
) {
return self::TYPE_JSON;
}
try {
$content = $this->getContent();
} catch (RequestContentException $e) {
return self::TYPE_BINARY;
}
// in case header failure
$arr = json_decode($content, true);
if (is_array($arr)) {
return self::TYPE_JSON;
}
return self::TYPE_STRING;
}
/**
*
*/
private function generateContentAsArray(): void {
try {
$content = $this->getContent();
if ($this->isContentType(self::TYPE_XRD)) {
$xml = simplexml_load_string($content);
$content = json_encode($xml, JSON_UNESCAPED_SLASHES);
}
$arr = json_decode($content, true);
if (is_array($arr)) {
$this->contentAsArray = $arr;
}
} catch (RequestContentException $e) {
}
}
/**
* @param BadResponseException $e
*
* @return self
*/
public function setException(BadResponseException $e): self {
$this->exception = $e;
$this->setStatusCode($e->getResponse()->getStatusCode());
return $this;
}
/**
* @return BadResponseException
*/
public function getException(): BadResponseException {
return $this->exception;
}
/**
* @return bool
*/
public function hasException(): bool {
return (!is_null($this->exception));
}
/**
* @return array
*/
public function jsonSerialize(): array {
try {
$content = $this->getContent();
} catch (RequestContentException $e) {
$content = 'not a string';
}
return [
'statusCode' => $this->getStatusCode(),
'headers' => $this->getHeaders(),
'content' => $content,
'contentAsArray' => $this->contentAsArray,
'contentType' => $this->getContentType()
];
}
}
@@ -0,0 +1,293 @@
<?php
declare(strict_types=1);
/**
* Circles - Bring cloud-users closer together.
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2022
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Circles\Tools\Model;
use JsonSerializable;
use OCA\Circles\Tools\Traits\TArrayTools;
class NCSignatory implements JsonSerializable {
use TArrayTools;
public const SHA256 = 'sha256';
public const SHA512 = 'sha512';
/** @var string */
private $instance = '';
/** @var string */
private $id = '';
/** @var string */
private $keyOwner = '';
/** @var string */
private $keyId = '';
/** @var string */
private $publicKey = '';
/** @var string */
private $privateKey = '';
/** @var array */
private $origData = [];
/** @var string */
private $algorithm = self::SHA256;
/**
* NC22Signatory constructor.
*
* @param string $id
*/
public function __construct(string $id = '') {
$this->id = self::removeFragment($id);
}
/**
* @param string $instance
*
* @return self
*/
public function setInstance(string $instance): self {
$this->instance = $instance;
return $this;
}
/**
* @return string
*/
public function getInstance(): string {
return $this->instance;
}
/**
* @return array
*/
public function getOrigData(): array {
return $this->origData;
}
/**
* /**
* @param array $data
*
* @return $this
*/
public function setOrigData(array $data): self {
$this->origData = $data;
return $this;
}
/**
* @return string
*/
public function getId(): string {
return $this->id;
}
/**
* @param string $id
*
* @return self
*/
public function setId(string $id): self {
$this->id = $id;
return $this;
}
/**
* @param string $keyId
*
* @return self
*/
public function setKeyId(string $keyId): self {
$this->keyId = $keyId;
return $this;
}
/**
* @return string
*/
public function getKeyId(): string {
return $this->keyId;
}
/**
* @param string $keyOwner
*
* @return self
*/
public function setKeyOwner(string $keyOwner): self {
$this->keyOwner = $keyOwner;
return $this;
}
/**
* @return string
*/
public function getKeyOwner(): string {
return $this->keyOwner;
}
/**
* @param string $publicKey
*
* @return self
*/
public function setPublicKey(string $publicKey): self {
$this->publicKey = $publicKey;
return $this;
}
/**
* @param string $privateKey
*
* @return self
*/
public function setPrivateKey(string $privateKey): self {
$this->privateKey = $privateKey;
return $this;
}
/**
* @return string
*/
public function getPublicKey(): string {
return $this->publicKey;
}
/**
* @return string
*/
public function getPrivateKey(): string {
return $this->privateKey;
}
/**
* @return bool
*/
public function hasPublicKey(): bool {
return ($this->publicKey !== '');
}
/**
* @return bool
*/
public function hasPrivateKey(): bool {
return ($this->privateKey !== '');
}
/**
* @param string $algorithm
*
* @return self
*/
public function setAlgorithm(string $algorithm): self {
$this->algorithm = $algorithm;
return $this;
}
/**
* @return string
*/
public function getAlgorithm(): string {
return $this->algorithm;
}
/**
* @param array $data
*
* @return $this
*/
public function import(array $data): self {
if ($this->getId() === '') {
$this->setId($this->get('id', $data));
}
$this->setKeyId($this->get('publicKey.id', $data));
$this->setKeyOwner($this->get('publicKey.owner', $data));
$this->setPublicKey($this->get('publicKey.publicKeyPem', $data));
return $this;
}
/**
* @return array
*/
public function jsonSerialize(): array {
return [
'id' => $this->getId(),
'publicKey' =>
[
'id' => $this->getKeyId(),
'owner' => $this->getKeyOwner(),
'publicKeyPem' => $this->getPublicKey()
]
];
}
/**
* @param string $id
*
* @return string
*/
public static function removeFragment(string $id): string {
$temp = strtok($id, '#');
if (is_string($temp)) {
$id = $temp;
}
return $id;
}
}
@@ -0,0 +1,346 @@
<?php
declare(strict_types=1);
/**
* Circles - Bring cloud-users closer together.
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2022
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Circles\Tools\Model;
use JsonSerializable;
use OCP\IRequest;
class NCSignedRequest implements JsonSerializable {
/** @var string */
private $body = '';
/** @var int */
private $time = 0;
/** @var IRequest */
private $incomingRequest;
/** @var NCRequest */
private $outgoingRequest;
/** @var string */
private $origin = '';
/** @var string */
private $digest = '';
/** @var SimpleDataStore */
private $signatureHeader;
/** @var string */
private $host = '';
/** @var string */
private $clearSignature = '';
/** @var string */
private $signedSignature = '';
/** @var NCSignatory */
private $signatory;
public function __construct(string $body = '') {
$this->setBody($body);
}
/**
* IRequest of the incoming request
* incoming
*
* @return IRequest
*/
public function getIncomingRequest(): IRequest {
return $this->incomingRequest;
}
/**
* @param IRequest $request
*
* @return NCSignedRequest
*/
public function setIncomingRequest(IRequest $request): self {
$this->incomingRequest = $request;
return $this;
}
/**
* NCRequest of the outgoing request
* outgoing
*
* @param NCRequest $request
*
* @return NCSignedRequest
*/
public function setOutgoingRequest(NCRequest $request): self {
$this->outgoingRequest = $request;
return $this;
}
/**
* @return NCRequest
*/
public function getOutgoingRequest(): NCRequest {
return $this->outgoingRequest;
}
/**
* Body content of the request
* incoming/outgoing
*
* @return string
*/
public function getBody(): string {
return $this->body;
}
/**
* @param string $body
*
* @return self
*/
public function setBody(string $body): self {
$this->body = $body;
$this->setDigest('SHA-256=' . base64_encode(hash("sha256", utf8_encode($body), true)));
return $this;
}
/**
* Timestamp of the request
* incoming (outgoing ?)
*
* @return int
*/
public function getTime(): int {
return $this->time;
}
/**
* @param int $time
*
* @return self
*/
public function setTime(int $time): self {
$this->time = $time;
return $this;
}
/**
* Origin of the request, based on the keyId
* incoming
*
* @return string
*/
public function getOrigin(): string {
return $this->origin;
}
/**
* @param string $origin
*
* @return self
*/
public function setOrigin(string $origin): self {
$this->origin = $origin;
return $this;
}
/**
* @return string
*/
public function getDigest(): string {
return $this->digest;
}
/**
* @param string $digest
*
* @return $this
*/
public function setDigest(string $digest): self {
$this->digest = $digest;
return $this;
}
/**
* Data from the 'Signature' header
* incoming/outgoing
*
* @return SimpleDataStore
*/
public function getSignatureHeader(): SimpleDataStore {
return $this->signatureHeader;
}
/**
* @param SimpleDataStore $signatureHeader
*
* @return self
*/
public function setSignatureHeader(SimpleDataStore $signatureHeader): self {
$this->signatureHeader = $signatureHeader;
return $this;
}
/**
* _Clear_ value of the Signature.
* incoming/outgoing
*
* - estimated signature on incoming request
* - generated signature on outgoing request
*
* @param string $clearSignature
*
* @return NCSignedRequest
*/
public function setClearSignature(string $clearSignature): self {
$this->clearSignature = $clearSignature;
return $this;
}
/**
* @return string
*/
public function getClearSignature(): string {
return $this->clearSignature;
}
/**
* _Signed_ value of the signature.
* /!\ base64_encoded, not RAW /!\
*
* incoming/outgoing
*
* @param string $signedSignature
*
* @return self
*/
public function setSignedSignature(string $signedSignature): self {
$this->signedSignature = $signedSignature;
return $this;
}
/**
* @return string
*/
public function getSignedSignature(): string {
return $this->signedSignature;
}
/**
* Host/Address to be used in the signature.
* incoming/outgoing
*
* - incoming should set the local address
* - outgoing should set the recipient address
*
* @param string $host
*
* @return NCSignedRequest
*/
public function setHost(string $host): self {
$this->host = $host;
return $this;
}
/**
* @return string
*/
public function getHost(): string {
return $this->host;
}
/**
* Signatory used to sign the request
* incoming/outgoing
*
* @param NCSignatory $signatory
*/
public function setSignatory(NCSignatory $signatory): void {
$this->signatory = $signatory;
}
/**
* @return NCSignatory
*/
public function getSignatory(): NCSignatory {
return $this->signatory;
}
/**
* @return bool
*/
public function hasSignatory(): bool {
return ($this->signatory !== null);
}
/**
* @return array
*/
public function jsonSerialize(): array {
return [
'body' => $this->getBody(),
'time' => $this->getTime(),
'incomingRequest' => ($this->incomingRequest !== null),
'outgoingRequest' => $this->outgoingRequest !== null ? $this->getOutgoingRequest() : false,
'origin' => $this->getOrigin(),
'digest' => $this->getDigest(),
'signatureHeader' => ($this->signatureHeader !== null) ? $this->getSignatureHeader() : false,
'host' => $this->getHost(),
'clearSignature' => $this->getClearSignature(),
'signedSignature' => base64_encode($this->getSignedSignature()),
'signatory' => ($this->hasSignatory()) ? $this->getSignatory() : false,
];
}
}
@@ -0,0 +1,197 @@
<?php
/*
* Circles - Bring cloud-users closer together.
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2017
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
declare(strict_types=1);
/**
* Circles - Bring cloud-users closer together.
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2022
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Circles\Tools\Model;
use JsonSerializable;
use OCA\Circles\Tools\Traits\TArrayTools;
class NCWebfinger implements JsonSerializable {
use TArrayTools;
/** @var string */
private $subject = '';
/** @var array */
private $aliases = [];
/** @var array */
private $properties = [];
/** @var NCWellKnownLink[] */
private $links = [];
/**
* NC22Webfinger constructor.
*
* @param array $json
*/
public function __construct(array $json = []) {
$this->setSubject($this->get('subject', $json));
$this->setAliases($this->getArray('subject', $json));
$this->setProperties($this->getArray('properties', $json));
foreach ($this->getArray('links', $json) as $link) {
$this->addLink(new NCWellKnownLink($link));
}
}
/**
* @return string
*/
public function getSubject(): string {
return $this->subject;
}
/**
* @param string $subject
*
* @return self
*/
public function setSubject(string $subject): self {
$this->subject = $subject;
return $this;
}
/**
* @return array
*/
public function getAliases(): array {
return $this->aliases;
}
/**
* @param array $aliases
*
* @return self
*/
public function setAliases(array $aliases): self {
$this->aliases = $aliases;
return $this;
}
/**
* @return array
*/
public function getProperties(): array {
return $this->properties;
}
/**
* @param array $properties
*
* @return self
*/
public function setProperties(array $properties): self {
$this->properties = $properties;
return $this;
}
/**
* @param string $key
*
* @return string
*/
public function getProperty(string $key): string {
return $this->get($key, $this->properties);
}
/**
* @return NCWellKnownLink[]
*/
public function getLinks(): array {
return $this->links;
}
/**
* @param NCWellKnownLink[] $links
*
* @return self
*/
public function setLinks(array $links): self {
$this->links = $links;
return $this;
}
public function addLink(NCWellKnownLink $link): self {
$this->links[] = $link;
return $this;
}
/**
* @return array
*/
public function jsonSerialize(): array {
return array_filter(
[
'subject' => $this->getSubject(),
'aliases' => $this->getAliases(),
'properties' => $this->getProperties(),
'links' => $this->getLinks()
]
);
}
}
@@ -0,0 +1,222 @@
<?php
/*
* Circles - Bring cloud-users closer together.
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2017
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
declare(strict_types=1);
/**
* Circles - Bring cloud-users closer together.
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2022
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Circles\Tools\Model;
use JsonSerializable;
use OCA\Circles\Tools\Traits\TArrayTools;
class NCWellKnownLink implements JsonSerializable {
use TArrayTools;
/** @var string */
private $rel = '';
/** @var string */
private $type = '';
/** @var string */
private $href = '';
/** @var array */
private $titles = [];
/** @var array */
private $properties = [];
/**
* NC22WellKnownLink constructor.
*
* @param array $json
*/
public function __construct(array $json = []) {
$this->setRel($this->get('rel', $json));
$this->setType($this->get('type', $json));
$this->setHref($this->get('href', $json));
$this->setTitles($this->getArray('titles', $json));
$this->setProperties($this->getArray('properties', $json));
}
/**
* @return string
*/
public function getRel(): string {
return $this->rel;
}
/**
* @param string $rel
*
* @return self
*/
public function setRel(string $rel): self {
$this->rel = $rel;
return $this;
}
/**
* @return string
*/
public function getType(): string {
return $this->type;
}
/**
* @param string $type
*
* @return self
*/
public function setType(string $type): self {
$this->type = $type;
return $this;
}
/**
* @return string
*/
public function getHref(): string {
return $this->href;
}
/**
* @param string $href
*
* @return self
*/
public function setHref(string $href): self {
$this->href = $href;
return $this;
}
/**
* @return array
*/
public function getTitles(): array {
return $this->titles;
}
/**
* @param array $titles
*
* @return self
*/
public function setTitles(array $titles): self {
$this->titles = $titles;
return $this;
}
/**
* @param string $key
*
* @return string
*/
public function getTitle(string $key): string {
return $this->get($key, $this->properties);
}
/**
* @return array
*/
public function getProperties(): array {
return $this->properties;
}
/**
* @param array $properties
*
* @return self
*/
public function setProperties(array $properties): self {
$this->properties = $properties;
return $this;
}
/**
* @param string $key
*
* @return string
*/
public function getProperty(string $key): string {
return $this->get($key, $this->properties);
}
/**
* @return array
*/
public function jsonSerialize(): array {
return array_filter(
[
'rel' => $this->getRel(),
'type' => $this->getType(),
'href' => $this->getHref(),
'titles' => $this->getTitles(),
'properties' => $this->getProperties()
]
);
}
}
@@ -0,0 +1,832 @@
<?php
declare(strict_types=1);
/**
* Circles - Bring cloud-users closer together.
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2022
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Circles\Tools\Model;
use JsonSerializable;
use OCA\Circles\Tools\Traits\TArrayTools;
class Request implements JsonSerializable {
use TArrayTools;
public const TYPE_GET = 0;
public const TYPE_POST = 1;
public const TYPE_PUT = 2;
public const TYPE_DELETE = 3;
public const QS_VAR_DUPLICATE = 1;
public const QS_VAR_ARRAY = 2;
/** @var string */
private $protocol = '';
/** @var array */
private $protocols = ['https'];
/** @var string */
private $host = '';
/** @var int */
private $port = 0;
/** @var string */
private $url = '';
/** @var string */
private $baseUrl = '';
/** @var int */
private $type = 0;
/** @var bool */
private $binary = false;
/** @var bool */
private $verifyPeer = true;
/** @var bool */
private $httpErrorsAllowed = false;
/** @var bool */
private $followLocation = true;
/** @var array */
private $headers = [];
/** @var array */
private $cookies = [];
/** @var array */
private $params = [];
/** @var array */
private $data = [];
/** @var int */
private $queryStringType = self::QS_VAR_DUPLICATE;
/** @var int */
private $timeout = 10;
/** @var string */
private $userAgent = '';
/** @var int */
private $resultCode = 0;
/** @var string */
private $contentType = '';
/**
* Request constructor.
*
* @param string $url
* @param int $type
* @param bool $binary
*/
public function __construct(string $url = '', int $type = 0, bool $binary = false) {
$this->url = $url;
$this->type = $type;
$this->binary = $binary;
}
/**
* @param string $protocol
*
* @return Request
*/
public function setProtocol(string $protocol): Request {
$this->protocols = [$protocol];
return $this;
}
/**
* @param array $protocols
*
* @return Request
*/
public function setProtocols(array $protocols): Request {
$this->protocols = $protocols;
return $this;
}
/**
* @return string[]
*/
public function getProtocols(): array {
return $this->protocols;
}
/**
* @return string
*/
public function getUsedProtocol(): string {
return $this->protocol;
}
/**
* @param string $protocol
*
* @return Request
*/
public function setUsedProtocol(string $protocol): Request {
$this->protocol = $protocol;
return $this;
}
/**
* @return string
* @deprecated - 19 - use getHost();
*/
public function getAddress(): string {
return $this->getHost();
}
/**
* @param string $address
*
* @return Request
* @deprecated - 19 - use setHost();
*/
public function setAddress(string $address): Request {
$this->setHost($address);
return $this;
}
/**
* @return string
*/
public function getHost(): string {
return $this->host;
}
/**
* @param string $host
*
* @return Request
*/
public function setHost(string $host): Request {
$this->host = $host;
return $this;
}
/**
* @return int
*/
public function getPort(): int {
return $this->port;
}
/**
* @param int $port
*
* @return Request
*/
public function setPort(int $port): Request {
$this->port = $port;
return $this;
}
/**
* @param string $instance
*
* @return Request
*/
public function setInstance(string $instance): Request {
if (strpos($instance, ':') === false) {
$this->setHost($instance);
return $this;
}
[$host, $port] = explode(':', $instance, 2);
$this->setHost($host);
if ($port !== '') {
$this->setPort((int)$port);
}
return $this;
}
/**
* @return string
*/
public function getInstance(): string {
$instance = $this->getHost();
if ($this->getPort() > 0) {
$instance .= ':' . $this->getPort();
}
return $instance;
}
/**
* @param string $url
*
* @deprecated - 19 - use basedOnUrl();
*/
public function setAddressFromUrl(string $url) {
$this->basedOnUrl($url);
}
/**
* @param string $url
*/
public function basedOnUrl(string $url) {
$protocol = parse_url($url, PHP_URL_SCHEME);
if ($protocol === null) {
if (strpos($url, '/') > -1) {
[$address, $baseUrl] = explode('/', $url, 2);
$this->setBaseUrl('/' . $baseUrl);
} else {
$address = $url;
}
if (strpos($address, ':') > -1) {
[$address, $port] = explode(':', $address, 2);
$this->setPort((int)$port);
}
$this->setHost($address);
} else {
$this->setProtocols([$protocol]);
$this->setUsedProtocol($protocol);
$this->setHost(parse_url($url, PHP_URL_HOST));
$this->setBaseUrl(parse_url($url, PHP_URL_PATH));
if (is_numeric($port = parse_url($url, PHP_URL_PORT))) {
$this->setPort($port);
}
}
}
/**
* @param string|null $baseUrl
*
* @return Request
*/
public function setBaseUrl(?string $baseUrl): Request {
if ($baseUrl !== null) {
$this->baseUrl = $baseUrl;
}
return $this;
}
/**
* @return bool
*/
public function isBinary(): bool {
return $this->binary;
}
/**
* @param bool $verifyPeer
*
* @return $this
*/
public function setVerifyPeer(bool $verifyPeer): Request {
$this->verifyPeer = $verifyPeer;
return $this;
}
/**
* @return bool
*/
public function isVerifyPeer(): bool {
return $this->verifyPeer;
}
/**
* @param bool $httpErrorsAllowed
*
* @return Request
*/
public function setHttpErrorsAllowed(bool $httpErrorsAllowed): Request {
$this->httpErrorsAllowed = $httpErrorsAllowed;
return $this;
}
/**
* @return bool
*/
public function isHttpErrorsAllowed(): bool {
return $this->httpErrorsAllowed;
}
/**
* @param bool $followLocation
*
* @return $this
*/
public function setFollowLocation(bool $followLocation): Request {
$this->followLocation = $followLocation;
return $this;
}
/**
* @return bool
*/
public function isFollowLocation(): bool {
return $this->followLocation;
}
/**
* @return string
* @deprecated - 19 - use getParametersUrl() + addParam()
*/
public function getParsedUrl(): string {
$url = $this->getPath();
$ak = array_keys($this->getData());
foreach ($ak as $k) {
if (!is_string($this->data[$k])) {
continue;
}
$url = str_replace(':' . $k, $this->data[$k], $url);
}
return $url;
}
/**
* @return string
*/
public function getParametersUrl(): string {
$url = $this->getPath();
$ak = array_keys($this->getParams());
foreach ($ak as $k) {
if (!is_string($this->params[$k])) {
continue;
}
$url = str_replace(':' . $k, $this->params[$k], $url);
}
return $url;
}
/**
* @return string
*/
public function getPath(): string {
return $this->baseUrl . $this->url;
}
/**
* @return string
* @deprecated - 19 - use getPath()
*/
public function getUrl(): string {
return $this->getPath();
}
/**
* @return string
*/
public function getCompleteUrl(): string {
$port = ($this->getPort() > 0) ? ':' . $this->getPort() : '';
return $this->getUsedProtocol() . '://' . $this->getHost() . $port . $this->getParametersUrl();
}
/**
* @return int
*/
public function getType(): int {
return $this->type;
}
public function addHeader($key, $value): Request {
$header = $this->get($key, $this->headers);
if ($header !== '') {
$header .= ', ' . $value;
} else {
$header = $value;
}
$this->headers[$key] = $header;
return $this;
}
/**
* @return array
*/
public function getHeaders(): array {
return array_merge(['User-Agent' => $this->getUserAgent()], $this->headers);
}
/**
* @param array $headers
*
* @return Request
*/
public function setHeaders(array $headers): Request {
$this->headers = $headers;
return $this;
}
/**
* @return array
*/
public function getCookies(): array {
return $this->cookies;
}
/**
* @param array $cookies
*
* @return Request
*/
public function setCookies(array $cookies): Request {
$this->cookies = $cookies;
return $this;
}
/**
* @param int $queryStringType
*
* @return Request
*/
public function setQueryStringType(int $queryStringType): self {
$this->queryStringType = $queryStringType;
return $this;
}
/**
* @return int
*/
public function getQueryStringType(): int {
return $this->queryStringType;
}
/**
* @return array
*/
public function getData(): array {
return $this->data;
}
/**
* @param array $data
*
* @return Request
*/
public function setData(array $data): Request {
$this->data = $data;
return $this;
}
/**
* @param string $data
*
* @return Request
*/
public function setDataJson(string $data): Request {
$this->setData(json_decode($data, true));
return $this;
}
/**
* @param JsonSerializable $data
*
* @return Request
*/
public function setDataSerialize(JsonSerializable $data): Request {
$this->setDataJson(json_encode($data));
return $this;
}
/**
* @return array
*/
public function getParams(): array {
return $this->params;
}
/**
* @param array $params
*
* @return Request
*/
public function setParams(array $params): Request {
$this->params = $params;
return $this;
}
/**
* @param string $k
* @param string $v
*
* @return Request
*/
public function addParam(string $k, string $v): Request {
$this->params[$k] = $v;
return $this;
}
/**
* @param string $k
* @param int $v
*
* @return Request
*/
public function addParamInt(string $k, int $v): Request {
$this->params[$k] = $v;
return $this;
}
/**
* @param string $k
* @param string $v
*
* @return Request
*/
public function addData(string $k, string $v): Request {
$this->data[$k] = $v;
return $this;
}
/**
* @param string $k
* @param int $v
*
* @return Request
*/
public function addDataInt(string $k, int $v): Request {
$this->data[$k] = $v;
return $this;
}
/**
* @return string
*/
public function getDataBody(): string {
return json_encode($this->getData());
}
/**
* @return string
* @deprecated - 19 - use getUrlParams();
*/
public function getUrlData(): string {
if ($this->getData() === []) {
return '';
}
return preg_replace(
'/([(%5B)]{1})[0-9]+([(%5D)]{1})/', '$1$2', http_build_query($this->getData())
);
}
/**
* @return string
* @deprecated - 21 - use getQueryString();
*/
public function getUrlParams(): string {
if ($this->getParams() === []) {
return '';
}
return preg_replace(
'/([(%5B)]{1})[0-9]+([(%5D)]{1})/', '$1$2', http_build_query($this->getParams())
);
}
/**
* @param int $type
*
* @return string
*/
public function getQueryString(): string {
if (empty($this->getParams())) {
return '';
}
switch ($this->getQueryStringType()) {
case self::QS_VAR_ARRAY:
return '?' . http_build_query($this->getParams());
case self::QS_VAR_DUPLICATE:
default:
return '?' . preg_replace(
'/%5B(?:[0-9]|[1-9][0-9]+)%5D=/', '=', http_build_query($this->getParams())
);
}
}
/**
* @return int
*/
public function getTimeout(): int {
return $this->timeout;
}
/**
* @param int $timeout
*
* @return Request
*/
public function setTimeout(int $timeout): Request {
$this->timeout = $timeout;
return $this;
}
/**
* @return string
*/
public function getUserAgent(): string {
return $this->userAgent;
}
/**
* @param string $userAgent
*
* @return Request
*/
public function setUserAgent(string $userAgent): Request {
$this->userAgent = $userAgent;
return $this;
}
/**
* @return int
*/
public function getResultCode(): int {
return $this->resultCode;
}
/**
* @param int $resultCode
*
* @return Request
*/
public function setResultCode(int $resultCode): Request {
$this->resultCode = $resultCode;
return $this;
}
/**
* @return string
*/
public function getContentType(): string {
return $this->contentType;
}
/**
* @param string $contentType
*
* @return Request
*/
public function setContentType(string $contentType): Request {
$this->contentType = $contentType;
return $this;
}
/**
* @return array
*/
public function jsonSerialize(): array {
return [
'protocols' => $this->getProtocols(),
'used_protocol' => $this->getUsedProtocol(),
'port' => $this->getPort(),
'host' => $this->getHost(),
'url' => $this->getPath(),
'timeout' => $this->getTimeout(),
'type' => $this->getType(),
'cookies' => $this->getCookies(),
'headers' => $this->getHeaders(),
'params' => $this->getParams(),
'data' => $this->getData(),
'userAgent' => $this->getUserAgent(),
'followLocation' => $this->isFollowLocation(),
'verifyPeer' => $this->isVerifyPeer(),
'binary' => $this->isBinary()
];
}
/**
* @param string $type
*
* @return int
*/
public static function type(string $type): int {
switch (strtoupper($type)) {
case 'GET':
return self::TYPE_GET;
case 'POST':
return self::TYPE_POST;
case 'PUT':
return self::TYPE_PUT;
case 'DELETE':
return self::TYPE_DELETE;
}
return 0;
}
public static function method(int $type): string {
switch ($type) {
case self::TYPE_GET:
return 'get';
case self::TYPE_POST:
return 'post';
case self::TYPE_PUT:
return 'put';
case self::TYPE_DELETE:
return 'delete';
}
return '';
}
}
@@ -0,0 +1,487 @@
<?php
declare(strict_types=1);
/**
* Circles - Bring cloud-users closer together.
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2022
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Circles\Tools\Model;
use JsonSerializable;
use OCA\Circles\Tools\Exceptions\InvalidItemException;
use OCA\Circles\Tools\Exceptions\ItemNotFoundException;
use OCA\Circles\Tools\Exceptions\MalformedArrayException;
use OCA\Circles\Tools\Exceptions\UnknownTypeException;
use OCA\Circles\Tools\IDeserializable;
use OCA\Circles\Tools\Traits\TArrayTools;
class SimpleDataStore implements JsonSerializable {
use TArrayTools;
/** @var array */
private $data;
/**
* SimpleDataStore constructor.
*
* @param array|null $data
*/
public function __construct(?array $data = []) {
if (!is_array($data)) {
$data = [];
}
$this->data = $data;
}
public function default(array $default = []): void {
$this->data = array_merge($default, $this->data);
}
/**
* @param string $key
* @param string $value
*
* @return SimpleDataStore
*/
public function s(string $key, string $value): self {
$this->data[$key] = $value;
return $this;
}
/**
* @param string $key
*
* @return string
*/
public function g(string $key): string {
return $this->get($key, $this->data);
}
/**
* @param string $key
*
* @return $this
*/
public function u(string $key): self {
if ($this->hasKey($key)) {
unset($this->data[$key]);
}
return $this;
}
/**
* @param string $key
* @param string $value
*
* @return SimpleDataStore
*/
public function a(string $key, string $value): self {
if (!array_key_exists($key, $this->data)) {
$this->data[$key] = [];
}
$this->data[$key][] = $value;
return $this;
}
/**
* @param string $key
* @param int $value
*
* @return SimpleDataStore
*/
public function sInt(string $key, int $value): self {
$this->data[$key] = $value;
return $this;
}
/**
* @param string $key
*
* @return int
*/
public function gInt(string $key): int {
return $this->getInt($key, $this->data);
}
/**
* @param string $key
* @param int $value
*
* @return SimpleDataStore
*/
public function aInt(string $key, int $value): self {
if (!array_key_exists($key, $this->data)) {
$this->data[$key] = [];
}
$this->data[$key][] = $value;
return $this;
}
/**
* @param string $key
* @param bool $value
*
* @return SimpleDataStore
*/
public function sBool(string $key, bool $value): self {
$this->data[$key] = $value;
return $this;
}
/**
* @param string $key
*
* @return bool
*/
public function gBool(string $key): bool {
return $this->getBool($key, $this->data);
}
/**
* @param string $key
* @param bool $value
*
* @return SimpleDataStore
*/
public function aBool(string $key, bool $value): self {
if (!array_key_exists($key, $this->data)) {
$this->data[$key] = [];
}
$this->data[$key][] = $value;
return $this;
}
/**
* @param string $key
* @param array $values
*
* @return SimpleDataStore
*/
public function sArray(string $key, array $values): self {
$this->data[$key] = $values;
return $this;
}
/**
* @param string $key
*
* @return array
*/
public function gArray(string $key): array {
return $this->getArray($key, $this->data);
}
/**
* @param string $key
* @param array $values
*
* @return SimpleDataStore
*/
public function aArray(string $key, array $values): self {
if (!array_key_exists($key, $this->data)) {
$this->data[$key] = [];
}
$this->data[$key] = array_merge($this->data[$key], $values);
return $this;
}
/**
* @param string $key
* @param JsonSerializable $value
*
* @return SimpleDataStore
*/
public function sObj(string $key, JsonSerializable $value): self {
$this->data[$key] = $value;
return $this;
}
/**
* @param string $key
* @param string $class
*
* @return JsonSerializable[]
*/
public function gObjs(string $key, string $class = ''): array {
$list = $this->gArray($key);
$result = [];
foreach ($list as $item) {
$data = new SimpleDataStore([$key => $item]);
$result[] = $data->gObj($key, $class);
}
return array_filter($result);
}
/**
* @param string $key
* @param string $class
*
* @return null|JsonSerializable
* @throws InvalidItemException
* @throws UnknownTypeException
* @throws ItemNotFoundException
*/
public function gObj(string $key, string $class = ''): ?JsonSerializable {
$type = $this->typeOf($key, $this->data);
if ($type === self::$TYPE_NULL) {
if ($class === '') {
return null;
}
throw new InvalidItemException();
}
if ($type === self::$TYPE_SERIALIZABLE) {
return $this->getObj($key, $this->data);
}
if ($type === self::$TYPE_ARRAY && $class !== '') {
$item = new $class();
if (!$item instanceof IDeserializable && !$item instanceof JsonSerializable) {
throw new InvalidItemException(
$class . ' does not implement IDeserializable and JsonSerializable'
);
}
$item->import($this->getArray($key, $this->data));
return $item;
}
throw new InvalidItemException();
}
/**
* @param string $key
* @param JsonSerializable $value
*
* @return SimpleDataStore
*/
public function aObj(string $key, JsonSerializable $value): self {
if (!array_key_exists($key, $this->data)) {
$this->data[$key] = [];
}
$this->data[$key][] = $value;
return $this;
}
/**
* @param string $key
* @param SimpleDataStore $data
*
* @return $this
*/
public function sData(string $key, SimpleDataStore $data): self {
$this->data[$key] = $data->gAll();
return $this;
}
/**
* @param string $key
* @param SimpleDataStore $data
*
* @return $this
*/
public function aData(string $key, SimpleDataStore $data): self {
if (!array_key_exists($key, $this->data) || !is_array($this->data[$key])) {
$this->data[$key] = [];
}
$this->data[$key][] = $data->gAll();
return $this;
}
/**
* @param string $key
*
* @return SimpleDataStore
*/
public function gData(string $key): SimpleDataStore {
return new SimpleDataStore($this->getArray($key, $this->data));
}
/**
* @param string $key
*
* @return mixed
* @throws ItemNotFoundException
*/
public function gItem(string $key) {
if (!array_key_exists($key, $this->data)) {
throw new ItemNotFoundException();
}
return $this->data[$key];
}
/**
* @return array
*/
public function gAll(): array {
return $this->data;
}
/**
* @param array $data
*
* @return SimpleDataStore
*/
public function sAll(array $data): self {
$this->data = $data;
return $this;
}
public function keys(): array {
return array_keys($this->data);
}
/**
* @param string $key
*
* @return bool
*/
public function hasKey(string $key): bool {
return (array_key_exists($key, $this->data));
}
/**
* @param array $keys
*
* @param bool $must
*
* @return bool
* @throws MalformedArrayException
*/
public function hasKeys(array $keys, bool $must = false): bool {
foreach ($keys as $key) {
if (!$this->haveKey($key)) {
if ($must) {
throw new MalformedArrayException($key . ' missing in ' . json_encode($this->keys()));
}
return false;
}
}
return true;
}
/**
* @param array $keys
* @param bool $must
*
* @return bool
* @throws MalformedArrayException
* @deprecated
*/
public function haveKeys(array $keys, bool $must = false): bool {
return $this->hasKeys($keys, $must);
}
/**
* @param string $key
*
* @return bool
* @deprecated
*/
public function haveKey(string $key): bool {
return $this->hasKey($key);
}
/**
* @param string $json
*
* @return $this
*/
public function json(string $json): self {
$data = json_decode($json, true);
if (is_array($data)) {
$this->data = $data;
}
return $this;
}
/**
* @param JsonSerializable $obj
*
* @return $this
*/
public function obj(JsonSerializable $obj): self {
$data = $obj->jsonSerialize();
if (is_array($data)) {
$this->data = $data;
}
return $this;
}
/**
* @return array
*/
public function jsonSerialize(): array {
return $this->data;
}
}
@@ -0,0 +1,230 @@
<?php
declare(strict_types=1);
/**
* Circles - Bring cloud-users closer together.
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2022
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Circles\Tools\Model;
class TreeNode {
/** @var self[] */
private $children = [];
/** @var self */
private $parent;
/** @var SimpleDataStore */
private $item;
/** @var self */
private $currentChild;
/** @var bool */
private $displayed = false;
/** @var bool */
private $splited = false;
/**
* NC22TreeNode constructor.
*
* @param self|null $parent
* @param SimpleDataStore $item
*/
public function __construct(?TreeNode $parent, SimpleDataStore $item) {
$this->parent = $parent;
$this->item = $item;
if ($this->parent !== null) {
$this->parent->addChild($this);
}
}
/**
* @return bool
*/
public function isRoot(): bool {
return (is_null($this->parent));
}
/**
* @param array $children
*
* @return TreeNode
*/
public function setChildren(array $children): self {
$this->children = $children;
return $this;
}
/**
* @param TreeNode $child
*
* @return $this
*/
public function addChild(TreeNode $child): self {
$this->children[] = $child;
return $this;
}
/**
* @return SimpleDataStore
*/
public function getItem(): SimpleDataStore {
$this->displayed = true;
return $this->item;
}
/**
* @return TreeNode
*/
public function getParent(): TreeNode {
return $this->parent;
}
/**
* @return $this
*/
public function getRoot(): TreeNode {
if ($this->isRoot()) {
return $this;
}
return $this->getParent()->getRoot();
}
/**
* @return TreeNode[]
*/
public function getPath(): array {
if ($this->isRoot()) {
return [$this];
}
return array_merge($this->parent->getPath(), [$this]);
}
/**
* @return int
*/
public function getLevel(): int {
if ($this->isRoot()) {
return 0;
}
return $this->getParent()->getLevel() + 1;
}
/**
* @return TreeNode|null
*/
public function current(): ?TreeNode {
if (!$this->isDisplayed()) {
return $this;
}
$this->splited = true;
if ($this->initCurrentChild()) {
$next = $this->getCurrentChild()->current();
if (!is_null($next)) {
return $next;
}
}
if (!$this->haveNext()) {
return null;
}
return $this->next();
}
/**
* @return TreeNode
*/
private function next(): TreeNode {
$this->currentChild = array_shift($this->children);
return $this->currentChild;
}
/**
* @return bool
*/
public function haveNext(): bool {
return !empty($this->children);
}
/**
* @return bool
*/
private function initCurrentChild(): bool {
if (is_null($this->currentChild)) {
if (!$this->haveNext()) {
return false;
}
$this->next();
}
return true;
}
/**
* @return TreeNode|null
*/
private function getCurrentChild(): ?TreeNode {
return $this->currentChild;
}
/**
* @return bool
*/
private function isDisplayed(): bool {
return $this->displayed;
}
/**
* @return bool
*/
public function isSplited(): bool {
return $this->splited;
}
}