protected function getReader($URI, $request)
    {
        if (!is_string($URI)) {
            throw new \InvalidArgumentException('Not a string');
        }

        if (!is_bool($request)) {
            throw new \InvalidArgumentException('Not a boolean');
        }

        $this->currentNode = null;
        $reader = new \XMLReader();
        $reader->open($URI, null, LIBXML_NONET | LIBXML_NOENT);
        if ($this->validate) {
            $schema = dirname(__DIR__) .
                DIRECTORY_SEPARATOR . 'data' .
                DIRECTORY_SEPARATOR;
            $schema .= $request ? 'request.rng' : 'response.rng';
            $reader->setRelaxNGSchema($schema);
        }
        return $reader;
    }

protected
function
getReader
(
$
URI
,
$
request
)
{
if
(
!
is_string
(
$
URI
)
)
{
throw
new
\
InvalidArgumentException
(
'Not a string'
)
;
}
if
(
!
is_bool
(
$
request
)
)
{
throw
new
\
InvalidArgumentException
(
'Not a boolean'
)
;
}
$
this
->
currentNode
=
;
$
reader
=
new
\
XMLReader
(
)
;
$
reader
->
open
(
$
URI
,
,
LIBXML_NONET
|
LIBXML_NOENT
)
;
if
(
$
this
->
validate
)
{
$
schema
=
dirname
(
__DIR__
)
.
DIRECTORY_SEPARATOR
.
'data'
.
DIRECTORY_SEPARATOR
;
$
schema
.=
$
request
'request.rng'
:
'response.rng'
;
$
reader
->
setRelaxNGSchema
(
$
schema
)
;
}
return
$
reader
;
}

Returns an XML reader for some data.

\param string $URI
URI to the XML data to process.

\param bool $request
Whether the data refers to an XML-RPC
request (\c true) or a response (\c false).

\retval XMLReader
An XML reader for the given data.

\throw InvalidArgumentException
You tried to pass something that is not
a boolean as the \c $request parameter.

\note
The reader is set to validate the document
on the fly if that's what this decoder was
configured to do during construction.


protected function readNode($reader)
    {
        if ($this->currentNode !== null) {
            return $this->currentNode;
        }

        $this->currentNode = new \fpoirotte\XRL\Node($reader, $this->validate, true);
        return $this->currentNode;
    }

protected function readNode ( $ reader ) { if ( $ this -> currentNode !== null ) { return $ this -> currentNode ; } $ this -> currentNode = new \ fpoirotte \ XRL \ Node ( $ reader , $ this -> validate , true ) ; return $ this -> currentNode ; }

Read a node from the XML reader
and return it.

\param XMLReader $reader
Reader to read the node from.

\retval fpoirotte::XRL::Node
The XML node that's been read.

Read a node from the XML reader and return it .


protected function expectStartTag($reader, $expectedTag)
    {
        $node = $this->readNode($reader);

        $type = $node->nodeType;
        if ($type !== \XMLReader::ELEMENT) {
            $type = isset(self::$types[$type]) ? self::$types[$type] : "#$type";
            throw new \InvalidArgumentException(
                "Expected an opening $expectedTag tag ".
                "but got a node of type $type instead"
            );
        }

        $readTag = $node->name;
        if ($readTag !== $expectedTag) {
            throw new \InvalidArgumentException(
                "Got opening tag for $readTag instead of $expectedTag"
            );
        }

        $this->prepareNextNode();
    }

Read a node from the document and throw
an exception if it is not an opening tag
with the given name.

\param XMLReader $reader
Reader object the node will be read from.

\param string $expectedTag
Name of the tag we're expecting.

\throw InvalidArgumentException
Thrown whenever one of the following
conditions is met:
- We reached the end of the document.
- The next node was not an opening tag.
- The next node was an opening tag, but
its name was not the one we expected.

Read a node from the document and throw an exception if it is not an opening tag with the given name .


protected function expectEndTag($reader, $expectedTag)
    {
        $node = $this->readNode($reader);

        $type = $node->nodeType;
        if ($type !== \XMLReader::END_ELEMENT) {
            $type = isset(self::$types[$type]) ? self::$types[$type] : "#$type";
            throw new \InvalidArgumentException(
                "Expected a closing $expectedTag tag ".
                "but got a node of type $type instead"
            );
        }

        $readTag = $node->name;
        if ($readTag !== $expectedTag) {
            throw new \InvalidArgumentException(
                "Got closing tag for $readTag instead of $expectedTag"
            );
        }

        $this->prepareNextNode();
    }

Read a node from the document and throw
an exception if it is not a closing tag
with the given name.

\param XMLReader $reader
Reader object the node will be read from.

\param string $expectedTag
Name of the tag we're expecting.

\throw InvalidArgumentException
Thrown whenever one of the following
conditions is met:
- We reached the end of the document.
- The next node was not a closing tag.
- The next node was a closing tag, but
its name was not the one we expected.

Read a node from the document and throw an exception if it is not a closing tag with the given name .


protected function parseText($reader)
    {
        $node = $this->readNode($reader);

        $type = $node->nodeType;
        if ($type !== \XMLReader::TEXT) {
            $type = isset(self::$types[$type]) ? self::$types[$type] : "#$type";
            throw new \InvalidArgumentException(
                "Expected a text node, but got ".
                "a node of type $type instead"
            );
        }

        $value = $node->value;
        $this->prepareNextNode();
        return $value;
    }

protected
function
parseText
(
$
reader
)
{
$
node
=
$
this
->
readNode
(
$
reader
)
;
$
type
=
$
node
->
nodeType
;
if
(
$
type
!==
\
XMLReader
::
TEXT
)
{
$
type
=
isset
(
self
::
$
types
[
$
type
]
)
self
::
$
types
[
$
type
]
:
"#$type"
;
throw
new
\
InvalidArgumentException
(
"Expected a text node, but got "
.
"a node of type $type instead"
)
;
}
$
value
=
$
node
->
value
;
$
this
->
prepareNextNode
(
)
;
return
$
value
;
}

Read a node from the document and throw
an exception if it is not a text node.
Otherwise, return its content.

\param XMLReader $reader
Reader object the node will be read from.

\retval string
The value of the text node.

\throw InvalidArgumentException
Thrown whenever one of the following
conditions is met:
- We reached the end of the document.
- The next node was not a text node.

Read a node from the document and throw an exception if it is not a text node . Otherwise return its content .


protected static function checkType(array $allowedTypes, $type, $value)
    {
        if (count($allowedTypes) && !in_array($type, $allowedTypes)) {
            $allowed = implode(', ', $allowedTypes);
            throw new \InvalidArgumentException(
                "Expected one of: $allowed; got $type"
            );
        }

        return $value;
    }

protected
static
function
checkType
(
array
$
allowedTypes
,
$
type
,
$
value
)
{
if
(
count
(
$
allowedTypes
)
&&
!
in_array
(
$
type
,
$
allowedTypes
)
)
{
$
allowed
=
implode
(
', '
,
$
allowedTypes
)
;
throw
new
\
InvalidArgumentException
(
"Expected one of: $allowed; got $type"
)
;
}
return
$
value
;
}

Check the type of a value.

\param array $allowedTypes
Whitelist of allowed types.
If empty, any type is allowed.

\param string $type
The actual type of the value
being tested.

\param mixed $value
The value being tested.

\retval mixed
The original value that was passed
to this method, if type allows.

\throw InvalidArgumentException
The given type cannot be used
in this context (disallowed).


public function checkbox(
        string $id,
        string $title,
        array $additionalArguments = null
    ): Field {
        $formControl = $this->builder->checkbox($id)->value('true');
        $this->optionStore->getBoolean($id) ? $formControl->check() : $formControl->uncheck();

        $additionalArguments = array_merge(
            [
                'type' => 'boolean',
                'sanitize_callback' => function ($value): bool {
                    return 'true' === sanitize_text_field($value);
                },
            ],
            (array) $additionalArguments
        );

        return new Field(
            $id,
            $title,
            $formControl,
            (array) $additionalArguments
        );
    }

public function checkbox ( string $ id , string $ title , array $ additionalArguments = null ) : Field { $ formControl = $ this -> builder -> checkbox ( $ id ) -> value ( 'true' ) ; $ this -> optionStore -> getBoolean ( $ id ) ? $ formControl -> check ( ) : $ formControl -> uncheck ( ) ; $ additionalArguments = array_merge ( [ 'type' => 'boolean' , 'sanitize_callback' => function ( $ value ) : bool { return 'true' === sanitize_text_field ( $ value ) ; } , ] , ( array ) $ additionalArguments ) ; return new Field ( $ id , $ title , $ formControl , ( array ) $ additionalArguments ) ; }

Build a checkbox field.

@param string $id                  String for use in the 'id' attribute of tags.
@param string $title               Title of the field.
@param array  $additionalArguments Optional. Additional arguments that are passed to `register_setting` and
`add_settings_field`.

@return Field


public function email(
        string $id,
        string $title,
        array $additionalArguments = null
    ): Field {
        $formControl = $this->builder->email($id)
                                     ->addClass('regular-text')
                                     ->value(
                                         $this->optionStore->getString($id)
                                     );

        $additionalArguments = array_merge(
            [
                'sanitize_callback' => 'sanitize_email',
            ],
            (array) $additionalArguments
        );

        return new Field(
            $id,
            $title,
            $formControl,
            (array) $additionalArguments
        );
    }

public function email ( string $ id , string $ title , array $ additionalArguments = null ) : Field { $ formControl = $ this -> builder -> email ( $ id ) -> addClass ( 'regular-text' ) -> value ( $ this -> optionStore -> getString ( $ id ) ) ; $ additionalArguments = array_merge ( [ 'sanitize_callback' => 'sanitize_email' , ] , ( array ) $ additionalArguments ) ; return new Field ( $ id , $ title , $ formControl , ( array ) $ additionalArguments ) ; }

Build an email field.

@param string $id                  String for use in the 'id' attribute of tags.
@param string $title               Title of the field.
@param array  $additionalArguments Optional. Additional arguments that are passed to `register_setting` and
`add_settings_field`.

@return Field


public function select(
        string $id,
        string $title,
        array $options,
        array $additionalArguments = null
    ): Field {
        $formControl = $this->builder->select($id, $options)
                                     ->select(
                                         $this->optionStore->getString($id)
                                     );

        $additionalArguments = array_merge(
            [
                'sanitize_callback' => function ($value) use ($options): string {
                    $value = sanitize_text_field($value);

                    return array_key_exists($value, $options) ? $value : '';
                },
            ],
            (array) $additionalArguments
        );

        return new Field(
            $id,
            $title,
            $formControl,
            (array) $additionalArguments
        );
    }

public function select ( string $ id , string $ title , array $ options , array $ additionalArguments = null ) : Field { $ formControl = $ this -> builder -> select ( $ id , $ options ) -> select ( $ this -> optionStore -> getString ( $ id ) ) ; $ additionalArguments = array_merge ( [ 'sanitize_callback' => function ( $ value ) use ( $ options ) : string { $ value = sanitize_text_field ( $ value ) ; return array_key_exists ( $ value , $ options ) ? $ value : '' ; } , ] , ( array ) $ additionalArguments ) ; return new Field ( $ id , $ title , $ formControl , ( array ) $ additionalArguments ) ; }

Build a select field.

@param string $id                  String for use in the 'id' attribute of tags.
@param string $title               Title of the field.
@param array  $options             Valid options.
@param array  $additionalArguments Optional. Additional arguments that are passed to `register_setting` and
`add_settings_field`.

@return Field


public function run()
    {
        array_map(
            function (SectionInterface $section) {
                $this->registerSection($section);
                $this->registerFields($section);
                $this->registerSettings($section);
            },
            $this->sections
        );
    }

public function run ( ) { array_map ( function ( SectionInterface $ section ) { $ this -> registerSection ( $ section ) ; $ this -> registerFields ( $ section ) ; $ this -> registerSettings ( $ section ) ; } , $ this -> sections ) ; }

