Skip to content
Snippets Groups Projects
TsrefRestService.php 12.3 KiB
Newer Older
<?php

namespace SGalinski\TypoScriptReferenceFrontend\Service;

damjan's avatar
damjan committed
use SGalinski\TypoScriptReferenceFrontend\Domain\Model\Attribute;
use SGalinski\TypoScriptReferenceFrontend\Utilities\Conversion;
use TYPO3\Flow\Annotations as Flow;

/**
 * The Class TsrefRestService contains methods for communication with TypoScript REST API.
 *
 * @package SGalinski\TypoScriptReferenceFrontend\Service
 * @Flow\Scope("singleton")
 */
class TsrefRestService {
	/**
	 * Default typo3 version of typoScript attributes.
	 * Filtering by this version (very high number) will fetch attributes of current version.
	const TYPO3_DEFAULT_VERSION = '99999';
	/**
	 * A label to be used in URL instead of TYPO3_DEFAULT_VERSION.
	 * In REST requests, TYPO3_DEFAULT_VERSION is sent instead of this label.
	 */
	const TYPO3_CURRENT_VERSION_LABEL = 'current';

	 * @var string
	 * @Flow\Inject(setting="backendWriteAccessToken")
	 */
	protected $backendWriteAccessToken;

	/**
	 * URL of REST API resource.
	 *
	 * @var string
	 * @Flow\Inject(setting="resourceUrl")
	protected $resourceUrl;
	/**
	 * Makes curl handle, sets some general options and returns the handle.
	 * It also checks if cURL is installed.
	 *
	 * @return resource
	 */
	protected function initialiseCurl($suffix = '/attributes') {
		// is cURL installed yet?
		if (!function_exists('curl_init')) {
			throw new \RuntimeException('Sorry cURL is not installed. Install cURL.');
		}

		$curlHandle = curl_init();
		// Set URL to download
		curl_setopt($curlHandle, CURLOPT_URL, $this->resourceUrl . '/api' . $suffix);

		// Should cURL return or print out the data? (true = return, false = print)
		curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, TRUE);

