setka-8.x-1.0/src/SetkaEditorHelper.php
src/SetkaEditorHelper.php
<?php
namespace Drupal\setka_editor;
use Drupal\Component\Serialization\Json;
use Drupal\Core\Config\ConfigFactory;
use Drupal\Core\File\FileSystem;
use Drupal\Core\Link;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\State\State;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url;
/**
* Setka Editor helper service.
*/
class SetkaEditorHelper {
use StringTranslationTrait;
const SETKA_EDITOR_TOOLBAR_OFFSET = 80;
const SETKA_EDITOR_DOMAIN = 'https://editor.setka.io';
const SETKA_EDITOR_SUPPORT = 'https://editor.setka.io/support';
/**
* Drupal messenger interface.
*
* @var \Drupal\Core\Messenger\MessengerInterface
*/
protected $messenger;
/**
* The configuration factory.
*
* @var \Drupal\Core\Config\ConfigFactory
*/
protected $configFactory;
/**
* {@inheritdoc}
*/
public function __construct(MessengerInterface $messenger, ConfigFactory $configFactory) {
$this->messenger = $messenger;
$this->configFactory = $configFactory;
}
/**
* Checks if setka editor meta data contains.
*
* @param array|null $metaData
* Setka editor layouts and themes data.
* @param string $postTheme
* Post theme id.
* @param string $postGrid
* Post layout id.
*
* @return array
* Check results array.
*/
public function checkPostMeta($metaData, $postTheme, $postGrid) {
if (!isset($postTheme) && !isset($postGrid)) {
return ['postTheme' => TRUE, 'postGrid' => TRUE];
}
$result = ['postTheme' => FALSE, 'postGrid' => FALSE];
if ($metaData) {
if (!is_array($metaData)) {
$metaData = $this->parseSetkaEditorMeta($metaData);
}
if (!empty($metaData['layouts'])) {
$result['postGrid'] = in_array($postGrid, $metaData['layouts']);
}
if (!empty($metaData['themes'])) {
$result['postTheme'] = in_array($postTheme, $metaData['themes']);
}
}
if (!$result['postTheme'] || !$result['postGrid']) {
$setkaSupportLink = Link::fromTextAndUrl(
$this->t('Setka Editor team'),
Url::fromUri(self::SETKA_EDITOR_SUPPORT, ['attributes' => ['target' => '_blank']])
)->toString();
$this->messenger->addError(
$this->t("Setka Editor can't be launched because Style or Grid System were removed from the Style Manager or you've changed your license key. Please contact @link.", ['@link' => $setkaSupportLink])
);
}
return $result;
}
/**
* Parses Style Manager data to array.
*
* @param array|null $currentBuild
* Current build data.
*
* @return array
* Parsed data array.
*/
public static function parseStyleManagerData($currentBuild) {
$values = [];
if (!empty($currentBuild['content_editor_version'])) {
$values['setka_editor_version'] = $currentBuild['content_editor_version'];
$values['setka_editor_public_token'] = $currentBuild['public_token'];
foreach ($currentBuild['content_editor_files'] as $fileData) {
switch ($fileData['filetype']) {
case 'js':
$values['setka_editor_js_cdn'] = $fileData['url'];
break;
case 'css':
$values['setka_editor_css_cdn'] = $fileData['url'];
break;
}
}
foreach ($currentBuild['theme_files'] as $fileData) {
switch ($fileData['filetype']) {
case 'css':
$values['setka_company_css_cdn'] = $fileData['url'];
break;
case 'json':
$values['setka_company_json_cdn'] = $fileData['url'];
$values['setka_company_meta_data'] = $fileData['url'];
break;
}
}
foreach ($currentBuild['plugins'] as $fileData) {
switch ($fileData['filetype']) {
case 'js':
$values['setka_public_js_cdn'] = $fileData['url'];
break;
}
}
}
return $values;
}
/**
* Downloads and returns internal file URL.
*
* @param string $fileUrl
* File CDN URL.
*
* @return string
* Internal file URL.
*/
public static function downloadSetkaEditorFile($fileUrl) {
$fileData = file_get_contents($fileUrl);
if ($fileData) {
preg_match('/.*?\/([^\/]+)$/', $fileUrl, $matches);
if ($matches[1]) {
$file = file_save_data($fileData, 'public://setka/' . $matches[1], FILE_EXISTS_REPLACE);
return $file ? file_create_url($file->getFileUri()) : FALSE;
}
}
return FALSE;
}
/**
* Checks if public://setka is writable directory.
*
* @param \Drupal\Core\File\FileSystem $fileSystem
* Drupal file system service.
*
* @return bool
* Directory is writable - TRUE, else - FALSE
*/
public static function checkSetkaFolderPermissions(FileSystem $fileSystem) {
$directory = $fileSystem->realpath("public://setka");
$is_writable = is_writable($directory);
$is_directory = is_dir($directory);
return ($is_writable && $is_directory);
}
/**
* Sets task of URLs to download.
*
* @param \Drupal\Core\Config\ImmutableConfig|\Drupal\Core\Config\Config $config
* Drupal config object.
* @param \Drupal\Core\State\State $drupalState
* Drupal state service.
* @param array $newSettings
* New Style Manager settings.
*/
public static function buildSetkaFilesUpdateTask($config, State $drupalState, array $newSettings) {
$updateTask = $drupalState->get('setka_update_task');
if (empty($updateTask)) {
$updateTask = [];
}
$styleManagerSettingsRequired = [
'setka_company_css',
'setka_company_json',
];
foreach ($styleManagerSettingsRequired as $settingName) {
$newValue = $newSettings[$settingName . '_cdn'];
$updateTask[$settingName] = $newValue;
}
$styleManagerSettings = [
'setka_editor_js',
'setka_editor_css',
'setka_public_js',
];
foreach ($styleManagerSettings as $settingName) {
$currentValue = $config->get($settingName . '_cdn');
$newValue = $newSettings[$settingName . '_cdn'];
if (!$drupalState->get($settingName) || $currentValue != $newValue) {
$updateTask[$settingName] = $newValue;
}
}
$drupalState->set('setka_update_task', $updateTask);
}
/**
* This method updates Style Editor files on server storage.
*
* @param \Drupal\Core\State\State $drupalState
* Drupal state service.
*/
public static function runSetkaFilesUpdateTask(State $drupalState) {
$updateTask = $drupalState->get('setka_update_task');
if (empty($updateTask)) {
return [];
}
$result = [];
foreach ($updateTask as $configName => $fileUrl) {
if ($localFileUrl = self::downloadSetkaEditorFile($fileUrl)) {
$result[$configName] = $localFileUrl;
unset($updateTask[$configName]);
}
else {
$result[$configName] = FALSE;
\Drupal::logger('setka_editor')->error('Unable to download Setka Editor file: @url', ['@url' => $fileUrl]);
}
}
if (!empty($updateTask)) {
$drupalState->set('setka_update_task', $updateTask);
}
else {
$drupalState->delete('setka_update_task');
}
$drupalState->setMultiple($result);
}
/**
* Returns max upload file size in bytes or 0 if unlimited.
*
* @return int
* Max upload file size in bytes.
*/
public static function getUploadMaxSize() {
$uploadMaxSize = self::getInBytes(ini_get('post_max_size'));
$uploadMaxFileSize = self::getInBytes(ini_get('upload_max_filesize'));
if (!$uploadMaxFileSize || ($uploadMaxSize && $uploadMaxFileSize > $uploadMaxSize)) {
$uploadMaxFileSize = $uploadMaxSize;
}
return (int) $uploadMaxFileSize;
}
/**
* Returns param value in bytes.
*
* @param string $val
* Php.ini param.
*
* @return bool|int
* Param value in bytes or FALSE.
*/
public static function getInBytes($val) {
$val = trim($val);
if (empty($val)) {
return FALSE;
}
$last = strtolower($val[strlen($val) - 1]);
switch ($last) {
case 'g':
$val = (int) $val * 1024;
case 'm':
$val = (int) $val * 1024;
case 'k':
$val = (int) $val * 1024;
}
return $val;
}
/**
* Download, parse and save to config Setka Editor meta data.
*
* @param string $url
* Meta data file URL.
*
* @return array
* Meta data array.
*/
public function parseSetkaEditorMeta($url) {
$setkaCompanyMetaData = ['layouts' => [], 'themes' => []];
if ($metaDataJson = file_get_contents($url)) {
$metaData = Json::decode($metaDataJson);
if (!empty($metaData['assets']['layouts'])) {
foreach ($metaData['assets']['layouts'] as $layout) {
$setkaCompanyMetaData['layouts'][] = $layout['id'];
}
}
if (!empty($metaData['assets']['themes'])) {
foreach ($metaData['assets']['themes'] as $theme) {
$setkaCompanyMetaData['themes'][] = $theme['id'];
}
}
$this->configFactory->getEditable('setka_editor.settings')
->set('setka_company_meta_data', $setkaCompanyMetaData)
->save();
}
return $setkaCompanyMetaData;
}
}
