protected function getDomainEventMessage(array $document): DomainEventMessageInterface
    {
        $payload = $this
            ->getSerializer()
            ->unserialize(new SerializedObject(
                $document['payload']['name'],
                $document['payload']['data']
            ));

        /** @var PayloadInterface $payload */
        return new DomainEventMessage(
            $payload,
            new PayloadType($payload),
            $document['occurred_on']->toDateTime(),
            $document['aggregate_id'],
            $document['sequence'],
            $document['meta_data']
        );
    }

protected
function
getDomainEventMessage
(
array
$
document
)
:
DomainEventMessageInterface
{
$
payload
=
$
this
->
getSerializer
(
)
->
unserialize
(
new
SerializedObject
(
$
document
[
'payload'
]
[
'name'
]
,
$
document
[
'payload'
]
[
'data'
]
)
)
;
/** @var PayloadInterface $payload */
return
new
DomainEventMessage
(
$
payload
,
new
PayloadType
(
$
payload
)
,
$
document
[
'occurred_on'
]
->
toDateTime
(
)
,
$
document
[
'aggregate_id'
]
,
$
document
[
'sequence'
]
,
$
document
[
'meta_data'
]
)
;
}

Get domain event message from Mongo document.

@param array $document
@return DomainEventMessageInterface
@throws SerializerException

Get domain event message from Mongo document .


public function reset()
    {
        unset($this->entity);
        unset($this->entities);
        unset($this->forms);
        unset($this->valid);
        unset($this->params);
        $this->setOperation(self::OPERATION_NONE);
        unset($this->formValidators);
        $this->errorMessages = array();
        $this->useSessionMessage = true;

        return $this;
    }

public function reset ( ) { unset ( $ this -> entity ) ; unset ( $ this -> entities ) ; unset ( $ this -> forms ) ; unset ( $ this -> valid ) ; unset ( $ this -> params ) ; $ this -> setOperation ( self :: OPERATION_NONE ) ; unset ( $ this -> formValidators ) ; $ this -> errorMessages = array ( ) ; $ this -> useSessionMessage = true ; return $ this ; }


protected function normalizeMessages($messages)
    {
        $queue = array();

        foreach ($messages as $key => $value) {
            if (is_array($value) && count($value)) {
                $queue[$key] = (array) array_pop($value);
            } else {
                $queue[$key] = (array) $value;
            }
        }

        return $queue;
    }

protected function normalizeMessages ( $ messages ) { $ queue = array ( ) ; foreach ( $ messages as $ key => $ value ) { if ( is_array ( $ value ) && count ( $ value ) ) { $ queue [ $ key ] = ( array ) array_pop ( $ value ) ; } else { $ queue [ $ key ] = ( array ) $ value ; } } return $ queue ; }

This is here to format standard form validation errors, so that
we can use customized error messaging instead of the 1 message only
practice from using annotations.

@param $messages
@return array

This is here to format standard form validation errors so that we can use customized error messaging instead of the 1 message only practice from using annotations .


protected function postValidate($valid, Params $params, $options = array())
    {
        if ($valid) {
            foreach ($this->getEntities() as $tag => $entity) {
                $this->em()->persist($entity);
            }
            if (!isset($options[static::OPTION_NO_FLUSH]) || !$options[static::OPTION_NO_FLUSH]) {
                $this->em()->flush();
            }
        }
    }

protected function postValidate ( $ valid , Params $ params , $ options = array ( ) ) { if ( $ valid ) { foreach ( $ this -> getEntities ( ) as $ tag => $ entity ) { $ this -> em ( ) -> persist ( $ entity ) ; } if ( ! isset ( $ options [ static :: OPTION_NO_FLUSH ] ) || ! $ options [ static :: OPTION_NO_FLUSH ] ) { $ this -> em ( ) -> flush ( ) ; } } }

Called after all forms have been validated.
Passed the validation result
@param boolean $valid
@param Param   $params

Called after all forms have been validated . Passed the validation result


protected function formDataEvent($tag, $callable = null)
    {
        $this->getEventManager()->attach(self::EVENT_FORM_DATA.$tag, function ($event) use ($callable) {
            $eventParams = $event->getParams();
            /* @var $form \Zend\Form\Form */
            $form = $eventParams['form'];
            /* @var $data Param */
            $data = $eventParams['data'];
            if (!empty($callable) && is_callable($callable)) {
                $data = call_user_func($callable, $data);
            }
            $form->setData($data->get());
        });
    }

protected
function
formDataEvent
(
$
tag
,
$
callable
=
)
{
$
this
->
getEventManager
(
)
->
attach
(
self
::
EVENT_FORM_DATA
.
$
tag
,
function
(
$
event
)
use
(
$
callable
)
{
$
eventParams
=
$
event
->
getParams
(
)
;
/* @var $form \Zend\Form\Form */
$
form
=
$
eventParams
[
'form'
]
;
/* @var $data Param */
$
data
=
$
eventParams
[
'data'
]
;
if
(
!
empty
(
$
callable
)
&&
is_callable
(
$
callable
)
)
{
$
data
=
call_user_func
(
$
callable
,
$
data
)
;
}
$
form
->
setData
(
$
data
->
get
(
)
)
;
}
)
;
}

Utility method for attaching a form data event listener
Utility method for attaching a form data event listener
for a form by a given tag. The optional 'callable' method
should accept and return a Param object.
@param $tag
@param null $callable

Utility method for attaching a form data event listener Utility method for attaching a form data event listener for a form by a given tag . The optional callable method should accept and return a Param object .


public function getForms()
    {
        if (!isset($this->forms)) {
            $forms = array();
            $entities = $this->getEntities();
            // set up any connections
            $this->beforeFormGeneration($entities);
            foreach ($entities as $tag => $entity) {
                /* @var $form \Zend\Form\Form */
                $form = $this->entityToForm($entity);
                $this->getEventManager()
                    ->trigger(self::EVENT_CONFIGURE_FORM.$tag, $this, array(
                        'tag' => $tag,
                        'entity' => $entity,
                        'form' => $form,
                        'entities' => $entities,
                    ));
                $forms[$tag] = $form;
            }
            $this->forms = $forms;
        }

        return $this->forms;
    }

public
function
getForms
(
)
{
if
(
!
isset
(
$
this
->
forms
)
)
{
$
forms
=
array
(
)
;
$
entities
=
$
this
->
getEntities
(
)
;
// set up any connections
$
this
->
beforeFormGeneration
(
$
entities
)
;
foreach
(
$
entities
as
$
tag
=>
$
entity
)
{
/* @var $form \Zend\Form\Form */
$
form
=
$
this
->
entityToForm
(
$
entity
)
;
$
this
->
getEventManager
(
)
->
trigger
(
self
::
EVENT_CONFIGURE_FORM
.
$
tag
,
$
this
,
array
(
'tag'
=>
$
tag
,
'entity'
=>
$
entity
,
'form'
=>
$
form
,
'entities'
=>
$
entities
,
)
)
;
$
forms
[
$
tag
]
=
$
form
;
}
$
this
->
forms
=
$
forms
;
}
return
$
this
->
forms
;
}

Generate forms from entities
@return array


protected function removeStringFromArray(&$list, $value)
    {
        $index = array_search($value, $list);
        if ($index !== false) {
            unset($list[$index]);
        }

        return $this;
    }

protected function removeStringFromArray ( & $ list , $ value ) { $ index = array_search ( $ value , $ list ) ; if ( $ index !== false ) { unset ( $ list [ $ index ] ) ; } return $ this ; }

Modify array to remove the specified value
@param $list
@param $value
@return $this


final public function getEntities()
    {
        if (!isset($this->entities)) {
            $this->entities = array();
            $entities = $this->generateEntities();
            $entities[static::MAIN_TAG] = $this->getEntity();
            /* @var $entity \FzyCommon\Entity\BaseInterface */
            foreach ($entities as $tag => $entity) {
                $this->getEventManager()
                    ->trigger(self::EVENT_CONFIGURE_ENTITY.$tag, $this, array(
                        'tag' => $tag,
                        'entity' => $entity,
                        'entities' => $entities,
                    ));
                $this->entities[$tag] = $entity;
                $entity->setFormTag($tag);
            }
        }

        return $this->entities;
    }

Ensures 'generateEntities' is only ever invoked once.
Fires the EVENT_CONFIGURE_ENTITY event on each entity
to allow for any configuration.

TODO: test that this even actually gets fired and provides
access/configuration to the entity

@return array

Ensures generateEntities is only ever invoked once . Fires the EVENT_CONFIGURE_ENTITY event on each entity to allow for any configuration .


final public function swapEntity($tag, BaseInterface $entity)
    {
        if (!isset($this->entities[$tag])) {
            throw new \RuntimeException("Unable to swap entity that does not exist");
        }
        $this->entities[$tag] = $entity;
        $entity->setFormTag($tag);
        $this->getEventManager()
            ->trigger(self::EVENT_CONFIGURE_ENTITY.$tag, $this, array(
                'tag' => $tag,
                'entity' => $entity,
                'entities' => $this->getEntities(),
            ));

        return $this;
    }

Utility to replace an entity at a tag
@param $tag
@param  BaseInterface     $entity
@return $this
@throws \RuntimeException


public function configureFormToExcludeData($tag, array $elementNames)
    {
        $removeCallable = array($this, 'removeStringFromArray');
        $self = $this;
        $this->getEventManager()->attach(self::EVENT_CONFIGURE_FORM.$tag, function (Event $event) use ($elementNames, $self) {
            /* @var $form \Zend\Form\Form */
            $form = $event->getParam('form');
            $fieldsToValidate = array_keys($form->getElements());
            foreach ($elementNames as $elementToRemove) {
                $self->removeStringFromArray($fieldsToValidate, $elementToRemove);
            }
            $form->setValidationGroup($fieldsToValidate);
        });
    }

public
function
configureFormToExcludeData
(
$
tag
,
array
$
elementNames
)
{
$
removeCallable
=
array
(
$
this
,
'removeStringFromArray'
)
;
$
self
=
$
this
;
$
this
->
getEventManager
(
)
->
attach
(
self
::
EVENT_CONFIGURE_FORM
.
$
tag
,
function
(
Event
$
event
)
use
(
$
elementNames
,
$
self
)
{
/* @var $form \Zend\Form\Form */
$
form
=
$
event
->
getParam
(
'form'
)
;
$
fieldsToValidate
=
array_keys
(
$
form
->
getElements
(
)
)
;
foreach
(
$
elementNames
as
$
elementToRemove
)
{
$
self
->
removeStringFromArray
(
$
fieldsToValidate
,
$
elementToRemove
)
;
}
$
form
->
setValidationGroup
(
$
fieldsToValidate
)
;
}
)
;
}

Removes some elements from being validated; best used for subforms
@param $tag
@param array $elementNames

Removes some elements from being validated ; best used for subforms


public function setSubFormDataHandler($tag, $paramName)
    {
        $this->formDataEvent($tag, function (Params $params) use ($paramName) {return Params::create($params->get($paramName));});

        return $this;
    }

public function setSubFormDataHandler ( $ tag , $ paramName ) { $ this -> formDataEvent ( $ tag , function ( Params $ params ) use ( $ paramName ) { return Params :: create ( $ params -> get ( $ paramName ) ) ; } ) ; return $ this ; }

Handler for subform data
@param $tag
@param $paramName
@return $this


public function afterAttach($formObject, $form, $mainEntity, $tag)
    {
        foreach ($this->getExcludedFieldsForEntityTag($tag) as $fieldName) {
            /* @var \Zend\Form\Form $form */
            $form->remove($fieldName);
        }
    }

public
function
afterAttach
(
$
formObject
,
$
form
,
$
mainEntity
,
$
tag
)
{
foreach
(
$
this
->
getExcludedFieldsForEntityTag
(
$
tag
)
as
$
fieldName
)
{
/* @var \Zend\Form\Form $form */
$
form
->
remove
(
$
fieldName
)
;
}
}

Function meant to be run as a callback for attacheToMainEntity.

In this case, it's being used to filter form fields from the sub
forms and entities.

@param $formObject
@param $form
@param $mainEntity
@param $tag

Function meant to be run as a callback for attacheToMainEntity .


public function addResponse($response, $url = null)
    {
        if (is_string($response)) {
            $response = self::createResponseFromString($response);
        } elseif (is_resource($response)) {
            $response = self::createResponseFromFile($response);
        } elseif (!$response instanceof HTTP_Request2_Response &&
                  !$response instanceof Exception
        ) {
            throw new HTTP_Request2_Exception('Parameter is not a valid response');
        }
        $this->responses[] = array($response, $url);
    }