		// Timeout in seconds
		curl_setopt($curlHandle, CURLOPT_TIMEOUT, 30);
		return $curlHandle;
	}

	 * Fetches attributes from web resource: RESOURCE_URL.
	 *
	 * @param boolean|null $isType - filters by isType
	 * @param bool $namesOnly - get urlNames and names only of attributes.
	 * @param string $typo3Version - filters by typo3Version
	 * @param int $typo3Group - filters by typo3Group
	 * @return mixed
	 */
	public function getAttributesJson(
		$isType = NULL, $namesOnly = TRUE, $typo3Version = self::TYPO3_DEFAULT_VERSION,
		$typo3Group = Attribute::NORMAL_GROUP
	) {
		$curlHandle = $this->initialiseCurl();

		$headerProperties = [
			'namesonly: ' . ($namesOnly ? '1' : '0'),
			'version: ' . $typo3Version,
			'typo3group: ' . $typo3Group
		];

		if ($isType !== NULL) {
			$headerProperties[] = 'istype: ' . ($isType ? '1' : '0');
		}

		curl_setopt($curlHandle, CURLOPT_HTTPHEADER, $headerProperties);

		// Download the given URL, and return output
		$output = curl_exec($curlHandle);
damjan's avatar
damjan committed
		$statusCode = curl_getinfo($curlHandle, CURLINFO_HTTP_CODE);

		// Close the cURL resource, and free system resources
		curl_close($curlHandle);
damjan's avatar
damjan committed
		$this->checkForErrors($statusCode, $output);
	/**
	 * Returns an attribute by its ID from RESOURCE_URL.
	 *
	 * @param int $attributeId
	 * @return mixed JSON
	 */
	public function getAttributeByIdJson($attributeId) {
		$curlHandle = $this->initialiseCurl('/attributes/' . $attributeId);

		// Download the given URL, and return output
		$output = curl_exec($curlHandle);
damjan's avatar
damjan committed
		$statusCode = curl_getinfo($curlHandle, CURLINFO_HTTP_CODE);

		// Close the cURL resource, and free system resources
		curl_close($curlHandle);
damjan's avatar
damjan committed
		$this->checkForErrors($statusCode, $output);
	/**
	 * Returns a type by its name from RESOURCE_URL.
	 *
	 * @param string $typeUrlName
	public function getTypeByUrlNameJson($typeUrlName) {
		$curlHandle = $this->initialiseCurl('/types/' . $typeUrlName);

		// Download the given URL, and return output
		$output = curl_exec($curlHandle);
damjan's avatar
damjan committed
		$statusCode = curl_getinfo($curlHandle, CURLINFO_HTTP_CODE);

		// Close the cURL resource, and free system resources
		curl_close($curlHandle);
damjan's avatar
damjan committed
		$this->checkForErrors($statusCode, $output);
	 * @param string $typeUrlName
	public function getTypeByUrlName($typeUrlName) {
		$typeJson = $this->getTypeByUrlNameJson($typeUrlName);
		$typePhp = json_decode($typeJson);
		return $typePhp;
	}

	/**
	 * Returns properties of a type (attribute which is a type) by its ID from RESOURCE_URL/ID/properties.
	 *
	 * @param int $attributeId
	 * @param string $typo3Version
	 * @param int $typo3Group
	public function getPropertiesByParentIdJson(
		$attributeId, $typo3Version = self::TYPO3_DEFAULT_VERSION, $typo3Group = Attribute::NORMAL_GROUP
	) {
		$curlHandle = $this->initialiseCurl('/attributes/' . $attributeId . '/properties');
		$headerProperties = [
			'version: ' . $typo3Version,
			'typo3group: ' . $typo3Group
		];

		curl_setopt($curlHandle, CURLOPT_HTTPHEADER, $headerProperties);

		// Download the given URL, and return output
		$output = curl_exec($curlHandle);
damjan's avatar
damjan committed
		$statusCode = curl_getinfo($curlHandle, CURLINFO_HTTP_CODE);

		// Close the cURL resource, and free system resources
		curl_close($curlHandle);
damjan's avatar
damjan committed
		$this->checkForErrors($statusCode, $output);
damjan's avatar
damjan committed
	 * Gets attribute by id.
damjan's avatar
damjan committed
	 * @return \stdClass
	 */
	public function getAttributeById($attributeId) {
		$attributeJson = $this->getAttributeByIdJson($attributeId);
		$attributePhp = json_decode($attributeJson);
		return $attributePhp;
	}

	/**
	 * Gets all type attributes by $typo3Version and $typo3Group from RESOURCE_URL
	 *
	 * @param int $attributeId
	 * @param string $typo3Version
	 * @param int $typo3Group
	public function getPropertiesByParentId(
		$attributeId, $typo3Version = self::TYPO3_DEFAULT_VERSION, $typo3Group = Attribute::NORMAL_GROUP
	) {
		$propertiesJson = $this->getPropertiesByParentIdJson($attributeId, $typo3Version, $typo3Group);
		$propertiesPhp = json_decode($propertiesJson);
		return $propertiesPhp;
	}

	/**
	 * Gets all type attributes by $typo3Version and $typo3Group from RESOURCE_URL
	 *
	 * @param bool $namesOnly
	 * @param string $typo3Version
	 * @param int $typo3Group
	 * @return mixed
	 */
	public function getTypes(
		$namesOnly = TRUE, $typo3Version = self::TYPO3_DEFAULT_VERSION, $typo3Group = Attribute::NORMAL_GROUP
	) {
		$typesJson = $this->getAttributesJson(TRUE, $namesOnly, $typo3Version, $typo3Group);
		$typesPhp = json_decode($typesJson);
		return $typesPhp;
	}

damjan's avatar
damjan committed
	/**
	 * Adds new attribute to REST API resource by use of POST method.
	 *
	 * @param Attribute $attribute
damjan's avatar
damjan committed
	 */
	public function addNewAttribute(Attribute $attribute) {
		$attributeJson = json_encode($attribute->toArray());
		$curlHandle = $this->initialiseCurl();

		curl_setopt($curlHandle, CURLOPT_POST, 1);
		curl_setopt(
			$curlHandle, CURLOPT_HTTPHEADER, [
				'Content-Type: application/json',
				'accesstoken: ' . $this->backendWriteAccessToken
		);
		curl_setopt($curlHandle, CURLOPT_POSTFIELDS, $attributeJson);

		// Download the given URL, and return output
damjan's avatar
damjan committed
		$outputJson = curl_exec($curlHandle);
		$statusCode = curl_getinfo($curlHandle, CURLINFO_HTTP_CODE);

		// Close the cURL resource, and free system resources
		curl_close($curlHandle);
damjan's avatar
damjan committed
		$this->checkForErrors($statusCode, $outputJson);
damjan's avatar
damjan committed
		return $outputJson;
	}

	/**
	 * Sends edited attribute to REST API resource by use of PUT method.
	 *
	 * @param Attribute $attribute
	 * @return mixed
	 */
	public function editAttribute(Attribute $attribute) {
		if ($attribute->getId() === NULL) {
			throw new \RuntimeException(
				'Edited attribute: ' . ($attribute->getName() ? $attribute->getName() : '...') . ' doesnt have ID.'
			);
		}
		$attributeJson = json_encode($attribute->toArray(TRUE));
		$curlHandle = $this->initialiseCurl('/attributes/' . $attribute->getId());

		curl_setopt($curlHandle, CURLOPT_CUSTOMREQUEST, 'PUT');
		curl_setopt(
			$curlHandle, CURLOPT_HTTPHEADER, [
				'Content-Type: application/json',
				'accesstoken: ' . $this->backendWriteAccessToken
		curl_setopt($curlHandle, CURLOPT_POSTFIELDS, $attributeJson);
		// Download the given URL, and return output
		$output = curl_exec($curlHandle);
damjan's avatar
damjan committed
		$statusCode = curl_getinfo($curlHandle, CURLINFO_HTTP_CODE);

		// Close the cURL resource, and free system resources
		curl_close($curlHandle);
damjan's avatar
damjan committed
		$this->checkForErrors($statusCode, $output);
	/**
	 * Changes only those fields specified in the array $data. Attribute to change is specified with $id.
	 *
	 * @param int $id
	 * @param array $data
	 * @return mixed
	 */
	public function patchAttribute($id, array $data) {
		if ($id === NULL) {
			throw new \RuntimeException(
				'$id must not be NULL.'
			);
		}
		$dataJson = json_encode($data);
		$curlHandle = $this->initialiseCurl('/attributes/' . $id);

		curl_setopt($curlHandle, CURLOPT_CUSTOMREQUEST, 'PATCH');
		curl_setopt(
			$curlHandle, CURLOPT_HTTPHEADER, [
				'Content-Type: application/json',
				'accesstoken: ' . $this->backendWriteAccessToken
			]
		);
		curl_setopt($curlHandle, CURLOPT_POSTFIELDS, $dataJson);

		// Download the given URL, and return output
		$output = curl_exec($curlHandle);
damjan's avatar
damjan committed
		$statusCode = curl_getinfo($curlHandle, CURLINFO_HTTP_CODE);

		// Close the cURL resource, and free system resources
		curl_close($curlHandle);
damjan's avatar
damjan committed
		$this->checkForErrors($statusCode, $output);

		return $output;
	}

	/**
	 * Downloads typo script reference xml from web resource.
	 *
	 * @param string $typo3Version
	 * @param int $typo3Group
	 * @return mixed
	 */
	public function getTsrefXml($typo3Version = self::TYPO3_DEFAULT_VERSION, $typo3Group = Attribute::NORMAL_GROUP) {
		$curlHandle = $this->initialiseCurl('/tsref');

		$headerProperties = [
			'version: ' . $typo3Version,
			'typo3group: ' . $typo3Group
		];

		curl_setopt($curlHandle, CURLOPT_HTTPHEADER, $headerProperties);

		curl_setopt($curlHandle, CURLOPT_FAILONERROR, 1);
		curl_setopt($curlHandle, CURLOPT_FOLLOWLOCATION, 1);

		// Download the given URL, and return output
		$output = curl_exec($curlHandle);
damjan's avatar
damjan committed
		$statusCode = curl_getinfo($curlHandle, CURLINFO_HTTP_CODE);

		// Close the cURL resource, and free system resources
		curl_close($curlHandle);
damjan's avatar
damjan committed
		$this->checkForErrors($statusCode, $output);
	/**
	 * Gets all categories from web resource and returns them as array.
	 *
	 * @return mixed
	 */
	public function getCategoriesJson() {
		$curlHandle = $this->initialiseCurl('/categories');

		// Download the given URL, and return output
		$output = curl_exec($curlHandle);
damjan's avatar
damjan committed
		$statusCode = curl_getinfo($curlHandle, CURLINFO_HTTP_CODE);

		// Close the cURL resource, and free system resources
		curl_close($curlHandle);
damjan's avatar
damjan committed
		$this->checkForErrors($statusCode, $output);

		return $output;
	}

	/**
	 * Gets all categories from web resource and returns them as stdClass.
	 *
	 * @return mixed
	 */
	public function getCategories() {
		$categoriesJson = $this->getCategoriesJson();
		$categoriesPhp = json_decode($categoriesJson);
		return $categoriesPhp;
	}

damjan's avatar
damjan committed
	/**
	 * Returns associative array of all typo3 groups.
	 *
	 * @return array
	 */
	public function getAllTypo3Groups() {
		return [
			Attribute::NORMAL_GROUP => 'Normal TypoScript',
			Attribute::PAGE_GROUP => 'Page TypoScript',
			Attribute::USER_GROUP => 'User TypoScript',
damjan's avatar
damjan committed

	/**
	 * Returns associative array of available typo3 versions.
	 *
	 * @return array
	 */
	public function getTypo3Versions() {
		return [
			TsrefRestService::TYPO3_CURRENT_VERSION_LABEL => 'Current',
damjan's avatar
damjan committed
			'7.4' => '7.4',
			'6.2' => '6.2',
			'4.5' => '4.5',
			'all' => 'All',

	/**
	 * Gets en array of types for given TYPO3 version. The types are fetched with name and id only.
	 *
	 * @param string $typo3Version
	 * @param int $typoScriptGroup
	public function getTypesWithNull($typo3Version, $typoScriptGroup = Attribute::NORMAL_GROUP) {
		$typesAssociative = Conversion::attributesToAssociativeIdArray($this->getTypes(TRUE, $typo3Version, $typoScriptGroup));
		$typesAssociative = [-1 => 'No type (NULL)'] + $typesAssociative;
		return $typesAssociative;
	}
damjan's avatar
damjan committed

	/**
	 * Checks if there was en error in response and trows exception.
	 *
	 * @param $statusCode
	 * @param $outputJson
	 */
	protected function checkForErrors($statusCode, $outputJson) {
		if (gettype($statusCode) === 'integer' && $statusCode >= 400) {
			$outputObject = json_decode($outputJson);
			$message = isset($outputObject->message) ? $outputObject->message : NULL;
			throw new \RuntimeException($message, $statusCode);
		}
	}