Register sections with WordPress.

@void


private function registerSection(SectionInterface $section)
    {
        add_settings_section(
            $section->getId(),
            $section->getTitle(),
            $section->getRenderClosure(),
            $this->pageSlug
        );
    }

private function registerSection ( SectionInterface $ section ) { add_settings_section ( $ section -> getId ( ) , $ section -> getTitle ( ) , $ section -> getRenderClosure ( ) , $ this -> pageSlug ) ; }

Register a section to the settings page with WordPress.

@param SectionInterface $section Section to be registered.

@void

Register a section to the settings page with WordPress .


private function registerFields(SectionInterface $section)
    {
        array_map(
            function (FieldInterface $field) use ($section) {
                add_settings_field(
                    $field->getId(),
                    $field->getTitle(),
                    $field->getRenderClosure(),
                    $this->pageSlug,
                    $section->getId(),
                    $field->getAdditionalArguments()
                );
            },
            $section->getFields()
        );
    }

private function registerFields ( SectionInterface $ section ) { array_map ( function ( FieldInterface $ field ) use ( $ section ) { add_settings_field ( $ field -> getId ( ) , $ field -> getTitle ( ) , $ field -> getRenderClosure ( ) , $ this -> pageSlug , $ section -> getId ( ) , $ field -> getAdditionalArguments ( ) ) ; } , $ section -> getFields ( ) ) ; }

Register fields of a section with WordPress.

@param SectionInterface $section Section which holds a list of its fields.

@return void

Register fields of a section with WordPress .


private function registerSettings(SectionInterface $section)
    {
        array_map(
            function (FieldInterface $field) {
                register_setting(
                    $this->pageSlug,
                    $field->getId(),
                    $field->getAdditionalArguments()
                );
            },
            $section->getFields()
        );
    }

private function registerSettings ( SectionInterface $ section ) { array_map ( function ( FieldInterface $ field ) { register_setting ( $ this -> pageSlug , $ field -> getId ( ) , $ field -> getAdditionalArguments ( ) ) ; } , $ section -> getFields ( ) ) ; }

Register a setting and its data with WordPress.

@param SectionInterface $section Section which holds a list of its fields.

@return void

Register a setting and its data with WordPress .


public function display($attributes = [], $options = [])
    {
        $isMultiple = (bool)$this->options->get('multiple', $options);
        if (!array_key_exists('id', $attributes)) {
            $attributes['id'] = $this->randomCaptchaId();
        }
        $html = '';
        if (!$isMultiple && array_get($attributes, 'add-js', true)) {
            $html .= '';
        }
        unset($attributes['add-js']);
        $attributeOptions = $this->options->get('attributes', $options);
        if (!empty($attributeOptions)) {
            $attributes = array_merge($attributeOptions, $attributes);
        }
        if ($isMultiple) {
            array_push($this->captchaAttributes, $attributes);
        } else {
            $attributes['data-sitekey'] = $this->config->get('captcha.sitekey');
        }

        return $html . '
buildAttributes($attributes) . '>
';
    }

public
function
display
(
$
attributes
=
[
]
,
$
options
=
[
]
)
{
$
isMultiple
=
(
bool
)
$
this
->
options
->
get
(
'multiple'
,
$
options
)
;
if
(
!
array_key_exists
(
'id'
,
$
attributes
)
)
{
$
attributes
[
'id'
]
=
$
this
->
randomCaptchaId
(
)
;
}
$
html
=
''
;
if
(
!
$
isMultiple
&&
array_get
(
$
attributes
,
'add-js'
,
true
)
)
{
$
html
.=
''
;
}
unset
(
$
attributes
[
'add-js'
]
)
;
$
attributeOptions
=
$
this
->
options
->
get
(
'attributes'
,
$
options
)
;
if
(
!
empty
(
$
attributeOptions
)
)
{
$
attributes
=
array_merge
(
$
attributeOptions
,
$
attributes
)
;
}
if
(
$
isMultiple
)
{
array_push
(
$
this
->
captchaAttributes
,
$
attributes
)
;
}
else
{
$
attributes
[
'data-sitekey'
]
=
$
this
->
config
->
get
(
'captcha.sitekey'
)
;
}
return
$
html
.
'

buildAttributes
(
$
attributes
)
.
'>
'
;
}

Create captcha html element

@param array $attributes
@param array $options
@return string


public function getJsLink($options = [])
    {
        $query = [];
        if ($this->options->get('multiple', $options)) {
            $query = [
                'onload' => $this->callbackName,
                'render' => 'explicit',
            ];
        }
        $lang = $this->options->get('lang', $options);
        if ($lang) {
            $query['hl'] = $lang;
        }

        return static::CAPTCHA_CLIENT_API . '?' . http_build_query($query, null, '&');
    }

public function getJsLink ( $ options = [ ] ) { $ query = [ ] ; if ( $ this -> options -> get ( 'multiple' , $ options ) ) { $ query = [ 'onload' => $ this -> callbackName , 'render' => 'explicit' , ] ; } $ lang = $ this -> options -> get ( 'lang' , $ options ) ; if ( $ lang ) { $ query [ 'hl' ] = $ lang ; } return static :: CAPTCHA_CLIENT_API . '?' . http_build_query ( $ query , null , '&' ) ; }

Create javascript api link with language

@param array $options
@return string


public function displayMultiple($options = [])
    {
        if (!$this->options->get('multiple', $options)) {
            return '';
        }
        $renderHtml = '';
        foreach ($this->captchaAttributes as $captchaAttribute){
            $renderHtml .= "{$this->widgetIdName}[\"{$captchaAttribute['id']}\"]={$this->buildCaptchaHtml($captchaAttribute)}";
        }

        return "<script type=\"text/javascript\">var {$this->widgetIdName}={};var {$this->callbackName}=function(){{$renderHtml}};</script>";
    }

Display multiple captcha on page

@param array $options
@return string


protected function buildCaptchaHtml(array $captchaAttribute)
    {
        $options = array_merge(
            ['sitekey' => $this->config->get('captcha.sitekey')],
            $this->config->get('captcha.attributes', [])
        );
        foreach ($captchaAttribute as $key => $value) {
            $options[str_replace('data-', '', $key)] = $value;
        }
        $options = json_encode($options);
        return "grecaptcha.render('{$captchaAttribute['id']}',{$options});";
    }

Build captcha by attributes

@param array $captchaAttribute

@return string


public function uploadAsset(\SplFileInfo $file, Library $library = null): MoovlyObject
    {
        $supportedExtensions = array_merge(
            self::SUPPORTED_AUDIO_EXTENSION,
            self::SUPPORTED_IMAGE_EXTENSIONS,
            self::SUPPORTED_VIDEO_EXTENSIONS
        );

        $assetExtensions = array_merge(
            self::SUPPORTED_AUDIO_EXTENSION,
            self::SUPPORTED_IMAGE_EXTENSIONS
        );

        if (!in_array($file->getExtension(), $supportedExtensions)) {
            throw new BadAssetException($file);
        }

        if (in_array($file->getExtension(), $assetExtensions)) {
            try {
                $object = $this->client->uploadAsset($file, is_null($library) ? null : $library->getId());
            } catch (ClientException $ce) {
                $response = $ce->getResponse();

                throw ExceptionFactory::create($response, $ce);
            }

            return ObjectFactory::createFromAPIResponse($object);
        }

        try {
            $object = $this->client->uploadAsset($file, is_null($library) ? null : $library->getId());
        } catch (ClientException $ce) {
            $response = $ce->getResponse();

            throw ExceptionFactory::create($response, $ce);
        }

        return ObjectFactory::createFromAPIResponse($object);
    }

public function uploadAsset ( \ SplFileInfo $ file , Library $ library = null ) : MoovlyObject { $ supportedExtensions = array_merge ( self :: SUPPORTED_AUDIO_EXTENSION , self :: SUPPORTED_IMAGE_EXTENSIONS , self :: SUPPORTED_VIDEO_EXTENSIONS ) ; $ assetExtensions = array_merge ( self :: SUPPORTED_AUDIO_EXTENSION , self :: SUPPORTED_IMAGE_EXTENSIONS ) ; if ( ! in_array ( $ file -> getExtension ( ) , $ supportedExtensions ) ) { throw new BadAssetException ( $ file ) ; } if ( in_array ( $ file -> getExtension ( ) , $ assetExtensions ) ) { try { $ object = $ this -> client -> uploadAsset ( $ file , is_null ( $ library ) ? null : $ library -> getId ( ) ) ; } catch ( ClientException $ ce ) { $ response = $ ce -> getResponse ( ) ; throw ExceptionFactory :: create ( $ response , $ ce ) ; } return ObjectFactory :: createFromAPIResponse ( $ object ) ; } try { $ object = $ this -> client -> uploadAsset ( $ file , is_null ( $ library ) ? null : $ library -> getId ( ) ) ; } catch ( ClientException $ ce ) { $ response = $ ce -> getResponse ( ) ; throw ExceptionFactory :: create ( $ response , $ ce ) ; } return ObjectFactory :: createFromAPIResponse ( $ object ) ; }

Uploads an asset to the Moovly API.

@param \SplFileInfo $file
@param Library      $library

@return MoovlyObject

@throws MoovlyException


public function getProject(string $projectId): Project
    {
        try {
            $project = ProjectFactory::createFromAPIResponse(
                $this->client->getProject($projectId)
            );
        } catch (ClientException $ce) {
            $response = $ce->getResponse();

            throw ExceptionFactory::create($response, $ce);
        }

        return $project;
    }

public function getProject ( string $ projectId ) : Project { try { $ project = ProjectFactory :: createFromAPIResponse ( $ this -> client -> getProject ( $ projectId ) ) ; } catch ( ClientException $ ce ) { $ response = $ ce -> getResponse ( ) ; throw ExceptionFactory :: create ( $ response , $ ce ) ; } return $ project ; }

Fetches one project.

@param string $projectId

@return Project

@throws MoovlyException


public function getProjects(?string $filter = 'unarchived'): array
    {
        if (is_null($filter)) {
            $filter = 'unarchived';
        }

        try {
            $response = $this->client->getProjects($filter);
        } catch (ClientException $ce) {
            $response = $ce->getResponse();

            throw ExceptionFactory::create($response, $ce);
        }

        $projects = array_map(function (array $project) {
            return ProjectFactory::createFromAPIResponse($project);
        }, $response);

        return $projects;
    }

public function getProjects ( ? string $ filter = 'unarchived' ) : array { if ( is_null ( $ filter ) ) { $ filter = 'unarchived' ; } try { $ response = $ this -> client -> getProjects ( $ filter ) ; } catch ( ClientException $ ce ) { $ response = $ ce -> getResponse ( ) ; throw ExceptionFactory :: create ( $ response , $ ce ) ; } $ projects = array_map ( function ( array $ project ) { return ProjectFactory :: createFromAPIResponse ( $ project ) ; } , $ response ) ; return $ projects ; }

Fetches all projects.

@param string $filter

@return Project[]

@throws MoovlyException


public function createTemplate(Project $project): Template
    {
        try {
            $template = TemplateFactory::createFromAPIResponse(
                $this->client->createTemplate($project->getId())
            );
        } catch (ClientException $ce) {
            $response = $ce->getResponse();

            throw ExceptionFactory::create($response, $ce);
        }

        return $template;
    }

public function createTemplate ( Project $ project ) : Template { try { $ template = TemplateFactory :: createFromAPIResponse ( $ this -> client -> createTemplate ( $ project -> getId ( ) ) ) ; } catch ( ClientException $ ce ) { $ response = $ ce -> getResponse ( ) ; throw ExceptionFactory :: create ( $ response , $ ce ) ; } return $ template ; }

Creates a template.

@param Project $project

@return Template

@throws MoovlyException


public function getTemplate(string $templateId): Template
    {
        try {
            $template = TemplateFactory::createFromAPIResponse($this->client->getTemplate($templateId));
        } catch (ClientException $ce) {
            $response = $ce->getResponse();

            throw ExceptionFactory::create($response, $ce);
        }

        return $template;
    }