public
function
addResponse
(
$
response
,
$
url
=
)
{
if
(
is_string
(
$
response
)
)
{
$
response
=
self
::
createResponseFromString
(
$
response
)
;
}
elseif
(
is_resource
(
$
response
)
)
{
$
response
=
self
::
createResponseFromFile
(
$
response
)
;
}
elseif
(
!
$
response
instanceof
HTTP_Request2_Response
&&
!
$
response
instanceof
Exception
)
{
throw
new
HTTP_Request2_Exception
(
'Parameter is not a valid response'
)
;
}
$
this
->
responses
[
]
=
array
(
$
response
,
$
url
)
;
}

Adds response to the queue

@param mixed  $response either a string, a pointer to an open file,
an instance of HTTP_Request2_Response or Exception
@param string $url      A request URL this response should be valid for
(see {@link http://pear.php.net/bugs/bug.php?id=19276})

@throws   HTTP_Request2_Exception


public static function createResponseFromString($str)
    {
        $parts       = preg_split('!(\r?\n){2}!m', $str, 2);
        $headerLines = explode("\n", $parts[0]);
        $response    = new HTTP_Request2_Response(array_shift($headerLines));
        foreach ($headerLines as $headerLine) {
            $response->parseHeaderLine($headerLine);
        }
        $response->parseHeaderLine('');
        if (isset($parts[1])) {
            $response->appendBody($parts[1]);
        }
        return $response;
    }

public static function createResponseFromString ( $ str ) { $ parts = preg_split ( '!(\r?\n){2}!m' , $ str , 2 ) ; $ headerLines = explode ( "\n" , $ parts [ 0 ] ) ; $ response = new HTTP_Request2_Response ( array_shift ( $ headerLines ) ) ; foreach ( $ headerLines as $ headerLine ) { $ response -> parseHeaderLine ( $ headerLine ) ; } $ response -> parseHeaderLine ( '' ) ; if ( isset ( $ parts [ 1 ] ) ) { $ response -> appendBody ( $ parts [ 1 ] ) ; } return $ response ; }

Creates a new HTTP_Request2_Response object from a string

@param string $str string containing HTTP response message

@return   HTTP_Request2_Response
@throws   HTTP_Request2_Exception


public static function createResponseFromFile($fp)
    {
        $response = new HTTP_Request2_Response(fgets($fp));
        do {
            $headerLine = fgets($fp);
            $response->parseHeaderLine($headerLine);
        } while ('' != trim($headerLine));

        while (!feof($fp)) {
            $response->appendBody(fread($fp, 8192));
        }
        return $response;
    }

public static function createResponseFromFile ( $ fp ) { $ response = new HTTP_Request2_Response ( fgets ( $ fp ) ) ; do { $ headerLine = fgets ( $ fp ) ; $ response -> parseHeaderLine ( $ headerLine ) ; } while ( '' != trim ( $ headerLine ) ) ; while ( ! feof ( $ fp ) ) { $ response -> appendBody ( fread ( $ fp , 8192 ) ) ; } return $ response ; }

Creates a new HTTP_Request2_Response object from a file

@param resource $fp file pointer returned by fopen()

@return   HTTP_Request2_Response
@throws   HTTP_Request2_Exception


public function makeHeadVersion($entity) {
        if($entity->isHead()) {
            return false;
        }

        $oldHead = $entity->getHead();

        // update references on all old versions
        $this->entities->createQueryBuilder()
            ->update($this->entityName, 'o')
            ->set('o.headVersion', ':newHead')
            ->where('o.headVersion = :oldHead')
            ->setParameter('newHead', $entity)
            ->setParameter('oldHead', $oldHead)
            ->getQuery()
            ->execute();

        // make the old head now just a sub-version
        $oldHead->setHead($entity);
        $this->persist($oldHead, false);

        // make this entity the head
        $entity->setHead(null);
        $this->persist($entity, false);

        $this->entities->flush();
        return true;
    }

Makes an entity the head version.

@param object $entity
@return boolean


protected function needsNewVersion($entity) {
        if(!$entity->isHead()) {
            return false;
        }

        if(!$entity->hasVersions()) {
            return true;
        }

        $oldTimestamp = $entity->getVersions()->first()->getUpdatedAt();
        $newTimestamp = Carbon::now();
        $diff = $newTimestamp->diffInHours($oldTimestamp);

        if($diff >= 24) {
            return true;
        }
    }

protected function needsNewVersion ( $ entity ) { if ( ! $ entity -> isHead ( ) ) { return false ; } if ( ! $ entity -> hasVersions ( ) ) { return true ; } $ oldTimestamp = $ entity -> getVersions ( ) -> first ( ) -> getUpdatedAt ( ) ; $ newTimestamp = Carbon :: now ( ) ; $ diff = $ newTimestamp -> diffInHours ( $ oldTimestamp ) ; if ( $ diff >= 24 ) { return true ; } }

Determines if the entity needs a new version created.

@param $entity
@return boolean

Determines if the entity needs a new version created .


public function persist($entity, $version = 'guess') {
        $this->entities->persist($entity);

        if($version === 'new' || ($version === 'guess' && $this->needsNewVersion($entity))) {
            $this->makeNewVersion($entity, false);
            $return = true;
        } else {
            $return = false;
        }

        $this->entities->flush();

        return $return;
    }

public function persist ( $ entity , $ version = 'guess' ) { $ this -> entities -> persist ( $ entity ) ; if ( $ version === 'new' || ( $ version === 'guess' && $ this -> needsNewVersion ( $ entity ) ) ) { $ this -> makeNewVersion ( $ entity , false ) ; $ return = true ; } else { $ return = false ; } $ this -> entities -> flush ( ) ; return $ return ; }

Persists an entity. Creating a new version of it if needed.

@param object $entity
@param string $version
@return boolean true if a new version was created

Persists an entity . Creating a new version of it if needed .


public function clearVersions($entity) {
        $entity = $entity->getHead();
        $versions = $entity->getVersions();

        foreach($versions as $version) {
            $this->delete($version, false);
        }
        $versions->clear();
        $this->persist($entity, 'overwrite');

        return $entity;
    }

public function clearVersions ( $ entity ) { $ entity = $ entity -> getHead ( ) ; $ versions = $ entity -> getVersions ( ) ; foreach ( $ versions as $ version ) { $ this -> delete ( $ version , false ) ; } $ versions -> clear ( ) ; $ this -> persist ( $ entity , 'overwrite' ) ; return $ entity ; }

Clears old versions of an entity.

@param object $entity
@return object


private function cleanUp($path)
    {
        $fs = $this->getFilesystem();
        $parts = explode('/', $path);

        while (0 < count($parts)) {
            $key = implode('/', $parts);
            if ($fs->has($key)) {
                $dir = $fs->get($key);
                if (!$dir->isDir() || 0 < count($fs->listContents($key))) {
                    break;
                }
                if (!$fs->deleteDir($key)) {
                    throw new UploadException(sprintf('Failed to delete directory "%s".', $key));
                }
            }
            array_pop($parts);
        }
    }

private
function
cleanUp
(
$
path
)
{
$
fs
=
$
this
->
getFilesystem
(
)
;
$
parts
=
explode
(
'/'
,
$
path
)
;
while
(
0
<
count
(
$
parts
)
)
{
$
key
=
implode
(
'/'
,
$
parts
)
;
if
(
$
fs
->
has
(
$
key
)
)
{
$
dir
=
$
fs
->
get
(
$
key
)
;
if
(
!
$
dir
->
isDir
(
)
||
0
<
count
(
$
fs
->
listContents
(
$
key
)
)
)
{
break
;
}
if
(
!
$
fs
->
deleteDir
(
$
key
)
)
{
throw
new
UploadException
(
sprintf
(
'Failed to delete directory "%s".'
,
$
key
)
)
;
}
}
array_pop
(
$
parts
)
;
}
}

Removes the path directories if they are empty.

@param string $path
@throws UploadException

Removes the path directories if they are empty .


private function checkKey($sourceKey)
    {
        if ($this->mountManager->has($sourceKey)) {
            return true;
        }

        if ($this->reconnectDistantFs($sourceKey)) {
            if ($this->mountManager->has($sourceKey)) {
                return true;
            }
        }

        return false;
    }

private function checkKey ( $ sourceKey ) { if ( $ this -> mountManager -> has ( $ sourceKey ) ) { return true ; } if ( $ this -> reconnectDistantFs ( $ sourceKey ) ) { if ( $ this -> mountManager -> has ( $ sourceKey ) ) { return true ; } } return false ; }

Check the distant source key.

@param string $sourceKey
@return bool


private function moveKey($sourceKey, $targetKey)
    {
        if (!$this->isDistant($sourceKey)) {
            return $this->mountManager->move($sourceKey, $targetKey);
        }

        if ($this->mountManager->copy($sourceKey, $targetKey)) {
            return true;
        }
        if ($this->reconnectDistantFs($sourceKey)) {
            if ($this->mountManager->copy($sourceKey, $targetKey)) {
                return true;
            }
        }

        return false;
    }

private function moveKey ( $ sourceKey , $ targetKey ) { if ( ! $ this -> isDistant ( $ sourceKey ) ) { return $ this -> mountManager -> move ( $ sourceKey , $ targetKey ) ; } if ( $ this -> mountManager -> copy ( $ sourceKey , $ targetKey ) ) { return true ; } if ( $ this -> reconnectDistantFs ( $ sourceKey ) ) { if ( $ this -> mountManager -> copy ( $ sourceKey , $ targetKey ) ) { return true ; } } return false ; }

Copies or moves the distant source key to target key.

@param string $sourceKey
@param string $targetKey
@return bool

Copies or moves the distant source key to target key .


private function reconnectDistantFs($key)
    {
        /** @noinspection PhpUnusedLocalVariableInspection */
        list($prefix, $args) = $this->mountManager->filterPrefix([$key]);

        /** @var \League\Flysystem\FileSystem $fs */
        $fs = $this->mountManager->getFilesystem($prefix);
        $adapter = $fs->getAdapter();

        // Try reconnection
        if (!$adapter instanceof AbstractFtpAdapter) {
            return false;
        }

        $adapter->disconnect();
        sleep(1);
        $adapter->connect();

        return true;
    }

Reconnects the file system adapter if possible.

@param string $key
@return bool

Reconnects the file system adapter if possible .


private function isDistant($key)
    {
        /** @noinspection PhpUnusedLocalVariableInspection */
        list($prefix, $args) = $this->mountManager->filterPrefix([$key]);

        /** @var \League\Flysystem\FileSystem $fs */
        $fs = $this->mountManager->getFilesystem($prefix);
        $adapter = $fs->getAdapter();

        // Try reconnection
        if ($adapter instanceof AbstractFtpAdapter) {
            return true;
        }

        return false;
    }

Returns whether the key is distant.

@param string $key
@return bool


static private function createPath($path)
    {
        if (is_dir($path)) return true;
        $prev_path = substr($path, 0, (strrpos($path, '/', -2) + 1));
        $return    = self::createPath($prev_path);
        return ($return && is_writable($prev_path)) ? mkdir($path) : false;

    }

static private function createPath ( $ path ) { if ( is_dir ( $ path ) ) return true ; $ prev_path = substr ( $ path , 0 , ( strrpos ( $ path , '/' , - 2 ) + 1 ) ) ; $ return = self :: createPath ( $ prev_path ) ; return ( $ return && is_writable ( $ prev_path ) ) ? mkdir ( $ path ) : false ; }

Recursively create a long directory path

@method createPath()
@access private
@param  string $path Path to create.
@return boolean


public function find($id, bool $getRelations = null): ? Entity
    {
        if (! \is_string($id) && ! \is_int($id)) {
            throw new InvalidArgumentException('ID should be an int or string only.');
        }

        return $this->findBy(
                [$this->entity::getIdField() => $id],
                null,
                null,
                null,
                null,
                $getRelations
            )[0]
            ?? null;
    }

public
function
find
(
$
id
,
bool
$
getRelations
=
)
:
Entity
{
if
(
!
\
is_string
(
$
id
)
&&
!
\
is_int
(
$
id
)
)
{
throw
new
InvalidArgumentException
(
'ID should be an int or string only.'
)
;
}
return
$
this
->
findBy
(
[
$
this
->
entity
::
getIdField
(
)
=>
$
id
]
,
,
,
,
,
$
getRelations
)
[
0
]
??
;
}

Find a single entity given its id.

@param string|int $id
@param bool|null  $getRelations

@throws InvalidArgumentException If id is not a string or int

@return \Valkyrja\ORM\Entity|null


public function create(Entity $entity): bool
    {
        $this->validateEntity($entity);

        return $this->saveCreateDelete('insert', $entity);
    }

public function create ( Entity $ entity ) : bool { $ this -> validateEntity ( $ entity ) ; return $ this -> saveCreateDelete ( 'insert' , $ entity ) ; }

Create a new model.

<code>
$this->create(Entity::class)
</code>

@param \Valkyrja\ORM\Entity $entity

@throws ExecuteException
@throws InvalidArgumentException
@throws InvalidEntityException

@return bool


public function save(Entity $entity): bool
    {
        $this->validateEntity($entity);

        return $this->saveCreateDelete('update', $entity);
    }

public function save ( Entity $ entity ) : bool { $ this -> validateEntity ( $ entity ) ; return $ this -> saveCreateDelete ( 'update' , $ entity ) ; }

Save an existing model given criteria to find. If no criteria specified uses all model properties.

<code>
$this->save(Entity::class)
</code>

@param \Valkyrja\ORM\Entity $entity

@throws ExecuteException
@throws InvalidArgumentException
@throws InvalidEntityException

@return bool

Save an existing model given criteria to find . If no criteria specified uses all model properties .


public function delete(Entity $entity): bool
    {
        $this->validateEntity($entity);

        return $this->saveCreateDelete('delete', $entity);
    }

public function delete ( Entity $ entity ) : bool { $ this -> validateEntity ( $ entity ) ; return $ this -> saveCreateDelete ( 'delete' , $ entity ) ; }

Delete an existing model.

<code>
$this->delete(Entity::class)
</code>

@param \Valkyrja\ORM\Entity $entity

@throws ExecuteException
@throws InvalidArgumentException
@throws InvalidEntityException

@return bool


protected function validateEntity(Entity $entity): void
    {
        if (! ($entity instanceof $this->entity)) {
            throw new InvalidEntityException(
                'This repository expects entities to be instances of '
                . $this->entity
                . '. Entity instanced from '
                . \get_class($entity)
                . ' provided instead.'
            );
        }
    }

Validate the passed entity.

@param Entity $entity

@throws InvalidEntityException

@return void


protected function select(
        array $columns = null,
        array $criteria = null,
        array $orderBy = null,
        int $limit = null,
        int $offset = null,
        bool $getRelations = null
    ) {
        // Build the query
        $query = $this->selectQueryBuilder($columns, $criteria, $orderBy, $limit, $offset);

        // Create a new PDO statement from the query builder
        $stmt = $this->store->prepare($query->getQuery());

        // Iterate through the criteria once more
        foreach ($criteria as $column => $criterion) {
            // If the criterion is null
            if ($criterion === null) {
                // Skip as we've already set the where to IS NULL
                continue;
            }

            // If the criterion is an array
            if (\is_array($criterion)) {
                // Iterate through the criterion and bind each value individually
                foreach ($criterion as $index => $criterionItem) {
                    $stmt->bindValue($this->columnParam($column . $index), $criterionItem);
                }

                continue;
            }

            // And bind each value to the column
            $stmt->bindValue($this->columnParam($column), $criterion);
        }

        // Execute the PDO statement
        $stmt->execute();

        // Get all the results from the PDO statement
        $rows    = $stmt->fetchAll(PDO::FETCH_ASSOC);
        $results = [];

        // If the result of the query was a count
        if (isset($rows[0]['COUNT(*)'])) {
            return (int) $rows[0]['COUNT(*)'];
        }

        // Iterate through the rows found
        foreach ($rows as $row) {
            // Create a new model
            /** @var \Valkyrja\ORM\Entity $entity */
            $entity = new $this->entity();
            // Apply the model's contents given the row
            $entity->fromArray($row);

            // If no columns were specified then we can safely get all the relations
            if (null === $columns && $getRelations === true) {
                // Add the model to the final results
                $results[] = $this->getEntityRelations($entity);
            } else {
                // Add the model to the final results
                $results[] = $entity;
            }
        }

        return $results;
    }

Select entities by given criteria.

<code>
$this->select(
[
'column',
'column2',
],
[
'column'  => 'value',
'column2' => 'value2',
],
[
'column'
'column2' => OrderBy::ASC,
'column3' => OrderBy::DESC,
],
1,
1
)
</code>

@param array|null $columns
@param array|null $criteria
@param array|null $orderBy
@param int|null   $limit
@param int|null   $offset
@param bool|null  $getRelations

@throws InvalidArgumentException

@return \Valkyrja\ORM\Entity[]|int


protected function selectQueryBuilder(
        array $columns = null,
        array $criteria = null,
        array $orderBy = null,
        int $limit = null,
        int $offset = null
    ): QueryBuilder {
        // Create a new query
        $query = $this->entityManager
            ->getQueryBuilder()
            ->select($columns)
            ->table($this->table);

        // If criteria has been passed
        if (null !== $criteria) {
            $this->setCriteriaInQuery($query, $criteria);
        }

        // If order by has been passed
        if (null !== $orderBy) {
            $this->setOrderByInQuery($query, $orderBy);
        }

        // If a limit is passed
        if (null !== $limit) {
            $this->setLimitInQuery($query, $limit);
        }

        // If an offset is passed
        if (null !== $offset) {
            $this->setOffsetInQuery($query, $offset);
        }

        return $query;
    }

protected
function
selectQueryBuilder
(
array
$
columns
=
,
array
$
criteria
=
,
array
$
orderBy
=
,
int
$
limit
=
,
int
$
offset
=
)
:
QueryBuilder
{
// Create a new query
$
query
=
$
this
->
entityManager
->
getQueryBuilder
(
)
->
select
(
$
columns
)
->
table
(
$
this
->
table
)
;
// If criteria has been passed
if
(
!==
$
criteria
)
{
$
this
->
setCriteriaInQuery
(
$
query
,
$
criteria
)
;
}
// If order by has been passed
if
(
!==
$
orderBy
)
{
$
this
->
setOrderByInQuery
(
$
query
,
$
orderBy
)
;
}
// If a limit is passed
if
(
!==
$
limit
)
{
$
this
->
setLimitInQuery
(
$
query
,
$
limit
)
;
}
// If an offset is passed
if
(
!==
$
offset
)
{
$
this
->
setOffsetInQuery
(
$
query
,
$
offset
)
;
}
return
$
query
;
}

Build a select query statement by given criteria.

<code>
$this->queryBuilder(
[
'column',
'column2',
],
[
'column'  => 'value',
'column2' => 'value2',
],
[
'column'
'column2' => OrderBy::ASC,
'column3' => OrderBy::DESC,
],
1,
1
)
</code>

@param array|null $columns
@param array|null $criteria
@param array|null $orderBy
@param int|null   $limit
@param int|null   $offset

@return QueryBuilder

Build a select query statement by given criteria .


protected function setCriteriaInQuery(QueryBuilder $query, array $criteria): void
    {
        // Iterate through each criteria and set the column = :column
        // so we can use bindColumn() in PDO later
        foreach ($criteria as $column => $criterion) {
            // If the criterion is null
            if ($criterion === null) {
                $this->setNullCriterionInQuery($query, $column);

                continue;
            }

            // If the criterion is an array
            if (\is_array($criterion)) {
                $this->setArrayCriterionInQuery($query, $column, $criterion);

                continue;
            }

            // If the criterion has a percent at the start or the end
            if ($criterion[0] === '%' || $criterion[\strlen($criterion) - 1] === '%') {
                $this->setLikeCriterionInQuery($query, $column);

                continue;
            }

            $this->setEqualCriterionInQuery($query, $column);
        }
    }

Set the criteria in the query builder.

@param QueryBuilder $query
@param array        $criteria

@return void


protected function setArrayCriterionInQuery(QueryBuilder $query, string $column, array $criterion): void
    {
        $criterionConcat = '';
        $lastIndex       = \count($criterion) - 1;

        // Iterate through the criterion and set each item individually to be bound later
        foreach ($criterion as $index => $criterionItem) {
            $criterionConcat .= $this->columnParam($column . $index);

            // If this is not the last index, add a comma
            if ($index < $lastIndex) {
                $criterionConcat .= ',';
            }
        }

        // Set the where statement as an in
        $query->where($column . ' IN (' . $criterionConcat . ')');
    }

Set an array criterion in the query builder.

@param QueryBuilder $query
@param string       $column
@param array        $criterion

@return void

Set an array criterion in the query builder .


protected function setOrderByInQuery(QueryBuilder $query, array $orderBy): void
    {
        // Iterate through each order by
        foreach ($orderBy as $column => $order) {
            // Switch through the order (value) set
            switch ($order) {
                // If the order is ascending
                case OrderBy::ASC:
                    // Set the column via the orderByAsc method
                    $query->orderByAsc($column);
                    break;
                // If the order is descending
                case OrderBy::DESC:
                    // Set the column via the orderByDesc method
                    $query->orderByDesc($column);
                    break;
                default:
                    // Otherwise set the order (which is the column)
                    $query->orderBy($order);
                    break;
            }
        }
    }

Set the order by options in a query builder.

@param QueryBuilder $query
@param array        $orderBy

@return void

Set the order by options in a query builder .


protected function saveCreateDelete(string $type, Entity $entity): int
    {
        if (! $this->store->inTransaction()) {
            $this->store->beginTransaction();
        }

        // Create a new query
        $query      = $this->entityManager
            ->getQueryBuilder()
            ->table($this->table)
            ->{$type}();
        $idField    = $entity::getIdField();
        $properties = $entity->forDataStore();

        /* @var QueryBuilder $query */

        // If this is an insert
        if ($type === 'insert') {
            // Ensure all the required properties are set
            $this->ensureRequiredProperties($entity, $properties);
        }

        // If this type isn't an insert
        if ($type !== 'insert') {
            // Set the id for the where clause
            $query->where($idField . ' = ' . $this->criterionParam($idField));
        }

        if ($type !== 'delete') {
            // Set the properties
            $this->setPropertiesForSaveCreateDeleteQuery($query, $properties);
        }

        // Prepare a PDO statement with the query
        $stmt = $this->store->prepare($query->getQuery());

        // If this type isn't an insert
        if ($type !== 'insert') {
            // Set the id value for the where clause
            $stmt->bindValue($this->criterionParam($idField), $properties[$idField]);
        }

        if ($type !== 'delete') {
            // Set the properties.
            $this->setPropertiesForSaveCreateDeleteStatement($stmt, $properties);
        }

        // If the execute failed
        if (! $executeResult = $stmt->execute()) {
            // Throw a fail exception
            throw new ExecuteException($stmt->errorInfo()[2]);
        }

        return $executeResult;
    }

Save or create or delete a row.

<code>
$this
->saveOrCreate(
'update' | 'insert' | 'delete',
Entity::class
)
</code>

@param string $type
@param Entity $entity

@throws ExecuteException
@throws InvalidArgumentException

@return int


protected function setPropertiesForSaveCreateDeleteQuery(QueryBuilder $query, array $properties): void
    {
        // Iterate through the properties
        foreach ($properties as $column => $property) {
            if ($property === null) {
                continue;
            }

            // Set the column and param name
            $query->set($column, $this->columnParam($column));
        }
    }

protected
function
setPropertiesForSaveCreateDeleteQuery
(
QueryBuilder
$
query
,
array
$
properties
)
:
void
{
// Iterate through the properties
foreach
(
$
properties
as
$
column
=>
$
property
)
{
if
(
$
property
===
)
{
continue
;
}
// Set the column and param name
$
query
->
set
(
$
column
,
$
this
->
columnParam
(
$
column
)
)
;
}
}

Set properties for save, delete, or create queries.

@param QueryBuilder $query
@param array        $properties

@return void

Set properties for save delete or create queries .


protected function setPropertiesForSaveCreateDeleteStatement(PDOStatement $statement, array $properties): void
    {
        // Iterate through the properties
        foreach ($properties as $column => $property) {
            if ($property === null) {
                continue;
            }

            // If the property is an object, then serialize it
            if (\is_object($property)) {
                $property = \serialize($property);
            } // Otherwise json encode if its an array
            elseif (\is_array($property)) {
                $property = \json_encode($property);
            }

            $type = PDO::PARAM_STR;

            if (\is_int($property) || \is_bool($property)) {
                $type     = PDO::PARAM_INT;
                $property = (int) $property;
            }

            // Bind each column's value to the statement
            $statement->bindValue($this->columnParam($column), $property, $type);
        }
    }

Set properties for save, create, or delete statements.

@param PDOStatement $statement
@param array        $properties

@return void

Set properties for save create or delete statements .


protected function getEntityRelations(Entity $entity): Entity
    {
        $propertyTypes  = $entity::getPropertyTypes();
        $propertyMapper = $entity->getPropertyMapper();

        // Iterate through the property types
        foreach ($propertyTypes as $property => $type) {
            $entityName  = \is_array($type) ? $type[0] : $type;
            $propertyMap = $propertyMapper[$property] ?? null;

            if (null !== $propertyMap && (\is_array($type) || ! PropertyType::isValid($type))) {
                $repository   = $this->entityManager->getRepository($entityName);
                $orderBy      = $propertyMap[PropertyMap::ORDER_BY] ?? null;
                $limit        = $propertyMap[PropertyMap::LIMIT] ?? null;
                $offset       = $propertyMap[PropertyMap::OFFSET] ?? null;
                $columns      = $propertyMap[PropertyMap::COLUMNS] ?? null;
                $getRelations = $propertyMap[PropertyMap::GET_RELATIONS] ?? true;

                unset(
                    $propertyMap[PropertyMap::ORDER_BY],
                    $propertyMap[PropertyMap::LIMIT],
                    $propertyMap[PropertyMap::OFFSET],
                    $propertyMap[PropertyMap::COLUMNS],
                    $propertyMap[PropertyMap::GET_RELATIONS]
                );

                $entities = $repository->findBy($propertyMap, $orderBy, $limit, $offset, $columns, $getRelations);

                if (\is_array($type)) {
                    $entity->{$property} = $entities;

                    continue;
                }

                if (empty($entities)) {
                    continue;
                }

                $entity->{$property} = $entities[0];
            }
        }

        return $entity;
    }

protected
function
getEntityRelations
(
Entity
$
entity
)
:
Entity
{
$
propertyTypes
=
$
entity
::
getPropertyTypes
(
)
;
$
propertyMapper
=
$
entity
->
getPropertyMapper
(
)
;
// Iterate through the property types
foreach
(
$
propertyTypes
as
$
property
=>
$
type
)
{
$
entityName
=
\
is_array
(
$
type
)
$
type
[
0
]
:
$
type
;
$
propertyMap
=
$
propertyMapper
[
$
property
]
??
;
if
(
!==
$
propertyMap
&&
(
\
is_array
(
$
type
)
||
!
PropertyType
::
isValid
(
$
type
)
)
)
{
$
repository
=
$
this
->
entityManager
->
getRepository
(
$
entityName
)
;
$
orderBy
=
$
propertyMap
[
PropertyMap
::
ORDER_BY
]
??
;
$
limit
=
$
propertyMap
[
PropertyMap
::
LIMIT
]
??
;
$
offset
=
$
propertyMap
[
PropertyMap
::
OFFSET
]
??
;
$
columns
=
$
propertyMap
[
PropertyMap
::
COLUMNS
]
??
;
$
getRelations
=
$
propertyMap
[
PropertyMap
::
GET_RELATIONS
]
??
true
;
unset
(
$
propertyMap
[
PropertyMap
::
ORDER_BY
]
,
$
propertyMap
[
PropertyMap
::
LIMIT
]
,
$
propertyMap
[
PropertyMap
::
OFFSET
]
,
$
propertyMap
[
PropertyMap
::
COLUMNS
]
,
$
propertyMap
[
PropertyMap
::
GET_RELATIONS
]
)
;
$
entities
=
$
repository
->
findBy
(
$
propertyMap
,
$
orderBy
,
$
limit
,
$
offset
,
$
columns
,
$
getRelations
)
;
if
(
\
is_array
(
$
type
)
)
{
$
entity
->
{
$
property
}
=
$
entities
;
continue
;
}
if
(
empty
(
$
entities
)
)
{
continue
;
}
$
entity
->
{
$
property
}
=
$
entities
[
0
]
;
}
}
return
$
entity
;
}

Get an entity with all its relations.

@param Entity $entity

@return Entity


protected function ensureRequiredProperties(Entity $entity, array $properties): void
    {
        // Iterate through the required properties
        foreach ($entity::getRequiredProperties() as $requiredProperty) {
            // If the required property is not set
            if (! isset($properties[$requiredProperty])) {
                // Throw an exception
                throw new InvalidArgumentException('Missing required property: ' . $requiredProperty);
            }
        }
    }

Ensure all required properties have been passed.

@param Entity $entity
@param array  $properties

@throws InvalidArgumentException

@return void

Ensure all required properties have been passed .


private function broadcast($body)
    {
        $method   = 'POST';
        $url      = "{$this->domain}/broadcast";
        $headears = $this->getHeaders();
        $body     = json_encode($body);

        try {
            $request = $this->getClient()->request($method, $url, [
                'headers' => $headears,
                'body'    => $body
            ]);

            $response = $request->getBody()->getContents();

            return json_decode($response, true);

        } catch (RequestException $e) {
            $response = $e->getResponse()->getBody()->getContents();
            $response = json_decode($response, true);
            return $response;
        } catch (\Exception $e) {
            return ['error' => $e->getCode(), 'error_description' => $e->getMessage()];
        }
    }

private function broadcast ( $ body ) { $ method = 'POST' ; $ url = "{$this->domain}/broadcast" ; $ headears = $ this -> getHeaders ( ) ; $ body = json_encode ( $ body ) ; try { $ request = $ this -> getClient ( ) -> request ( $ method , $ url , [ 'headers' => $ headears , 'body' => $ body ] ) ; $ response = $ request -> getBody ( ) -> getContents ( ) ; return json_decode ( $ response , true ) ; } catch ( RequestException $ e ) { $ response = $ e -> getResponse ( ) -> getBody ( ) -> getContents ( ) ; $ response = json_decode ( $ response , true ) ; return $ response ; } catch ( \ Exception $ e ) { return [ 'error' => $ e -> getCode ( ) , 'error_description' => $ e -> getMessage ( ) ] ; } }

Execute broadcast operations

@param array  $body
@return array


public function exec($do, array $params)
    {
        $body = call_user_func_array(array($this->operations, $do), $params);

        return $this->broadcast($body);
    }

public function exec ( $ do , array $ params ) { $ body = call_user_func_array ( array ( $ this -> operations , $ do ) , $ params ) ; return $ this -> broadcast ( $ body ) ; }

Execute an operation to broadcast!

@param  string $do     Name of the operation
@param  array  $params Required parameters
@return array


private function getScriptSrc($callbackName = null)
    {
        $queries = [];

        if ($this->hasLang()) {
            array_set($queries, 'hl', $this->lang);
        }

        if ($this->hasCallbackName($callbackName)) {
            array_set($queries, 'onload', $callbackName);
            array_set($queries, 'render', 'explicit');
        }

        return static::CLIENT_URL . (count($queries) ? '?' . http_build_query($queries) : '');
    }

private function getScriptSrc ( $ callbackName = null ) { $ queries = [ ] ; if ( $ this -> hasLang ( ) ) { array_set ( $ queries , 'hl' , $ this -> lang ) ; } if ( $ this -> hasCallbackName ( $ callbackName ) ) { array_set ( $ queries , 'onload' , $ callbackName ) ; array_set ( $ queries , 'render' , 'explicit' ) ; } return static :: CLIENT_URL . ( count ( $ queries ) ? '?' . http_build_query ( $ queries ) : '' ) ; }

Get script source link.

@param  string|null  $callbackName

@return string


public function display($name = null, array $attributes = [])
    {
        $output = $this->attributes->build($this->siteKey, array_merge(
            $this->attributes->prepareNameAttribute($name),
            $attributes
        ));

        return '<div ' . $output . '></div>';
    }

public
function
display
(
$
name
=
,
array
$
attributes
=
[
]
)
{
$
output
=
$
this
->
attributes
->
build
(
$
this
->
siteKey
,
array_merge
(
$
this
->
attributes
->
prepareNameAttribute
(
$
name
)
,
$
attributes
)
)
;
return
'<div '
.
$
output
.
'></div>'
;
}

Display Captcha.

@param  string|null  $name
@param  array        $attributes

@return string


public function image($name = null, array $attributes = [])
    {
        return $this->display(
            $name, array_merge($attributes, $this->attributes->getImageAttribute())
        );
    }

public function image ( $ name = null , array $ attributes = [ ] ) { return $ this -> display ( $ name , array_merge ( $ attributes , $ this -> attributes -> getImageAttribute ( ) ) ) ; }

Display image Captcha.

@param  string|null  $name
@param  array        $attributes

@return string


public function audio($name = null, array $attributes = [])
    {
        return $this->display(
            $name, array_merge($attributes, $this->attributes->getAudioAttribute())
        );
    }

public function audio ( $ name = null , array $ attributes = [ ] ) { return $ this -> display ( $ name , array_merge ( $ attributes , $ this -> attributes -> getAudioAttribute ( ) ) ) ; }

Display audio Captcha.

@param  string|null  $name
@param  array        $attributes

@return string


public function verify($response, $clientIp = null)
    {
        if (empty($response)) return false;

        $response = $this->sendVerifyRequest([
            'secret'   => $this->secret,
            'response' => $response,
            'remoteip' => $clientIp
        ]);

        return isset($response['success']) && $response['success'] === true;
    }

public function verify ( $ response , $ clientIp = null ) { if ( empty ( $ response ) ) return false ; $ response = $ this -> sendVerifyRequest ( [ 'secret' => $ this -> secret , 'response' => $ response , 'remoteip' => $ clientIp ] ) ; return isset ( $ response [ 'success' ] ) && $ response [ 'success' ] === true ; }

Verify Response.

@param  string  $response
@param  string  $clientIp

@return bool


public function verifyRequest(ServerRequestInterface $request)
    {
        $body   = $request->getParsedBody();
        $server = $request->getServerParams();

        $response = isset($body[self::CAPTCHA_NAME])
            ? $body[self::CAPTCHA_NAME]
            : '';

        $remoteIp = isset($server['REMOTE_ADDR'])
            ? $server['REMOTE_ADDR']
            : null;

        return $this->verify($response, $remoteIp);
    }

public function verifyRequest ( ServerRequestInterface $ request ) { $ body = $ request -> getParsedBody ( ) ; $ server = $ request -> getServerParams ( ) ; $ response = isset ( $ body [ self :: CAPTCHA_NAME ] ) ? $ body [ self :: CAPTCHA_NAME ] : '' ; $ remoteIp = isset ( $ server [ 'REMOTE_ADDR' ] ) ? $ server [ 'REMOTE_ADDR' ] : null ; return $ this -> verify ( $ response , $ remoteIp ) ; }

Calls the reCAPTCHA siteverify API to verify whether the user passes CAPTCHA
test using a PSR-7 ServerRequest object.

@param  \Psr\Http\Message\ServerRequestInterface  $request

@return bool

Calls the reCAPTCHA siteverify API to verify whether the user passes CAPTCHA test using a PSR - 7 ServerRequest object .


public function script($callbackName = null)
    {
        $script = '';

        if ( ! $this->scriptLoaded) {
            $script = '<script src="' . $this->getScriptSrc($callbackName) . '" async defer></script>';
            $this->scriptLoaded = true;
        }

        return $script;
    }

public
function
script
(
$
callbackName
=
)
{
$
script
=
''
;
if
(
!
$
this
->
scriptLoaded
)
{
$
script
=
'<script src="'
.
$
this
->
getScriptSrc
(
$
callbackName
)
.
'" async defer></script>'
;
$
this
->
scriptLoaded
=
true
;
}
return
$
script
;
}

Get script tag.

@param  string|null  $callbackName

@return string


public function scriptWithCallback(array $captchas, $callbackName = 'captchaRenderCallback')
    {
        $script = $this->script($callbackName);

        if (empty($script) || empty($captchas)) {
            return $script;
        }

        return implode(PHP_EOL, [implode(PHP_EOL, [
            '<script>',
                "
                var ".implode(',', $captchas).";
                var $callbackName = function() {",
                    $this->renderCaptchas($captchas),
                '};',
            '</script>'
        ]), $script]);
    }

";
                var $callbackName = function() {"

Get script tag with a callback function.

@param  array   $captchas
@param  string  $callbackName

@return string

Get script tag with a callback function .


private function checkKey($name, &$value)
    {
        $this->checkIsString($name, $value);

        $value = trim($value);

        $this->checkIsNotEmpty($name, $value);
    }

private function checkKey ( $ name , & $ value ) { $ this -> checkIsString ( $ name , $ value ) ; $ value = trim ( $ value ) ; $ this -> checkIsNotEmpty ( $ name , $ value ) ; }

Check key.

@param  string  $name
@param  string  $value

@throws \Arcanedev\NoCaptcha\Exceptions\ApiException


private function checkIsString($name, $value)
    {
        if ( ! is_string($value)) {
            throw new Exceptions\ApiException(
                'The ' . $name . ' must be a string value, ' . gettype($value) . ' given'
            );
        }
    }

private
function
checkIsString
(
$
name
,
$
value
)
{
if
(
!
is_string
(
$
value
)
)
{
throw
new
Exceptions
\
ApiException
(
'The '
.
$
name
.
' must be a string value, '
.
gettype
(
$
value
)
.
' given'
)
;
}
}

Check if the value is a string value.

@param  string  $name
@param  string  $value

@throws \Arcanedev\NoCaptcha\Exceptions\ApiException


private function sendVerifyRequest(array $query = [])
    {
        $query    = array_filter($query);
        $url      = static::VERIFY_URL . '?' . http_build_query($query);
        $response = $this->request->send($url);

        return $response;
    }

private function sendVerifyRequest ( array $ query = [ ] ) { $ query = array_filter ( $ query ) ; $ url = static :: VERIFY_URL . '?' . http_build_query ( $ query ) ; $ response = $ this -> request -> send ( $ url ) ; return $ response ; }

Send verify request to API and get response.

@param  array  $query

@return array

Send verify request to API and get response .


public function init()
    {
        parent::init();
        if (is_array($this->theme)) {
            if (!isset($this->theme['class'])) {
                $this->theme['class'] = 'Reaction\Base\Theme';
            }
            $this->theme = \Reaction::create($this->theme);
        } elseif (is_string($this->theme)) {
            $this->theme = \Reaction::create($this->theme);
        }
    }

public function init ( ) { parent :: init ( ) ; if ( is_array ( $ this -> theme ) ) { if ( ! isset ( $ this -> theme [ 'class' ] ) ) { $ this -> theme [ 'class' ] = 'Reaction\Base\Theme' ; } $ this -> theme = \ Reaction :: create ( $ this -> theme ) ; } elseif ( is_string ( $ this -> theme ) ) { $ this -> theme = \ Reaction :: create ( $ this -> theme ) ; } }


public function findViewFile($view, $context = null)
    {
        if (strncmp($view, '@', 1) === 0) {
            // e.g. "@app/views/main"
            $file = \Reaction::$app->getAlias($view);
        } elseif (strncmp($view, '//', 2) === 0) {
            // e.g. "//layouts/main"
            $file = Reaction::$app->getViewPath() . DIRECTORY_SEPARATOR . ltrim($view, '/');
        } elseif ($context instanceof ViewContextInterface) {
            $view = ltrim($view, '/');
            $file = $context->getViewPath() . DIRECTORY_SEPARATOR . $view;
        } elseif (($currentViewFile = $this->getViewFile()) !== false) {
            $file = dirname($currentViewFile) . DIRECTORY_SEPARATOR . $view;
        } else {
            throw new InvalidCallException("Unable to resolve view file for view '$view': no active view context.");
        }

        $pathInfo = pathinfo($file, PATHINFO_EXTENSION);
        if ($pathInfo !== '' && !empty($pathInfo)) {
            return $file;
        }
        $path = $file . '.' . $this->defaultExtension;
        if ($this->defaultExtension !== 'php' && !is_file($path)) {
            $path = $file . '.php';
        }

        return $path;
    }

Finds the view file based on the given view name.
@param string $view the view name or the [path alias](guide:concept-aliases) of the view file. Please refer to [[render()]]
on how to specify this parameter.
@param object $context the context to be assigned to the view and can later be accessed via [[context]]
in the view. If the context implements [[ViewContextInterface]], it may also be used to locate
the view file corresponding to a relative view name.
@return string the view file path. Note that the file may not exist.
@throws InvalidCallException if a relative view name is given while there is no active context to
determine the corresponding view file.

Finds the view file based on the given view name .


public static function renderPhpStateless($_file_, $_params_ = [])
    {
        $_file_ = Reaction::$app->getAlias($_file_);
        $_obInitialLevel_ = ob_get_level();
        ob_start();
        ob_implicit_flush(false);
        extract($_params_, EXTR_OVERWRITE);
        try {
            require $_file_;
            return ob_get_clean();
        } catch (\Exception $e) {
            while (ob_get_level() > $_obInitialLevel_) {
                if (!@ob_end_clean()) {
                    ob_clean();
                }
            }
            throw $e;
        } catch (\Throwable $e) {
            while (ob_get_level() > $_obInitialLevel_) {
                if (!@ob_end_clean()) {
                    ob_clean();
                }
            }
            throw $e;
        }
    }

public static function renderPhpStateless ( $ _file_ , $ _params_ = [ ] ) { $ _file_ = Reaction :: $ app -> getAlias ( $ _file_ ) ; $ _obInitialLevel_ = ob_get_level ( ) ; ob_start ( ) ; ob_implicit_flush ( false ) ; extract ( $ _params_ , EXTR_OVERWRITE ) ; try { require $ _file_ ; return ob_get_clean ( ) ; } catch ( \ Exception $ e ) { while ( ob_get_level ( ) > $ _obInitialLevel_ ) { if ( ! @ ob_end_clean ( ) ) { ob_clean ( ) ; } } throw $ e ; } catch ( \ Throwable $ e ) { while ( ob_get_level ( ) > $ _obInitialLevel_ ) { if ( ! @ ob_end_clean ( ) ) { ob_clean ( ) ; } } throw $ e ; } }

Static helper for rendering any php file
@param string $_file_
@param array $_params_
@return string
@throws \Throwable


public function registerPostTypes()
    {

        if (!function_exists('register_post_type')) {
            return;
        }

        $this->postTypes->rewind();
        while ($this->postTypes->valid()) {

            $postType = $this->postTypes->current();
            register_post_type($postType->getName(), $postType->getArgs());
            $this->postTypes->next();

        }

    }

public function registerPostTypes ( ) { if ( ! function_exists ( 'register_post_type' ) ) { return ; } $ this -> postTypes -> rewind ( ) ; while ( $ this -> postTypes -> valid ( ) ) { $ postType = $ this -> postTypes -> current ( ) ; register_post_type ( $ postType -> getName ( ) , $ postType -> getArgs ( ) ) ; $ this -> postTypes -> next ( ) ; } }

Registers all the post types added
@author Tim Perry


public function generateToken($token, KeyPairReference $keyPair = null)
	{
		return new Token($token, $this->prepareKeyPair($keyPair));
	}

public function generateToken ( $ token , KeyPairReference $ keyPair = null ) { return new Token ( $ token , $ this -> prepareKeyPair ( $ keyPair ) ) ; }

Generates a new token object

@param  string 					$token 		token string to use
@param  KeyPairReference|null 	$keyPair 	key pair to use with encrypting token (optional)
@return TokenInterface generated token


public function generateMemoryToken($token, KeyPairReference $keyPair = null)
	{
		return new MemoryToken($token, $this->prepareKeyPair($keyPair));
	}

public function generateMemoryToken ( $ token , KeyPairReference $ keyPair = null ) { return new MemoryToken ( $ token , $ this -> prepareKeyPair ( $ keyPair ) ) ; }

Generates a new memory token object; decrypted token is stored in memory during execution

@param  string 					$token 		Token string to use
@param  KeyPairReference|null	$keyPair 	Key pair to use with encrypting token (optional)
@return TokenInterface Generated token

Generates a new memory token object ; decrypted token is stored in memory during execution


public function execute(string $projectFolder) {
    $shell = $this->getShell()->setDirectory(implode(DIRECTORY_SEPARATOR, [rtrim($this->getBaseFolder(), '\/'), ltrim($projectFolder, '\/')]));
    $shell->run($this->getCommandBuilder()->reset()->addParam('prototype'));
    $shell->run($this->getCommandBuilder()->reset()->addParam('update'));
  }

public function execute ( string $ projectFolder ) { $ shell = $ this -> getShell ( ) -> setDirectory ( implode ( DIRECTORY_SEPARATOR , [ rtrim ( $ this -> getBaseFolder ( ) , '\/' ) , ltrim ( $ projectFolder , '\/' ) ] ) ) ; $ shell -> run ( $ this -> getCommandBuilder ( ) -> reset ( ) -> addParam ( 'prototype' ) ) ; $ shell -> run ( $ this -> getCommandBuilder ( ) -> reset ( ) -> addParam ( 'update' ) ) ; }

Builds the project path from the basePath and the given project folder, then executes the composer prototyp and composer update commands with the commandBuilder and the
shell.

The commandBuilder is reset before every use so this could be executed multiple times

@param string $projectFolder

Builds the project path from the basePath and the given project folder then executes the composer prototyp and composer update commands with the commandBuilder and the shell .


public function messageFilterCallback( $key /*...*/ ) {
		$params = func_get_args();
		array_shift( $params );
		if ( count( $params ) == 1 && is_array( $params[0] ) ) {
			// Unwrap args array
			$params = $params[0];
		}
		$msg = $this->ctx->message( $key, $params );
		return $msg->plain();
	}

public
function
messageFilterCallback
(
$
key
/*...*/
)
{
$
params
=
func_get_args
(
)
;
array_shift
(
$
params
)
;
if
(
count
(
$
params
)
==
1
&&
is_array
(
$
params
[
0
]
)
)
{
// Unwrap args array
$
params
=
$
params
[
0
]
;
}
$
msg
=
$
this
->
ctx
->
message
(
$
key
,
$
params
)
;
return
$
msg
->
plain
(
)
;
}

Callback for 'message' filter.

<code>
{{ 'my-message-key'|message }}
{{ 'my-message-key'|message( 'foo', 'bar' ) }}
{{ 'my-message-key'|message( [ 'foo', 'bar' ] ) }}
{{ 'my-message-key'|message( 'foo', 'bar' )|raw }}
</code>

@param string $key Message key
@param string ... Message params
@return string Unescaped message content
@see I18nContext::message


public function notice($message, array $context = array(), $traceShift = 0)
    {
        $this->log(LogLevel::NOTICE, $message, $context, $traceShift);
    }

public function notice ( $ message , array $ context = array ( ) , $ traceShift = 0 ) { $ this -> log ( LogLevel :: NOTICE , $ message , $ context , $ traceShift ) ; }

Normal but significant events.

@param string|mixed $message
@param array        $context
@param int          $traceShift

@return void


public function info($message, array $context = array(), $traceShift = 0)
    {
        $this->log(LogLevel::INFO, $message, $context, $traceShift);
    }

public function info ( $ message , array $ context = array ( ) , $ traceShift = 0 ) { $ this -> log ( LogLevel :: INFO , $ message , $ context , $ traceShift ) ; }

Interesting events.

Example: User logs in, SQL logs.

@param string|mixed $message
@param array        $context
@param int          $traceShift

@return void


public function debug($message, array $context = array(), $traceShift = 0)
    {
        $this->log(LogLevel::DEBUG, $message, $context, $traceShift);
    }

public function debug ( $ message , array $ context = array ( ) , $ traceShift = 0 ) { $ this -> log ( LogLevel :: DEBUG , $ message , $ context , $ traceShift ) ; }

Detailed debug information.

@param string|mixed $message
@param array        $context
@param int          $traceShift

@return void


public function logRaw($message, array $context = array(), $traceShift = 0)
    {
        $this->log(static::LOG_LEVEL_RAW, $message, $context, $traceShift);
    }

public function logRaw ( $ message , array $ context = array ( ) , $ traceShift = 0 ) { $ this -> log ( static :: LOG_LEVEL_RAW , $ message , $ context , $ traceShift ) ; }

Print raw message

@param string|mixed $message
@param array        $context
@param int          $traceShift
@return void


public function profileEnd($endId, $message = null, $traceShift = null)
    {
        if (!isset($endId)) {
            return;
        }
        $this->profile($message, $endId, $traceShift);
    }

public function profileEnd ( $ endId , $ message = null , $ traceShift = null ) { if ( ! isset ( $ endId ) ) { return ; } $ this -> profile ( $ message , $ endId , $ traceShift ) ; }

Profiler shortcut method for end
@param string $message
@param string $endId
@param int    $traceShift


public function log($level, $message, array $context = [], $traceShift = 0)
    {
        $this->checkCorrectLogLevel($level);
        $message = $this->convertMessageToString($message);
        $message = $this->processPlaceHolders($message, $context);
        if (strlen($message) > 0 && mb_substr($message, -1) !== "\n" && !$this->newLine) {
            $message .= self::NEW_LINE;
        }
        if ($this->hideLevel === false) {
            $logColors = isset(static::$LOG_COLORS[$level]) ? static::$LOG_COLORS[$level] : [];
            if ($level !== static::LOG_LEVEL_RAW) {
                $message = str_pad('[' . $level . ']', 10, ' ') . $message;
            }
            if (!empty($logColors)) {
                $message = $this->colorizeText($message, $logColors);
            }
        }
        if ($this->newLine === true) {
            $message .= self::NEW_LINE;
        }
        //Add script and line number
        if ($this->withLineNum) {
            $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
            $lineNum = $this->getCalleeData($trace, $traceShift + 1);
            $unixTime = microtime(true);
            $micro = substr(sprintf("%06d", ($unixTime - floor($unixTime)) * 1000000), 0, 3);
            $time = date('H:i:s') . '.' . $micro;
            $message .= $this->colorizeText('^^^ ' . $time . ' - ' . $lineNum, static::FG_BLACK) . self::NEW_LINE;
        }
        $message = $this->format($message, $context);
        $this->stdio->write($message);
    }

public
function
log
(
$
level
,
$
message
,
array
$
context
=
[
]
,
$
traceShift
=
0
)
{
$
this
->
checkCorrectLogLevel
(
$
level
)
;
$
message
=
$
this
->
convertMessageToString
(
$
message
)
;
$
message
=
$
this
->
processPlaceHolders
(
$
message
,
$
context
)
;
if
(
strlen
(
$
message
)
>
0
&&
mb_substr
(
$
message
,
1
)
!==
"\n"
&&
!
$
this
->
newLine
)
{
$
message
.=
self
::
NEW_LINE
;
}
if
(
$
this
->
hideLevel
===
false
)
{
$
logColors
=
isset
(
static
::
$
LOG_COLORS
[
$
level
]
)
static
::
$
LOG_COLORS
[
$
level
]
:
[
]
;
if
(
$
level
!==
static
::
LOG_LEVEL_RAW
)
{
$
message
=
str_pad
(
'['
.
$
level
.
']'
,
10
,
' '
)
.
$
message
;
}
if
(
!
empty
(
$
logColors
)
)
{
$
message
=
$
this
->
colorizeText
(
$
message
,
$
logColors
)
;
}
}
if
(
$
this
->
newLine
===
true
)
{
$
message
.=
self
::
NEW_LINE
;
}
//Add script and line number
if
(
$
this
->
withLineNum
)
{
$
trace
=
debug_backtrace
(
DEBUG_BACKTRACE_IGNORE_ARGS
)
;
$
lineNum
=
$
this
->
getCalleeData
(
$
trace
,
$
traceShift
+
1
)
;
$
unixTime
=
microtime
(
true
)
;
$
micro
=
substr
(
sprintf
(
"%06d"
,
(
$
unixTime
floor
(
$
unixTime
)
)
*
1000000
)
,
0
,
3
)
;
$
time
=
date
(
'H:i:s'
)
.
'.'
.
$
micro
;
$
message
.=
$
this
->
colorizeText
(
'^^^ '
.
$
time
.
' - '
.
$
lineNum
,
static
::
FG_BLACK
)
.
self
::
NEW_LINE
;
}
$
message
=
$
this
->
format
(
$
message
,
$
context
)
;
$
this
->
stdio
->
write
(
$
message
)
;
}

Log message to STDOUT
@param string $level
@param string $message
@param array  $context
@param int    $traceShift


protected function convertMessageToString($message) {
        $messageStr = $message;
        if ($message === null) {
            $messageStr = 'NULL';
        } elseif ($message instanceof \Throwable) {
            $messageStr = $this->convertErrorToString($message);
        } elseif (is_bool($message)) {
            $messageStr = $message ? 'TRUE' : 'FALSE';
        } elseif (!is_scalar($message)) {
            $messageStr = print_r($message, true);
        }
        return $messageStr;
    }

protected function convertMessageToString ( $ message ) { $ messageStr = $ message ; if ( $ message === null ) { $ messageStr = 'NULL' ; } elseif ( $ message instanceof \ Throwable ) { $ messageStr = $ this -> convertErrorToString ( $ message ) ; } elseif ( is_bool ( $ message ) ) { $ messageStr = $ message ? 'TRUE' : 'FALSE' ; } elseif ( ! is_scalar ( $ message ) ) { $ messageStr = print_r ( $ message , true ) ; } return $ messageStr ; }

Convert message to string
@param mixed $message
@return mixed|string


protected function convertErrorToString(\Throwable $e, $withTrace = true) {
        $message = [
            $e->getMessage(),
            !empty($e->getFile()) ? $e->getFile() . ' #' . $e->getLine() : "",
            $e->getTraceAsString(),
        ];
        if ($withTrace) {
            $message[] = $e->getTraceAsString();
            if ($e->getPrevious() !== null) {
                $message[] = $this->convertErrorToString($e->getPrevious(), false);
            }
        }
        return implode("\n", $message);
    }

protected
function
convertErrorToString
(
\
Throwable
$
e
,
$
withTrace
=
true
)
{
$
message
=
[
$
e
->
getMessage
(
)
,
!
empty
(
$
e
->
getFile
(
)
)
$
e
->
getFile
(
)
.
' #'
.
$
e
->
getLine
(
)
:
""
,
$
e
->
getTraceAsString
(
)
,
]
;
if
(
$
withTrace
)
{
$
message
[
]
=
$
e
->
getTraceAsString
(
)
;
if
(
$
e
->
getPrevious
(
)
!==
)
{
$
message
[
]
=
$
this
->
convertErrorToString
(
$
e
->
getPrevious
(
)
,
false
)
;
}
}
return
implode
(
"\n"
,
$
message
)
;
}

Convert exception to string
@param \Throwable $e
@param bool       $withTrace
@return string


protected function colorizeText($text, ...$colors) {
        if (is_array($colors[0])) {
            $colors = $colors[0];
        }
        for ($i = 0; $i < count($colors); $i++) {
            $text = $this->_colorizeTextInternal($text, $colors[$i]);
        }
        return $text;
    }

protected function colorizeText ( $ text , ... $ colors ) { if ( is_array ( $ colors [ 0 ] ) ) { $ colors = $ colors [ 0 ] ; } for ( $ i = 0 ; $ i < count ( $ colors ) ; $ i ++ ) { $ text = $ this -> _colorizeTextInternal ( $ text , $ colors [ $ i ] ) ; } return $ text ; }

Colorize text for console
@param string $text
@param mixed  ...$colors
@return bool|string


private function getCalleeData($trace, $pos = 0) {
        $traceRow = isset($trace[$pos]) ? $trace[$pos] : end($trace);
        $file = isset($traceRow['file']) ? $traceRow['file'] : '[internal function]';
        $line = isset($traceRow['line']) ? '#' . $traceRow['line'] : '';
        $str = $file . " " . $line;
        return $str;
    }

private
function
getCalleeData
(
$
trace
,
$
pos
=
0
)
{
$
traceRow
=
isset
(
$
trace
[
$
pos
]
)
$
trace
[
$
pos
]
:
end
(
$
trace
)
;
$
file
=
isset
(
$
traceRow
[
'file'
]
)
$
traceRow
[
'file'
]
:
'[internal function]'
;
$
line
=
isset
(
$
traceRow
[
'line'
]
)
'#'
.
$
traceRow
[
'line'
]
:
''
;
$
str
=
$
file
.
" "
.
$
line
;
return
$
str
;
}

Get callee data from backtrace array
@param array $trace
@param int $pos
@return string


protected function processPlaceHolders(string $message, array $context): string
    {
        if (false === strpos($message, '{')) {
            return $message;
        }

        $replacements = [];
        foreach ($context as $key => $value) {
            $replacements['{' . $key . '}'] = $this->formatValue($value);
        }

        return strtr($message, $replacements);
    }

protected function processPlaceHolders ( string $ message , array $ context ) : string { if ( false === strpos ( $ message , '{' ) ) { return $ message ; } $ replacements = [ ] ; foreach ( $ context as $ key => $ value ) { $ replacements [ '{' . $ key . '}' ] = $ this -> formatValue ( $ value ) ; } return strtr ( $ message , $ replacements ) ; }

Replace placeholders in text
@param  string $message
@param  array  $context
@return string


protected function formatValue($value): string
    {
        if (is_null($value) || is_scalar($value) || (is_object($value) && method_exists($value, '__toString'))) {
            return (string)$value;
        }

        if (is_object($value)) {
            return '[object ' . get_class($value) . ']';
        }

        return '[' . gettype($value) . ']';
    }

protected
function
formatValue
(
$
value
)
:
string
{
if
(
is_null
(
$
value
)
||
is_scalar
(
$
value
)
||
(
is_object
(
$
value
)
&&
method_exists
(
$
value
,
'__toString'
)
)
)
{
return
(
string
)
$
value
;
}
if
(
is_object
(
$
value
)
)
{
return
'[object '
.
get_class
(
$
value
)
.
']'
;
}
return
'['
.
gettype
(
$
value
)
.
']'
;
}

Format mixed value as a String
@param mixed $value
@return string


public static function find(ActiveRecord $owner, $condition = 0)
    {
        $seo = new self();
        $seo->_owner = $owner;
        $condition = (int)$condition;
        $data = $owner->getIsNewRecord() ? false : (new Query())
            ->from(Seo::tableName($owner))
            ->limit(1)
            ->andWhere([
                'condition' => $condition,
                'model_id' => $owner->getPrimaryKey(),
            ])->one($owner->getDb());
        $seo->_isNewRecord = empty($data);
        if ($data) {
            $seo->setAttributes($data);
        }
        $seo->condition = $condition;
        return $seo;
    }

public static function find ( ActiveRecord $ owner , $ condition = 0 ) { $ seo = new self ( ) ; $ seo -> _owner = $ owner ; $ condition = ( int ) $ condition ; $ data = $ owner -> getIsNewRecord ( ) ? false : ( new Query ( ) ) -> from ( Seo :: tableName ( $ owner ) ) -> limit ( 1 ) -> andWhere ( [ 'condition' => $ condition , 'model_id' => $ owner -> getPrimaryKey ( ) , ] ) -> one ( $ owner -> getDb ( ) ) ; $ seo -> _isNewRecord = empty ( $ data ) ; if ( $ data ) { $ seo -> setAttributes ( $ data ) ; } $ seo -> condition = $ condition ; return $ seo ; }

Search SEO data. If not found, will be returned new SEO model with empty data
@param ActiveRecord $owner the ActiveRecord model for which to find data
@param int $condition optional condition for searched SEO data
@return self

Search SEO data . If not found will be returned new SEO model with empty data


public static function tableName(ActiveRecord $activeRecord)
    {
        $tableName = $activeRecord->tableName();
        if (substr($tableName, -2) == '}}') {
            return preg_replace('/{{(.+)}}/', '{{$1_' . self::$tableSuffix . '}}', $tableName);
        } else {
            return $tableName . '_' . self::$tableSuffix;
        }
    }

public static function tableName ( ActiveRecord $ activeRecord ) { $ tableName = $ activeRecord -> tableName ( ) ; if ( substr ( $ tableName , - 2 ) == '}}' ) { return preg_replace ( '/{{(.+)}}/' , '{{$1_' . self :: $ tableSuffix . '}}' , $ tableName ) ; } else { return $ tableName . '_' . self :: $ tableSuffix ; } }

Get table name of SEO data table for ActiveRecord
@param ActiveRecord $activeRecord
@return string


public static function deleteAll(ActiveRecord $owner)
    {
        $owner->getDb()->createCommand()->delete(self::tableName($owner), ['model_id' => $owner->getPrimaryKey()])->execute();
    }

public static function deleteAll ( ActiveRecord $ owner ) { $ owner -> getDb ( ) -> createCommand ( ) -> delete ( self :: tableName ( $ owner ) , [ 'model_id' => $ owner -> getPrimaryKey ( ) ] ) -> execute ( ) ; }

Delete all SEO data for ActiveRecord
@param ActiveRecord $owner


public function save()
    {
        if (empty($this->_owner)) {
            $this->addError('owner', "You can't use Seo model without owner");
            return false;
        }
        $this->model_id = $this->_owner->getPrimaryKey();
        $command = $this->_owner->getDb()->createCommand();
        $attributes = ['title', 'keywords', 'description'];
        $tableName = self::tableName($this->_owner);
        if ($this->_isNewRecord) {
            if (empty(array_filter($this->getAttributes($attributes)))) {
                // don't save new SEO data with empty values
                return true;
            }
            $command->insert($tableName, $this->toArray());
        } else {
            $command->update(
                $tableName, $this->toArray($attributes),
                ['model_id' => $this->model_id, 'condition' => $this->condition]
            );
        }
        $command->execute();
        $this->_isNewRecord = false;
        return true;
    }


static function init(){
		global $databaseConfig;

		if (!isset($databaseConfig)) {
			$databaseConfig = array (
				'server'    => SS_DATABASE_SERVER,
				'username'  => SS_DATABASE_USERNAME,
				'password'  => SS_DATABASE_PASSWORD,
				'database'  => SS_DATABASE_NAME,
			);
		}

		self::$conn = new mysqli($databaseConfig['server'], $databaseConfig['username'], $databaseConfig['password'], $databaseConfig['database']);
		self::$conn->query("set sql_mode='ansi'");
	}

static
function
init
(
)
{
global
$
databaseConfig
;
if
(
!
isset
(
$
databaseConfig
)
)
{
$
databaseConfig
=
array
(
'server'
=>
SS_DATABASE_SERVER
,
'username'
=>
SS_DATABASE_USERNAME
,
'password'
=>
SS_DATABASE_PASSWORD
,
'database'
=>
SS_DATABASE_NAME
,
)
;
}
self
::
$
conn
=
new
mysqli
(
$
databaseConfig
[
'server'
]
,
$
databaseConfig
[
'username'
]
,
$
databaseConfig
[
'password'
]
,
$
databaseConfig
[
'database'
]
)
;
self
::
$
conn
->
query
(
"set sql_mode='ansi'"
)
;
}


function PEAR_Command_Common(&$ui, &$config)
    {
        parent::PEAR();
        $this->config = &$config;
        $this->ui = &$ui;
    }

function PEAR_Command_Common ( & $ ui , & $ config ) { parent :: PEAR ( ) ; $ this -> config = & $ config ; $ this -> ui = & $ ui ; }

PEAR_Command_Common constructor.

@access public


function getCommands()
    {
        $ret = array();
        foreach (array_keys($this->commands) as $command) {
            $ret[$command] = $this->commands[$command]['summary'];
        }

        return $ret;
    }

function getCommands ( ) { $ ret = array ( ) ; foreach ( array_keys ( $ this -> commands ) as $ command ) { $ ret [ $ command ] = $ this -> commands [ $ command ] [ 'summary' ] ; } return $ ret ; }

Return a list of all the commands defined by this class.
@return array list of commands
@access public

Return a list of all the commands defined by this class .


function getShortcuts()
    {
        $ret = array();
        foreach (array_keys($this->commands) as $command) {
            if (isset($this->commands[$command]['shortcut'])) {
                $ret[$this->commands[$command]['shortcut']] = $command;
            }
        }

        return $ret;
    }

function getShortcuts ( ) { $ ret = array ( ) ; foreach ( array_keys ( $ this -> commands ) as $ command ) { if ( isset ( $ this -> commands [ $ command ] [ 'shortcut' ] ) ) { $ ret [ $ this -> commands [ $ command ] [ 'shortcut' ] ] = $ command ; } } return $ ret ; }

Return a list of all the command shortcuts defined by this class.
@return array shortcut => command
@access public

Return a list of all the command shortcuts defined by this class .


function getHelp($command)
    {
        $config = &PEAR_Config::singleton();
        if (!isset($this->commands[$command])) {
            return "No such command \"$command\"";
        }

        $help = null;
        if (isset($this->commands[$command]['doc'])) {
            $help = $this->commands[$command]['doc'];
        }

        if (empty($help)) {
            // XXX (cox) Fallback to summary if there is no doc (show both?)
            if (!isset($this->commands[$command]['summary'])) {
                return "No help for command \"$command\"";
            }
            $help = $this->commands[$command]['summary'];
        }

        if (preg_match_all('/{config\s+([^\}]+)}/e', $help, $matches)) {
            foreach($matches[0] as $k => $v) {
                $help = preg_replace("/$v/", $config->get($matches[1][$k]), $help);
            }
        }

        return array($help, $this->getHelpArgs($command));
    }

Returns the help message for the given command

@param string $command The command
@return mixed A fail string if the command does not have help or
a two elements array containing [0]=>help string,
[1]=> help string for the accepted cmd args


function getHelpArgs($command)
    {
        if (isset($this->commands[$command]['options']) &&
            count($this->commands[$command]['options']))
        {
            $help = "Options:\n";
            foreach ($this->commands[$command]['options'] as $k => $v) {
                if (isset($v['arg'])) {
                    if ($v['arg'][0] == '(') {
                        $arg = substr($v['arg'], 1, -1);
                        $sapp = " [$arg]";
                        $lapp = "[=$arg]";
                    } else {
                        $sapp = " $v[arg]";
                        $lapp = "=$v[arg]";
                    }
                } else {
                    $sapp = $lapp = "";
                }

                if (isset($v['shortopt'])) {
                    $s = $v['shortopt'];
                    $help .= "  -$s$sapp, --$k$lapp\n";
                } else {
                    $help .= "  --$k$lapp\n";
                }

                $p = "        ";
                $doc = rtrim(str_replace("\n", "\n$p", $v['doc']));
                $help .= "        $doc\n";
            }

            return $help;
        }

        return null;
    }

function
getHelpArgs
(
$
command
)
{
if
(
isset
(
$
this
->
commands
[
$
command
]
[
'options'
]
)
&&
count
(
$
this
->
commands
[
$
command
]
[
'options'
]
)
)
{
$
help
=
"Options:\n"
;
foreach
(
$
this
->
commands
[
$
command
]
[
'options'
]
as
$
k
=>
$
v
)
{
if
(
isset
(
$
v
[
'arg'
]
)
)
{
if
(
$
v
[
'arg'
]
[
0
]
==
'('
)
{
$
arg
=
substr
(
$
v
[
'arg'
]
,
1
,
1
)
;
$
sapp
=
" [$arg]"
;
$
lapp
=
"[=$arg]"
;
}
else
{
$
sapp
=
" $v[arg]"
;
$
lapp
=
"=$v[arg]"
;
}
}
else
{
$
sapp
=
$
lapp
=
""
;
}
if
(
isset
(
$
v
[
'shortopt'
]
)
)
{
$
s
=
$
v
[
'shortopt'
]
;
$
help
.=
"  -$s$sapp, --$k$lapp\n"
;
}
else
{
$
help
.=
"  --$k$lapp\n"
;
}
$
p
=
"        "
;
$
doc
=
rtrim
(
str_replace
(
"\n"
,
"\n$p"
,
$
v
[
'doc'
]
)
)
;
$
help
.=
"        $doc\n"
;
}
return
$
help
;
}
return
;
}

Returns the help for the accepted arguments of a command

@param  string $command
@return string The help string


public function onPostPackageEvent(PackageEvent $event)
    {
        $package = $this->getOpenBizPackage($event->getOperation());
        if ($package) {
            // By explicitly setting the package, the onPostCmdEvent() will
            // process the update automatically.
            $this->OpenBizPackage = $package;
        }
    }

Execute update after update command has been executed, if applicable.

@param PackageEvent $event

Execute update after update command has been executed if applicable .


static public function compileDSN(&$params) {
        $dsn = '';
        if (!isset($params['user'])) $params['user'] = 'root';
        if (!isset($params['pass'])) $params['pass'] = null;
        if (!isset($params['type'])) $params['type'] = 'mysql';
        if (!isset($params['host'])) $params['host'] = '127.0.0.1';

        if (!empty($params['dsn'])) {
            $dsn = $params['dsn'];
        } else {
            $dsn = $params['type'] . ':host='.$params['host'];
        }
        return $dsn;
    }

static public function compileDSN ( & $ params ) { $ dsn = '' ; if ( ! isset ( $ params [ 'user' ] ) ) $ params [ 'user' ] = 'root' ; if ( ! isset ( $ params [ 'pass' ] ) ) $ params [ 'pass' ] = null ; if ( ! isset ( $ params [ 'type' ] ) ) $ params [ 'type' ] = 'mysql' ; if ( ! isset ( $ params [ 'host' ] ) ) $ params [ 'host' ] = '127.0.0.1' ; if ( ! empty ( $ params [ 'dsn' ] ) ) { $ dsn = $ params [ 'dsn' ] ; } else { $ dsn = $ params [ 'type' ] . ':host=' . $ params [ 'host' ] ; } return $ dsn ; }

Parse database config and prepare DSN

@static
@param @params part of database config
@return array


public function escape($value) {
        if (is_array($value)) {
            $res = '';
            if (count($value) == 0) return 'null';
            foreach($value as $val) {
                $res .= $this->escapeOne($val).',';
            }
            $res = substr($res, 0, -1);
            return $res;
        } else {
            return $this->escapeOne($value);
        }
    }

public function escape ( $ value ) { if ( is_array ( $ value ) ) { $ res = '' ; if ( count ( $ value ) == 0 ) return 'null' ; foreach ( $ value as $ val ) { $ res .= $ this -> escapeOne ( $ val ) . ',' ; } $ res = substr ( $ res , 0 , - 1 ) ; return $ res ; } else { return $ this -> escapeOne ( $ value ) ; } }

Escape values for using in queries

@param mixed $value to be escaped
@return mixed $value  Escaped


public static function addTemplateRoot(
		array &$globalConfig,
		string $directory,
		string $trim,
		string $referenceName = ''
	) {
		if (!isset($globalConfig['view'])) {
			$globalConfig['view'] = [];
		}
		if (!isset($globalConfig['view'][self::CONFIG_TEMPLATE_ROOTS])) {
			$globalConfig['view'][self::CONFIG_TEMPLATE_ROOTS] = [];
		}
		$globalConfig['view'][self::CONFIG_TEMPLATE_ROOTS][] = [
			'directory' => $directory,
			'trim'      => $trim,
			'name'      => $referenceName,
		];
	}

public static function addTemplateRoot ( array & $ globalConfig , string $ directory , string $ trim , string $ referenceName = '' ) { if ( ! isset ( $ globalConfig [ 'view' ] ) ) { $ globalConfig [ 'view' ] = [ ] ; } if ( ! isset ( $ globalConfig [ 'view' ] [ self :: CONFIG_TEMPLATE_ROOTS ] ) ) { $ globalConfig [ 'view' ] [ self :: CONFIG_TEMPLATE_ROOTS ] = [ ] ; } $ globalConfig [ 'view' ] [ self :: CONFIG_TEMPLATE_ROOTS ] [ ] = [ 'directory' => $ directory , 'trim' => $ trim , 'name' => $ referenceName , ] ; }

Helper function to add a template root directory.

@param array  $globalConfig  The global configuration array.
@param string $directory     The directory to look for a template in.
@param string $trim          Parts to remove from the controller name
@param string $referenceName Name to reference root by. Can be used with some template engines.

Helper function to add a template root directory .


public function getCount($collection, $column, $value, $excludeId = null, $idColumn = null, array $extra = []) {
        $idColumn = $idColumn !== null ? $idColumn : 'id';

        $qb = $this->createCountQuery($collection)
                   ->where('o.' . $column . ' = :value')
                   ->setParameter('value', $value);

        if (!is_null($excludeId) && $excludeId != 'NULL')  {
            $qb->andWhere('o.' . $idColumn .' <> :excludeId')
               ->setParameter('excludeId', $excludeId);
        }

        foreach($extra as $key => $extraValue) {
            $this->addWhere($qb, $key, $extraValue);
        }

        return (int) $qb->getQuery()->getSingleScalarResult();
    }

public
function
getCount
(
$
collection
,
$
column
,
$
value
,
$
excludeId
=
,
$
idColumn
=
,
array
$
extra
=
[
]
)
{
$
idColumn
=
$
idColumn
!==
$
idColumn
:
'id'
;
$
qb
=
$
this
->
createCountQuery
(
$
collection
)
->
where
(
'o.'
.
$
column
.
' = :value'
)
->
setParameter
(
'value'
,
$
value
)
;
if
(
!
is_null
(
$
excludeId
)
&&
$
excludeId
!=
'NULL'
)
{
$
qb
->
andWhere
(
'o.'
.
$
idColumn
.
' <> :excludeId'
)
->
setParameter
(
'excludeId'
,
$
excludeId
)
;
}
foreach
(
$
extra
as
$
key
=>
$
extraValue
)
{
$
this
->
addWhere
(
$
qb
,
$
key
,
$
extraValue
)
;
}
return
(
int
)
$
qb
->
getQuery
(
)
->
getSingleScalarResult
(
)
;
}

Count the number of objects in a collection having the given value.

@param  string $collection
@param  string $column
@param  string $value
@param  int $excludeId
@param  string $idColumn
@param  array $extra
@return int

Count the number of objects in a collection having the given value .


public function getMultiCount($collection, $column, array $values, array $extra = []) {
        $qb = $this->createCountQuery($collection)
                   ->where('o.', $column . ' IN (:values)')
                   ->setParameter('values', array_values($values));

        foreach($extra as $key => $extraValue) {
            $this->addWhere($qb, $key, $extraValue);
        }

        return (int) $qb->getQuery()->getSingleScalarResult();
    }

public
function
getMultiCount
(
$
collection
,
$
column
,
array
$
values
,
array
$
extra
=
[
]
)
{
$
qb
=
$
this
->
createCountQuery
(
$
collection
)
->
where
(
'o.'
,
$
column
.
' IN (:values)'
)
->
setParameter
(
'values'
,
array_values
(
$
values
)
)
;
foreach
(
$
extra
as
$
key
=>
$
extraValue
)
{
$
this
->
addWhere
(
$
qb
,
$
key
,
$
extraValue
)
;
}
return
(
int
)
$
qb
->
getQuery
(
)
->
getSingleScalarResult
(
)
;
}

Count the number of objects in a collection with the given values.

@param  string $collection
@param  string $column
@param  array $values
@param  array $extra
@return int

Count the number of objects in a collection with the given values .


protected function createCountQuery($collection, $alias = 'o') {
        return $this->getEntityManager()->createQueryBuilder()
            ->select('COUNT(' . $alias . ')')
            ->from($collection, $alias);
    }

protected function createCountQuery ( $ collection , $ alias = 'o' ) { return $ this -> getEntityManager ( ) -> createQueryBuilder ( ) -> select ( 'COUNT(' . $ alias . ')' ) -> from ( $ collection , $ alias ) ; }

Creates a query builder.

@param string $collection
@param string $alias
@return QueryBuilder


protected function getEntityManager() {
        if($this->entities === null) {
            $callable = $this->factory;
            $this->entities = $callable();
        }

        return $this->entities;
    }

protected function getEntityManager ( ) { if ( $ this -> entities === null ) { $ callable = $ this -> factory ; $ this -> entities = $ callable ( ) ; } return $ this -> entities ; }

Returns the EntityManager, loading it if it hasn't been created yet.

@return \Doctrine\ORM\EntityManagerInterface

Returns the EntityManager loading it if it hasn t been created yet .


protected static function getCurrentPath(RequestApplicationInterface $app, $onlyStaticPart = false) {
        $route = $app->getRoute();
        return $route ? $route->getRoutePath($onlyStaticPart) : null;
    }

protected static function getCurrentPath ( RequestApplicationInterface $ app , $ onlyStaticPart = false ) { $ route = $ app -> getRoute ( ) ; return $ route ? $ route -> getRoutePath ( $ onlyStaticPart ) : null ; }

Get current path from request & current controller
@param RequestApplicationInterface $app
@param bool                $onlyStaticPart
@return null|string


public function load($name, array $params = array(), $object_loader = null, $force_overload = false)
    {
        $config = $this->get('config')->get($name, \CarteBlanche\App\Config::NOT_FOUND_GRACEFULLY, array());
        $factory = \Library\Factory::create()
            ->factoryName(__CLASS__)
            ->mustImplement(Kernel::DEPENDENCY_LOADER_INTERFACE)
            ->defaultNamespace(array(
                Kernel::DEPENDENCY_LOADER_DEFAULT_NAMESPACE,
                Kernel::CARTE_BLANCHE_NAMESPACE.Kernel::DEPENDENCY_LOADER_DEFAULT_NAMESPACE
            ))
            ->classNameMask(array('%s', '%s'.Kernel::DEPENDENCY_LOADER_SUFFIX))
            ->callMethod('load')
            ;
        if (!isset($params['config'])) {
            $params['config'] = $config;
        }
        if (!isset($params['options'])) {
            $params['options'] = $config;
        }
        if (!isset($params['container'])) {
            $params['container'] = $this;
        }
        $object = $factory->build(empty($object_loader) ? $name : $object_loader, $params);

/*
        if (empty($object_loader)) {
            $object_loader = Kernel::DEPENDENCY_LOADER_DEFAULT_NAMESPACE
                .ucfirst(TextHelper::toCamelCase($name));
            if (!class_exists($object_loader)) {
                $object_loader .= Kernel::DEPENDENCY_LOADER_SUFFIX;
            }
        }
        if (!class_exists($object_loader)) {
            throw new \RuntimeException(
                sprintf('Unknown dependency loader for reference "%s"!', $name)
            );
        } elseif (!CodeHelper::impelementsInterface($object_loader, Kernel::DEPENDENCY_LOADER_INTERFACE)) {
            throw new \DomainException(
                sprintf('Dependency loader "%s" doesn\'t implement the "%s" interface!',
                    $object_loader, Kernel::DEPENDENCY_LOADER_INTERFACE)
            );
        }
        $loader = new $object_loader;
        $config = $this->get('config')->get($name, \CarteBlanche\App\Config::NOT_FOUND_GRACEFULLY, array());
        $object = $loader->load($config, $this);
*/
        return $this->set($name, $object, $force_overload);
    }

Instance loader and setter

@param   string  $name           The variable name to set
@param   array   $params         An array of parameters to pass to loader
@param   object  $object_loader  The loader class if so
@param   bool    $force_overload Over-write an existing value ?
@return  bool

@todo Pass arguments (via parameter here and configuration settings)


public function clear($name)
    {
        if (true===$this->instances->isEntry($name)) {
            $this->instances->setEntry($name, null);
        }
    }

public function clear ( $ name ) { if ( true === $ this -> instances -> isEntry ( $ name ) ) { $ this -> instances -> setEntry ( $ name , null ) ; } }

Clear a container entry

@param   string  $name   The variable name to set
@return  bool


public function getBundle($name)
    {
        if (true===$this->instances->isEntry($name,'bundles')) {
            return $this->instances->getEntry($name,'bundles');
        }
        return null;
    }

public function getBundle ( $ name ) { if ( true === $ this -> instances -> isEntry ( $ name , 'bundles' ) ) { return $ this -> instances -> getEntry ( $ name , 'bundles' ) ; } return null ; }

Global bundle getter

@param   string  $name   The bundle name to get
@return  mixed   The value of the registry bundle
@see     \Patterns\Commons\Registry::getEntry()


public function setBundle($name = null, $val = null, $force_overload = false)
    {
        if (!is_object($val)) {
            throw new DomainException(
                sprintf('A bundle entry must be an object (got "%s" for bundle "%s")!', gettype($val), $name)
            );
        }
        if (!CodeHelper::isClassInstance($val, Kernel::BUNDLE_CLASS)) {
            throw new DomainException(
                sprintf('A bundle entry must be a "%s" instance (for "%s")!', Kernel::BUNDLE_CLASS, $name)
            );
        }
        if (true===$this->instances->isEntry($name, 'bundles') && true!==$force_overload) {
            throw new InvalidArgumentException(
                sprintf('You can not over-write a container bundle (for "%s")!', $name)
            );
        }
        return $this->instances->setEntry($name,$val,'bundles');
    }

Global bundle setter

@param   string  $name           The bundle name to set
@param   mixed   $val            The bundle value to set
@param   bool    $force_overload Over-write an existing value ?
@return  \Patterns\Commons\Registry::setEntry()
@throws  \CarteBlanche\Exception\DomainException if `$val` is not an object
@throws  \CarteBlanche\Exception\DomainException if `$val` is not a `\CarteBlanche\App\Kernel::BUNDLE_CLASS` instance
@throws  \CarteBlanche\Exception\InvalidArgumentException if the entry is already defined and `$force_overload = false`


public function clearBundle($name)
    {
        if (true===$this->instances->isEntry($name,'bundles')) {
            $this->instances->setEntry($name,null,'bundles');
        }
    }

public function clearBundle ( $ name ) { if ( true === $ this -> instances -> isEntry ( $ name , 'bundles' ) ) { $ this -> instances -> setEntry ( $ name , null , 'bundles' ) ; } }

Clear a container bundle entry

@param   string  $name   The bundle name to unset


public function invalidate(EntityManager $em, $entity) {
        $this->log->info('Invalidating entity of class ' . get_class($entity) . ' with ID ' . $entity->getId());
        $this->events->fire('oxygen.entity.cache.invalidated', [$entity]);

        // if the cache depends on any entities of a given type
        foreach($this->cacheSettings->get(get_class($entity)) as $entity) {
            $this->invalidate($em, $this->find($em, $entity));
        }

        // if the cache depends on a specific entity
        if($entity instanceof CacheInvalidatorInterface) {
            foreach($entity->getEntitiesToBeInvalidated() as $entity) {
                $this->invalidate($em, $this->find($em, $entity));
            }
        }
    }

Invalidates the cache.

@param \Doctrine\ORM\EntityManager $em
@param object                      $entity


function assertDepsDB()
    {
        if (!is_file($this->_depdb)) {
            $this->rebuildDB();
            return;
        }

        $depdb = $this->_getDepDB();
        // Datatype format has been changed, rebuild the Deps DB
        if ($depdb['_version'] < $this->_version) {
            $this->rebuildDB();
        }

        if ($depdb['_version']{0} > $this->_version{0}) {
            return PEAR::raiseError('Dependency database is version ' .
                $depdb['_version'] . ', and we are version ' .
                $this->_version . ', cannot continue');
        }
    }

Create the dependency database, if it doesn't exist.  Error if the database is
newer than the code reading it.
@return void|PEAR_Error

Create the dependency database if it doesn t exist . Error if the database is newer than the code reading it .


function getDependentPackageDependencies(&$pkg)
    {
        $data = $this->_getDepDB();
        if (is_object($pkg)) {
            $channel = strtolower($pkg->getChannel());
            $package = strtolower($pkg->getPackage());
        } else {
            $channel = strtolower($pkg['channel']);
            $package = strtolower($pkg['package']);
        }

        $depend = $this->getDependentPackages($pkg);
        if (!$depend) {
            return false;
        }

        $dependencies = array();
        foreach ($depend as $info) {
            $temp = $this->getDependencies($info);
            foreach ($temp as $dep) {
                if (
                    isset($dep['dep'], $dep['dep']['channel'], $dep['dep']['name']) &&
                    strtolower($dep['dep']['channel']) == $channel &&
                    strtolower($dep['dep']['name']) == $package
                ) {
                    if (!isset($dependencies[$info['channel']])) {
                        $dependencies[$info['channel']] = array();
                    }

                    if (!isset($dependencies[$info['channel']][$info['package']])) {
                        $dependencies[$info['channel']][$info['package']] = array();
                    }
                    $dependencies[$info['channel']][$info['package']][] = $dep;
                }
            }
        }

        return $dependencies;
    }

function getDependentPackageDependencies ( & $ pkg ) { $ data = $ this -> _getDepDB ( ) ; if ( is_object ( $ pkg ) ) { $ channel = strtolower ( $ pkg -> getChannel ( ) ) ; $ package = strtolower ( $ pkg -> getPackage ( ) ) ; } else { $ channel = strtolower ( $ pkg [ 'channel' ] ) ; $ package = strtolower ( $ pkg [ 'package' ] ) ; } $ depend = $ this -> getDependentPackages ( $ pkg ) ; if ( ! $ depend ) { return false ; } $ dependencies = array ( ) ; foreach ( $ depend as $ info ) { $ temp = $ this -> getDependencies ( $ info ) ; foreach ( $ temp as $ dep ) { if ( isset ( $ dep [ 'dep' ] , $ dep [ 'dep' ] [ 'channel' ] , $ dep [ 'dep' ] [ 'name' ] ) && strtolower ( $ dep [ 'dep' ] [ 'channel' ] ) == $ channel && strtolower ( $ dep [ 'dep' ] [ 'name' ] ) == $ package ) { if ( ! isset ( $ dependencies [ $ info [ 'channel' ] ] ) ) { $ dependencies [ $ info [ 'channel' ] ] = array ( ) ; } if ( ! isset ( $ dependencies [ $ info [ 'channel' ] ] [ $ info [ 'package' ] ] ) ) { $ dependencies [ $ info [ 'channel' ] ] [ $ info [ 'package' ] ] = array ( ) ; } $ dependencies [ $ info [ 'channel' ] ] [ $ info [ 'package' ] ] [ ] = $ dep ; } } } return $ dependencies ; }

Get a list of the actual dependencies of installed packages that depend on
a package.
@param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
@return array|false

Get a list of the actual dependencies of installed packages that depend on a package .