mirror of
https://github.com/espocrm/espocrm.git
synced 2026-06-28 06:56:05 +00:00
cs fix
This commit is contained in:
@@ -65,11 +65,10 @@ class FieldValidationManager
|
||||
* @param Entity $entity An entity.
|
||||
* @param ?StdClass $data Raw request payload data.
|
||||
* @param ?Params $params Validation additional parameters.
|
||||
|
||||
*
|
||||
* @throws BadRequest If data is not valid.
|
||||
*/
|
||||
public function process(Entity $entity, ?StdClass $data = null, ?Params $params = null) : void
|
||||
public function process(Entity $entity, ?StdClass $data = null, ?Params $params = null): void
|
||||
{
|
||||
$dataIsSet = $data !== null;
|
||||
|
||||
@@ -105,7 +104,7 @@ class FieldValidationManager
|
||||
/**
|
||||
* Check a specific field for a specific validation type.
|
||||
*/
|
||||
public function check(Entity $entity, string $field, string $type, ?StdClass $data = null) : bool
|
||||
public function check(Entity $entity, string $field, string $type, ?StdClass $data = null): bool
|
||||
{
|
||||
if (!$data) {
|
||||
$data = $data ?? (object) [];
|
||||
@@ -139,7 +138,7 @@ class FieldValidationManager
|
||||
return true;
|
||||
}
|
||||
|
||||
private function processField(Entity $entity, string $field, Params $params, StdClass $data) : void
|
||||
private function processField(Entity $entity, string $field, Params $params, StdClass $data): void
|
||||
{
|
||||
$entityType = $entity->getEntityType();
|
||||
|
||||
@@ -168,8 +167,12 @@ class FieldValidationManager
|
||||
}
|
||||
|
||||
private function processFieldCheck(
|
||||
string $entityType, string $type, Entity $entity, string $field, $validationValue
|
||||
) : bool {
|
||||
string $entityType,
|
||||
string $type,
|
||||
Entity $entity,
|
||||
string $field,
|
||||
$validationValue
|
||||
): bool {
|
||||
|
||||
$checker = $this->getFieldTypeChecker($entityType, $field);
|
||||
|
||||
@@ -187,8 +190,12 @@ class FieldValidationManager
|
||||
}
|
||||
|
||||
private function processFieldRawCheck(
|
||||
string $entityType, string $type, StdClass $data, string $field, $validationValue
|
||||
) : bool {
|
||||
string $entityType,
|
||||
string $type,
|
||||
StdClass $data,
|
||||
string $field,
|
||||
$validationValue
|
||||
): bool {
|
||||
|
||||
$checker = $this->getFieldTypeChecker($entityType, $field);
|
||||
|
||||
@@ -205,7 +212,7 @@ class FieldValidationManager
|
||||
return $checker->$methodName($data, $field, $validationValue);
|
||||
}
|
||||
|
||||
private function getFieldTypeChecker(string $entityType, string $field) : ?object
|
||||
private function getFieldTypeChecker(string $entityType, string $field): ?object
|
||||
{
|
||||
$key = $entityType . '_' . $field;
|
||||
|
||||
@@ -216,7 +223,7 @@ class FieldValidationManager
|
||||
return $this->checkerCache[$key];
|
||||
}
|
||||
|
||||
private function loadFieldTypeChecker(string $entityType, string $field) : void
|
||||
private function loadFieldTypeChecker(string $entityType, string $field): void
|
||||
{
|
||||
$key = $entityType . '_' . $field;
|
||||
|
||||
@@ -229,7 +236,7 @@ class FieldValidationManager
|
||||
$this->checkerCache[$key] = $this->factory->create($entityType, $field);
|
||||
}
|
||||
|
||||
private function isFieldSetInData(string $entityType, string $field, StdClass $data) : bool
|
||||
private function isFieldSetInData(string $entityType, string $field, StdClass $data): bool
|
||||
{
|
||||
$attributeList = $this->fieldUtil->getActualAttributeList($entityType, $field);
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ class Params
|
||||
*
|
||||
* @return array<string>
|
||||
*/
|
||||
public function getSkipFieldList() : array
|
||||
public function getSkipFieldList(): array
|
||||
{
|
||||
return $this->skipFieldList;
|
||||
}
|
||||
@@ -54,7 +54,7 @@ class Params
|
||||
*
|
||||
* @return array<string>
|
||||
*/
|
||||
public function getTypeSkipFieldList(string $type) : array
|
||||
public function getTypeSkipFieldList(string $type): array
|
||||
{
|
||||
return $this->typeSkipFieldListData[$type] ?? [];
|
||||
}
|
||||
@@ -64,7 +64,7 @@ class Params
|
||||
*
|
||||
* @param array<string> $list
|
||||
*/
|
||||
public function withSkipFieldList(array $list) : self
|
||||
public function withSkipFieldList(array $list): self
|
||||
{
|
||||
$obj = clone $this;
|
||||
|
||||
@@ -78,7 +78,7 @@ class Params
|
||||
*
|
||||
* @param array<string> $list
|
||||
*/
|
||||
public function withTypeSkipFieldList(string $type, array $list) : self
|
||||
public function withTypeSkipFieldList(string $type, array $list): self
|
||||
{
|
||||
$obj = clone $this;
|
||||
|
||||
@@ -90,7 +90,7 @@ class Params
|
||||
/**
|
||||
* Create an empty instance.
|
||||
*/
|
||||
public static function fromNothing() : self
|
||||
public static function fromNothing(): self
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ class ValidatorFactory
|
||||
/**
|
||||
* Whether can be created.
|
||||
*/
|
||||
public function isCreatable(string $entityType, string $field) : bool
|
||||
public function isCreatable(string $entityType, string $field): bool
|
||||
{
|
||||
return (bool) $this->getClassName($entityType, $field);
|
||||
}
|
||||
@@ -63,7 +63,7 @@ class ValidatorFactory
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function create(string $entityType, string $field) : object
|
||||
public function create(string $entityType, string $field): object
|
||||
{
|
||||
$className = $this->getClassName($entityType, $field);
|
||||
|
||||
@@ -74,7 +74,7 @@ class ValidatorFactory
|
||||
return $this->injectableFactory->create($className);
|
||||
}
|
||||
|
||||
private function getClassName(string $entityType, string $field) : ?string
|
||||
private function getClassName(string $entityType, string $field): ?string
|
||||
{
|
||||
$key = $entityType . '_' . $field;
|
||||
|
||||
@@ -85,7 +85,7 @@ class ValidatorFactory
|
||||
return $this->classNameCache[$key];
|
||||
}
|
||||
|
||||
private function getClassNameNoCache(string $entityType, string $field) : ?string
|
||||
private function getClassNameNoCache(string $entityType, string $field): ?string
|
||||
{
|
||||
$className1 = $this->metadata
|
||||
->get(['entityDefs', $entityType, 'fields', $field, 'validatorClassName']);
|
||||
|
||||
@@ -34,5 +34,5 @@ interface Attachment
|
||||
/**
|
||||
* Get a source ID.
|
||||
*/
|
||||
public function getSourceId() : string;
|
||||
public function getSourceId(): string;
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ class AttachmentEntityWrapper implements Attachment
|
||||
$this->attachment = $attachment;
|
||||
}
|
||||
|
||||
public function getSourceId() : string
|
||||
public function getSourceId(): string
|
||||
{
|
||||
return $this->attachment->getSourceId();
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ class Factory
|
||||
$this->injectableFactory = $injectableFactory;
|
||||
}
|
||||
|
||||
public function create(string $name) : Storage
|
||||
public function create(string $name): Storage
|
||||
{
|
||||
$className = $this->metadata->get(['app', 'fileStorage', 'implementationClassNameMap', $name]);
|
||||
|
||||
|
||||
@@ -37,5 +37,5 @@ interface Local
|
||||
/**
|
||||
* Get a local file path.
|
||||
*/
|
||||
public function getLocalFilePath(Attachment $attachment) : string;
|
||||
public function getLocalFilePath(Attachment $attachment): string;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ class Manager
|
||||
/**
|
||||
* Whether a file exists in a storage.
|
||||
*/
|
||||
public function exists(AttachmentEntity $attachment) : bool
|
||||
public function exists(AttachmentEntity $attachment): bool
|
||||
{
|
||||
$implementation = $this->getImplementation($attachment);
|
||||
|
||||
@@ -66,7 +66,7 @@ class Manager
|
||||
/**
|
||||
* Get a file size.
|
||||
*/
|
||||
public function getSize(AttachmentEntity $attachment) : int
|
||||
public function getSize(AttachmentEntity $attachment): int
|
||||
{
|
||||
$implementation = $this->getImplementation($attachment);
|
||||
|
||||
@@ -76,7 +76,7 @@ class Manager
|
||||
/**
|
||||
* Get file contents.
|
||||
*/
|
||||
public function getContents(AttachmentEntity $attachment) : string
|
||||
public function getContents(AttachmentEntity $attachment): string
|
||||
{
|
||||
$implementation = $this->getImplementation($attachment);
|
||||
|
||||
@@ -86,7 +86,7 @@ class Manager
|
||||
/**
|
||||
* Get a file contents stream.
|
||||
*/
|
||||
public function getStream(AttachmentEntity $attachment) : StreamInterface
|
||||
public function getStream(AttachmentEntity $attachment): StreamInterface
|
||||
{
|
||||
$implementation = $this->getImplementation($attachment);
|
||||
|
||||
@@ -96,7 +96,7 @@ class Manager
|
||||
/**
|
||||
* Store file contents represented as a stream.
|
||||
*/
|
||||
public function putStream(AttachmentEntity $attachment, StreamInterface $stream) : void
|
||||
public function putStream(AttachmentEntity $attachment, StreamInterface $stream): void
|
||||
{
|
||||
$implementation = $this->getImplementation($attachment);
|
||||
|
||||
@@ -106,7 +106,7 @@ class Manager
|
||||
/**
|
||||
* Store file contents.
|
||||
*/
|
||||
public function putContents(AttachmentEntity $attachment, string $contents) : void
|
||||
public function putContents(AttachmentEntity $attachment, string $contents): void
|
||||
{
|
||||
$implementation = $this->getImplementation($attachment);
|
||||
|
||||
@@ -118,7 +118,7 @@ class Manager
|
||||
/**
|
||||
* Remove a file.
|
||||
*/
|
||||
public function unlink(AttachmentEntity $attachment) : void
|
||||
public function unlink(AttachmentEntity $attachment): void
|
||||
{
|
||||
$implementation = $this->getImplementation($attachment);
|
||||
|
||||
@@ -128,7 +128,7 @@ class Manager
|
||||
/**
|
||||
* Whether an attachment storage is local.
|
||||
*/
|
||||
public function isLocal(AttachmentEntity $attachment) : bool
|
||||
public function isLocal(AttachmentEntity $attachment): bool
|
||||
{
|
||||
$implementation = $this->getImplementation($attachment);
|
||||
|
||||
@@ -138,7 +138,7 @@ class Manager
|
||||
/**
|
||||
* Get a local file path. If a file is not stored locally, a temporary file will be created.
|
||||
*/
|
||||
public function getLocalFilePath(AttachmentEntity $attachment) : string
|
||||
public function getLocalFilePath(AttachmentEntity $attachment): string
|
||||
{
|
||||
$implementation = $this->getImplementation($attachment);
|
||||
|
||||
@@ -160,12 +160,12 @@ class Manager
|
||||
return $path;
|
||||
}
|
||||
|
||||
private static function wrapAttachmentEntity(AttachmentEntity $attachment) : AttachmentEntityWrapper
|
||||
private static function wrapAttachmentEntity(AttachmentEntity $attachment): AttachmentEntityWrapper
|
||||
{
|
||||
return new AttachmentEntityWrapper($attachment);
|
||||
}
|
||||
|
||||
private function getImplementation(AttachmentEntity $attachment) : Storage
|
||||
private function getImplementation(AttachmentEntity $attachment): Storage
|
||||
{
|
||||
$storage = $attachment->getStorage();
|
||||
|
||||
|
||||
@@ -39,25 +39,25 @@ interface Storage
|
||||
/**
|
||||
* Get file contents as a stream.
|
||||
*/
|
||||
public function getStream(Attachment $attachment) : StreamInterface;
|
||||
public function getStream(Attachment $attachment): StreamInterface;
|
||||
|
||||
/**
|
||||
* Store file contents.
|
||||
*/
|
||||
public function putStream(Attachment $attachment, StreamInterface $stream) : void;
|
||||
public function putStream(Attachment $attachment, StreamInterface $stream): void;
|
||||
|
||||
/**
|
||||
* Whether a file exists.
|
||||
*/
|
||||
public function exists(Attachment $attachment) : bool;
|
||||
public function exists(Attachment $attachment): bool;
|
||||
|
||||
/**
|
||||
* Delete a file.
|
||||
*/
|
||||
public function unlink(Attachment $attachment) : void;
|
||||
public function unlink(Attachment $attachment): void;
|
||||
|
||||
/**
|
||||
* Get a file size.
|
||||
*/
|
||||
public function getSize(Attachment $attachment) : int;
|
||||
public function getSize(Attachment $attachment): int;
|
||||
}
|
||||
|
||||
@@ -80,29 +80,29 @@ class AwsS3 implements Storage
|
||||
$this->filesystem = new Filesystem($adapter);
|
||||
}
|
||||
|
||||
public function unlink(Attachment $attachment) : void
|
||||
public function unlink(Attachment $attachment): void
|
||||
{
|
||||
$this->filesystem->delete($attachment->getSourceId());
|
||||
}
|
||||
|
||||
public function exists(Attachment $attachment) : bool
|
||||
public function exists(Attachment $attachment): bool
|
||||
{
|
||||
return $this->filesystem->fileExists($attachment->getSourceId());
|
||||
}
|
||||
|
||||
public function getSize(Attachment $attachment) : int
|
||||
public function getSize(Attachment $attachment): int
|
||||
{
|
||||
return $this->filesystem->fileSize($attachment->getSourceId());
|
||||
}
|
||||
|
||||
public function getStream(Attachment $attachment) : StreamInterface
|
||||
public function getStream(Attachment $attachment): StreamInterface
|
||||
{
|
||||
$resource = $this->filesystem->readStream($attachment->getSourceId());
|
||||
|
||||
return new Stream($resource);
|
||||
}
|
||||
|
||||
public function putStream(Attachment $attachment, StreamInterface $stream) : void
|
||||
public function putStream(Attachment $attachment, StreamInterface $stream): void
|
||||
{
|
||||
// League\Flysystem does not support StreamInterface.
|
||||
// Need to pass a resource.
|
||||
|
||||
@@ -50,21 +50,21 @@ class EspoUploadDir implements Storage, Local
|
||||
$this->fileManager = $fileManager;
|
||||
}
|
||||
|
||||
public function unlink(Attachment $attachment) : void
|
||||
public function unlink(Attachment $attachment): void
|
||||
{
|
||||
$this->fileManager->unlink(
|
||||
$this->getFilePath($attachment)
|
||||
);
|
||||
}
|
||||
|
||||
public function exists(Attachment $attachment) : bool
|
||||
public function exists(Attachment $attachment): bool
|
||||
{
|
||||
$filePath = $this->getFilePath($attachment);
|
||||
|
||||
return $this->fileManager->isFile($filePath);
|
||||
}
|
||||
|
||||
public function getSize(Attachment $attachment) : int
|
||||
public function getSize(Attachment $attachment): int
|
||||
{
|
||||
$filePath = $this->getFilePath($attachment);
|
||||
|
||||
@@ -75,7 +75,7 @@ class EspoUploadDir implements Storage, Local
|
||||
return filesize($filePath);
|
||||
}
|
||||
|
||||
public function getStream(Attachment $attachment) : StreamInterface
|
||||
public function getStream(Attachment $attachment): StreamInterface
|
||||
{
|
||||
$filePath = $this->getFilePath($attachment);
|
||||
|
||||
@@ -88,7 +88,7 @@ class EspoUploadDir implements Storage, Local
|
||||
return new Stream($resouce);
|
||||
}
|
||||
|
||||
public function putStream(Attachment $attachment, StreamInterface $stream) : void
|
||||
public function putStream(Attachment $attachment, StreamInterface $stream): void
|
||||
{
|
||||
$filePath = $this->getFilePath($attachment);
|
||||
|
||||
@@ -101,7 +101,7 @@ class EspoUploadDir implements Storage, Local
|
||||
}
|
||||
}
|
||||
|
||||
public function getLocalFilePath(Attachment $attachment) : string
|
||||
public function getLocalFilePath(Attachment $attachment): string
|
||||
{
|
||||
return $this->getFilePath($attachment);
|
||||
}
|
||||
|
||||
@@ -46,9 +46,11 @@ class Argument implements Evaluatable
|
||||
/**
|
||||
* Get an argument type (function name).
|
||||
*/
|
||||
public function getType() : ?string
|
||||
public function getType(): ?string
|
||||
{
|
||||
if (!is_object($this->data)) return null;
|
||||
if (!is_object($this->data)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->data->type ?? null;
|
||||
}
|
||||
@@ -56,7 +58,7 @@ class Argument implements Evaluatable
|
||||
/**
|
||||
* Get a nested argument list.
|
||||
*/
|
||||
public function getArgumentList() : ArgumentList
|
||||
public function getArgumentList(): ArgumentList
|
||||
{
|
||||
if (!is_object($this->data)) {
|
||||
throw new Error("Can't get an argument list from a scalar value item.");
|
||||
@@ -64,9 +66,11 @@ class Argument implements Evaluatable
|
||||
|
||||
if (!property_exists($this->data, 'value')) {
|
||||
$argumentList = new ArgumentList([]);
|
||||
} else if (is_array($this->data->value)) {
|
||||
}
|
||||
else if (is_array($this->data->value)) {
|
||||
$argumentList = new ArgumentList($this->data->value);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
$argumentList = new ArgumentList([$this->data->value]);
|
||||
}
|
||||
|
||||
@@ -75,6 +79,8 @@ class Argument implements Evaluatable
|
||||
|
||||
/**
|
||||
* Get RAW data.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
|
||||
@@ -29,10 +29,17 @@
|
||||
|
||||
namespace Espo\Core\Formula;
|
||||
|
||||
use BadMethodCallException;
|
||||
use OutOfBoundsException;
|
||||
use Iterator;
|
||||
use Countable;
|
||||
use ArrayAccess;
|
||||
use SeekableIterator;
|
||||
|
||||
/**
|
||||
* A list of function arguments.
|
||||
*/
|
||||
class ArgumentList implements Evaluatable, \Iterator, \Countable, \ArrayAccess, \SeekableIterator
|
||||
class ArgumentList implements Evaluatable, Iterator, Countable, ArrayAccess, SeekableIterator
|
||||
{
|
||||
protected $dataList;
|
||||
|
||||
@@ -46,25 +53,30 @@ class ArgumentList implements Evaluatable, \Iterator, \Countable, \ArrayAccess,
|
||||
private function getLastValidKey()
|
||||
{
|
||||
$keys = array_keys($this->dataList);
|
||||
|
||||
$i = end($keys);
|
||||
|
||||
while ($i > 0) {
|
||||
if (array_key_exists($i, $this->dataList)) {
|
||||
break;
|
||||
}
|
||||
|
||||
$i--;
|
||||
}
|
||||
|
||||
return $i;
|
||||
}
|
||||
|
||||
public function rewind()
|
||||
{
|
||||
$this->position = 0;
|
||||
|
||||
while (!$this->valid() && $this->position <= $this->getLastValidKey()) {
|
||||
$this->position ++;
|
||||
}
|
||||
}
|
||||
|
||||
protected function getArgumentByIndex(int $index) : Argument
|
||||
private function getArgumentByIndex(int $index): Argument
|
||||
{
|
||||
return new Argument($this->dataList[$index]);
|
||||
}
|
||||
@@ -110,12 +122,12 @@ class ArgumentList implements Evaluatable, \Iterator, \Countable, \ArrayAccess,
|
||||
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
throw new \BadMethodCallException('Setting is not allowed.');
|
||||
throw new BadMethodCallException('Setting is not allowed.');
|
||||
}
|
||||
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
throw new \BadMethodCallException('Unsetting is not allowed.');
|
||||
throw new BadMethodCallException('Unsetting is not allowed.');
|
||||
}
|
||||
|
||||
public function count() : int
|
||||
@@ -126,8 +138,9 @@ class ArgumentList implements Evaluatable, \Iterator, \Countable, \ArrayAccess,
|
||||
public function seek($offset)
|
||||
{
|
||||
$this->position = $offset;
|
||||
|
||||
if (!$this->valid()) {
|
||||
throw new \OutOfBoundsException("Invalid seek offset ($offset).");
|
||||
throw new OutOfBoundsException("Invalid seek offset ($offset).");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,34 +38,45 @@ class AttributeFetcher
|
||||
{
|
||||
private $relatedEntitiesCacheMap = [];
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function fetch(Entity $entity, string $attribute, bool $getFetchedAttribute = false)
|
||||
{
|
||||
if (strpos($attribute, '.') !== false) {
|
||||
$arr = explode('.', $attribute);
|
||||
|
||||
$key = $this->buildKey($entity, $arr[0]);
|
||||
|
||||
if (!array_key_exists($key, $this->relatedEntitiesCacheMap)) {
|
||||
$this->relatedEntitiesCacheMap[$key] = $entity->get($arr[0]);
|
||||
}
|
||||
|
||||
$relatedEntity = $this->relatedEntitiesCacheMap[$key];
|
||||
|
||||
if ($relatedEntity && ($relatedEntity instanceof Entity) && count($arr) > 0) {
|
||||
return $this->fetch($relatedEntity, $arr[1]);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
$methodName = 'get';
|
||||
|
||||
if ($getFetchedAttribute) {
|
||||
$methodName = 'getFetched';
|
||||
}
|
||||
|
||||
if ($entity->getAttributeParam($attribute, 'isParentName') && $methodName == 'get') {
|
||||
$relationName = $entity->getAttributeParam($attribute, 'relation');
|
||||
|
||||
if ($parent = $entity->get($relationName)) {
|
||||
return $parent->get('name');
|
||||
}
|
||||
} else if ($entity->getAttributeParam($attribute, 'isLinkMultipleIdList') && $methodName == 'get') {
|
||||
}
|
||||
else if ($entity->getAttributeParam($attribute, 'isLinkMultipleIdList') && $methodName == 'get') {
|
||||
$relationName = $entity->getAttributeParam($attribute, 'relation');
|
||||
|
||||
if (!$entity->has($attribute)) {
|
||||
$entity->loadLinkMultipleField($relationName);
|
||||
}
|
||||
@@ -74,12 +85,12 @@ class AttributeFetcher
|
||||
return $entity->$methodName($attribute);
|
||||
}
|
||||
|
||||
public function resetRuntimeCache()
|
||||
public function resetRuntimeCache(): void
|
||||
{
|
||||
$this->relatedEntitiesCacheMap = [];
|
||||
}
|
||||
|
||||
protected function buildKey(Entity $entity, string $link) : string
|
||||
private function buildKey(Entity $entity, string $link): string
|
||||
{
|
||||
return spl_object_hash($entity) . '-' . $link;
|
||||
}
|
||||
|
||||
@@ -61,9 +61,13 @@ class Evaluator
|
||||
$this->functionClassNameMap = $functionClassNameMap;
|
||||
|
||||
$this->parser = new Parser();
|
||||
|
||||
$this->parsedHash = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function process(string $expression, ?Entity $entity = null, ?StdClass $variables = null)
|
||||
{
|
||||
$this->processor = new Processor(
|
||||
@@ -79,7 +83,7 @@ class Evaluator
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function getParsedExpression(string $expression) : Argument
|
||||
private function getParsedExpression(string $expression): Argument
|
||||
{
|
||||
if (!array_key_exists($expression, $this->parsedHash)) {
|
||||
$this->parsedHash[$expression] = $this->parser->parse($expression);
|
||||
|
||||
@@ -59,19 +59,23 @@ class FunctionFactory
|
||||
$this->classNameMap = $classNameMap;
|
||||
}
|
||||
|
||||
public function create(string $name, ?Entity $entity = null, ?StdClass $variables = null)
|
||||
public function create(string $name, ?Entity $entity = null, ?StdClass $variables = null): object
|
||||
{
|
||||
if ($this->classNameMap && array_key_exists($name, $this->classNameMap)) {
|
||||
$className = $this->classNameMap[$name];
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
$arr = explode('\\', $name);
|
||||
|
||||
foreach ($arr as $i => $part) {
|
||||
if ($i < count($arr) - 1) {
|
||||
$part = $part . 'Group';
|
||||
}
|
||||
$arr[$i] = ucfirst($part);
|
||||
}
|
||||
|
||||
$typeName = implode('\\', $arr);
|
||||
|
||||
$className = 'Espo\\Core\\Formula\\Functions\\' . $typeName . 'Type';
|
||||
}
|
||||
|
||||
@@ -87,7 +91,10 @@ class FunctionFactory
|
||||
'attributeFetcher' => $this->attributeFetcher,
|
||||
]);
|
||||
|
||||
if (property_exists($className, 'hasAttributeFetcher') || method_exists($className, 'setAttributeFetcher')) {
|
||||
if (
|
||||
property_exists($className, 'hasAttributeFetcher') ||
|
||||
method_exists($className, 'setAttributeFetcher')
|
||||
) {
|
||||
$object->setAttributeFetcher($this->attributeFetcher);
|
||||
}
|
||||
|
||||
|
||||
@@ -59,12 +59,12 @@ abstract class BaseFunction
|
||||
|
||||
protected $log;
|
||||
|
||||
protected function getVariables() : StdClass
|
||||
protected function getVariables(): StdClass
|
||||
{
|
||||
return $this->variables;
|
||||
}
|
||||
|
||||
protected function getEntity() : Entity
|
||||
protected function getEntity(): Entity
|
||||
{
|
||||
if (!$this->entity) {
|
||||
throw new NotPassedEntity('function: ' . $this->name);
|
||||
@@ -74,7 +74,11 @@ abstract class BaseFunction
|
||||
}
|
||||
|
||||
public function __construct(
|
||||
string $name, Processor $processor, ?Entity $entity = null, ?StdClass $variables = null, ?Log $log = null
|
||||
string $name,
|
||||
Processor $processor,
|
||||
?Entity $entity = null,
|
||||
?StdClass $variables = null,
|
||||
?Log $log = null
|
||||
) {
|
||||
$this->name = $name;
|
||||
$this->processor = $processor;
|
||||
|
||||
@@ -52,6 +52,8 @@ class Manager
|
||||
|
||||
/**
|
||||
* Executes a script and returns its result.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function run(string $script, ?Entity $entity = null, ?StdClass $variables = null)
|
||||
{
|
||||
|
||||
@@ -38,7 +38,7 @@ use StdClass;
|
||||
*/
|
||||
class Parser
|
||||
{
|
||||
protected $priorityList = [
|
||||
private $priorityList = [
|
||||
['='],
|
||||
['||'],
|
||||
['&&'],
|
||||
@@ -47,7 +47,7 @@ class Parser
|
||||
['*', '/', '%'],
|
||||
];
|
||||
|
||||
protected $operatorMap = [
|
||||
private $operatorMap = [
|
||||
'=' => 'assign',
|
||||
'||' => 'logical\\or',
|
||||
'&&' => 'logical\\and',
|
||||
@@ -64,12 +64,12 @@ class Parser
|
||||
'<=' => 'comparison\\lessThanOrEquals',
|
||||
];
|
||||
|
||||
public function parse(string $expression) : StdClass
|
||||
public function parse(string $expression): StdClass
|
||||
{
|
||||
return $this->split($expression);
|
||||
}
|
||||
|
||||
protected function applyOperator(string $operator, string $firstPart, string $secondPart) : StdClass
|
||||
private function applyOperator(string $operator, string $firstPart, string $secondPart): StdClass
|
||||
{
|
||||
if ($operator === '=') {
|
||||
if (strlen($firstPart)) {
|
||||
@@ -97,6 +97,7 @@ class Parser
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
throw new SyntaxError("Bad operator usage.");
|
||||
}
|
||||
|
||||
@@ -111,9 +112,13 @@ class Parser
|
||||
];
|
||||
}
|
||||
|
||||
protected function processStrings(
|
||||
string &$string, string &$modifiedString, ?array &$splitterIndexList = null, bool $intoOneLine = false
|
||||
) {
|
||||
private function processStrings(
|
||||
string &$string,
|
||||
string &$modifiedString,
|
||||
?array &$splitterIndexList = null,
|
||||
bool $intoOneLine = false
|
||||
): bool {
|
||||
|
||||
$isString = false;
|
||||
$isSingleQuote = false;
|
||||
$isComment = false;
|
||||
@@ -153,12 +158,13 @@ class Parser
|
||||
if ($isString) {
|
||||
if ($string[$i] === '(' || $string[$i] === ')') {
|
||||
$modifiedString[$i] = '_';
|
||||
} else if (!$isStringStart) {
|
||||
}
|
||||
else if (!$isStringStart) {
|
||||
$modifiedString[$i] = ' ';
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (!$isLineComment && !$isComment) {
|
||||
|
||||
if (!$isComment) {
|
||||
if ($i && $string[$i] === '/' && $string[$i - 1] === '/') {
|
||||
$isLineComment = true;
|
||||
@@ -174,6 +180,7 @@ class Parser
|
||||
if ($string[$i] === '(') {
|
||||
$braceCounter++;
|
||||
}
|
||||
|
||||
if ($string[$i] === ')') {
|
||||
$braceCounter--;
|
||||
}
|
||||
@@ -184,6 +191,7 @@ class Parser
|
||||
$splitterIndexList[] = $i;
|
||||
}
|
||||
}
|
||||
|
||||
if ($intoOneLine) {
|
||||
if ($string[$i] === "\r" || $string[$i] === "\n" || $string[$i] === "\t") {
|
||||
$string[$i] = ' ';
|
||||
@@ -209,7 +217,7 @@ class Parser
|
||||
return $isString;
|
||||
}
|
||||
|
||||
protected function split(string $expression) : StdClass
|
||||
private function split(string $expression): StdClass
|
||||
{
|
||||
$expression = trim($expression);
|
||||
|
||||
@@ -237,24 +245,34 @@ class Parser
|
||||
if ($modifiedExpression[$i] === '(') {
|
||||
$braceCounter++;
|
||||
}
|
||||
|
||||
if ($modifiedExpression[$i] === ')') {
|
||||
$braceCounter--;
|
||||
}
|
||||
|
||||
if ($braceCounter === 0 && $i < strlen($modifiedExpression) - 1) {
|
||||
$hasExcessBraces = false;
|
||||
}
|
||||
|
||||
if ($braceCounter === 0) {
|
||||
$expressionOutOfBraceList[] = true;
|
||||
} else {
|
||||
$expressionOutOfBraceList[] = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($braceCounter !== 0) {
|
||||
throw new SyntaxError('Incorrect round brackets in expression ' . $expression . '.');
|
||||
}
|
||||
|
||||
if (strlen($expression) > 1 && $expression[0] === '(' && $expression[strlen($expression) - 1] === ')' && $hasExcessBraces) {
|
||||
if (
|
||||
strlen($expression) > 1 &&
|
||||
$expression[0] === '(' &&
|
||||
$expression[strlen($expression) - 1] === ')' &&
|
||||
$hasExcessBraces
|
||||
) {
|
||||
$expression = substr($expression, 1, strlen($expression) - 2);
|
||||
|
||||
return $this->split($expression);
|
||||
}
|
||||
|
||||
@@ -262,14 +280,25 @@ class Parser
|
||||
if ($expression[strlen($expression) - 1] !== ';') {
|
||||
$splitterIndexList[] = strlen($expression);
|
||||
}
|
||||
|
||||
$parsedPartList = [];
|
||||
|
||||
for ($i = 0; $i < count($splitterIndexList); $i++) {
|
||||
if ($i > 0) {
|
||||
$previousSplitterIndex = $splitterIndexList[$i - 1] + 1;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
$previousSplitterIndex = 0;
|
||||
}
|
||||
$part = trim(substr($expression, $previousSplitterIndex, $splitterIndexList[$i] - $previousSplitterIndex));
|
||||
|
||||
$part = trim(
|
||||
substr(
|
||||
$expression,
|
||||
$previousSplitterIndex,
|
||||
$splitterIndexList[$i] - $previousSplitterIndex
|
||||
)
|
||||
);
|
||||
|
||||
$parsedPartList[] = $this->parse($part);
|
||||
}
|
||||
return (object) [
|
||||
@@ -281,44 +310,62 @@ class Parser
|
||||
$firstOperator = null;
|
||||
$minIndex = null;
|
||||
|
||||
if ($expression === '') return (object) [
|
||||
'type' => 'value',
|
||||
'value' => null,
|
||||
];
|
||||
if ($expression === '') {
|
||||
return (object) [
|
||||
'type' => 'value',
|
||||
'value' => null,
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($this->priorityList as $operationList) {
|
||||
foreach ($operationList as $operator) {
|
||||
$startFrom = 1;
|
||||
|
||||
while (true) {
|
||||
$index = strpos($expression, $operator, $startFrom);
|
||||
if ($index === false) break;
|
||||
if ($expressionOutOfBraceList[$index]) break;
|
||||
|
||||
if ($index === false) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ($expressionOutOfBraceList[$index]) {
|
||||
break;
|
||||
}
|
||||
|
||||
$startFrom = $index + 1;
|
||||
}
|
||||
if ($index !== false) {
|
||||
$possibleRightOperator = null;
|
||||
|
||||
if (strlen($operator) === 1) {
|
||||
if ($index < strlen($expression) - 1) {
|
||||
$possibleRightOperator = trim($operator . $expression[$index + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
$possibleRightOperator &&
|
||||
$possibleRightOperator != $operator &&
|
||||
!empty($this->operatorMap[$possibleRightOperator])
|
||||
) continue;
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$possibleLeftOperator = null;
|
||||
|
||||
if (strlen($operator) === 1) {
|
||||
if ($index > 0) {
|
||||
$possibleLeftOperator = trim($expression[$index - 1] . $operator);
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
$possibleLeftOperator &&
|
||||
$possibleLeftOperator != $operator &&
|
||||
!empty($this->operatorMap[$possibleLeftOperator])
|
||||
) continue;
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$firstPart = substr($expression, 0, $index);
|
||||
$secondPart = substr($expression, $index + strlen($operator));
|
||||
@@ -326,6 +373,7 @@ class Parser
|
||||
$modifiedFirstPart = $modifiedSecondPart = '';
|
||||
|
||||
$isString = $this->processStrings($firstPart, $modifiedFirstPart);
|
||||
|
||||
$this->processStrings($secondPart, $modifiedSecondPart);
|
||||
|
||||
if (
|
||||
@@ -337,14 +385,18 @@ class Parser
|
||||
) {
|
||||
if ($minIndex === null) {
|
||||
$minIndex = $index;
|
||||
|
||||
$firstOperator = $operator;
|
||||
} else if ($index < $minIndex) {
|
||||
}
|
||||
else if ($index < $minIndex) {
|
||||
$minIndex = $index;
|
||||
|
||||
$firstOperator = $operator;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($firstOperator) {
|
||||
break;
|
||||
}
|
||||
@@ -358,7 +410,8 @@ class Parser
|
||||
$secondPart = trim($secondPart);
|
||||
|
||||
return $this->applyOperator($firstOperator, $firstPart, $secondPart);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
$expression = trim($expression);
|
||||
|
||||
if ($expression[0] === '!') {
|
||||
@@ -420,22 +473,25 @@ class Parser
|
||||
if ($expression === 'true') {
|
||||
return (object) [
|
||||
'type' => 'value',
|
||||
'value' => true
|
||||
'value' => true,
|
||||
];
|
||||
} else if ($expression === 'false') {
|
||||
}
|
||||
else if ($expression === 'false') {
|
||||
return (object) [
|
||||
'type' => 'value',
|
||||
'value' => false
|
||||
'value' => false,
|
||||
];
|
||||
} else if ($expression === 'null') {
|
||||
}
|
||||
else if ($expression === 'null') {
|
||||
return (object) [
|
||||
'type' => 'value',
|
||||
'value' => null
|
||||
'value' => null,
|
||||
];
|
||||
}
|
||||
|
||||
if ($expression[strlen($expression) - 1] === ')') {
|
||||
$firstOpeningBraceIndex = strpos($expression, '(');
|
||||
|
||||
if ($firstOpeningBraceIndex > 0) {
|
||||
$functionName = trim(substr($expression, 0, $firstOpeningBraceIndex));
|
||||
$functionContent = substr($expression, $firstOpeningBraceIndex + 1, -1);
|
||||
@@ -443,13 +499,14 @@ class Parser
|
||||
$argumentList = $this->parseArgumentListFromFunctionContent($functionContent);
|
||||
|
||||
$argumentSplitedList = [];
|
||||
|
||||
foreach ($argumentList as $argument) {
|
||||
$argumentSplitedList[] = $this->split($argument);
|
||||
}
|
||||
|
||||
return (object) [
|
||||
'type' => $functionName,
|
||||
'value' => $argumentSplitedList
|
||||
'value' => $argumentSplitedList,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -461,21 +518,28 @@ class Parser
|
||||
}
|
||||
}
|
||||
|
||||
protected function stripComments(string &$expression, string &$modifiedExpression)
|
||||
private function stripComments(string &$expression, string &$modifiedExpression): void
|
||||
{
|
||||
$commentIndexStart = null;
|
||||
|
||||
for ($i = 0; $i < strlen($modifiedExpression); $i++) {
|
||||
if (is_null($commentIndexStart)) {
|
||||
if ($modifiedExpression[$i] === '/' && $i < strlen($modifiedExpression) - 1 && $modifiedExpression[$i + 1] === '/') {
|
||||
if (
|
||||
$modifiedExpression[$i] === '/' &&
|
||||
$i < strlen($modifiedExpression) - 1 &&
|
||||
$modifiedExpression[$i + 1] === '/'
|
||||
) {
|
||||
$commentIndexStart = $i;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if ($modifiedExpression[$i] === "\n" || $i === strlen($modifiedExpression) - 1) {
|
||||
for ($j = $commentIndexStart; $j <= $i; $j++) {
|
||||
$modifiedExpression[$j] = ' ';
|
||||
|
||||
$expression[$j] = ' ';
|
||||
}
|
||||
|
||||
$commentIndexStart = null;
|
||||
}
|
||||
}
|
||||
@@ -486,19 +550,22 @@ class Parser
|
||||
if ($modifiedExpression[$i] === '/' && $modifiedExpression[$i + 1] === '*') {
|
||||
$commentIndexStart = $i;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if ($modifiedExpression[$i] === '*' && $modifiedExpression[$i + 1] === '/') {
|
||||
for ($j = $commentIndexStart; $j <= $i + 1; $j++) {
|
||||
$modifiedExpression[$j] = ' ';
|
||||
|
||||
$expression[$j] = ' ';
|
||||
}
|
||||
|
||||
$commentIndexStart = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function parseArgumentListFromFunctionContent(string $functionContent) : array
|
||||
private function parseArgumentListFromFunctionContent(string $functionContent): array
|
||||
{
|
||||
$functionContent = trim($functionContent);
|
||||
|
||||
@@ -511,21 +578,25 @@ class Parser
|
||||
|
||||
$commaIndexList = [];
|
||||
$braceCounter = 0;
|
||||
|
||||
for ($i = 0; $i < strlen($functionContent); $i++) {
|
||||
if ($functionContent[$i] === "'" && ($i === 0 || $functionContent[$i - 1] !== "\\")) {
|
||||
if (!$isString) {
|
||||
$isString = true;
|
||||
$isSingleQuote = true;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if ($isSingleQuote) {
|
||||
$isString = false;
|
||||
}
|
||||
}
|
||||
} else if ($functionContent[$i] === "\"" && ($i === 0 || $functionContent[$i - 1] !== "\\")) {
|
||||
}
|
||||
else if ($functionContent[$i] === "\"" && ($i === 0 || $functionContent[$i - 1] !== "\\")) {
|
||||
if (!$isString) {
|
||||
$isString = true;
|
||||
$isSingleQuote = false;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (!$isSingleQuote) {
|
||||
$isString = false;
|
||||
}
|
||||
@@ -535,7 +606,8 @@ class Parser
|
||||
if (!$isString) {
|
||||
if ($functionContent[$i] === '(') {
|
||||
$braceCounter++;
|
||||
} else if ($functionContent[$i] === ')') {
|
||||
}
|
||||
else if ($functionContent[$i] === ')') {
|
||||
$braceCounter--;
|
||||
}
|
||||
}
|
||||
@@ -548,13 +620,23 @@ class Parser
|
||||
$commaIndexList[] = strlen($functionContent);
|
||||
|
||||
$argumentList = [];
|
||||
|
||||
for ($i = 0; $i < count($commaIndexList); $i++) {
|
||||
if ($i > 0) {
|
||||
$previousCommaIndex = $commaIndexList[$i - 1] + 1;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
$previousCommaIndex = 0;
|
||||
}
|
||||
$argument = trim(substr($functionContent, $previousCommaIndex, $commaIndexList[$i] - $previousCommaIndex));
|
||||
|
||||
$argument = trim(
|
||||
substr(
|
||||
$functionContent,
|
||||
$previousCommaIndex,
|
||||
$commaIndexList[$i] - $previousCommaIndex
|
||||
)
|
||||
);
|
||||
|
||||
$argumentList[] = $argument;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,12 @@ class Processor
|
||||
?Entity $entity = null,
|
||||
?StdClass $variables = null
|
||||
) {
|
||||
$this->functionFactory = new FunctionFactory($this, $injectableFactory, $attributeFetcher, $functionClassNameMap);
|
||||
$this->functionFactory = new FunctionFactory(
|
||||
$this,
|
||||
$injectableFactory,
|
||||
$attributeFetcher,
|
||||
$functionClassNameMap
|
||||
);
|
||||
|
||||
$this->entity = $entity;
|
||||
$this->variables = $variables ?? (object) [];
|
||||
@@ -88,12 +93,14 @@ class Processor
|
||||
return $function->process($item->getArgumentList());
|
||||
}
|
||||
|
||||
private function processList(ArgumentList $args) : array
|
||||
private function processList(ArgumentList $args): array
|
||||
{
|
||||
$list = [];
|
||||
|
||||
foreach ($args as $item) {
|
||||
$list[] = $this->process($item);
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user