public function getTemplate ( string $ templateId ) : Template { try { $ template = TemplateFactory :: createFromAPIResponse ( $ this -> client -> getTemplate ( $ templateId ) ) ; } catch ( ClientException $ ce ) { $ response = $ ce -> getResponse ( ) ; throw ExceptionFactory :: create ( $ response , $ ce ) ; } return $ template ; }

Fetches a template.

@param string $templateId

@return Template

@throws MoovlyException


public function getTemplates(): array
    {
        try {
            $response = $this->client->getTemplates();
        } catch (ClientException $ce) {
            $response = $ce->getResponse();

            throw ExceptionFactory::create($response, $ce);
        }

        $templates = array_map(function (array $template) {
            return TemplateFactory::createFromAPIResponse($template);
        }, $response);

        return $templates;
    }

public function getTemplates ( ) : array { try { $ response = $ this -> client -> getTemplates ( ) ; } catch ( ClientException $ ce ) { $ response = $ ce -> getResponse ( ) ; throw ExceptionFactory :: create ( $ response , $ ce ) ; } $ templates = array_map ( function ( array $ template ) { return TemplateFactory :: createFromAPIResponse ( $ template ) ; } , $ response ) ; return $ templates ; }

Fetches all templates the bearer has access to.

@return Template[]

@throws MoovlyException

Fetches all templates the bearer has access to .


public function createJob(Job $job): Job
    {
        $validQualities = ['480p', '720p', '1080p'];

        $options = array_merge([
            'quality'     => '480p',
            'create_moov' => false,
            'auto_render' => true,
        ], $job->getOptions());

        if (!in_array($options['quality'], $validQualities)) {
            throw new BadRequestException(
                sprintf(
                    'The given quality (%s) for a job is invalid, please use a valid one (%s).',
                    $options['quality'],
                    implode(', ', $validQualities)
                )
            );
        }

        if (!is_null($job->getId())) {
            throw new BadRequestException(
                'The given job already has an id. This either means you set this manually, or this is a job already ' .
                    ' registered in Moovly. In the first case, stop assigning a job id, in the latter case, just ' .
                    ' read the job.'
            );
        }

        if (is_null($job->getTemplate())) {
            throw new BadRequestException(
                'You have not supplied a template in the job request. Please run $job->setTemplate() before calling' .
                    ' $service->createJob().'
            );
        }

        $values = array_map(function (Value $value) {
            return [
                'external_id' => $value->getExternalId(),
                'title'       => $value->getTitle(),
                'template_variables' => $value->getTemplateVariables()
            ];
        }, $job->getValues());

        try {
            $result = JobFactory::createFromAPIResponse(
                $this->client->createJob($job->getTemplate()->getId(), $options, $values)
            );

            $result
                ->setTemplate($job->getTemplate())
                ->setOptions($job->getOptions())
                ->setValues($this->mergeJobValues($job->getValues(), $result->getValues()))
            ;
        } catch (ClientException $ce) {
            $response = $ce->getResponse();

            throw ExceptionFactory::create($response, $ce);
        }

        return $result;
    }

Registers a new Job request in the Moovly API. This expects a Job model. Use the
JobFactory and the ValueFactory to create this.

@param Job   $job

@return Job

@throws MoovlyException

Registers a new Job request in the Moovly API . This expects a Job model . Use the JobFactory and the ValueFactory to create this .


public function getJob(string $jobId): Job
    {
        try {
            $job = JobFactory::createFromAPIResponse($this->client->getJob($jobId));
        } catch (ClientException $ce) {
            $response = $ce->getResponse();

            throw ExceptionFactory::create($response, $ce);
        }

        return $job;
    }

public function getJob ( string $ jobId ) : Job { try { $ job = JobFactory :: createFromAPIResponse ( $ this -> client -> getJob ( $ jobId ) ) ; } catch ( ClientException $ ce ) { $ response = $ ce -> getResponse ( ) ; throw ExceptionFactory :: create ( $ response , $ ce ) ; } return $ job ; }

Gets a job.

@param string $jobId

@return Job

@throws MoovlyException


public function getJobsByTemplate(Template $template): array
    {
        try {
            $response = $this->client->getJobsByTemplate($template->getId());
        } catch (ClientException $ce) {
            $response = $ce->getResponse();

            throw ExceptionFactory::create($response, $ce);
        }

        $jobs = array_map(function (array $job) {
            return JobFactory::createFromAPIResponse($job);
        }, $response);

        return $jobs;
    }

public function getJobsByTemplate ( Template $ template ) : array { try { $ response = $ this -> client -> getJobsByTemplate ( $ template -> getId ( ) ) ; } catch ( ClientException $ ce ) { $ response = $ ce -> getResponse ( ) ; throw ExceptionFactory :: create ( $ response , $ ce ) ; } $ jobs = array_map ( function ( array $ job ) { return JobFactory :: createFromAPIResponse ( $ job ) ; } , $ response ) ; return $ jobs ; }

Gets all the jobs that were made with a template.

@param Template $template

@return Job[]

@throws MoovlyException

Gets all the jobs that were made with a template .


public function getCurrentUser(): User
    {
        try {
            $user = UserFactory::createFromAPIResponse($this->client->getUser());
        } catch (ClientException $ce) {
            $response = $ce->getResponse();

            throw ExceptionFactory::create($response, $ce);
        }

        return $user;
    }

public function getCurrentUser ( ) : User { try { $ user = UserFactory :: createFromAPIResponse ( $ this -> client -> getUser ( ) ) ; } catch ( ClientException $ ce ) { $ response = $ ce -> getResponse ( ) ; throw ExceptionFactory :: create ( $ response , $ ce ) ; } return $ user ; }

Returns the current user.

@return User

@throws MoovlyException


public function getPersonalLibraryForUser(): Library
    {
        try {
            $library = LibraryFactory::createFromAPIResponse($this->client->getUserPersonalLibrary());
        } catch (ClientException $ce) {
            $response = $ce->getResponse();

            throw ExceptionFactory::create($response, $ce);
        }

        return $library;
    }

public function getPersonalLibraryForUser ( ) : Library { try { $ library = LibraryFactory :: createFromAPIResponse ( $ this -> client -> getUserPersonalLibrary ( ) ) ; } catch ( ClientException $ ce ) { $ response = $ ce -> getResponse ( ) ; throw ExceptionFactory :: create ( $ response , $ ce ) ; } return $ library ; }

Get the user's personal library.

@return Library

@throws MoovlyException


private function mergeJobValues(array $preRequestValues, array $postRequestValues)
    {
        $result = array_map(function (Value $postValue) use ($preRequestValues) {
            $preValues = array_filter($preRequestValues, function (Value $preValue) use ($postValue) {
                return $postValue->getExternalId() === $preValue->getExternalId();
            });

            /** @var Value $preValue */
            $preValue = $preValues[0];

            $postValue
                ->setTemplateVariables($preValue->getTemplateVariables())
                ->setTitle($preValue->getTitle())
            ;

            return $postValue;
        }, $postRequestValues);

        return $result;
    }

private
function
mergeJobValues
(
array
$
preRequestValues
,
array
$
postRequestValues
)
{
$
result
=
array_map
(
function
(
Value
$
postValue
)
use
(
$
preRequestValues
)
{
$
preValues
=
array_filter
(
$
preRequestValues
,
function
(
Value
$
preValue
)
use
(
$
postValue
)
{
return
$
postValue
->
getExternalId
(
)
===
$
preValue
->
getExternalId
(
)
;
}
)
;
/** @var Value $preValue */
$
preValue
=
$
preValues
[
0
]
;
$
postValue
->
setTemplateVariables
(
$
preValue
->
getTemplateVariables
(
)
)
->
setTitle
(
$
preValue
->
getTitle
(
)
)
;
return
$
postValue
;
}
,
$
postRequestValues
)
;
return
$
result
;
}

Makes sure the API of newly created jobs is as complete for values as possible.

@param array $preRequestValues
@param array $postRequestValues

@return array

Makes sure the API of newly created jobs is as complete for values as possible .


public function getLdapUser($attribute, $value)
    {
        try {
            $query = $this->ldap->buildLdapQuery()
                ->select($this->getAttributesToSelect())
                ->from($this->options['ldap_object_type'])
                ->where([$attribute => $value]);
            if (!is_null($this->options['search_base'])) {
                $query->setBaseDn($this->options['search_base']);
            }
            return $query->getLdapQuery()->getSingleResult();
        } catch (EmptyResultException $e) {
            throw new UsernameNotFoundException(sprintf('Username "%s" was not found.', $value));
        } catch (MultiResultException $e) {
            throw new UsernameNotFoundException(sprintf('Multiple results for "%s" were found.', $value));
        }
    }

public
function
getLdapUser
(
$
attribute
,
$
value
)
{
try
{
$
query
=
$
this
->
ldap
->
buildLdapQuery
(
)
->
select
(
$
this
->
getAttributesToSelect
(
)
)
->
from
(
$
this
->
options
[
'ldap_object_type'
]
)
->
where
(
[
$
attribute
=>
$
value
]
)
;
if
(
!
is_null
(
$
this
->
options
[
'search_base'
]
)
)
{
$
query
->
setBaseDn
(
$
this
->
options
[
'search_base'
]
)
;
}
return
$
query
->
getLdapQuery
(
)
->
getSingleResult
(
)
;
}
catch
(
EmptyResultException
$
e
)
{
throw
new
UsernameNotFoundException
(
sprintf
(
'Username "%s" was not found.'
,
$
value
)
)
;
}
catch
(
MultiResultException
$
e
)
{
throw
new
UsernameNotFoundException
(
sprintf
(
'Multiple results for "%s" were found.'
,
$
value
)
)
;
}
}

Search for, and return, the LDAP user by a specific attribute.

@param string $attribute
@param string $value
@return LdapObject

Search for and return the LDAP user by a specific attribute .


protected function setLdapConfigDefinition(ContainerBuilder $container, array $config)
    {
        $ldapCfg = ['general' => $config['general']];

        // Only tag the cache warmer if there are domains listed in the config...
        if (isset($config['domains']) && !empty($config['domains'])) {
            $ldapCfg['domains'] = $config['domains'];
            $container->getDefinition('ldap_tools.cache_warmer.ldap_tools_cache_warmer')->addTag('kernel.cache_warmer');
        } else {
            $container->getDefinition('data_collector.ldap_tools')->replaceArgument(0, null);
        }

        $definition = $container->getDefinition('LdapTools\Configuration');
        $definition->addMethodCall('loadFromArray', [$ldapCfg]);
        $definition->addMethodCall('setEventDispatcher', [new Reference('ldap_tools.event_dispatcher')]);

        $loggerChain = $container->getDefinition('ldap_tools.log.logger_chain');
        if ($config['logging']) {
            $loggerChain->addMethodCall('addLogger', [new Reference('ldap_tools.log.logger')]);
        }
        if ($config['profiling']) {
            $loggerChain->addMethodCall('addLogger', [new Reference('ldap_tools.log.profiler')]);
        }
        if ($config['logging'] || $config['profiling']) {
            $definition->addMethodCall('setLogger', [new Reference('ldap_tools.log.logger_chain')]);
        }
    }

Pass the configuration to be loaded for the LdapTools Configuration class.

@param ContainerBuilder $container
@param array $config

Pass the configuration to be loaded for the LdapTools Configuration class .


public function checkLdapErrorCode(UserInterface $user, $code, $ldapType)
    {
        if ($ldapType == LdapConnection::TYPE_AD && $code == ResponseCode::AccountLocked) {
            $ex = new LockedException('User account is locked.');
            $ex->setUser($user);
            throw $ex;
        }

        if ($ldapType == LdapConnection::TYPE_AD && $code == ResponseCode::AccountPasswordMustChange) {
            $ex = new CredentialsExpiredException('User credentials have expired.');
            $ex->setUser($user);
            throw $ex;
        }

        if ($ldapType == LdapConnection::TYPE_AD && $code == ResponseCode::AccountDisabled) {
            $ex = new DisabledException('User account is disabled.');
            $ex->setUser($user);
            throw $ex;
        }
    }

public
function
checkLdapErrorCode
(
UserInterface
$
user
,
$
code
,
$
ldapType
)
{
if
(
$
ldapType
==
LdapConnection
::
TYPE_AD
&&
$
code
==
ResponseCode
::
AccountLocked
)
{
$
ex
=
new
LockedException
(
'User account is locked.'
)
;
$
ex
->
setUser
(
$
user
)
;
throw
$
ex
;
}
if
(
$
ldapType
==
LdapConnection
::
TYPE_AD
&&
$
code
==
ResponseCode
::
AccountPasswordMustChange
)
{
$
ex
=
new
CredentialsExpiredException
(
'User credentials have expired.'
)
;
$
ex
->
setUser
(
$
user
)
;
throw
$
ex
;
}
if
(
$
ldapType
==
LdapConnection
::
TYPE_AD
&&
$
code
==
ResponseCode
::
AccountDisabled
)
{
$
ex
=
new
DisabledException
(
'User account is disabled.'
)
;
$
ex
->
setUser
(
$
user
)
;
throw
$
ex
;
}
}

Based on the LDAP error code and the LDAP type, throw any specific exceptions detected.

@param UserInterface $user The user object.
@param int $code The extended LDAP error code.
@param string $ldapType The LDAP type used for authentication.

Based on the LDAP error code and the LDAP type throw any specific exceptions detected .


protected function setAllowedTypes(OptionsResolver $resolver)
    {
        $allowed = ['ldap_query_builder', ['\Closure', 'LdapTools\Query\LdapQueryBuilder', 'null']];

        $reflection = new \ReflectionClass(get_class($resolver));
        $parameters = $reflection->getMethod('addAllowedTypes')->getParameters();

        if ($parameters[0]->isArray()) {
            $resolver->setAllowedTypes([$allowed[0] => $allowed[1]]);
        } else {
            $resolver->setAllowedTypes(...$allowed);
        }
    }

protected function setAllowedTypes ( OptionsResolver $ resolver ) { $ allowed = [ 'ldap_query_builder' , [ '\Closure' , 'LdapTools\Query\LdapQueryBuilder' , 'null' ] ] ; $ reflection = new \ ReflectionClass ( get_class ( $ resolver ) ) ; $ parameters = $ reflection -> getMethod ( 'addAllowedTypes' ) -> getParameters ( ) ; if ( $ parameters [ 0 ] -> isArray ( ) ) { $ resolver -> setAllowedTypes ( [ $ allowed [ 0 ] => $ allowed [ 1 ] ] ) ; } else { $ resolver -> setAllowedTypes ( ... $ allowed ) ; } }

A rather ugly way of allowing compatibility with the resolver component for pre 2.6 versions.

@param OptionsResolver $resolver

A rather ugly way of allowing compatibility with the resolver component for pre 2 . 6 versions .


protected function setLdapCredentialsIfNeeded($username, $password, UserProviderInterface $userProvider)
    {
        // Only care about this in the context of the LDAP user provider...
        if (!$userProvider instanceof LdapUserProvider) {
            return;
        }

        // Only if the username/password are not defined in the config....
        $config = $this->ldap->getConnection()->getConfig();
        if (!(empty($config->getUsername()) && (empty($config->getPassword() && $config->getPassword() !== '0')))) {
            return;
        }

        $config->setUsername($username);
        $config->setPassword($password);
    }

If no LDAP credentials are in the config then attempt to use the user supplied credentials from the login. But
only if we are using the LdapUserProvider.

@param string $username
@param string $password
@param UserProviderInterface $userProvider

If no LDAP credentials are in the config then attempt to use the user supplied credentials from the login . But only if we are using the LdapUserProvider .


protected function switchDomainIfNeeded($domain)
    {
        if (!empty($domain) && $this->ldap->getDomainContext() !== $domain) {
            $this->ldap->switchDomain($domain);
        }
    }

protected function switchDomainIfNeeded ( $ domain ) { if ( ! empty ( $ domain ) && $ this -> ldap -> getDomainContext ( ) !== $ domain ) { $ this -> ldap -> switchDomain ( $ domain ) ; } }

If the domain needs to a different context for the request, then switch it.

@param string|null $domain

If the domain needs to a different context for the request then switch it .


protected function switchDomainBackIfNeeded($domain)
    {
        if ($domain !== $this->ldap->getDomainContext()) {
            $this->ldap->switchDomain($domain);
        }
    }

protected function switchDomainBackIfNeeded ( $ domain ) { if ( $ domain !== $ this -> ldap -> getDomainContext ( ) ) { $ this -> ldap -> switchDomain ( $ domain ) ; } }

If the passed domain is not the current context, then switch back to it.

@param string $domain

If the passed domain is not the current context then switch back to it .


protected function hideOrThrow(\Exception $e, $hideUserNotFoundExceptions)
    {
        if ($hideUserNotFoundExceptions) {
            throw new BadCredentialsException('Bad credentials.', 0, $e);
        }

        // Specifically show LdapTools related exceptions, ignore others.
        // Custom auth exception messages don't exist until Symfony 2.8, 2.7 is still under support...
        if (!$hideUserNotFoundExceptions && $e instanceof Exception && class_exists('Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException')) {
            throw new CustomUserMessageAuthenticationException($e->getMessage(), [], $e->getCode());
        }

        throw $e;
    }

Determine whether or not the exception should be masked with a BadCredentials or not.

@param \Exception $e
@param bool $hideUserNotFoundExceptions
@throws \Exception

Determine whether or not the exception should be masked with a BadCredentials or not .


protected function getUsernamePasswordToken(Request $request)
    {
        if ($this->options['post_only']) {
            $username = trim($this->getParameterFromBag($request->request, $this->options['username_parameter']));
            $password = $this->getParameterFromBag($request->request, $this->options['password_parameter']);
        } else {
            $username = trim($this->getParameterFromRequest($request, $this->options['username_parameter']));
            $password = $this->getParameterFromRequest($request, $this->options['password_parameter']);
        }
        $request->getSession()->set(Security::LAST_USERNAME, $username);

        $token = new UsernamePasswordToken($username, $password, $this->providerKey);
        $this->addDomainToTokenIfPresent($request, $token);

        return $token;
    }

protected function getUsernamePasswordToken ( Request $ request ) { if ( $ this -> options [ 'post_only' ] ) { $ username = trim ( $ this -> getParameterFromBag ( $ request -> request , $ this -> options [ 'username_parameter' ] ) ) ; $ password = $ this -> getParameterFromBag ( $ request -> request , $ this -> options [ 'password_parameter' ] ) ; } else { $ username = trim ( $ this -> getParameterFromRequest ( $ request , $ this -> options [ 'username_parameter' ] ) ) ; $ password = $ this -> getParameterFromRequest ( $ request , $ this -> options [ 'password_parameter' ] ) ; } $ request -> getSession ( ) -> set ( Security :: LAST_USERNAME , $ username ) ; $ token = new UsernamePasswordToken ( $ username , $ password , $ this -> providerKey ) ; $ this -> addDomainToTokenIfPresent ( $ request , $ token ) ; return $ token ; }

Get the UsernamePasswordToken based off the Request parameters.

@param Request $request
@return UsernamePasswordToken

Get the UsernamePasswordToken based off the Request parameters .


protected function addDomainToTokenIfPresent(Request $request, UsernamePasswordToken $token)
    {
        if ($this->options['post_only'] && $request->request->has($this->options['domain_parameter'])) {
            $token->setAttribute(
                'ldap_domain',
                trim($this->getParameterFromBag($request->request, $this->options['domain_parameter']))
            );
        } elseif ($domain = trim($this->getParameterFromRequest($request, $this->options['domain_parameter']))) {
            $token->setAttribute('ldap_domain', $domain);
        }
    }

protected function addDomainToTokenIfPresent ( Request $ request , UsernamePasswordToken $ token ) { if ( $ this -> options [ 'post_only' ] && $ request -> request -> has ( $ this -> options [ 'domain_parameter' ] ) ) { $ token -> setAttribute ( 'ldap_domain' , trim ( $ this -> getParameterFromBag ( $ request -> request , $ this -> options [ 'domain_parameter' ] ) ) ) ; } elseif ( $ domain = trim ( $ this -> getParameterFromRequest ( $ request , $ this -> options [ 'domain_parameter' ] ) ) ) { $ token -> setAttribute ( 'ldap_domain' , $ domain ) ; } }

Add the domain name for the login request to the token if specified.

@param Request $request
@param UsernamePasswordToken $token

Add the domain name for the login request to the token if specified .


protected function transformValueForDb(LifecycleEventArgs $args)
    {
        $entity = $this->getObjectFromLifeCycleArgs($args);
        $om = $this->getOmFromLifeCycleArgs($args);

        $properties = $this->getLdapObjectAnnotationProperties($entity, $om);
        foreach ($properties as $info) {
            if ($info['property']->getValue($entity)) {
                $this->setLdapValueForProperty($info['property'], $info['annotation'], $entity);
            }
        }
    }

protected function transformValueForDb ( LifecycleEventArgs $ args ) { $ entity = $ this -> getObjectFromLifeCycleArgs ( $ args ) ; $ om = $ this -> getOmFromLifeCycleArgs ( $ args ) ; $ properties = $ this -> getLdapObjectAnnotationProperties ( $ entity , $ om ) ; foreach ( $ properties as $ info ) { if ( $ info [ 'property' ] -> getValue ( $ entity ) ) { $ this -> setLdapValueForProperty ( $ info [ 'property' ] , $ info [ 'annotation' ] , $ entity ) ; } } }

Handles transforming the value as it currently is to the value the DB expects.

@param LifecycleEventArgs $args

Handles transforming the value as it currently is to the value the DB expects .


protected function getLdapObjectAnnotationProperties($entity, $om)
    {
        $properties = $om->getClassMetadata(get_class($entity))->getReflectionProperties();

        $ldapObjectProps = [];
        foreach ($properties as $prop) {
            $annotation = $this->reader->getPropertyAnnotation($prop, self::ANNOTATION);
            if (!empty($annotation)) {
                $ldapObjectProps[] = ['annotation' => $annotation, 'property' => $prop];
            }
        }

        return $ldapObjectProps;
    }

protected function getLdapObjectAnnotationProperties ( $ entity , $ om ) { $ properties = $ om -> getClassMetadata ( get_class ( $ entity ) ) -> getReflectionProperties ( ) ; $ ldapObjectProps = [ ] ; foreach ( $ properties as $ prop ) { $ annotation = $ this -> reader -> getPropertyAnnotation ( $ prop , self :: ANNOTATION ) ; if ( ! empty ( $ annotation ) ) { $ ldapObjectProps [ ] = [ 'annotation' => $ annotation , 'property' => $ prop ] ; } } return $ ldapObjectProps ; }

Get all the properties from the entity that have a LdapObject annotation defined.

@param object $entity
@param ObjectManager $om
@return array

Get all the properties from the entity that have a LdapObject annotation defined .


protected function setLdapObjectForProperty(\ReflectionProperty $property, LdapObjectAnnotation $annotation, $entity)
    {
        if (empty($property->getValue($entity))) {
            return;
        }
        $domain = $this->ldap->getDomainContext();
        $switchDomain = $annotation->domain ?: null;
        if ($switchDomain) {
            $this->ldap->switchDomain($annotation->domain);
        }

        $results = $this->queryLdapForObjects($property, $annotation, $entity);
        $property->setValue($entity, $results);

        if ($switchDomain) {
            $this->ldap->switchDomain($domain);
        }
    }

protected function setLdapObjectForProperty ( \ ReflectionProperty $ property , LdapObjectAnnotation $ annotation , $ entity ) { if ( empty ( $ property -> getValue ( $ entity ) ) ) { return ; } $ domain = $ this -> ldap -> getDomainContext ( ) ; $ switchDomain = $ annotation -> domain ? : null ; if ( $ switchDomain ) { $ this -> ldap -> switchDomain ( $ annotation -> domain ) ; } $ results = $ this -> queryLdapForObjects ( $ property , $ annotation , $ entity ) ; $ property -> setValue ( $ entity , $ results ) ; if ( $ switchDomain ) { $ this -> ldap -> switchDomain ( $ domain ) ; } }

Based on an array of IDs for LDAP objects, set the property to either a LdapObject for LdapObjectCollection.

@param \ReflectionProperty $property
@param LdapObjectAnnotation $annotation
@param $entity

Based on an array of IDs for LDAP objects set the property to either a LdapObject for LdapObjectCollection .


protected function setLdapValueForProperty(\ReflectionProperty $property, LdapObjectAnnotation $annotation, $entity)
    {
        $value = $property->getValue($entity);

        if ($value instanceof LdapObject) {
            $ldapValues = $value->get($annotation->id);
        } elseif ($value instanceof LdapObjectCollection) {
            $ldapValues = [];
            foreach ($value->toArray() as $ldapObject) {
                $ldapValues[] = $ldapObject->get($annotation->id);
            }
        } else {
            throw new \InvalidArgumentException(sprintf(
                'Class "%s" is not valid. Expected a LdapObject or LdapObjectCollection',
                get_class($value)
            ));
        }

        $property->setValue($entity, $ldapValues);
    }

Get the specified ID for each LDAP object and save it to an array.

@param \ReflectionProperty $property
@param LdapObjectAnnotation $annotation
@param $entity

Get the specified ID for each LDAP object and save it to an array .


public function build(ContainerBuilder $container)
    {
        parent::build($container);
        $extension = $container->getExtension('security');
        $extension->addSecurityListenerFactory(new LdapFormLoginFactory());
        $container->addCompilerPass(new EventRegisterPass());
        $container->addCompilerPass(new LdifUrlLoaderPass());
    }

public function build ( ContainerBuilder $ container ) { parent :: build ( $ container ) ; $ extension = $ container -> getExtension ( 'security' ) ; $ extension -> addSecurityListenerFactory ( new LdapFormLoginFactory ( ) ) ; $ container -> addCompilerPass ( new EventRegisterPass ( ) ) ; $ container -> addCompilerPass ( new LdifUrlLoaderPass ( ) ) ; }

Make Symfony aware of the LDAP listener factory and add the compiler pass.

@param ContainerBuilder $container

Make Symfony aware of the LDAP listener factory and add the compiler pass .


protected function getLdapValuesForChoices(LdapObject ...$choices)
    {
        $values = [];

        foreach ($choices as $i => $ldapObject) {
            $values[$i] = (string) $ldapObject->get($this->id);
        }

        return $values;
    }

protected function getLdapValuesForChoices ( LdapObject ... $ choices ) { $ values = [ ] ; foreach ( $ choices as $ i => $ ldapObject ) { $ values [ $ i ] = ( string ) $ ldapObject -> get ( $ this -> id ) ; } return $ values ; }

Get the values of a set of choices.

@param LdapObject[] $choices
@return array


protected function getLdapObjectsByQuery($values = [])
    {
        if (!$this->ldapQueryBuilder) {
            $query = $this->ldap->buildLdapQuery()
                ->select([$this->id, $this->labelAttribute])
                ->from($this->type);
        } else {
            $query = clone $this->ldapQueryBuilder;
        }

        if (!empty($values)) {
            foreach ($values as $value) {
                $query->orWhere([$this->id => $value]);
            }
        }
        if ($this->queryCallback) {
            $closure = $this->queryCallback;
            $closure($query);
        }

        return $query->getLdapQuery()->getResult();
    }

protected function getLdapObjectsByQuery ( $ values = [ ] ) { if ( ! $ this -> ldapQueryBuilder ) { $ query = $ this -> ldap -> buildLdapQuery ( ) -> select ( [ $ this -> id , $ this -> labelAttribute ] ) -> from ( $ this -> type ) ; } else { $ query = clone $ this -> ldapQueryBuilder ; } if ( ! empty ( $ values ) ) { foreach ( $ values as $ value ) { $ query -> orWhere ( [ $ this -> id => $ value ] ) ; } } if ( $ this -> queryCallback ) { $ closure = $ this -> queryCallback ; $ closure ( $ query ) ; } return $ query -> getLdapQuery ( ) -> getResult ( ) ; }

Get the LDAP objects from LDAP. Optionally only get those specified by the passed values.

@param array $values The values used to narrow the LDAP query.
@return \LdapTools\Object\LdapObjectCollection

Get the LDAP objects from LDAP . Optionally only get those specified by the passed values .


public function getOperations($domain = null)
    {
        if (!is_null($domain) && !isset($this->opsByDomain[$domain])) {
            return [];
        } elseif (!is_null($domain)) {
            return $this->opsByDomain[$domain];
        }

        return $this->allOperations;
    }

public function getOperations ( $ domain = null ) { if ( ! is_null ( $ domain ) && ! isset ( $ this -> opsByDomain [ $ domain ] ) ) { return [ ] ; } elseif ( ! is_null ( $ domain ) ) { return $ this -> opsByDomain [ $ domain ] ; } return $ this -> allOperations ; }

Get all of the operations recorded by the profiler. Or get the operations for a specific domain.

@param null|string $domain
@return LogOperation[]

Get all of the operations recorded by the profiler . Or get the operations for a specific domain .


public function setRoles(LdapUserInterface $user)
    {
        $roles = [];

        if ($this->options['default_role']) {
            $roles[] = $this->options['default_role'];
        }

        if (!empty($this->options['roles'])) {
            $groups = $this->getGroupsForUser($user);

            foreach ($this->options['roles'] as $role => $roleGroups) {
                if ($this->hasGroupForRoles($roleGroups, $groups)) {
                    $roles[] = $role;
                }
            }
        }

        $user->setRoles($roles);

        return $user;
    }

public function setRoles ( LdapUserInterface $ user ) { $ roles = [ ] ; if ( $ this -> options [ 'default_role' ] ) { $ roles [ ] = $ this -> options [ 'default_role' ] ; } if ( ! empty ( $ this -> options [ 'roles' ] ) ) { $ groups = $ this -> getGroupsForUser ( $ user ) ; foreach ( $ this -> options [ 'roles' ] as $ role => $ roleGroups ) { if ( $ this -> hasGroupForRoles ( $ roleGroups , $ groups ) ) { $ roles [ ] = $ role ; } } } $ user -> setRoles ( $ roles ) ; return $ user ; }

Set the roles for the user based on LDAP group membership.

@param LdapUserInterface $user
@return LdapUserInterface

Set the roles for the user based on LDAP group membership .


protected function hasGroupForRoles(array $roleGroups, LdapObjectCollection $ldapGroups)
    {
        foreach ($roleGroups as $roleGroup) {
            if (LdapUtilities::isValidLdapObjectDn($roleGroup)) {
                $attribute = 'dn';
            } elseif (preg_match(LdapUtilities::MATCH_GUID, $roleGroup)) {
                $attribute = $this->options['role_attributes']['guid'];
            } elseif (preg_match(LdapUtilities::MATCH_SID, $roleGroup)) {
                $attribute = $this->options['role_attributes']['sid'];
            } else {
                $attribute = $this->options['role_attributes']['name'];
            }

            if ($this->hasGroupWithAttributeValue($ldapGroups, $attribute, $roleGroup)) {
                return true;
            }
        }

        return false;
    }

protected function hasGroupForRoles ( array $ roleGroups , LdapObjectCollection $ ldapGroups ) { foreach ( $ roleGroups as $ roleGroup ) { if ( LdapUtilities :: isValidLdapObjectDn ( $ roleGroup ) ) { $ attribute = 'dn' ; } elseif ( preg_match ( LdapUtilities :: MATCH_GUID , $ roleGroup ) ) { $ attribute = $ this -> options [ 'role_attributes' ] [ 'guid' ] ; } elseif ( preg_match ( LdapUtilities :: MATCH_SID , $ roleGroup ) ) { $ attribute = $ this -> options [ 'role_attributes' ] [ 'sid' ] ; } else { $ attribute = $ this -> options [ 'role_attributes' ] [ 'name' ] ; } if ( $ this -> hasGroupWithAttributeValue ( $ ldapGroups , $ attribute , $ roleGroup ) ) { return true ; } } return false ; }

Check all of the groups that are valid for a specific role against all of the LDAP groups that the user belongs
to.

@param array $roleGroups
@param LdapObjectCollection $ldapGroups
@return bool

Check all of the groups that are valid for a specific role against all of the LDAP groups that the user belongs to .


protected function hasGroupWithAttributeValue(LdapObjectCollection $groups, $attribute, $value)
    {
        $value = strtolower($value);

        /** @var \LdapTools\Object\LdapObject $group */
        foreach ($groups as $group) {
            if ($group->has($attribute) && strtolower($group->get($attribute)) === $value) {
                return true;
            }
        }

        return false;
    }

Check each LDAP group to see if any of them have an attribute with a specific value.

@param LdapObjectCollection $groups
@param string $attribute
@param string $value
@return bool

Check each LDAP group to see if any of them have an attribute with a specific value .


protected function log(LogOperation $log)
    {
        $message = $this->getLogMessage($log);

        if (!is_null($log->getError())) {
            $this->logger->error($message);
        } else {
            $this->logger->debug($message);
        }
    }

protected function log ( LogOperation $ log ) { $ message = $ this -> getLogMessage ( $ log ) ; if ( ! is_null ( $ log -> getError ( ) ) ) { $ this -> logger -> error ( $ message ) ; } else { $ this -> logger -> debug ( $ message ) ; } }

Logs a message.

@param LogOperation $log


public function saveMedia($file, $group = 'default', $type = 'single', $options = []) {
    $this->file = $file;
    $this->group = $group;
    $this->type   = $type;
    $this->options = $options;

    $this->setup();

    $this->parseOptions();

    if ($this->type == 'single') {
      $this->removeExistingMedia();
    }

    $result = $this->databasePut();

    $this->storagePut();

    return $result;
  }

public function saveMedia ( $ file , $ group = 'default' , $ type = 'single' , $ options = [ ] ) { $ this -> file = $ file ; $ this -> group = $ group ; $ this -> type = $ type ; $ this -> options = $ options ; $ this -> setup ( ) ; $ this -> parseOptions ( ) ; if ( $ this -> type == 'single' ) { $ this -> removeExistingMedia ( ) ; } $ result = $ this -> databasePut ( ) ; $ this -> storagePut ( ) ; return $ result ; }

Save the media to disk and DB

@param $file object
The Symfony\Component\HttpFoundation\File\UploadedFile Object

@param $group string
The group of file being uploaded, to allow for say a profile picture and a
background to be uploaded for a user

@param $type string
If the field is for a single file that gets deleted set it to 'single',
or if it is a multiple file upload, set it to 'multiple'

@param $options array
An array of extra options for the file

@return object
The Devfactory\Media\Models\Media Object


public function updateMediaById($id, $options) {
    $this->options = $options;

    $this->parseOptions();

    $model = config('media.config.model');
    $this->media = $model::find($id);

    $this->media->alt = $this->getAlt();
    $this->media->title = $this->getTitle();
    $this->media->name = $this->getName();
    $this->media->weight = $this->getWeight();

    $this->media->save();
  }

public function updateMediaById ( $ id , $ options ) { $ this -> options = $ options ; $ this -> parseOptions ( ) ; $ model = config ( 'media.config.model' ) ; $ this -> media = $ model :: find ( $ id ) ; $ this -> media -> alt = $ this -> getAlt ( ) ; $ this -> media -> title = $ this -> getTitle ( ) ; $ this -> media -> name = $ this -> getName ( ) ; $ this -> media -> weight = $ this -> getWeight ( ) ; $ this -> media -> save ( ) ; }

Update the meta data of a certain media file.

@param $id int
The ID of the media item to update

@param $options array
An key => value array of elements in the DB to change, key must be one of:
'alt', 'title', 'name', 'weight'

@return void

Update the meta data of a certain media file .


public function getMedia($group = NULL) {
    if (is_null($group)) {
      return $this->media()->orderBy('weight', 'ASC')->get();
    }

    return $this->getMediaByGroup($group);
  }

public function getMedia ( $ group = NULL ) { if ( is_null ( $ group ) ) { return $ this -> media ( ) -> orderBy ( 'weight' , 'ASC' ) -> get ( ) ; } return $ this -> getMediaByGroup ( $ group ) ; }

Get all the media assigned to the current model instance

@param $group string
The file group to retrieve

@return object
A Illuminate\Database\Eloquent\Collection Object of
Devfactory\Media\Models\Media Objects


private function removeMedia($media) {
    $this->setup();

    if (File::delete($this->public_path . $this->files_directory . $media->filename)) {
      $media->delete();
      return TRUE;
    }

    return FALSE;
  }

private function removeMedia ( $ media ) { $ this -> setup ( ) ; if ( File :: delete ( $ this -> public_path . $ this -> files_directory . $ media -> filename ) ) { $ media -> delete ( ) ; return TRUE ; } return FALSE ; }

Perform the actual delete of the database row and removal of the
file from the filesystem

@param $group string
The file group to delete

@return bool


private function parseOptions() {
    $default_options = [
      'alt' => NULL,
      'title' => NULL,
      'name' => NULL,
      'weight' => NULL,
    ];

    $this->options += $default_options;

    $this->options = (object) $this->options;
  }

private function parseOptions ( ) { $ default_options = [ 'alt' => NULL , 'title' => NULL , 'name' => NULL , 'weight' => NULL , ] ; $ this -> options += $ default_options ; $ this -> options = ( object ) $ this -> options ; }

Parse the optional arguments and merge them with the defaults


private function getFilename() {
    switch (config('media.config.rename')) {
      case 'transliterate':
        $this->filename_new = \Transliteration::clean_filename($this->filename_original);
        break;
      case 'unique':
        $this->filename_new = md5(microtime() . str_random(5)) .'.'. $this->filename_original;
        break;
      case 'nothing':
        $this->filename_new = $this->file->getClientOriginalName();
        break;
    }

    return $this->fileExistsRename();
  }

private function getFilename ( ) { switch ( config ( 'media.config.rename' ) ) { case 'transliterate' : $ this -> filename_new = \ Transliteration :: clean_filename ( $ this -> filename_original ) ; break ; case 'unique' : $ this -> filename_new = md5 ( microtime ( ) . str_random ( 5 ) ) . '.' . $ this -> filename_original ; break ; case 'nothing' : $ this -> filename_new = $ this -> file -> getClientOriginalName ( ) ; break ; } return $ this -> fileExistsRename ( ) ; }

Helper function to process the media filename according to the settings

@return string
The parsed filename


private function fileExistsRename() {
    if (!File::exists($this->directory . $this->filename_new)) {
      return $this->filename_new;
    }

    return $this->fileRename();
  }

private function fileExistsRename ( ) { if ( ! File :: exists ( $ this -> directory . $ this -> filename_new ) ) { return $ this -> filename_new ; } return $ this -> fileRename ( ) ; }

Checks if a file exists and creates a new name if it does

@return string
The uniquely named file


private function fileRename() {
    $filename = $this->filename_new;
    $extension = '.' . File::extension($this->filename_new);
    $basename = rtrim($filename, $extension);

    $increment = 0;

    while (File::exists($this->directory . $filename)) {
      $filename = $basename . '_' . ++$increment . $extension;
    }

    return $this->filename_new = $filename;
  }

private function fileRename ( ) { $ filename = $ this -> filename_new ; $ extension = '.' . File :: extension ( $ this -> filename_new ) ; $ basename = rtrim ( $ filename , $ extension ) ; $ increment = 0 ; while ( File :: exists ( $ this -> directory . $ filename ) ) { $ filename = $ basename . '_' . ++ $ increment . $ extension ; } return $ this -> filename_new = $ filename ; }

Appends _X to the file's basename if it already exists

@return string
The newly renamed file

Appends _X to the file s basename if it already exists


private function getAlt() {
    if (!is_null($this->options->alt)) {
      return $this->options->alt;
    }

    if (!is_null($this->media)) {
      return $this->media->alt;
    }

    return '';
  }

private function getAlt ( ) { if ( ! is_null ( $ this -> options -> alt ) ) { return $ this -> options -> alt ; } if ( ! is_null ( $ this -> media ) ) { return $ this -> media -> alt ; } return '' ; }

Get the alt text for the file, from options, then from db, otherwise ''

@return string
The Alt text

Get the alt text for the file from options then from db otherwise


private function getTitle() {
    if (!is_null($this->options->title)) {
      return $this->options->title;
    }

    if (!is_null($this->media)) {
      return $this->media->title;
    }

    return '';
  }

private function getTitle ( ) { if ( ! is_null ( $ this -> options -> title ) ) { return $ this -> options -> title ; } if ( ! is_null ( $ this -> media ) ) { return $ this -> media -> title ; } return '' ; }

Get the Title text for the file, from options, then from db, otherwise ''

@return string
The Title text

Get the Title text for the file from options then from db otherwise


private function getName() {
    if (!is_null($this->options->name)) {
      return $this->options->name;
    }

    if (!is_null($this->media)) {
      return $this->media->name;
    }

    return '';
  }

private function getName ( ) { if ( ! is_null ( $ this -> options -> name ) ) { return $ this -> options -> name ; } if ( ! is_null ( $ this -> media ) ) { return $ this -> media -> name ; } return '' ; }

Get the Name text for the file, from options, then from db, otherwise ''

@return string
The Name text

Get the Name text for the file from options then from db otherwise


private function getWeight() {
    if (!is_null($this->options->weight)) {
      return $this->options->weight;
    }

    if (!is_null($this->media)) {
      return $this->media->weight;
    }

    return $this->media()->where('group', $this->group)->count();
  }

private function getWeight ( ) { if ( ! is_null ( $ this -> options -> weight ) ) { return $ this -> options -> weight ; } if ( ! is_null ( $ this -> media ) ) { return $ this -> media -> weight ; } return $ this -> media ( ) -> where ( 'group' , $ this -> group ) -> count ( ) ; }

Calculate the weight of the image from options, then from existing media,
then compared to others in the group

@return int
The weight of the image

Calculate the weight of the image from options then from existing media then compared to others in the group


private function databasePut() {
    $media = [
      'filename' => $this->directory_uri . $this->filename_new,
      'mime' => $this->file->getMimeType(),
      'size' => $this->file->getSize(),
      'title' => $this->getTitle(),
      'alt' => $this->getAlt(),
      'name' => $this->getName(),
      'group' => $this->group,
      'status' => TRUE,
      'weight' => $this->getWeight(),
    ];

    $model = config('media.config.model');
    return $this->media()->save(new $model($media));
  }

private function databasePut ( ) { $ media = [ 'filename' => $ this -> directory_uri . $ this -> filename_new , 'mime' => $ this -> file -> getMimeType ( ) , 'size' => $ this -> file -> getSize ( ) , 'title' => $ this -> getTitle ( ) , 'alt' => $ this -> getAlt ( ) , 'name' => $ this -> getName ( ) , 'group' => $ this -> group , 'status' => TRUE , 'weight' => $ this -> getWeight ( ) , ] ; $ model = config ( 'media.config.model' ) ; return $ this -> media ( ) -> save ( new $ model ( $ media ) ) ; }

Insert the media into the database

@return object
Devfactory\Media\Models\Media Object


private function removeExistingMedia() {
    $existing_media = $this->getMedia($this->group);

    if (!$existing_media->isEmpty()) {
      return $this->deleteMedia($this->group);
    }

    return 0;
  }

private function removeExistingMedia ( ) { $ existing_media = $ this -> getMedia ( $ this -> group ) ; if ( ! $ existing_media -> isEmpty ( ) ) { return $ this -> deleteMedia ( $ this -> group ) ; } return 0 ; }

Remove any media that already exists for the current group type

@return int
The number of elements removed


private function storagePut() {
    if ($this->makeDirectory($this->directory)) {
      $this->file->move($this->directory, $this->filename_new);
    }
  }

private function storagePut ( ) { if ( $ this -> makeDirectory ( $ this -> directory ) ) { $ this -> file -> move ( $ this -> directory , $ this -> filename_new ) ; } }


private function storageClone() {
    if ($this->makeDirectory($this->directory)) {
      return File::copy($this->public_path . $this->files_directory . $this->media->filename, $this->directory . $this->filename_new);
    }

    return false;
  }

private function storageClone ( ) { if ( $ this -> makeDirectory ( $ this -> directory ) ) { return File :: copy ( $ this -> public_path . $ this -> files_directory . $ this -> media -> filename , $ this -> directory . $ this -> filename_new ) ; } return false ; }

Clone a file from passed Media Object to a new Media location on disk

@return bool
TRUE if the file copied, FALSE if it could not be copied


private function makeDirectory($directory) {
    if (File::isDirectory($directory)) {
      return TRUE;
    }

    return File::makeDirectory($directory, 0755, TRUE);
  }

private function makeDirectory ( $ directory ) { if ( File :: isDirectory ( $ directory ) ) { return TRUE ; } return File :: makeDirectory ( $ directory , 0755 , TRUE ) ; }

Creates the passed directory if it doesn't exist

@param $directory string
The full path of the directory to create

@return bool
TRUE if the directory exists, FALSE if it could not be created

Creates the passed directory if it doesn t exist


public function cloneMedia($media, $clone_storage = false, $clone_attributes = []) {
    $this->media = $media->replicate();
    $this->setup();
    $this->filename_new = basename($media->filename);

    if ($clone_storage) {
      $this->fileExistsRename();
      $this->storageClone();
    }

    $this->media->fill($clone_attributes);
    $this->media->filename = $this->directory_uri . $this->filename_new;

    return $this->media()->save($this->media);
  }

public function cloneMedia ( $ media , $ clone_storage = false , $ clone_attributes = [ ] ) { $ this -> media = $ media -> replicate ( ) ; $ this -> setup ( ) ; $ this -> filename_new = basename ( $ media -> filename ) ; if ( $ clone_storage ) { $ this -> fileExistsRename ( ) ; $ this -> storageClone ( ) ; } $ this -> media -> fill ( $ clone_attributes ) ; $ this -> media -> filename = $ this -> directory_uri . $ this -> filename_new ; return $ this -> media ( ) -> save ( $ this -> media ) ; }

Clone an existing media item, onto a new model instance.

@param object $media
The old Media that should be cloned to the current instance.
@param bool $storage_clone
Optionally, also copy the file in storage to a new, unique file
@param $clone_attributes
Optionally, override certain attributes on the clone

@return \Devfactory\Media\Models\Media

Clone an existing media item onto a new model instance .


protected function bootConfig()
    {
        $path = __DIR__ . '/config/pricing.php';

        $this->mergeConfigFrom($path, 'pricing');

        if (function_exists('config_path')) {
            $this->publishes([$path => config_path('pricing.php')]);
        }
    }

protected function bootConfig ( ) { $ path = __DIR__ . '/config/pricing.php' ; $ this -> mergeConfigFrom ( $ path , 'pricing' ) ; if ( function_exists ( 'config_path' ) ) { $ this -> publishes ( [ $ path => config_path ( 'pricing.php' ) ] ) ; } }


public function register()
    {
        sage()->singleton(BladeSvgSage::class, function () {
            return $this;
        });

        sage()->singleton(SvgFactory::class, function () {
            return new SvgFactory($this->config());
        });
    }

public function register ( ) { sage ( ) -> singleton ( BladeSvgSage :: class , function ( ) { return $ this ; } ) ; sage ( ) -> singleton ( SvgFactory :: class , function ( ) { return new SvgFactory ( $ this -> config ( ) ) ; } ) ; }

Register BladeSvgSage and SvgFactory with the Sage container.

@return void

Register BladeSvgSage and SvgFactory with the Sage container .


public function directives()
    {
        /** Create @icon() Blade directive */
        sage('blade')->compiler()->directive('icon', function ($expression) {
            return "<?php echo e(App\svg_image({$expression})) ?>";
        });

        /** Create @svg() Blade directive */
        sage('blade')->compiler()->directive('svg', function ($expression) {
            return "<?php echo e(App\svg_image({$expression})) ?>";
        });

        /** Create @spritesheet Blade directive */
        sage('blade')->compiler()->directive('spritesheet', function () {
            return "<?php echo e(App\svg_spritesheet()) ?>";
        });
    }

Register Directives with Blade.

@return void


protected function config()
    {
        if (! file_exists($config = __DIR__.'/../config/config.php')) {
            return;
        }

        $config = collect(apply_filters('bladesvg', require($config)));

        return $config->merge([
            'svg_path'         => $this->path($config->get('svg_path')),
            'spritesheet_path' => $this->path($config->get('spritesheet_path'))
        ])->all();
    }

protected function config ( ) { if ( ! file_exists ( $ config = __DIR__ . '/../config/config.php' ) ) { return ; } $ config = collect ( apply_filters ( 'bladesvg' , require ( $ config ) ) ) ; return $ config -> merge ( [ 'svg_path' => $ this -> path ( $ config -> get ( 'svg_path' ) ) , 'spritesheet_path' => $ this -> path ( $ config -> get ( 'spritesheet_path' ) ) ] ) -> all ( ) ; }

Returns the config.

@return \Illuminate\Support\Collection


public function svg($name = '', $class = '', $attrs = [])
    {
        if (empty($name)) {
            return;
        }

        return sage(SvgFactory::class)->svg($name, $class, $attrs);
    }

public function svg ( $ name = '' , $ class = '' , $ attrs = [ ] ) { if ( empty ( $ name ) ) { return ; } return sage ( SvgFactory :: class ) -> svg ( $ name , $ class , $ attrs ) ; }

Returns the rendered SVG for the image specified.

@param  string $name
@param  string $class
@param  array  $attrs
@return mixed

Returns the rendered SVG for the image specified .


public function transmitItemVariable($variables, $transmissionId, $itemUri = '', $testUri = '') {

        $itemVariableSet = [];

        if (is_array($variables) === false) {
            $variables = [$variables];
        }

        foreach ($variables as $variable) {
            $identifier = $variable->getIdentifier();

            if ($variable instanceof OutcomeVariable) {
                $value = $variable->getValue();

                $resultVariable = new taoResultServer_models_classes_OutcomeVariable();
                $resultVariable->setIdentifier($identifier);
                $resultVariable->setBaseType(BaseType::getNameByConstant($variable->getBaseType()));
                $resultVariable->setCardinality(Cardinality::getNameByConstant($variable->getCardinality()));
                $resultVariable->setValue(self::transformValue($value));

                $itemVariableSet[] = $resultVariable;
            }
            else if ($variable instanceof ResponseVariable) {
                // ResponseVariable.
                $value = $variable->getValue();

                $resultVariable = new taoResultServer_models_classes_ResponseVariable();
                $resultVariable->setIdentifier($identifier);
                $resultVariable->setBaseType(BaseType::getNameByConstant($variable->getBaseType()));
                $resultVariable->setCardinality(Cardinality::getNameByConstant($variable->getCardinality()));
                $resultVariable->setCandidateResponse(self::transformValue($value));

                // The fact that the response is correct must not be sent for built-in
                // response variables 'duration' and 'numAttempts'.
                if (!in_array($identifier, array('duration', 'numAttempts', 'comment'))) {
                    $resultVariable->setCorrectResponse($variable->isCorrect());
                }

                $itemVariableSet[] = $resultVariable;
            }
        }

        try {
            common_Logger::d("Sending Item Variables to result server.");
            $this->getResultStorage()->storeItemVariables($testUri, $itemUri, $itemVariableSet, $transmissionId);
        }
        catch (Exception $e) {
            $msg = "An error occured while transmitting one or more Outcome/Response Variable(s) to the target result server.";
            $code = taoQtiCommon_helpers_ResultTransmissionException::OUTCOME;
            throw new taoQtiCommon_helpers_ResultTransmissionException($msg, $code);
        }
    }

Transmit a QtiSm Runtime Variable to the target Result Server as an Item Result.

@param mixed $variables QtiSm Runtime Variable(s).
@param string $transmissionId A unique identifier that identifies uniquely the visited item.
@param string $itemUri An optional URI that identifies uniquely the item the $variable comes from.
@param string $testUri An optional URL that identifies uniquely the test the $variable comes from.
@throws taoQtiCommon_helpers_ResultTransmissionException If an error occurs while transmitting the Variable to the target Result Server.

Transmit a QtiSm Runtime Variable to the target Result Server as an Item Result .


private static function transformValue($value) {
        if (gettype($value) === 'object') {

            if ($value instanceof QtiFile) {
                return taoQtiCommon_helpers_Utils::qtiFileToString($value);
            }
            else {
                return $value->__toString();
            }
        }
        else {
            return $value;
        }
    }

private static function transformValue ( $ value ) { if ( gettype ( $ value ) === 'object' ) { if ( $ value instanceof QtiFile ) { return taoQtiCommon_helpers_Utils :: qtiFileToString ( $ value ) ; } else { return $ value -> __toString ( ) ; } } else { return $ value ; } }

Transform a QTI Datatype value to a value compliant
with result server.

@param mixed $value
@return string

Transform a QTI Datatype value to a value compliant with result server .


public function addVariable(Variable $variable) {
        $output = &$this->getOutput();
        $varName = $variable->getIdentifier();
        $marshaller = new taoQtiCommon_helpers_PciJsonMarshaller();
        $output[$varName] = $marshaller->marshall($variable->getValue(), taoQtiCommon_helpers_PciJsonMarshaller::MARSHALL_ARRAY);
    }

public function addVariable ( Variable $ variable ) { $ output = & $ this -> getOutput ( ) ; $ varName = $ variable -> getIdentifier ( ) ; $ marshaller = new taoQtiCommon_helpers_PciJsonMarshaller ( ) ; $ output [ $ varName ] = $ marshaller -> marshall ( $ variable -> getValue ( ) , taoQtiCommon_helpers_PciJsonMarshaller :: MARSHALL_ARRAY ) ; }

Add a variable to be transformed into its IMS PCI JSON Representation
for a later output.

@param Variable $variable

Add a variable to be transformed into its IMS PCI JSON Representation for a later output .


static public function isQtiFilePlaceHolder(Variable $variable) {

        $correctBaseType = $variable->getBaseType() === BaseType::FILE;
        $correctCardinality = $variable->getCardinality() === Cardinality::SINGLE;

        if ($correctBaseType === true && $correctCardinality === true) {

            $value = $variable->getValue();
            $notNull = $value !== null;
            $mime = taoQtiCommon_helpers_PciJsonMarshaller::FILE_PLACEHOLDER_MIMETYPE;

            if ($notNull === true && $value->getMimeType() === $mime) {
                return true;
            }
        }

        return false;
    }

static public function isQtiFilePlaceHolder ( Variable $ variable ) { $ correctBaseType = $ variable -> getBaseType ( ) === BaseType :: FILE ; $ correctCardinality = $ variable -> getCardinality ( ) === Cardinality :: SINGLE ; if ( $ correctBaseType === true && $ correctCardinality === true ) { $ value = $ variable -> getValue ( ) ; $ notNull = $ value !== null ; $ mime = taoQtiCommon_helpers_PciJsonMarshaller :: FILE_PLACEHOLDER_MIMETYPE ; if ( $ notNull === true && $ value -> getMimeType ( ) === $ mime ) { return true ; } } return false ; }

Whether or not a given QTI Variable contains the QTI Placeholder File.

@param Variable $variable
@return boolean

Whether or not a given QTI Variable contains the QTI Placeholder File .


static public function isQtiFile(Variable $variable, $considerNull = true) {

        $correctBaseType = $variable->getBaseType() === BaseType::FILE;
        $correctCardinality = $variable->getCardinality() === Cardinality::SINGLE;
        $nullConsideration = ($considerNull === true) ? true : $variable->getValue() !== null;

        return $correctBaseType === true && $correctCardinality === true && $nullConsideration === true;
    }

static public function isQtiFile ( Variable $ variable , $ considerNull = true ) { $ correctBaseType = $ variable -> getBaseType ( ) === BaseType :: FILE ; $ correctCardinality = $ variable -> getCardinality ( ) === Cardinality :: SINGLE ; $ nullConsideration = ( $ considerNull === true ) ? true : $ variable -> getValue ( ) !== null ; return $ correctBaseType === true && $ correctCardinality === true && $ nullConsideration === true ; }

Whether or not a given QTI Variable contains a QTI File value.

@param Variable $variable
@param boolean $considerNull Whether or not to consider File variables containing NULL variables.
@return boolean

Whether or not a given QTI Variable contains a QTI File value .


static public function toQtiDatatype($cardinality, $basetype, $value)
    {
        // @todo support all baseTypes
        $datatype = null;

        if (is_string($value) && empty($value) === false && $cardinality !== 'record' && ($basetype === 'identifier' || $basetype === 'pair' || $basetype === 'directedPair' || $basetype === 'boolean')) {
            if ($cardinality !== 'simple') {
                $value = trim($value, "<>[]");
                $value = explode(';', $value);
            } else {
                $value = array($value);
            }

            if (count($value) === 1 && empty($value[0]) === true) {
                $value = array();
            }

            $value = array_map(
                function($val) {
                    return trim($val);
                },
                $value
            );

            $qtiBasetype = BaseType::getConstantByName($basetype);
            $datatype = ($cardinality === 'ordered') ? new OrderedContainer($qtiBasetype) : new MultipleContainer($qtiBasetype);
            foreach ($value as $val) {
                try {
                    switch ($basetype) {
                        case 'identifier':
                            $datatype[] = new QtiIdentifier($val);
                            break;

                        case 'pair':
                            $pair = explode("\x20", $val);
                            if (count($pair) === 2) {
                                $datatype[] = new QtiPair($pair[0], $pair[1]);
                            }
                            break;

                        case 'directedPair':
                            $pair = explode("\x20", $val);
                            if (count($pair) === 2) {
                                $datatype[] = new QtiDirectedPair($pair[0], $pair[1]);
                            }
                            break;

                        case 'boolean':
                            if ($val === 'true') {
                                $datatype[] = new QtiBoolean(true);
                            } elseif ($val === 'false') {
                                $datatype[] = new QtiBoolean(false);
                            } else {
                                $datatype[] = new QtiBoolean($val);
                            }
                            break;
                    }
                } catch (InvalidArgumentException $e) {
                    $datatype = null;
                    break;
                }
            }

            $datatype = ($cardinality === 'single') ? (isset($datatype[0]) ? $datatype[0] : null) : $datatype;
        }

        return $datatype;
    }

static
public
function
toQtiDatatype
(
$
cardinality
,
$
basetype
,
$
value
)
{
// @todo support all baseTypes
$
datatype
=
;
if
(
is_string
(
$
value
)
&&
empty
(
$
value
)
===
false
&&
$
cardinality
!==
'record'
&&
(
$
basetype
===
'identifier'
||
$
basetype
===
'pair'
||
$
basetype
===
'directedPair'
||
$
basetype
===
'boolean'
)
)
{
if
(
$
cardinality
!==
'simple'
)
{
$
value
=
trim
(
$
value
,
"<>[]"
)
;
$
value
=
explode
(
';'
,
$
value
)
;
}
else
{
$
value
=
array
(
$
value
)
;
}
if
(
count
(
$
value
)
===
1
&&
empty
(
$
value
[
0
]
)
===
true
)
{
$
value
=
array
(
)
;
}
$
value
=
array_map
(
function
(
$
val
)
{
return
trim
(
$
val
)
;
}
,
$
value
)
;
$
qtiBasetype
=
BaseType
::
getConstantByName
(
$
basetype
)
;
$
datatype
=
(
$
cardinality
===
'ordered'
)
new
OrderedContainer
(
$
qtiBasetype
)
:
new
MultipleContainer
(
$
qtiBasetype
)
;
foreach
(
$
value
as
$
val
)
{
try
{
switch
(
$
basetype
)
{
case
'identifier'
:
$
datatype
[
]
=
new
QtiIdentifier
(
$
val
)
;
break
;
case
'pair'
:
$
pair
=
explode
(
"\x20"
,
$
val
)
;
if
(
count
(
$
pair
)
===
2
)
{
$
datatype
[
]
=
new
QtiPair
(
$
pair
[
0
]
,
$
pair
[
1
]
)
;
}
break
;
case
'directedPair'
:
$
pair
=
explode
(
"\x20"
,
$
val
)
;
if
(
count
(
$
pair
)
===
2
)
{
$
datatype
[
]
=
new
QtiDirectedPair
(
$
pair
[
0
]
,
$
pair
[
1
]
)
;
}
break
;
case
'boolean'
:
if
(
$
val
===
'true'
)
{
$
datatype
[
]
=
new
QtiBoolean
(
true
)
;
}
elseif
(
$
val
===
'false'
)
{
$
datatype
[
]
=
new
QtiBoolean
(
false
)
;
}
else
{
$
datatype
[
]
=
new
QtiBoolean
(
$
val
)
;
}
break
;
}
}
catch
(
InvalidArgumentException
$
e
)
{
$
datatype
=
;
break
;
}
}
$
datatype
=
(
$
cardinality
===
'single'
)
(
isset
(
$
datatype
[
0
]
)
$
datatype
[
0
]
:
)
:
$
datatype
;
}
return
$
datatype
;
}

Transform a TAO serialized result value to its QtiDatatype equivalent.

This method transforms a TAO serialized result $value to a the equivalent QtiDatatype depending
on result's $cardinality and $baseType.

Note: at the present time, this implementation only supports 'single', 'multiple', and 'ordered' cardinality in conjunction
with the 'identifier', 'boolean', 'pair' or 'directedPair' baseType.

@param string $cardinality i.e. 'ordered', 'multiple' or 'single'.
@param string $basetype i.e. 'identifier'
@param string $value A TAO serialized result value e.g. '<choice1 choice2 choice3>'
@return mixed A QtiDatatype object or null in case of no possibility to transform $value in the appropriate target $cardinality and $basetype.

Transform a TAO serialized result value to its QtiDatatype equivalent .


public function createFromObject(RevisionableInterface $obj)
    {
        $prevRev = $this->lastObjectRevision($obj);

        $this->setTargetType($obj->objType());
        $this->setTargetId($obj->id());
        $this->setRevNum($prevRev->revNum() + 1);
        $this->setRevTs('now');

        if (is_callable([$obj, 'lastModifiedBy'])) {
            $this->setRevUser($obj->lastModifiedBy());
        }

        $this->setDataObj($obj->data());
        $this->setDataPrev($prevRev->dataObj());

        $diff = $this->createDiff();
        $this->setDataDiff($diff);

        return $this;
    }

public function createFromObject ( RevisionableInterface $ obj ) { $ prevRev = $ this -> lastObjectRevision ( $ obj ) ; $ this -> setTargetType ( $ obj -> objType ( ) ) ; $ this -> setTargetId ( $ obj -> id ( ) ) ; $ this -> setRevNum ( $ prevRev -> revNum ( ) + 1 ) ; $ this -> setRevTs ( 'now' ) ; if ( is_callable ( [ $ obj , 'lastModifiedBy' ] ) ) { $ this -> setRevUser ( $ obj -> lastModifiedBy ( ) ) ; } $ this -> setDataObj ( $ obj -> data ( ) ) ; $ this -> setDataPrev ( $ prevRev -> dataObj ( ) ) ; $ diff = $ this -> createDiff ( ) ; $ this -> setDataDiff ( $ diff ) ; return $ this ; }

Create a new revision from an object

1. Load the last revision
2. Load the current item from DB
3. Create diff from (1) and (2).

@param RevisionableInterface $obj The object to create the revision from.
@return ObjectRevision Chainable


public function recursiveDiff(array $array1, array $array2)
    {
        $diff = [];

        // Compare array1
        foreach ($array1 as $key => $value) {
            if (!array_key_exists($key, $array2)) {
                $diff[0][$key] = $value;
            } elseif (is_array($value)) {
                if (!is_array($array2[$key])) {
                    $diff[0][$key] = $value;
                    $diff[1][$key] = $array2[$key];
                } else {
                    $new = $this->recursiveDiff($value, $array2[$key]);
                    if ($new !== false) {
                        if (isset($new[0])) {
                            $diff[0][$key] = $new[0];
                        }
                        if (isset($new[1])) {
                            $diff[1][$key] = $new[1];
                        }
                    }
                }
            } elseif ($array2[$key] !== $value) {
                $diff[0][$key] = $value;
                $diff[1][$key] = $array2[$key];
            }
        }

        // Compare array2
        foreach ($array2 as $key => $value) {
            if (!array_key_exists($key, $array1)) {
                $diff[1][$key] = $value;
            }
        }

        return $diff;
    }

public
function
recursiveDiff
(
array
$
array1
,
array
$
array2
)
{
$
diff
=
[
]
;
// Compare array1
foreach
(
$
array1
as
$
key
=>
$
value
)
{
if
(
!
array_key_exists
(
$
key
,
$
array2
)
)
{
$
diff
[
0
]
[
$
key
]
=
$
value
;
}
elseif
(
is_array
(
$
value
)
)
{
if
(
!
is_array
(
$
array2
[
$
key
]
)
)
{
$
diff
[
0
]
[
$
key
]
=
$
value
;
$
diff
[
1
]
[
$
key
]
=
$
array2
[
$
key
]
;
}
else
{
$
new
=
$
this
->
recursiveDiff
(
$
value
,
$
array2
[
$
key
]
)
;
if
(
$
new
!==
false
)
{
if
(
isset
(
$
new
[
0
]
)
)
{
$
diff
[
0
]
[
$
key
]
=
$
new
[
0
]
;
}
if
(
isset
(
$
new
[
1
]
)
)
{
$
diff
[
1
]
[
$
key
]
=
$
new
[
1
]
;
}
}
}
}
elseif
(
$
array2
[
$
key
]
!==
$
value
)
{
$
diff
[
0
]
[
$
key
]
=
$
value
;
$
diff
[
1
]
[
$
key
]
=
$
array2
[
$
key
]
;
}
}
// Compare array2
foreach
(
$
array2
as
$
key
=>
$
value
)
{
if
(
!
array_key_exists
(
$
key
,
$
array1
)
)
{
$
diff
[
1
]
[
$
key
]
=
$
value
;
}
}
return
$
diff
;
}

Recursive arrayDiff.

@param array $array1 First array.
@param array $array2 Second Array.
@return array The array diff.


public function setIp($ip)
    {
        if ($ip === null) {
            $this->ip = null;
            return $this;
        }

        if (is_string($ip)) {
            $ip = ip2long($ip);
        } elseif (is_numeric($ip)) {
            $ip = intval($ip);
        } else {
            $ip = 0;
        }

        $this->ip = $ip;

        return $this;
    }

public function setIp ( $ ip ) { if ( $ ip === null ) { $ this -> ip = null ; return $ this ; } if ( is_string ( $ ip ) ) { $ ip = ip2long ( $ ip ) ; } elseif ( is_numeric ( $ ip ) ) { $ ip = intval ( $ ip ) ; } else { $ ip = 0 ; } $ this -> ip = $ ip ; return $ this ; }

Set the client IP address.

@param  integer|null $ip The remote IP at object creation.
@return UserDataInterface Chainable


public function setLang($lang)
    {
        if ($lang !== null) {
            if (!is_string($lang)) {
                throw new InvalidArgumentException(
                    'Language must be a string'
                );
            }
        }

        $this->lang = $lang;

        return $this;
    }

public
function
setLang
(
$
lang
)
{
if
(
$
lang
!==
)
{
if
(
!
is_string
(
$
lang
)
)
{
throw
new
InvalidArgumentException
(
'Language must be a string'
)
;
}
}
$
this
->
lang
=
$
lang
;
return
$
this
;
}

Set the origin language.

@param  string $lang The language code.
@throws InvalidArgumentException If the argument is not a string.
@return UserDataInterface Chainable


public function setOrigin($origin)
    {
        if ($origin !== null) {
            if (!is_string($origin)) {
                throw new InvalidArgumentException(
                    'Origin must be a string.'
                );
            }
        }

        $this->origin = $origin;

        return $this;
    }

public
function
setOrigin
(
$
origin
)
{
if
(
$
origin
!==
)
{
if
(
!
is_string
(
$
origin
)
)
{
throw
new
InvalidArgumentException
(
'Origin must be a string.'
)
;
}
}
$
this
->
origin
=
$
origin
;
return
$
this
;
}

Set the origin of the object submission.

@param  string $origin The source URL or identifier of the submission.
@throws InvalidArgumentException If the argument is not a string.
@return UserDataInterface Chainable

Set the origin of the object submission .


public function resolveOrigin()
    {
        $host = getenv('HTTP_HOST');
        $uri  = '';
        if ($host) {
            $uri = 'http';

            if (getenv('HTTPS') === 'on') {
                $uri .= 's';
            }

            $uri .= '://'.$host;
        }
        $uri .= getenv('REQUEST_URI');

        return $uri;
    }

public function resolveOrigin ( ) { $ host = getenv ( 'HTTP_HOST' ) ; $ uri = '' ; if ( $ host ) { $ uri = 'http' ; if ( getenv ( 'HTTPS' ) === 'on' ) { $ uri .= 's' ; } $ uri .= '://' . $ host ; } $ uri .= getenv ( 'REQUEST_URI' ) ; return $ uri ; }

Resolve the origin of the user data.

@return string


public function setTs($timestamp)
    {
        if ($timestamp === null) {
            $this->ts = null;
            return $this;
        }

        if (is_string($timestamp)) {
            try {
                $timestamp = new DateTime($timestamp);
            } catch (Exception $e) {
                throw new InvalidArgumentException(sprintf(
                    'Invalid timestamp: %s',
                    $e->getMessage()
                ), 0, $e);
            }
        }

        if (!$timestamp instanceof DateTimeInterface) {
            throw new InvalidArgumentException(
                'Invalid timestamp value. Must be a date/time string or a DateTime object.'
            );
        }

        $this->ts = $timestamp;

        return $this;
    }

Set when the object was created.

@param  DateTimeInterface|string|null $timestamp The timestamp at object's creation.
NULL is accepted and instances of DateTimeInterface are recommended;
any other value will be converted (if possible) into one.
@throws InvalidArgumentException If the timestamp is invalid.
@return UserDataInterface Chainable


protected function preSave()
    {
        $result = parent::preSave();

        $this->setTs('now');

        if (getenv('REMOTE_ADDR')) {
            $this->setIp(getenv('REMOTE_ADDR'));
        }

        if (!isset($this->origin)) {
            $this->setOrigin($this->resolveOrigin());
        }

        return $result;
    }

protected function preSave ( ) { $ result = parent :: preSave ( ) ; $ this -> setTs ( 'now' ) ; if ( getenv ( 'REMOTE_ADDR' ) ) { $ this -> setIp ( getenv ( 'REMOTE_ADDR' ) ) ; } if ( ! isset ( $ this -> origin ) ) { $ this -> setOrigin ( $ this -> resolveOrigin ( ) ) ; } return $ result ; }

Event called before _creating_ the object.

@see    Charcoal\Source\StorableTrait::preSave() For the "create" Event.
@return boolean

Event called before _creating_ the object .