public static function create(
        $amount,
        $currency,
        $paymentMethod,
        array $paymentMethodDetails = [],
        $description = null,
        $merchantOrderId = null,
        $returnUrl = null,
        $expirationPeriod = null,
        $customer = null,
        $extra = null,
        $webhookUrl = null,
        $orderLines = null
    ) {
        return new static(
            Transactions::fromArray(
                [
                    [
                        'payment_method' => $paymentMethod,
                        'payment_method_details' => $paymentMethodDetails
                    ]
                ]
            ),
            Amount::fromInteger($amount),
            Currency::fromString($currency),
            ($description !== null) ? Description::fromString($description) : null,
            ($merchantOrderId !== null) ? MerchantOrderId::fromString($merchantOrderId) : null,
            ($returnUrl !== null) ? Url::fromString($returnUrl) : null,
            ($expirationPeriod !== null) ? new \DateInterval($expirationPeriod) : null,
            null,
            null,
            null,
            null,
            null,
            null,
            ($customer !== null) ? Customer::fromArray($customer) : null,
            ($extra !== null) ? Extra::fromArray($extra) : null,
            ($webhookUrl !== null) ? Url::fromString($webhookUrl) : null,
            ($orderLines !== null) ? OrderLines::fromArray($orderLines) : null
        );
    }

public static function create ( $ amount , $ currency , $ paymentMethod , array $ paymentMethodDetails = [ ] , $ description = null , $ merchantOrderId = null , $ returnUrl = null , $ expirationPeriod = null , $ customer = null , $ extra = null , $ webhookUrl = null , $ orderLines = null ) { return new static ( Transactions :: fromArray ( [ [ 'payment_method' => $ paymentMethod , 'payment_method_details' => $ paymentMethodDetails ] ] ) , Amount :: fromInteger ( $ amount ) , Currency :: fromString ( $ currency ) , ( $ description !== null ) ? Description :: fromString ( $ description ) : null , ( $ merchantOrderId !== null ) ? MerchantOrderId :: fromString ( $ merchantOrderId ) : null , ( $ returnUrl !== null ) ? Url :: fromString ( $ returnUrl ) : null , ( $ expirationPeriod !== null ) ? new \ DateInterval ( $ expirationPeriod ) : null , null , null , null , null , null , null , ( $ customer !== null ) ? Customer :: fromArray ( $ customer ) : null , ( $ extra !== null ) ? Extra :: fromArray ( $ extra ) : null , ( $ webhookUrl !== null ) ? Url :: fromString ( $ webhookUrl ) : null , ( $ orderLines !== null ) ? OrderLines :: fromArray ( $ orderLines ) : null ) ; }

Create a new Order.

@param integer $amount Amount in cents.
@param string $currency A valid currency code.
@param string $paymentMethod The payment method to use.
@param array $paymentMethodDetails An array of extra payment method details.
@param string $description A description of the order.
@param string $merchantOrderId A merchant-defined order identifier.
@param string $returnUrl The return URL.
@param string $expirationPeriod The expiration period as an ISO 8601 duration
@param array $customer Customer information.
@param array $extra Extra information.
@param string $webhookUrl The webhook URL.
@param array $orderLines Order lines.

@return Order


public static function withoutNullValues(array $array)
    {
        static $fn = __FUNCTION__;

        foreach ($array as $key => $value) {
            if (is_array($value)) {
                $array[$key] = self::$fn($array[$key]);
            }

            if (empty($array[$key]) && $array[$key] !== '0' && $array[$key] !== 0) {
                unset($array[$key]);
            }
        }

        return $array;
    }

public static function withoutNullValues ( array $ array ) { static $ fn = __FUNCTION__ ; foreach ( $ array as $ key => $ value ) { if ( is_array ( $ value ) ) { $ array [ $ key ] = self :: $ fn ( $ array [ $ key ] ) ; } if ( empty ( $ array [ $ key ] ) && $ array [ $ key ] !== '0' && $ array [ $ key ] !== 0 ) { unset ( $ array [ $ key ] ) ; } } return $ array ; }

Returns a new array with all elements which have a null value removed.

@param array $array
@return array

Returns a new array with all elements which have a null value removed .


public static function createClient($apiKey, $product = null)
    {
        Guard::uuid(
            static::apiKeyToUuid($apiKey),
            'ING API key is invalid: '.$apiKey
        );

        if (!static::validPHPVersion()) {
            throw new \Exception('Minimum required PHP version must be '.MIN_PHP_VERSION.' or above.');
        }

        return new Client(
            strtr(
                static::getEndpoint($product),
                ['{version}' => self::API_VERSION]
            ),
            Request::init()
                ->authenticateWith($apiKey, '')
                ->addHeaders([
                    'User-Agent' => 'ing-php/'.self::CLIENT_VERSION,
                    'X-PHP-Version' => PHP_VERSION
                ])
        );
    }

public
static
function
createClient
(
$
apiKey
,
$
product
=
)
{
Guard
::
uuid
(
static
::
apiKeyToUuid
(
$
apiKey
)
,
'ING API key is invalid: '
.
$
apiKey
)
;
if
(
!
static
::
validPHPVersion
(
)
)
{
throw
new
\
Exception
(
'Minimum required PHP version must be '
.
MIN_PHP_VERSION
.
' or above.'
)
;
}
return
new
Client
(
strtr
(
static
::
getEndpoint
(
$
product
)
,
[
'{version}'
=>
self
::
API_VERSION
]
)
,
Request
::
init
(
)
->
authenticateWith
(
$
apiKey
,
''
)
->
addHeaders
(
[
'User-Agent'
=>
'ing-php/'
.
self
::
CLIENT_VERSION
,
'X-PHP-Version'
=>
PHP_VERSION
]
)
)
;
}

Create a new API client.

@param string $apiKey Your API key.
@param string $product PSP product
@return Client
@throws \Exception
@throws \Assert\AssertionFailedException


public static function getEndpoint($product)
    {
        switch ($product) {
            case 'kassacompleet':
                return (new Client\EndpointResolver())->getEndpointKassa();
            case 'ingcheckout':
                return (new Client\EndpointResolver())->getEndpointIng();
            case 'epay':
                return (new Client\EndpointResolver())->getEndpointEpay();
            default:
                return (new Client\EndpointResolver())->getEndpointGinger();
        }
    }

public static function getEndpoint ( $ product ) { switch ( $ product ) { case 'kassacompleet' : return ( new Client \ EndpointResolver ( ) ) -> getEndpointKassa ( ) ; case 'ingcheckout' : return ( new Client \ EndpointResolver ( ) ) -> getEndpointIng ( ) ; case 'epay' : return ( new Client \ EndpointResolver ( ) ) -> getEndpointEpay ( ) ; default : return ( new Client \ EndpointResolver ( ) ) -> getEndpointGinger ( ) ; } }

Get API endpoint based on product

@param string $product
@return string


public static function isValid($value)
    {
        try {
            $ISO3166 = new Alcohol\ISO3166();
            $ISO3166->getByAlpha2($value);
            return true;
        } catch (\DomainException $e) {
            return false;
        }
    }

public static function isValid ( $ value ) { try { $ ISO3166 = new Alcohol \ ISO3166 ( ) ; $ ISO3166 -> getByAlpha2 ( $ value ) ; return true ; } catch ( \ DomainException $ e ) { return false ; } }

Check if provided value is ISO 3166-1 alpha-2 country standard

@param string $value
@return bool

Check if provided value is ISO 3166 - 1 alpha - 2 country standard


public function build($intent, $payer, $urls, $transactions, $returnArray = false)
    {
        $this->assertIntent($intent);
        $this->intent = $intent;

        $requestBody = array();
        $requestBody['intent'] = $this->intent;
        $requestBody['payer'] = $this->payerBuilder->buildArray($payer);
        $requestBody['transactions'] = $this->transactionsBuilder->buildArray($transactions);
        $requestBody['redirect_urls'] = $this->urlsBuilder->buildArray($urls);

        if ($returnArray) {
            return $requestBody;
        }

        return json_encode($requestBody);
    }

public function build ( $ intent , $ payer , $ urls , $ transactions , $ returnArray = false ) { $ this -> assertIntent ( $ intent ) ; $ this -> intent = $ intent ; $ requestBody = array ( ) ; $ requestBody [ 'intent' ] = $ this -> intent ; $ requestBody [ 'payer' ] = $ this -> payerBuilder -> buildArray ( $ payer ) ; $ requestBody [ 'transactions' ] = $ this -> transactionsBuilder -> buildArray ( $ transactions ) ; $ requestBody [ 'redirect_urls' ] = $ this -> urlsBuilder -> buildArray ( $ urls ) ; if ( $ returnArray ) { return $ requestBody ; } return json_encode ( $ requestBody ) ; }

Build an array or a json string that represents the body of a payment request

@param string $intent not null and should be one of the following values: sale, authorize, order
@param array|\ArrayAccess|PayPalRestApiClient\Model\PayerInterface $payer checkout the PayerBuilder documentation
@param array|\ArrayAccess $urls checkout the UrlsBuilder documentation
@param array|\ArrayAccess|PayPalRestApiClient\Model\TransactionInterface $transactions
@param $returnArray boolean default false

@return array|json return by default a json string, if $returnArray is set to true it will return an array

@throws PayPalRestApiClient\Exception\BuilderException if intent is not valid or the other arrays will not pass the validation on the other builders

@see https://developer.paypal.com/docs/api/#payments


public function execute(
        AccessToken $accessToken,
        Payment $payment,
        $payerId
    ) {
        $request = $this->client->createRequest(
            'POST',
            $payment->getExecuteUrl(),
            array(
                'Accept' => 'application/json',
                'Accept-Language' => 'en_US',
                'Authorization' => $accessToken->getTokenType().' '.$accessToken->getAccessToken(),
                'Content-Type' => 'application/json'
            ),
            '{"payer_id":"'.$payerId.'"}',
            array(
                'debug' => $this->debug
            )
        );

        $response = $this->send($request, 200, "Payment error:");
        $data = json_decode($response->getBody(), true);

        if ('authorize' === $data['intent']) {

            $authorizationBuilder = new PaymentAuthorizationBuilder();
            $authorization = $authorizationBuilder->build($data);

            return $authorization;
        }

        $paymentBuilder = new PaymentBuilder();
        $payment = $paymentBuilder->build($data);

        return $payment;
    }

public
function
execute
(
AccessToken
$
accessToken
,
Payment
$
payment
,
$
payerId
)
{
$
request
=
$
this
->
client
->
createRequest
(
'POST'
,
$
payment
->
getExecuteUrl
(
)
,
array
(
'Accept'
=>
'application/json'
,
'Accept-Language'
=>
'en_US'
,
'Authorization'
=>
$
accessToken
->
getTokenType
(
)
.
' '
.
$
accessToken
->
getAccessToken
(
)
,
'Content-Type'
=>
'application/json'
)
,
'{"payer_id":"'
.
$
payerId
.
'"}'
,
array
(
'debug'
=>
$
this
->
debug
)
)
;
$
response
=
$
this
->
send
(
$
request
,
200
,
"Payment error:"
)
;
$
data
=
json_decode
(
$
response
->
getBody
(
)
,
true
)
;
if
(
'authorize'
===
$
data
[
'intent'
]
)
{
$
authorizationBuilder
=
new
PaymentAuthorizationBuilder
(
)
;
$
authorization
=
$
authorizationBuilder
->
build
(
$
data
)
;
return
$
authorization
;
}
$
paymentBuilder
=
new
PaymentBuilder
(
)
;
$
payment
=
$
paymentBuilder
->
build
(
$
data
)
;
return
$
payment
;
}

Execute a payment or an authorization that was previously approved by the client.

@param PayPalRestApiClient\Model\AccessToken $accessToken
@param PayPalRestApiClient\Model\Payment $payment payment previously created with the "PaymentService::create" method
@param string $payerId not null, parameter "payerId" that is passed in the success url when using paypal payment method

@return PayPalRestApiClient\Model\Payment

Execute a payment or an authorization that was previously approved by the client .


public function capture(AccessToken $accessToken, PaymentAuthorizationInterface $paymentAuthorization, $isFinalCapture = true)
    {
        $amount = $paymentAuthorization->getAmount();
        $data = array(
            'amount' => array(
                'total' => $amount->getTotal(),
                'currency' => $amount->getCurrency()
            ),
            'is_final_capture' => $isFinalCapture
        );

        $request = $this->client->createRequest(
            'POST',
            $paymentAuthorization->getCaptureUrl(),
            array(
                'Accept' => 'application/json',
                'Accept-Language' => 'en_US',
                'Authorization' => $accessToken->getTokenType().' '.$accessToken->getAccessToken(),
                'Content-Type' => 'application/json'
            ),
            json_encode($data),
            array(
                'debug' => $this->debug
            )
        );

        $response = $this->send($request, 200, "Payment error:");
        $data = json_decode($response->getBody(), true);

        $captureBuilder = new CaptureBuilder();
        $capture = $captureBuilder->build($data);

        return $capture;
    }

public
function
capture
(
AccessToken
$
accessToken
,
PaymentAuthorizationInterface
$
paymentAuthorization
,
$
isFinalCapture
=
true
)
{
$
amount
=
$
paymentAuthorization
->
getAmount
(
)
;
$
data
=
array
(
'amount'
=>
array
(
'total'
=>
$
amount
->
getTotal
(
)
,
'currency'
=>
$
amount
->
getCurrency
(
)
)
,
'is_final_capture'
=>
$
isFinalCapture
)
;
$
request
=
$
this
->
client
->
createRequest
(
'POST'
,
$
paymentAuthorization
->
getCaptureUrl
(
)
,
array
(
'Accept'
=>
'application/json'
,
'Accept-Language'
=>
'en_US'
,
'Authorization'
=>
$
accessToken
->
getTokenType
(
)
.
' '
.
$
accessToken
->
getAccessToken
(
)
,
'Content-Type'
=>
'application/json'
)
,
json_encode
(
$
data
)
,
array
(
'debug'
=>
$
this
->
debug
)
)
;
$
response
=
$
this
->
send
(
$
request
,
200
,
"Payment error:"
)
;
$
data
=
json_decode
(
$
response
->
getBody
(
)
,
true
)
;
$
captureBuilder
=
new
CaptureBuilder
(
)
;
$
capture
=
$
captureBuilder
->
build
(
$
data
)
;
return
$
capture
;
}

Capture payment that was previously authorized by the client or witha credit card.

@param PayPalRestApiClient\Model\AccessToken $accessToken
@param PayPalRestApiClient\Model\Payment $payment payment previously authorized with the "PaymentService::authorize" method
@param boolean $isFinalCapture default true

@return PayPalRestApiClient\Model\Capture

Capture payment that was previously authorized by the client or witha credit card .


public function authorize(
        AccessToken $accessToken,
        $payer,
        $urls,
        $transactions
    ) {
        $requestBody = $this->paymentRequestBodyBuilder->build(
            'authorize',
            $payer,
            $urls,
            $transactions
        );

        $this->assertReqeustJsonSchema($requestBody);

        $request = $this->buildRequest($accessToken, $requestBody);

        $response = $this->send($request, 201, "Payment error:");

        $data = json_decode($response->getBody(), true);

        $authorizationBuilder = new PaymentAuthorizationBuilder();
        $authorization = $authorizationBuilder->build($data);

        return $authorization;
    }

public
function
authorize
(
AccessToken
$
accessToken
,
$
payer
,
$
urls
,
$
transactions
)
{
$
requestBody
=
$
this
->
paymentRequestBodyBuilder
->
build
(
'authorize'
,
$
payer
,
$
urls
,
$
transactions
)
;
$
this
->
assertReqeustJsonSchema
(
$
requestBody
)
;
$
request
=
$
this
->
buildRequest
(
$
accessToken
,
$
requestBody
)
;
$
response
=
$
this
->
send
(
$
request
,
201
,
"Payment error:"
)
;
$
data
=
json_decode
(
$
response
->
getBody
(
)
,
true
)
;
$
authorizationBuilder
=
new
PaymentAuthorizationBuilder
(
)
;
$
authorization
=
$
authorizationBuilder
->
build
(
$
data
)
;
return
$
authorization
;
}

Authorize a payment

@param PayPalRestApiClient\Model\AccessToken $accessToken
@param mixed $payer array or object that represents a paypal payer
@param array $urls array of the cancel and redirection url
@param array $transactions array of transaction objects

@return PayPalRestApiClient\Model\Payment|PayPalRestApiClient\Model\PaymentAuthorization


public function create(
        AccessToken $accessToken,
        $payer,
        $urls,
        $transactions
    ) {
        $requestBody = $this->paymentRequestBodyBuilder->build(
            'sale',
            $payer,
            $urls,
            $transactions
        );

        $this->assertReqeustJsonSchema($requestBody);

        $request = $this->buildRequest($accessToken, $requestBody);

        $response = $this->send($request, 201, "Payment error:");

        $data = json_decode($response->getBody(), true);

        $paymentBuilder = new PaymentBuilder();
        $payment = $paymentBuilder->build($data);

        return $payment;
    }

public
function
create
(
AccessToken
$
accessToken
,
$
payer
,
$
urls
,
$
transactions
)
{
$
requestBody
=
$
this
->
paymentRequestBodyBuilder
->
build
(
'sale'
,
$
payer
,
$
urls
,
$
transactions
)
;
$
this
->
assertReqeustJsonSchema
(
$
requestBody
)
;
$
request
=
$
this
->
buildRequest
(
$
accessToken
,
$
requestBody
)
;
$
response
=
$
this
->
send
(
$
request
,
201
,
"Payment error:"
)
;
$
data
=
json_decode
(
$
response
->
getBody
(
)
,
true
)
;
$
paymentBuilder
=
new
PaymentBuilder
(
)
;
$
payment
=
$
paymentBuilder
->
build
(
$
data
)
;
return
$
payment
;
}

Create a payment

@param PayPalRestApiClient\Model\AccessToken $accessToken
@param mixed $payer array or object that represents a paypal payer
@param array $urls array of the cancel and redirection url
@param array $transactions array of transaction objects

@return PayPalRestApiClient\Model\Payment


public function getAccessToken($clientId, $secret)
    {
        $request = $this->client->createRequest(
            'POST',
            $this->baseUrl.'/v1/oauth2/token',
            array(
                'Accept' => 'application/json',
                'Accept-Language' => 'en_US',
                'Content-Type' => 'application/x-www-form-urlencoded'
            ),
            'grant_type=client_credentials',
            array(
                'auth' => array($clientId, $secret),
                'debug' => $this->debug
            )
        );

        $response = $this->send($request, $acceptedStatusCode = 200, 'Error requesting token:');
        $data = json_decode($response->getBody(), true);

        $builder = new AccessTokenBuilder();

        return $builder->build($data);
    }

public
function
getAccessToken
(
$
clientId
,
$
secret
)
{
$
request
=
$
this
->
client
->
createRequest
(
'POST'
,
$
this
->
baseUrl
.
'/v1/oauth2/token'
,
array
(
'Accept'
=>
'application/json'
,
'Accept-Language'
=>
'en_US'
,
'Content-Type'
=>
'application/x-www-form-urlencoded'
)
,
'grant_type=client_credentials'
,
array
(
'auth'
=>
array
(
$
clientId
,
$
secret
)
,
'debug'
=>
$
this
->
debug
)
)
;
$
response
=
$
this
->
send
(
$
request
,
$
acceptedStatusCode
=
200
,
'Error requesting token:'
)
;
$
data
=
json_decode
(
$
response
->
getBody
(
)
,
true
)
;
$
builder
=
new
AccessTokenBuilder
(
)
;
return
$
builder
->
build
(
$
data
)
;
}

Returns an access token object if paypal accepts the given credential

For the time being, expires_in is not taken into consideration.
Calling twice the getAccessToken method with the same credential will give you two different token.

@param string $clientId not null
@param string $secret not null

@return PayPalRestApiClient\Model\AccessToken


public function build(array $data)
    {
        $this->validateArrayKeys(
            array('href', 'rel', 'method'),
            $data
        );

        $link = new Link(
            $data['href'],
            $data['rel'],
            $data['method']
        );

        return $link;
    }

public function build ( array $ data ) { $ this -> validateArrayKeys ( array ( 'href' , 'rel' , 'method' ) , $ data ) ; $ link = new Link ( $ data [ 'href' ] , $ data [ 'rel' ] , $ data [ 'method' ] ) ; return $ link ; }

Build an instance of PayPalRestApiClient\Model\Link given an array

@param array $data The array should contains the following keys:
href, rel, method.

@return PayPalRestApiClient\Model\Link

@throws PayPalRestApiClient\Exception\BuilderException

@see https://developer.paypal.com/docs/api/#hateoas-links

Build an instance of PayPalRestApiClient \ Model \ Link given an array


public function build(array $data)
    {
        $this->validateArrayKeys(
            array('id', 'create_time', 'update_time', 'amount', 'is_final_capture', 'state', 'parent_payment', 'links'),
            $data
        );

        $links = array();
        foreach ($data['links'] as $link) {
            $links[] = $this->linkBuilder->build($link);
        }

        $capture = new Capture(
            $data['id'],
            $data['create_time'],
            $data['update_time'],
            $this->amountBuilder->build($data['amount']),
            $data['is_final_capture'],
            $data['state'],
            $data['parent_payment'],
            $links
        );
        $capture->setPaypalData($data);

        return $capture;
    }

public function build ( array $ data ) { $ this -> validateArrayKeys ( array ( 'id' , 'create_time' , 'update_time' , 'amount' , 'is_final_capture' , 'state' , 'parent_payment' , 'links' ) , $ data ) ; $ links = array ( ) ; foreach ( $ data [ 'links' ] as $ link ) { $ links [ ] = $ this -> linkBuilder -> build ( $ link ) ; } $ capture = new Capture ( $ data [ 'id' ] , $ data [ 'create_time' ] , $ data [ 'update_time' ] , $ this -> amountBuilder -> build ( $ data [ 'amount' ] ) , $ data [ 'is_final_capture' ] , $ data [ 'state' ] , $ data [ 'parent_payment' ] , $ links ) ; $ capture -> setPaypalData ( $ data ) ; return $ capture ; }

Build an instance of PayPalRestApiClient\Model\Capture given an array

@param array $data The array should contains the following keys:
id, create_time, update_time, amount, is_final_capture, state, parent_payment, links.

@return PayPalRestApiClient\Model\Capture

@throws PayPalRestApiClient\Exception\BuilderException If not all keys are set

@see https://developer.paypal.com/docs/api/#capture-object

Build an instance of PayPalRestApiClient \ Model \ Capture given an array


public function build(array $data)
    {
        $this->validateArrayKeys(
            array('currency', 'total'),
            $data
        );

        $details = array();
        if (isset($data['details'])) {
            $details = $data['details'];
        }

        $amount = new Amount(
            $data['currency'],
            $data['total'],
            $details
        );

        return $amount;
    }

public function build ( array $ data ) { $ this -> validateArrayKeys ( array ( 'currency' , 'total' ) , $ data ) ; $ details = array ( ) ; if ( isset ( $ data [ 'details' ] ) ) { $ details = $ data [ 'details' ] ; } $ amount = new Amount ( $ data [ 'currency' ] , $ data [ 'total' ] , $ details ) ; return $ amount ; }

Build an instance of PayPalRestApiClient\Model\Amount given an array

@param array $data

@return PayPalRestApiClient\Model\Amount

@throws PayPalRestApiClient\Exception\BuilderException

@see https://developer.paypal.com/docs/api/#authentication--headers

Build an instance of PayPalRestApiClient \ Model \ Amount given an array


public function buildArray($urls)
    {
        if (
            ($urls instanceof \ArrayAccess || is_array($urls)) &&
            (isset($urls['return_url']) && isset($urls['cancel_url']))
        ) {

            return array(
                'return_url' => $urls['return_url'],
                'cancel_url' => $urls['cancel_url']
            );
        }

        throw new BuilderException("urls array is not valid: return_url and cancel_url are mandatory");
    }

Build an array that represents paypal redirection urls

@param array|\ArrayAccess $urls an array that should have the following keys: return_url and cancel_url

@return array represents paypal redirection urls

@throws PayPalRestApiClient\Exception\BuilderException if the input parameter is not an array or an object instance of \ArrayAccess, or the array keys "return_url" and "cancel_url" are not set

@see https://developer.paypal.com/docs/api/#redirecturls-object


public function build(array $data)
    {
        $this->validateArrayKeys(
            array('scope', 'access_token', 'token_type', 'app_id', 'expires_in'),
            $data
        );

        if (empty($data['access_token'])) {
            throw new BuilderException('access_token is mandatory and should not be empty');
        }

        $accessToken = new AccessToken(
            $data['access_token'],
            $data['token_type'],
            $data['app_id'],
            $data['expires_in'],
            $data['scope']
        );
        $accessToken->setPaypalData($data);

        return $accessToken;
    }

Build an instance of PayPalRestApiClient\Model\AccessToken given an array

@param array $data The array should contains the following keys:
scope, access_token, token_type, app_id, expires_in.
The "access_token" key value should not be empty

@return PayPalRestApiClient\Model\AccessToken

@throws PayPalRestApiClient\Exception\BuilderException If not all keys are set or when "access_token" is empty

@see https://developer.paypal.com/docs/api/#authentication--headers

Build an instance of PayPalRestApiClient \ Model \ AccessToken given an array


public function build(array $transactions)
    {
        $results = array();
        foreach ($transactions as $transaction) {
            $results[] = $this->buildTransaction($transaction);
        }

        return $results;
    }

public function build ( array $ transactions ) { $ results = array ( ) ; foreach ( $ transactions as $ transaction ) { $ results [ ] = $ this -> buildTransaction ( $ transaction ) ; } return $ results ; }

Build an array of PayPalRestApiClient\Model\Transaction instances given an array of arrays

@param array $transactions Should contains arrays with at least the amount key set

@return array of PayPalRestApiClient\Model\Transaction instances

@throws PayPalRestApiClient\Exception\BuilderException If not all keys are set for each transaction

@see https://developer.paypal.com/docs/api/#transaction-object

Build an array of PayPalRestApiClient \ Model \ Transaction instances given an array of arrays


public function buildArray($transactions)
    {
        $this->assertTransactions($transactions);

        $transactionsData = array();
        foreach ($transactions as $transaction) {
            if ($transaction instanceof TransactionInterface) {
                $data = array(
                    'amount' => array(
                        'total' => $transaction->getAmount()->getTotal(),
                        'currency' => $transaction->getAmount()->getCurrency(),
                    ),
                    'description' => $transaction->getDescription()
                );

                if ($itemList = $transaction->getItemList())
                {
                    $data['item_list'] = $itemList;
                }

                $transactionsData[] = $data;
            }
            else {
                $data = array(
                    'amount' => array(
                        'total' => $transaction['amount']['total'],
                        'currency' => $transaction['amount']['currency'],
                    ),
                    'description' => $transaction['description']
                );

                if (isset($transaction['item_list']) && ! empty($transaction['item_list']))
                {
                    $data['item_list'] = $transaction['item_list'];
                }

                $transactionsData[] = $data;
            }
        }

        return $transactionsData;
    }

public function buildArray ( $ transactions ) { $ this -> assertTransactions ( $ transactions ) ; $ transactionsData = array ( ) ; foreach ( $ transactions as $ transaction ) { if ( $ transaction instanceof TransactionInterface ) { $ data = array ( 'amount' => array ( 'total' => $ transaction -> getAmount ( ) -> getTotal ( ) , 'currency' => $ transaction -> getAmount ( ) -> getCurrency ( ) , ) , 'description' => $ transaction -> getDescription ( ) ) ; if ( $ itemList = $ transaction -> getItemList ( ) ) { $ data [ 'item_list' ] = $ itemList ; } $ transactionsData [ ] = $ data ; } else { $ data = array ( 'amount' => array ( 'total' => $ transaction [ 'amount' ] [ 'total' ] , 'currency' => $ transaction [ 'amount' ] [ 'currency' ] , ) , 'description' => $ transaction [ 'description' ] ) ; if ( isset ( $ transaction [ 'item_list' ] ) && ! empty ( $ transaction [ 'item_list' ] ) ) { $ data [ 'item_list' ] = $ transaction [ 'item_list' ] ; } $ transactionsData [ ] = $ data ; } } return $ transactionsData ; }

Build an array that represents a paypal transactions array

@param array|\ArrayAccess $transactions an array of arrays or instances of PayPalRestApiClient\Model\TransactionInterface od \ArrayAccess

@return array represents an array of transaction

@throws PayPalRestApiClient\Exception\BuilderException if at least one transaction is not an array, or an object implementing \ArrayAccess interface or PayPalRestApiClient\Model\TransactionInterface

@see https://developer.paypal.com/docs/api/#transaction-object


public function send($request, $acceptedStatusCode = 200, $errorLabel = 'Error sending Request:')
    {
        try {
            $response = $this->getClient()->send($request);
        }
        catch (ClientErrorResponseException $e) {

            $response = $e->getResponse();
            $details = json_decode($response->getBody(), true);

            $reason = implode(
                ', ',
                array_map(
                    function ($vvalue, $key) {
                        return $key . ': ' . $vvalue;
                    },
                    $details,
                    array_keys($details)
                )
            );

            throw new CallException(
                $errorLabel.
                " response status ".$response->getStatusCode()." ".$response->getReasonPhrase().", ".
                " reason: ".$reason
            );
        }

        if ($acceptedStatusCode != $response->getStatusCode()) {
            throw new CallException(
                $errorLabel.
                "response status ".$response->getStatusCode()." ".$response->getReasonPhrase()
            );
        }

        return $response;
    }

public
function
send
(
$
request
,
$
acceptedStatusCode
=
200
,
$
errorLabel
=
'Error sending Request:'
)
{
try
{
$
response
=
$
this
->
getClient
(
)
->
send
(
$
request
)
;
}
catch
(
ClientErrorResponseException
$
e
)
{
$
response
=
$
e
->
getResponse
(
)
;
$
details
=
json_decode
(
$
response
->
getBody
(
)
,
true
)
;
$
reason
=
implode
(
', '
,
array_map
(
function
(
$
vvalue
,
$
key
)
{
return
$
key
.
': '
.
$
vvalue
;
}
,
$
details
,
array_keys
(
$
details
)
)
)
;
throw
new
CallException
(
$
errorLabel
.
" response status "
.
$
response
->
getStatusCode
(
)
.
" "
.
$
response
->
getReasonPhrase
(
)
.
", "
.
" reason: "
.
$
reason
)
;
}
if
(
$
acceptedStatusCode
!=
$
response
->
getStatusCode
(
)
)
{
throw
new
CallException
(
$
errorLabel
.
"response status "
.
$
response
->
getStatusCode
(
)
.
" "
.
$
response
->
getReasonPhrase
(
)
)
;
}
return
$
response
;
}

Sends a request and chatches exception if something does wrong.

@param mixed $request
@param integer $acceptedStatusCode which http status code represens a "all is well" response for the call
@param string $errorLabel label that describes the context of an error

@return mixed $response
@throws PayPalRestApiClient\Exception\CallException

Sends a request and chatches exception if something does wrong .


public function build(array $data)
    {
        $this->validateArrayKeys(
            array('id', 'create_time', 'state', 'intent', 'payer', 'transactions', 'links'),
            $data
        );

        if (empty($data['id'])) {
            throw new BuilderException('id is mandatory and should not be empty');
        }

        $links = array();
        foreach ($data['links'] as $link) {
            $links[] = $this->linkBuilder->build($link);
        }

        $payment = new Payment(
            $data['id'],
            $data['create_time'],
            $data['state'],
            $data['intent'],
            $this->payerBuilder->build($data['payer']),
            $this->transactionsBuilder->build($data['transactions']),
            $links,
            isset($data['update_time']) ? $data['update_time'] : null
        );
        $payment->setPaypalData($data);

        return $payment;
    }

Build an instance of PayPalRestApiClient\Model\Payment given an array

@param array $data The array should contains the following keys:
id, create_time, state, intent, payer, transactions, links
The "id" key value should not be empty.

@return PayPalRestApiClient\Model\Payment

@throws PayPalRestApiClient\Exception\BuilderException If not all keys are set

@see https://developer.paypal.com/docs/api/#payment-object

Build an instance of PayPalRestApiClient \ Model \ Payment given an array


public function build(array $data)
    {
        $this->validateArrayKeys(
            array('id', 'create_time', 'update_time', 'state', 'intent', 'payer', 'transactions', 'links'),
            $data
        );

        if (empty($data['id'])) {
            throw new BuilderException('id is mandatory and should not be empty');
        }

        $payer = $this->payerBuilder->build($data['payer']);
        $transactions = $this->transactionsBuilder->build($data['transactions']);

        $links = array();
        foreach ($data['links'] as $link) {
            $links[] = $this->linkBuilder->build($link);
        }

        if ($data['payer']['payment_method'] === 'paypal') {
            $authorization = new PaypalPaymentAuthorization(
                $data['id'],
                $data['create_time'],
                $data['state'],
                $data['intent'],
                $payer,
                $transactions,
                $links,
                $data['update_time']
            );
            $authorization->setPaypalData($data);

            return $authorization;
        }

        $authorization = new CreditCardPaymentAuthorization(
            $data['id'],
            $data['create_time'],
            $data['state'],
            $data['intent'],
            $payer,
            $transactions,
            $links,
            $data['update_time']
        );
        $authorization->setPaypalData($data);

        return $authorization;
    }

Build an instance of PayPalRestApiClient\Model\PaymentAuthorization given an array

@param array $data The array should contains the following keys:
id, create_time, update_time, state, intent, payer, transactions, links.
The "id" key value should not be empty.

@return PayPalRestApiClient\Model\PaypalPaymentAuthorization|PayPalRestApiClient\Model\CreditCardPaymentAuthorization

@throws PayPalRestApiClient\Exception\BuilderException If not all keys are set or when "id" is empty

@see https://developer.paypal.com/docs/integration/direct/capture-payment/#authorize-the-payment

Build an instance of PayPalRestApiClient \ Model \ PaymentAuthorization given an array


public function build(array $data)
    {
        $this->validateArrayKeys(
            array('payment_method'),
            $data
        );

        if ( ! in_array($data['payment_method'], array('credit_card', 'paypal'))) {

            throw new BuilderException('Parameter payment_method not valid. Allowed values: "credit_card" and "paypal"');
        }

        $fundingInstruments = array();
        if (isset($data['funding_instruments'])) {
            $fundingInstruments = $data['funding_instruments'];
        }

        $info = array();
        if (isset($data['payer_info'])) {
            $info = $data['payer_info'];
        }

        return new Payer($data['payment_method'], $fundingInstruments, $info);
    }

Build an instance of PayPalRestApiClient\Model\Payer given an array

@param array $data The array should contains the payment_method following

@return PayPalRestApiClient\Model\Payer

@throws PayPalRestApiClient\Exception\BuilderException

@see https://developer.paypal.com/docs/api/#payer-object

Build an instance of PayPalRestApiClient \ Model \ Payer given an array


public function buildArray($payer)
    {
        $payerData = array();
        if ($payer instanceof PayerInterface) {

            $payerData['payment_method'] = $payer->getPaymentMethod();

            if ($fundingInstruments = $payer->getFundingInstruments())
            {
                $payerData['funding_instruments'] = $fundingInstruments;
            }

            if ($info = $payer->getInfo())
            {
                $payerData['payer_info'] = $info;
            }

            return $payerData;
        }

        if (
            ($payer instanceof \ArrayAccess || is_array($payer)) &&
            isset($payer['payment_method'])
        ) {

            $payerData['payment_method'] = $payer['payment_method'];

            if (isset($payer['funding_instruments']))
            {
                $payerData['funding_instruments'] = $payer['funding_instruments'];
            }

            if (isset($payer['payer_info']))
            {
                $payerData['payer_info'] = $payer['payer_info'];
            }

            return $payerData;
        }

        throw new BuilderException('Payer is not valid');
    }

public
function
buildArray
(
$
payer
)
{
$
payerData
=
array
(
)
;
if
(
$
payer
instanceof
PayerInterface
)
{
$
payerData
[
'payment_method'
]
=
$
payer
->
getPaymentMethod
(
)
;
if
(
$
fundingInstruments
=
$
payer
->
getFundingInstruments
(
)
)
{
$
payerData
[
'funding_instruments'
]
=
$
fundingInstruments
;
}
if
(
$
info
=
$
payer
->
getInfo
(
)
)
{
$
payerData
[
'payer_info'
]
=
$
info
;
}
return
$
payerData
;
}
if
(
(
$
payer
instanceof
\
ArrayAccess
||
is_array
(
$
payer
)
)
&&
isset
(
$
payer
[
'payment_method'
]
)
)
{
$
payerData
[
'payment_method'
]
=
$
payer
[
'payment_method'
]
;
if
(
isset
(
$
payer
[
'funding_instruments'
]
)
)
{
$
payerData
[
'funding_instruments'
]
=
$
payer
[
'funding_instruments'
]
;
}
if
(
isset
(
$
payer
[
'payer_info'
]
)
)
{
$
payerData
[
'payer_info'
]
=
$
payer
[
'payer_info'
]
;
}
return
$
payerData
;
}
throw
new
BuilderException
(
'Payer is not valid'
)
;
}

Build an array that represents a paypal payer

@param array|\ArrayAccess|PayPalRestApiClient\Model\PayerInterface $payer an array of values
or an istance of a class implmenting PayPalRestApiClient\Model\PayerInterface or \ArrayAccess interface

@return array

@throws PayPalRestApiClient\Exception\BuilderException if the given input parameter is not an array or
it is not an object implementing PayPalRestApiClient\Model\PayerInterface or \ArrayAccess interface

@see https://developer.paypal.com/docs/api/#payer-object


public function build(array $data)
    {
        $this->validateArrayKeys(
            array('amount', 'create_time', 'update_time', 'state', 'parent_payment', 'id', 'valid_until', 'links'),
            $data
        );

        $links = array();
        foreach ($data['links'] as $link) {
            $links[] = $this->linkBuilder->build($link);
        }

        $authorization = new Authorization(
            $data['id'],
            $data['create_time'],
            $data['update_time'],
            $this->amountBuilder->build($data['amount']),
            $data['state'],
            $data['parent_payment'],
            $data['valid_until'],
            $links
        );

        return $authorization;
    }

public function build ( array $ data ) { $ this -> validateArrayKeys ( array ( 'amount' , 'create_time' , 'update_time' , 'state' , 'parent_payment' , 'id' , 'valid_until' , 'links' ) , $ data ) ; $ links = array ( ) ; foreach ( $ data [ 'links' ] as $ link ) { $ links [ ] = $ this -> linkBuilder -> build ( $ link ) ; } $ authorization = new Authorization ( $ data [ 'id' ] , $ data [ 'create_time' ] , $ data [ 'update_time' ] , $ this -> amountBuilder -> build ( $ data [ 'amount' ] ) , $ data [ 'state' ] , $ data [ 'parent_payment' ] , $ data [ 'valid_until' ] , $ links ) ; return $ authorization ; }

Build an instance of PayPalRestApiClient\Model\Authorization given an array

@param array $data The array should contains the following keys:
amount, create_time, state, parent_payment, id, valid_until, links.

@return PayPalRestApiClient\Model\Authorization

@throws PayPalRestApiClient\Exception\BuilderException

@see https://developer.paypal.com/docs/api/#authorization-object

Build an instance of PayPalRestApiClient \ Model \ Authorization given an array


public static function make($value)
    {
        $safe = '';

        foreach (str_split($value) as $letter) {
            if (ord($letter) > 128)
                return $letter;

            self::makeSafer($safe, $letter);
        }

        return $safe;
    }

public static function make ( $ value ) { $ safe = '' ; foreach ( str_split ( $ value ) as $ letter ) { if ( ord ( $ letter ) > 128 ) return $ letter ; self :: makeSafer ( $ safe , $ letter ) ; } return $ safe ; }

Obfuscate a string to prevent spam-bots from sniffing it.

@param  string  $value

@return string

Obfuscate a string to prevent spam - bots from sniffing it .


private static function makeSafer(&$safe, $letter)
    {
        // To properly obfuscate the value, we will randomly convert each letter to
        // its entity or hexadecimal representation, keeping a bot from sniffing
        // the randomly obfuscated letters out of the string on the responses.
        switch (rand(1, 3)) {
            case 1:
                $safe .= '&#' . ord($letter).';';
                break;

            case 2:
                $safe .= '&#x' . dechex(ord($letter)).';';
                break;

            case 3:
                $safe .= $letter;
                // no break
        }
    }

Make safer.

@param  string  $letter
@param  string  $safe


public function getFormValue($key)
    {
        $value = $this->getAttributeFromArray($key);

        if (in_array($key, $this->getDates()) && ! is_null($value))
            $value = $this->asDateTime($value);

        return $this->hasFormMutator($key)
            ? $this->mutateFormAttribute($key, $value)
            : data_get($this, $key); // No form mutator, let the model resolve this
    }

Get form value from the eloquent model.

@param  string  $key

@return mixed

Get form value from the eloquent model .


protected function hasFormMutator($key)
    {
        $methods  = $this->getReflection()->getMethods(ReflectionMethod::IS_PUBLIC);

        return collect($methods)->filter(function (ReflectionMethod $method) use ($key) {
            return $method->name === $this->getMutateFromMethodName($key);
        })->isNotEmpty();
    }

protected function hasFormMutator ( $ key ) { $ methods = $ this -> getReflection ( ) -> getMethods ( ReflectionMethod :: IS_PUBLIC ) ; return collect ( $ methods ) -> filter ( function ( ReflectionMethod $ method ) use ( $ key ) { return $ method -> name === $ this -> getMutateFromMethodName ( $ key ) ; } ) -> isNotEmpty ( ) ; }

Check if has a form mutator.

@param  string  $key

@return bool


protected function getReflection()
    {
        if (is_null($this->reflection)) {
            $this->reflection = new ReflectionClass($this);
        }

        return $this->reflection;
    }

protected function getReflection ( ) { if ( is_null ( $ this -> reflection ) ) { $ this -> reflection = new ReflectionClass ( $ this ) ; } return $ this -> reflection ; }

Get a ReflectionClass Instance.

@return \ReflectionClass

@throws \ReflectionException


public function favicon($url, array $attributes = [], $secure = null)
    {
        $attributes = array_merge([
            'rel'  => 'shortcut icon',
            'type' => 'image/x-icon',
        ], $attributes);

        return Elements\Element::withTag('link')
            ->attribute('href', $this->url->asset($url, $secure))
            ->attributes($attributes)
            ->render();
    }

public
function
favicon
(
$
url
,
array
$
attributes
=
[
]
,
$
secure
=
)
{
$
attributes
=
array_merge
(
[
'rel'
=>
'shortcut icon'
,
'type'
=>
'image/x-icon'
,
]
,
$
attributes
)
;
return
Elements
\
Element
::
withTag
(
'link'
)
->
attribute
(
'href'
,
$
this
->
url
->
asset
(
$
url
,
$
secure
)
)
->
attributes
(
$
attributes
)
->
render
(
)
;
}

Generate a link to a Favicon file.

@param  string  $url
@param  array   $attributes
@param  bool    $secure

@return \Illuminate\Support\HtmlString


public function link($url, $title = null, array $attributes = [], $secure = null, $escaped = true)
    {
        $url = $this->url->to($url, [], $secure);

        if (is_null($title) || $title === false)
            $title = $url;

        return Elements\A::make()
            ->href($this->entities($url))
            ->attributes($attributes)
            ->html($escaped ? $this->entities($title) : $title)
            ->render();
    }

public function link ( $ url , $ title = null , array $ attributes = [ ] , $ secure = null , $ escaped = true ) { $ url = $ this -> url -> to ( $ url , [ ] , $ secure ) ; if ( is_null ( $ title ) || $ title === false ) $ title = $ url ; return Elements \ A :: make ( ) -> href ( $ this -> entities ( $ url ) ) -> attributes ( $ attributes ) -> html ( $ escaped ? $ this -> entities ( $ title ) : $ title ) -> render ( ) ; }

Generate a HTML link.

@param  string       $url
@param  string|null  $title
@param  array        $attributes
@param  bool         $secure
@param  bool         $escaped

@return \Illuminate\Support\HtmlString


public function ol(array $items, array $attributes = [])
    {
        return Elements\Ol::make()
            ->items($items)
            ->attributes($attributes)
            ->render();
    }

public function ol ( array $ items , array $ attributes = [ ] ) { return Elements \ Ol :: make ( ) -> items ( $ items ) -> attributes ( $ attributes ) -> render ( ) ; }

Generate an ordered list of items.

@param  array  $items
@param  array  $attributes

@return \Illuminate\Support\HtmlString


public function ul(array $items, array $attributes = [])
    {
        return Elements\Ul::make()
            ->items($items)
            ->attributes($attributes)
            ->render();
    }

public function ul ( array $ items , array $ attributes = [ ] ) { return Elements \ Ul :: make ( ) -> items ( $ items ) -> attributes ( $ attributes ) -> render ( ) ; }

Generate an un-ordered list of items.

@param  array  $items
@param  array  $attributes

@return \Illuminate\Support\HtmlString

Generate an un - ordered list of items .


private function getModelValueAttribute($name, $model = null)
    {
        $model = $model ?: $this->getModel();

        $key = self::transformKey($name);

        if (strpos($key, '.') !== false) {
            $keys = explode('.', $key, 2);

            return $this->getModelValueAttribute(
                $keys[1],
                $this->getModelValueAttribute($keys[0], $model)
            );
        }

        return method_exists($model, 'getFormValue')
            ? $model->getFormValue($key)
            : data_get($model, $key);
    }

private function getModelValueAttribute ( $ name , $ model = null ) { $ model = $ model ? : $ this -> getModel ( ) ; $ key = self :: transformKey ( $ name ) ; if ( strpos ( $ key , '.' ) !== false ) { $ keys = explode ( '.' , $ key , 2 ) ; return $ this -> getModelValueAttribute ( $ keys [ 1 ] , $ this -> getModelValueAttribute ( $ keys [ 0 ] , $ model ) ) ; } return method_exists ( $ model , 'getFormValue' ) ? $ model -> getFormValue ( $ key ) : data_get ( $ model , $ key ) ; }

Get the model value that should be assigned to the field.

@param  string                               $name
@param  \Illuminate\Database\Eloquent\Model  $model

@return mixed

Get the model value that should be assigned to the field .


public function text($name, $value = null, array $attributes = [])
    {
        return $this->input('text', $name, $value, $attributes);
    }

public function text ( $ name , $ value = null , array $ attributes = [ ] ) { return $ this -> input ( 'text' , $ name , $ value , $ attributes ) ; }

Create a text input field.

@param  string        $name
@param  string|mixed  $value
@param  array         $attributes

@return \Arcanedev\Html\Elements\Input


public function email($name, $value = null, array $attributes = [])
    {
        return $this->input('email', $name, $value, $attributes);
    }

public function email ( $ name , $ value = null , array $ attributes = [ ] ) { return $ this -> input ( 'email' , $ name , $ value , $ attributes ) ; }

Create an e-mail input field.

@param  string        $name
@param  string|mixed  $value
@param  array         $attributes

@return \Arcanedev\Html\Elements\Input


public function tel($name, $value = null, array $attributes = [])
    {
        return $this->input('tel', $name, $value, $attributes);
    }

public function tel ( $ name , $ value = null , array $ attributes = [ ] ) { return $ this -> input ( 'tel' , $ name , $ value , $ attributes ) ; }

Create a tel input field.

@param  string        $name
@param  string|mixed  $value
@param  array         $attributes

@return \Arcanedev\Html\Elements\Input


public function number($name, $value = null, array $attributes = [])
    {
        return $this->input('number', $name, $value, $attributes);
    }

public function number ( $ name , $ value = null , array $ attributes = [ ] ) { return $ this -> input ( 'number' , $ name , $ value , $ attributes ) ; }

Create a number input field.

@param  string        $name
@param  string|mixed  $value
@param  array         $attributes

@return \Arcanedev\Html\Elements\Input


public function url($name, $value = null, array $attributes = [])
    {
        return $this->input('url', $name, $value, $attributes);
    }

public function url ( $ name , $ value = null , array $ attributes = [ ] ) { return $ this -> input ( 'url' , $ name , $ value , $ attributes ) ; }

Create a url input field.

@param  string  $name
@param  string  $value
@param  array   $attributes

@return \Arcanedev\Html\Elements\Input


public function color($name, $value = null, array $attributes = [])
    {
        return $this->input('color', $name, $value, $attributes);
    }

public function color ( $ name , $ value = null , array $ attributes = [ ] ) { return $ this -> input ( 'color' , $ name , $ value , $ attributes ) ; }

Create a color input field.

@param  string        $name
@param  string|mixed  $value
@param  array         $attributes

@return \Arcanedev\Html\Elements\Input


private function getCheckboxCheckedState($name, $value, $checked)
    {
        if (
            isset($this->session) &&
            ! $this->oldInputIsEmpty() &&
            is_null($this->old($name))
        )
            return false;

        if ($this->missingOldAndModel($name))
            return $checked;

        $posted = $this->getValueAttribute($name, $checked);

        if (is_array($posted))
            return in_array($value, $posted);

        if ($posted instanceof Collection)
            return $posted->contains('id', $value);

        return (bool) $posted;
    }

private function getCheckboxCheckedState ( $ name , $ value , $ checked ) { if ( isset ( $ this -> session ) && ! $ this -> oldInputIsEmpty ( ) && is_null ( $ this -> old ( $ name ) ) ) return false ; if ( $ this -> missingOldAndModel ( $ name ) ) return $ checked ; $ posted = $ this -> getValueAttribute ( $ name , $ checked ) ; if ( is_array ( $ posted ) ) return in_array ( $ value , $ posted ) ; if ( $ posted instanceof Collection ) return $ posted -> contains ( 'id' , $ value ) ; return ( bool ) $ posted ; }

Get the check state for a checkbox input.

@param  string     $name
@param  mixed      $value
@param  bool|null  $checked

@return bool

Get the check state for a checkbox input .


private function getUrlAction($attribute)
    {
        return is_array($attribute)
            ? $this->url->to($attribute[0], array_slice($attribute, 1))
            : $this->url->to($attribute);
    }

private function getUrlAction ( $ attribute ) { return is_array ( $ attribute ) ? $ this -> url -> to ( $ attribute [ 0 ] , array_slice ( $ attribute , 1 ) ) : $ this -> url -> to ( $ attribute ) ; }

Get the action for a "url" option.

@param  array|string  $attribute

@return string


private function getRouteAction($attribute)
    {
        return is_array($attribute)
            ? $this->url->route($attribute[0], array_slice($attribute, 1))
            : $this->url->route($attribute);
    }

private function getRouteAction ( $ attribute ) { return is_array ( $ attribute ) ? $ this -> url -> route ( $ attribute [ 0 ] , array_slice ( $ attribute , 1 ) ) : $ this -> url -> route ( $ attribute ) ; }

Get the action for a "route" option.

@param  array|string  $attribute

@return string


private function getControllerAction($attribute)
    {
        return is_array($attribute)
            ? $this->url->action($attribute[0], array_slice($attribute, 1))
            : $this->url->action($attribute);
    }

private function getControllerAction ( $ attribute ) { return is_array ( $ attribute ) ? $ this -> url -> action ( $ attribute [ 0 ] , array_slice ( $ attribute , 1 ) ) : $ this -> url -> action ( $ attribute ) ; }

Get the action for an "action" option.

@param  array|string  $attribute

@return string


public function insert(string $string, int $position)
    {
        $this->data = substr_replace($this->data, $string, $position, 0);
    }

public function insert ( string $ string , int $ position ) { $ this -> data = substr_replace ( $ this -> data , $ string , $ position , 0 ) ; }

Inserts the string at the given position in the buffer.

@param string $string
@param int $position

Inserts the string at the given position in the buffer .


public function search($string, $reverse = false)
    {
        if ($reverse) {
            return strrpos($this->data, $string);
        }

        return strpos($this->data, $string);
    }

public function search ( $ string , $ reverse = false ) { if ( $ reverse ) { return strrpos ( $ this -> data , $ string ) ; } return strpos ( $ this -> data , $ string ) ; }

Returns the position of the given pattern in the buffer if it exists, or false if it does not.

@param string $string String to search for.
@param bool $reverse Start search from end of buffer.

@return int|bool

@see strpos()

Returns the position of the given pattern in the buffer if it exists or false if it does not .


public function offsetSet($index, $data)
    {
        $this->data = substr_replace($this->data, $data, $index, 1);
    }

public function offsetSet ( $ index , $ data ) { $ this -> data = substr_replace ( $ this -> data , $ data , $ index , 1 ) ; }

Replaces the character in the buffer at the given position with the given string.

@param int $index
@param string $data

Replaces the character in the buffer at the given position with the given string .


public function offsetUnset($index)
    {
        if (isset($this->data[$index])) {
            $this->data = substr_replace($this->data, null, $index, 1);
        }
    }

public function offsetUnset ( $ index ) { if ( isset ( $ this -> data [ $ index ] ) ) { $ this -> data = substr_replace ( $ this -> data , null , $ index , 1 ) ; } }

Removes the character at the given index from the buffer.

@param int $index

Removes the character at the given index from the buffer .


private function fetch($resource, int $length = self::CHUNK_SIZE, string $byte = null): string
    {
        $remaining = $length;

        if (('' === $this->buffer || 0 < ($remaining -= strlen($this->buffer))) && is_resource($resource)) {
            // Error reporting suppressed since fread() produces a warning if the stream unexpectedly closes.
            $this->buffer .= @fread($resource, $remaining);
        }

        if (null === $byte || false === ($position = strpos($this->buffer, $byte))) {
            if (strlen($this->buffer) <= $length) {
                $data = $this->buffer;
                $this->buffer = '';
                return $data;
            }

            $position = $length;
        } else {
            ++$position; // Include byte in result.
        }

        $data = (string) substr($this->buffer, 0, $position);
        $this->buffer = (string) substr($this->buffer, $position);
        return $data;
    }

Reads data from the stream socket resource based on set length and read-to byte.

@param resource $resource
@param int $length
@param string|null $byte

@return string

Reads data from the stream socket resource based on set length and read - to byte .


protected function parseFile($name, Closure $callback)
    {
        $url = $this->files[$name]['url'];
        $basename = basename($url);
        $storagePath = config('geonames.storagePath');
        // Final file path
        $path = $storagePath . '/' . $this->files[$name]['filename'] . '.txt';

        // Check if file exists (should be since we just downloaded them)
        $downloadedFilePath = $storagePath . '/' . $basename;
        if (!file_exists($downloadedFilePath)) {
            throw new RuntimeException('File does not exist: ' . $downloadedFilePath);
        }
        // If it is a zip file we must unzip it
        if (substr($basename, -4) === '.zip') {
            $this->unZip($name);
        }

        $steps = $this->getLineCount($path);

        /* @var $output OutputStyle */
        $output = $this->getOutput();
        $bar = $output->createProgressBar($steps);
        $bar->setFormat('<info>Seeding File:</info> ' . basename($path) . ' %current%/%max% %bar% %percent%% <info>Remaining Time:</info> %remaining%');

        $steps = 0;
        $fh = fopen($path, 'r');
        if (!$fh) {
            throw new RuntimeException("Can not open file: $path");
        }
        while (!feof($fh)) {
            $line = fgets($fh);
            // ignore empty lines and comments
            if (!$line or $line === '' or strpos($line, '#') === 0) continue;
            // Geonames format is tab seperated
            $line = explode("\t", $line);
            // Insert using closure
            $callback($line);
            $steps++;
            if (isset($bar) && $steps % ($this->bufferSize * 10) === 0)
                $bar->advance($this->bufferSize * 10);
        }
        fclose($fh);
        if (isset($bar)) {
            $bar->finish();
            $output->newLine();
        }
        // If we wont keep txt version delete file
        if (substr($basename, -4) === '.zip' && !config('geonames.keepTxt')) {
            $this->line('<info>Removing File:</info> ' . basename($path));
            unlink($path);
        }
    }

Parse a given file and insert into databaase using closure.

@param  string $name
@param  Closure $callback
@return void

Parse a given file and insert into databaase using closure .


protected function getLineCount($path)
    {
        $fh = fopen($path, 'r');
        if (!$fh) {
            throw new RuntimeException("Can not open file: $path");
        }
        $fileSize = @filesize($path);
        /* @var $output OutputStyle */
        $output = $this->getOutput();
        $bar = $output->createProgressBar($fileSize);
        $bar->setFormat('<info>Reading File:</info> ' . basename($path) . ' %bar% %percent%% <info>Remaining Time:</info> %remaining%');

        $steps = 0;
        $currentSize = 0;
        while (!feof($fh)) {
            $line = fgets($fh);
            $currentSize += strlen($line);
            // ignore empty lines and comments
            if (!$line or $line === '' or strpos($line, '#') === 0) continue;
            $steps++;
            // Reading is so much faster, must slow down advances
            if (isset($bar) && $steps % ($this->bufferSize * 100) === 0) {
                $bar->advance($currentSize);
                $currentSize = 0;
            }
        }
        fclose($fh);
        if (isset($bar)) {
            $bar->finish();
            $output->newLine();
        }
        return $steps;
    }

Read the file and get line count
Not very efficient but does the job well...

@param  string $path
@return int $count

Read the file and get line count Not very efficient but does the job well ...


protected function unZip($name)
    {
        $zipFileName = basename($this->files[$name]['url']);
        if (!substr($zipFileName, -4) === '.zip')
            throw new RuntimeException($zipFileName . ' does not have .zip extension');

        // Final file path
        $storagePath = config('geonames.storagePath');
        $extractedFile = $this->files[$name]['filename'] . '.txt';
        $path = $storagePath . '/' . $extractedFile;

        // Open zip archive because we need the size of extracted file
        $zipArchive = new ZipArchive;
        $zipArchive->open($storagePath . '/' . $zipFileName);

        if (file_exists($path)) {
            $uncompressedSize = $zipArchive->statName($extractedFile)['size'];
            $fileSize = filesize($path);
            if ($uncompressedSize !== $fileSize) {
                $this->line('<info>Existing File:</info> ' . basename($path) . ' size does not match the one in ' . $zipFileName);
            } else {
                // Do not extract again
                $this->line('<info>Existing File:</info> ' . 'Found ' . basename($path) . ' file extracted from ' . $zipFileName);
                $zipArchive->close();
                return;
            }
        }
        // File does not exist or size does not match
        $this->line('<info>Extracting File:</info> ' . $extractedFile . ' from ' . $zipFileName . ' ...!!!Please Wait!!!...');
        // Extract file
        $zipArchive->extractTo($storagePath . '/', $extractedFile);
        $zipArchive->close();
    }


protected function getUrlSize($url)
    {
        $data = get_headers($url, true);
        if (isset($data['Content-Length']))
            return (int)$data['Content-Length'];
        return false;
    }

protected function getUrlSize ( $ url ) { $ data = get_headers ( $ url , true ) ; if ( isset ( $ data [ 'Content-Length' ] ) ) return ( int ) $ data [ 'Content-Length' ] ; return false ; }

Get Remote File Size

@param string $url remote address
@return int|boolean URL size in bytes or false


protected function getFilesArray()
    {
        static $firstRun = true;
        if ($firstRun) {
            $this->updateFilesList();
            $firstRun = false;
        }
        $data = $this->files;
        foreach ($data as $key => $value) {
            if (in_array($value['table'], config('geonames.ignoreTables'))) {
                unset($data[$key]);
            }
        }
        return $data;
    }

protected function getFilesArray ( ) { static $ firstRun = true ; if ( $ firstRun ) { $ this -> updateFilesList ( ) ; $ firstRun = false ; } $ data = $ this -> files ; foreach ( $ data as $ key => $ value ) { if ( in_array ( $ value [ 'table' ] , config ( 'geonames.ignoreTables' ) ) ) { unset ( $ data [ $ key ] ) ; } } return $ data ; }

Returns files array after removing entries in
ignoreTables config option and adding custom countries from
countries config option if necessary

@return array


protected function free(\Throwable $exception = null)
    {
        $this->readable = false;
        $this->writable = false;

        if (null !== $this->delayed) {
            $this->delayed->resolve('');
        }

        if (0 !== $this->hwm) {
            while (!$this->queue->isEmpty()) {
                /** @var \Icicle\Awaitable\Delayed $delayed */
                $delayed = $this->queue->shift();
                $delayed->reject(
                    $exception = $exception ?: new ClosedException('The stream was unexpectedly closed.')
                );
            }
        }
    }

Closes the stream and rejects any pending promises.

@param \Throwable|null $exception

Closes the stream and rejects any pending promises .


private function remove(): string
    {
        if (null !== $this->byte && false !== ($position = $this->buffer->search($this->byte))) {
            if (0 === $this->length || $position < $this->length) {
                return $this->buffer->shift($position + 1);
            }

            return $this->buffer->shift($this->length);
        }

        if (0 === $this->length) {
            return $this->buffer->drain();
        }

        return $this->buffer->shift($this->length);
    }

private function remove ( ) : string { if ( null !== $ this -> byte && false !== ( $ position = $ this -> buffer -> search ( $ this -> byte ) ) ) { if ( 0 === $ this -> length || $ position < $ this -> length ) { return $ this -> buffer -> shift ( $ position + 1 ) ; } return $ this -> buffer -> shift ( $ this -> length ) ; } if ( 0 === $ this -> length ) { return $ this -> buffer -> drain ( ) ; } return $ this -> buffer -> shift ( $ this -> length ) ; }

Returns bytes from the buffer based on the current length or current search byte.

@return string

Returns bytes from the buffer based on the current length or current search byte .


public function seek($position)
    {
        $position = (int) $position;
        if (0 > $position) {
            $position = 0;
        }

        $this->current = $position;
    }

public function seek ( $ position ) { $ position = ( int ) $ position ; if ( 0 > $ position ) { $ position = 0 ; } $ this -> current = $ position ; }

Moves to the given position in the buffer.

@param int $position

Moves to the given position in the buffer .


public function insert(string $data)
    {
        if (!$this->valid()) {
            throw new OutOfBoundsException('The iterator is not valid!');
        }

        $this->buffer[$this->current] = $data . $this->buffer[$this->current];
    }

public
function
insert
(
string
$
data
)
{
if
(
!
$
this
->
valid
(
)
)
{
throw
new
OutOfBoundsException
(
'The iterator is not valid!'
)
;
}
$
this
->
buffer
[
$
this
->
current
]
=
$
data
.
$
this
->
buffer
[
$
this
->
current
]
;
}

Inserts the given string into the buffer at the current iterator position.

@param string $data

@throws \Icicle\Stream\Exception\OutOfBoundsException If the iterator is invalid.

Inserts the given string into the buffer at the current iterator position .


public function replace(string $data): string
    {
        if (!$this->valid()) {
            throw new OutOfBoundsException('The iterator is not valid!');
        }

        $temp = $this->buffer[$this->current];

        $this->buffer[$this->current] = $data;

        return $temp;
    }

public
function
replace
(
string
$
data
)
:
string
{
if
(
!
$
this
->
valid
(
)
)
{
throw
new
OutOfBoundsException
(
'The iterator is not valid!'
)
;
}
$
temp
=
$
this
->
buffer
[
$
this
->
current
]
;
$
this
->
buffer
[
$
this
->
current
]
=
$
data
;
return
$
temp
;
}

Replaces the byte at the current iterator position with the given string.

@param string $data

@return string

@throws \Icicle\Stream\Exception\OutOfBoundsException If the iterator is invalid.

Replaces the byte at the current iterator position with the given string .


public function remove(): string
    {
        if (!$this->valid()) {
            throw new OutOfBoundsException('The iterator is not valid!');
        }

        $temp = $this->buffer[$this->current];

        unset($this->buffer[$this->current]);

        --$this->current;

        return $temp;
    }

public
function
remove
(
)
:
string
{
if
(
!
$
this
->
valid
(
)
)
{
throw
new
OutOfBoundsException
(
'The iterator is not valid!'
)
;
}
$
temp
=
$
this
->
buffer
[
$
this
->
current
]
;
unset
(
$
this
->
buffer
[
$
this
->
current
]
)
;
$
this
->
current
;
return
$
temp
;
}

Removes the byte at the current iterator position and moves the iterator to the previous character.

@return string

@throws \Icicle\Stream\Exception\OutOfBoundsException If the iterator is invalid.

Removes the byte at the current iterator position and moves the iterator to the previous character .


protected function publishDirectory($from, $to)
    {
        $toContents = $this->files->files($to);
        $fromContents = $this->files->files($from);

        foreach ($fromContents as $file) {
            $newFile = $to . DIRECTORY_SEPARATOR . $this->files->name($file) . '.' . $this->files->extension($file);
            if ($this->files->isFile($file) && (!in_array($newFile, $toContents) || $this->option('force'))) {
                $this->files->copy($file, $newFile);
            }
        }

        $this->status($from, $to, 'Directory');
    }

protected function publishDirectory ( $ from , $ to ) { $ toContents = $ this -> files -> files ( $ to ) ; $ fromContents = $ this -> files -> files ( $ from ) ; foreach ( $ fromContents as $ file ) { $ newFile = $ to . DIRECTORY_SEPARATOR . $ this -> files -> name ( $ file ) . '.' . $ this -> files -> extension ( $ file ) ; if ( $ this -> files -> isFile ( $ file ) && ( ! in_array ( $ newFile , $ toContents ) || $ this -> option ( 'force' ) ) ) { $ this -> files -> copy ( $ file , $ newFile ) ; } } $ this -> status ( $ from , $ to , 'Directory' ) ; }

Publish the directory to the given directory.

@param  string $from
@param  string $to
@return void

Publish the directory to the given directory .


public function close()
    {
        if (is_resource($this->resource)) {
            fclose($this->resource);
        }

        $this->resource = null;
        $this->autoClose = false;
    }

public function close ( ) { if ( is_resource ( $ this -> resource ) ) { fclose ( $ this -> resource ) ; } $ this -> resource = null ; $ this -> autoClose = false ; }


public function scopeAdmin1($query)
    {
        $table = 'geonames_geonames';

        if (!isset($query->getQuery()->columns))
            $query = $query->addSelect($this->usefulScopeColumns);

        $query = $query
            ->leftJoin('geonames_admin1_codes as admin1', 'admin1.code', '=',
                DB::raw('CONCAT_WS(\'.\',' .
                    $table . '.country_code,' .
                    $table . '.admin1_code)')
            )
            ->addSelect(
                'admin1.geoname_id as admin1_geoname_id',
                'admin1.name as admin1_name'
            );

        return $query;
    }

Return admin1 information in result

@param \Illuminate\Database\Query\Builder $query
@return \Illuminate\Database\Query\Builder


public function scopeAddCountryInfo($query)
    {
        $table = 'geonames_geonames';

        if (!isset($query->getQuery()->columns))
            $query = $query->addSelect($this->usefulScopeColumns);

        $query = $query
            ->leftJoin('geonames_country_infos as country_info', $table . '.country_code', '=',
                'country_info.iso'
            )
            ->addSelect(
                'country_info.geoname_id as country_info_geoname_id',
                'country_info.country as country_info_country'
            );

        return $query;
    }

Return country information in result

@param \Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder $query
@return \Illuminate\Database\Query\Builder


public function scopeCity($query, $name = null, $featureCodes = ['PPLC', 'PPLA', 'PPLA2', 'PPLA3'])
    {
        return $this->scopeSearchByFeature($query,$name,'P',$featureCodes);
    }

public function scopeCity ( $ query , $ name = null , $ featureCodes = [ 'PPLC' , 'PPLA' , 'PPLA2' , 'PPLA3' ] ) { return $ this -> scopeSearchByFeature ( $ query , $ name , 'P' , $ featureCodes ) ; }

Build a query to find major cities. Accepts wildcards eg. 'Helsin%'

Suggested index for search:
ALTER TABLE geonames_geonames ADD INDEX geonames_geonames_feature_name_index
(`feature_class`,`feature_code`,`name`);
and if you will limit queries by country you should also use:
ALTER TABLE geonames_geonames ADD INDEX geonames_geonames_country_feature_name_index
(`country_code`,`feature_class`,`feature_code`,`name`);

@param \Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder $query
@param String $name
@param array $featureCodes List of feature codes to use when returning results
defaults to ['PPLC','PPLA','PPLA2', 'PPLA3']
@return \Illuminate\Database\Query\Builder

Build a query to find major cities . Accepts wildcards eg . Helsin%


public function scopeCountry($query, $name = null, $featureCodes = ['PCLI'])
    {
        return $this->scopeSearchByFeature($query,$name,'A',$featureCodes);
    }

public function scopeCountry ( $ query , $ name = null , $ featureCodes = [ 'PCLI' ] ) { return $ this -> scopeSearchByFeature ( $ query , $ name , 'A' , $ featureCodes ) ; }

Build a query to find major ccountries. Accepts wildcards eg. '%Finland%'

Suggested index for search:
ALTER TABLE geonames_geonames ADD INDEX geonames_geonames_feature_name_index
(`feature_class`,`feature_code`,`name`);

@param \Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder $query
@param String $name
@param array $featureCodes List of feature codes to use when returning results
defaults to ['PCLI']
@return \Illuminate\Database\Query\Builder

Build a query to find major ccountries . Accepts wildcards eg . %Finland%


public function scopeSearchByFeature($query, $name = null, $feature_class=null, $featureCodes = null)
    {
        $table = 'geonames_geonames';

        if (!isset($query->getQuery()->columns))
            $query = $query->addSelect($this->usefulScopeColumns);

        if ($name !== null)
            $query = $query->where($table . '.name', 'LIKE', $name);

        $query = $query
            ->where($table . '.feature_class', $feature_class)
            ->whereIn($table . '.feature_code', $featureCodes);

        return $query;
    }

public function scopeSearchByFeature ( $ query , $ name = null , $ feature_class = null , $ featureCodes = null ) { $ table = 'geonames_geonames' ; if ( ! isset ( $ query -> getQuery ( ) -> columns ) ) $ query = $ query -> addSelect ( $ this -> usefulScopeColumns ) ; if ( $ name !== null ) $ query = $ query -> where ( $ table . '.name' , 'LIKE' , $ name ) ; $ query = $ query -> where ( $ table . '.feature_class' , $ feature_class ) -> whereIn ( $ table . '.feature_code' , $ featureCodes ) ; return $ query ; }

Generic query used by scopes, but you can call it with custom feataure codes.

@param \Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder $query
@param String $name
@param String $feature_class The 1 character feature class
@param array $featureCodes List of feature codes to use when returning results
@return \Illuminate\Database\Query\Builder

Generic query used by scopes but you can call it with custom feataure codes .


public function createPendingRedirects()
    {
        $this->nodeFactory->reset();
        foreach ($this->pendingRedirects as $nodeIdentifierAndWorkspace => $oldUriPerDimensionCombination) {
            list($nodeIdentifier, $workspaceName) = explode('@', $nodeIdentifierAndWorkspace);
            $this->buildRedirects($nodeIdentifier, $workspaceName, $oldUriPerDimensionCombination);
        }

        $this->persistenceManager->persistAll();
    }

public function createPendingRedirects ( ) { $ this -> nodeFactory -> reset ( ) ; foreach ( $ this -> pendingRedirects as $ nodeIdentifierAndWorkspace => $ oldUriPerDimensionCombination ) { list ( $ nodeIdentifier , $ workspaceName ) = explode ( '@' , $ nodeIdentifierAndWorkspace ) ; $ this -> buildRedirects ( $ nodeIdentifier , $ workspaceName , $ oldUriPerDimensionCombination ) ; } $ this -> persistenceManager -> persistAll ( ) ; }

Creates the queued redirects provided we can find the node.

@return void
@throws \Neos\Flow\Mvc\Routing\Exception\MissingActionNameException

Creates the queued redirects provided we can find the node .


protected function hasNodeUriChanged(NodeInterface $node, Workspace $targetWorkspace): bool
    {
        $newUriPath = $this->buildUriPathForNode($node);
        $newUriPath = $this->removeContextInformationFromRelativeNodeUri($newUriPath);

        $nodeInTargetWorkspace = $this->getNodeInWorkspace($node, $targetWorkspace);
        if (!$nodeInTargetWorkspace) {
            return false;
        }
        $oldUriPath = $this->buildUriPathForNode($nodeInTargetWorkspace);
        $oldUriPath = $this->removeContextInformationFromRelativeNodeUri($oldUriPath);

        return ($newUriPath !== $oldUriPath);
    }

Has the Uri changed at all.

@param NodeInterface $node
@param Workspace $targetWorkspace
@return bool
@throws \Neos\Flow\Mvc\Routing\Exception\MissingActionNameException


protected function buildRedirects(string $nodeIdentifier, string $workspaceName, array $oldUriPerDimensionCombination)
    {
        foreach ($oldUriPerDimensionCombination as list($oldRelativeUri, $dimensionCombination)) {
            $this->createRedirectFrom($oldRelativeUri, $nodeIdentifier, $workspaceName, $dimensionCombination);
        }
    }

protected function buildRedirects ( string $ nodeIdentifier , string $ workspaceName , array $ oldUriPerDimensionCombination ) { foreach ( $ oldUriPerDimensionCombination as list ( $ oldRelativeUri , $ dimensionCombination ) ) { $ this -> createRedirectFrom ( $ oldRelativeUri , $ nodeIdentifier , $ workspaceName , $ dimensionCombination ) ; } }

Build redirects in all dimensions for a given node.

@param string $nodeIdentifier
@param string $workspaceName
@param $oldUriPerDimensionCombination
@return void
@throws \Neos\Flow\Mvc\Routing\Exception\MissingActionNameException

Build redirects in all dimensions for a given node .


protected function createRedirectFrom(string $oldUri, string $nodeIdentifer, string $workspaceName, array $dimensionCombination): bool
    {
        $node = $this->getNodeInWorkspaceAndDimensions($nodeIdentifer, $workspaceName, $dimensionCombination);
        if ($node === null) {
            return false;
        }

        if ($this->isRestrictedByNodeType($node) || $this->isRestrictedByPath($node)) {
            return false;
        }

        $newUri = $this->buildUriPathForNode($node);

        if ($node->isRemoved()) {
            return $this->removeNodeRedirectIfNeeded($node, $newUri);
        }

        if ($oldUri === $newUri) {
            return false;
        }

        $hosts = $this->getHostnames($node->getContext());
        $this->flushRoutingCacheForNode($node);
        $statusCode = (integer)$this->defaultStatusCode['redirect'];

        $this->redirectStorage->addRedirect($oldUri, $newUri, $statusCode, $hosts);

        return true;
    }

protected function createRedirectFrom ( string $ oldUri , string $ nodeIdentifer , string $ workspaceName , array $ dimensionCombination ) : bool { $ node = $ this -> getNodeInWorkspaceAndDimensions ( $ nodeIdentifer , $ workspaceName , $ dimensionCombination ) ; if ( $ node === null ) { return false ; } if ( $ this -> isRestrictedByNodeType ( $ node ) || $ this -> isRestrictedByPath ( $ node ) ) { return false ; } $ newUri = $ this -> buildUriPathForNode ( $ node ) ; if ( $ node -> isRemoved ( ) ) { return $ this -> removeNodeRedirectIfNeeded ( $ node , $ newUri ) ; } if ( $ oldUri === $ newUri ) { return false ; } $ hosts = $ this -> getHostnames ( $ node -> getContext ( ) ) ; $ this -> flushRoutingCacheForNode ( $ node ) ; $ statusCode = ( integer ) $ this -> defaultStatusCode [ 'redirect' ] ; $ this -> redirectStorage -> addRedirect ( $ oldUri , $ newUri , $ statusCode , $ hosts ) ; return true ; }

Gets the node in the given dimensions and workspace and redirects the oldUri to the new one.

@param string $oldUri
@param string $nodeIdentifer
@param string $workspaceName
@param array $dimensionCombination
@return bool
@throws \Neos\Flow\Mvc\Routing\Exception\MissingActionNameException

Gets the node in the given dimensions and workspace and redirects the oldUri to the new one .


protected function removeNodeRedirectIfNeeded(NodeInterface $node, string $newUri): bool
    {
        // By default the redirect handling for removed nodes is activated.
        // If it is deactivated in your settings you will be able to handle the redirects on your own.
        // For example redirect to dedicated landing pages for deleted campaign NodeTypes
        if ($this->enableRemovedNodeRedirect) {
            $hosts = $this->getHostnames($node->getContext());
            $this->flushRoutingCacheForNode($node);
            $statusCode = (integer)$this->defaultStatusCode['gone'];
            $this->redirectStorage->addRedirect($newUri, '', $statusCode, $hosts);

            return true;
        }

        return false;
    }

Removes a redirect

@param NodeInterface $node
@param string $newUri
@return bool


protected function isRestrictedByNodeType(NodeInterface $node): bool
    {
        if (!isset($this->restrictByNodeType)) {
            return false;
        }

        foreach ($this->restrictByNodeType as $disabledNodeType => $status) {
            if ($status !== true) {
                continue;
            }
            if ($node->getNodeType()->isOfType($disabledNodeType)) {
                $this->systemLogger->log(vsprintf('Redirect skipped based on the current node type (%s) for node %s because is of type %s', [
                    $node->getNodeType()->getName(),
                    $node->getContextPath(),
                    $disabledNodeType
                ]), LOG_DEBUG, null, 'RedirectHandler');

                return true;
            }
        }

        return false;
    }

Check if the current node type is restricted by Settings

@param NodeInterface $node
@return bool


protected function isRestrictedByPath(NodeInterface $node): bool
    {
        if (!isset($this->restrictByPathPrefix)) {
            return false;
        }

        foreach ($this->restrictByPathPrefix as $pathPrefix => $status) {
            if ($status !== true) {
                continue;
            }
            $pathPrefix = rtrim($pathPrefix, '/') . '/';
            if (mb_strpos($node->getPath(), $pathPrefix) === 0) {
                $this->systemLogger->log(vsprintf('Redirect skipped based on the current node path (%s) for node %s because prefix matches %s', [
                    $node->getPath(),
                    $node->getContextPath(),
                    $pathPrefix
                ]), LOG_DEBUG, null, 'RedirectHandler');

                return true;
            }
        }

        return false;
    }

Check if the current node path is restricted by Settings

@param NodeInterface $node
@return bool


protected function getHostnames(ContentContext $contentContext): array
    {
        $domains = [];
        $site = $contentContext->getCurrentSite();
        if ($site === null) {
            return $domains;
        }

        foreach ($site->getActiveDomains() as $domain) {
            /** @var Domain $domain */
            $domains[] = $domain->getHostname();
        }

        return $domains;
    }

protected
function
getHostnames
(
ContentContext
$
contentContext
)
:
array
{
$
domains
=
[
]
;
$
site
=
$
contentContext
->
getCurrentSite
(
)
;
if
(
$
site
===
)
{
return
$
domains
;
}
foreach
(
$
site
->
getActiveDomains
(
)
as
$
domain
)
{
/** @var Domain $domain */
$
domains
[
]
=
$
domain
->
getHostname
(
)
;
}
return
$
domains
;
}

Collects all hostnames from the Domain entries attached to the current site.

@param ContentContext $contentContext
@return array

Collects all hostnames from the Domain entries attached to the current site .


protected function getUriBuilder(): UriBuilder
    {
        if ($this->uriBuilder !== null) {
            return $this->uriBuilder;
        }

        $httpRequest = Request::createFromEnvironment();
        $actionRequest = new ActionRequest($httpRequest);
        $this->uriBuilder = new UriBuilder();
        $this->uriBuilder
            ->setRequest($actionRequest);
        $this->uriBuilder
            ->setFormat('html')
            ->setCreateAbsoluteUri(false);

        return $this->uriBuilder;
    }

protected function getUriBuilder ( ) : UriBuilder { if ( $ this -> uriBuilder !== null ) { return $ this -> uriBuilder ; } $ httpRequest = Request :: createFromEnvironment ( ) ; $ actionRequest = new ActionRequest ( $ httpRequest ) ; $ this -> uriBuilder = new UriBuilder ( ) ; $ this -> uriBuilder -> setRequest ( $ actionRequest ) ; $ this -> uriBuilder -> setFormat ( 'html' ) -> setCreateAbsoluteUri ( false ) ; return $ this -> uriBuilder ; }

Creates an UriBuilder instance for the current request

@return UriBuilder


public function loadName($varValue, DataContainer $dc)
    {
        // check for query parameters
        if (strpos($varValue, '?') !== false)
        {
            $pos = strpos($varValue, '?');
            $url = substr($varValue, 0, $pos);
            $par = substr($varValue, $pos + 1);

            if ($par)
            {
                parse_str($par, $arrParameters);
                return rawurldecode($url) . '?' . http_build_query($arrParameters);
            }
        }

        return rawurldecode($varValue);
    }

public
function
loadName
(
$
varValue
,
DataContainer
$
dc
)
{
// check for query parameters
if
(
strpos
(
$
varValue
,
'?'
)
!==
false
)
{
$
pos
=
strpos
(
$
varValue
,
'?'
)
;
$
url
=
substr
(
$
varValue
,
0
,
$
pos
)
;
$
par
=
substr
(
$
varValue
,
$
pos
+
1
)
;
if
(
$
par
)
{
parse_str
(
$
par
,
$
arrParameters
)
;
return
rawurldecode
(
$
url
)
.
'?'
.
http_build_query
(
$
arrParameters
)
;
}
}
return
rawurldecode
(
$
varValue
)
;
}

Decodes the name
@param mixed         $varValue
@param DataContainer $dc
@return string


private function validate($name, $domain)
    {
        // check if a page exists
        if( !\Config::get('urlSuffix') && ( $objPages = \PageModel::findByAlias( $name ) ) !== null )
        {
            // check if short url has a domain
            if( $domain > 0 )
            {
                $valid = true;
                while( $objPages->next() )
                {
                    // load page details
                    $objPages->current()->loadDetails();

                    // if one of the found pages is within the same domain, do not allow it
                    if( $objPages->rootId == $domain )
                    {
                        $valid = false;
                        break;
                    }
                }

                if( $valid )
                    return;
            }

            // otherwise throw exception
            throw new Exception(sprintf($GLOBALS['TL_LANG']['tl_short_urls']['pageExists'], $name));
        }
    }

Validate the name of a short url
@param  string $name
@param  string $domain
@return void


public function pagePicker(DataContainer $dc)
    {
        return ' table . '&field=' . $dc->field . '&value=' . str_replace(array('{{link_url::', '}}'), '', $dc->value) . '&switch=1' . '" title="' . specialchars($GLOBALS['TL_LANG']['MSC']['pagepicker']) . '" onclick="Backend.getScrollOffset();Backend.openModalSelector({\'width\':768,\'title\':\'' . specialchars(str_replace("'", "\\'", $GLOBALS['TL_LANG']['MOD']['page'][0])) . '\',\'url\':this.href,\'id\':\'' . $dc->field . '\',\'tag\':\'ctrl_'. $dc->field . ((Input::get('act') == 'editAll') ? '_' . $dc->id : '') . '\',\'self\':this});return false">' . Image::getHtml('pickpage.gif', $GLOBALS['TL_LANG']['MSC']['pagepicker'], 'style="vertical-align:top;cursor:pointer"') . '';
    }

Generate the page picker link

@param DataContainer $dc

@return string


public function labelCallback($arrRow)
    {
        // get the target URL
        $targetURL = \ShortURLs::processTarget( $arrRow['target'] );

        // remove current host
        $targetURL = str_replace( \Environment::get('base'), '', $targetURL );

        // check for domain restriction
        $domain = '';
        if( $arrRow['domain'] && ( $objPage = \PageModel::findById( $arrRow['domain'] ) ) !== null )
            $domain = $objPage->dns . '/';

        // generate list record
        return '
[' . ( $arrRow['redirect'] == 'permanent' ? 301 : 302 ) . ']

' . $domain . rawurldecode($arrRow['name']) . ' » ' . rawurldecode($targetURL) . '
';
    }

Display list info in the backend

@param array $arrRow

@return string


public static function init() {
		$class = get_called_class();

		// Admin menu entry for upload debugging.
		add_action('admin_menu', array($class, 'menu_debug'));

		// Override upload file validation (general).
		add_filter('wp_check_filetype_and_ext', array($class, 'check_filetype_and_ext'), 10, 4);

		// Override upload file validation (SVG).
		add_filter('wp_check_filetype_and_ext', array($class, 'check_filetype_and_ext_svg'), 15, 4);

		// Set up translations.
		add_action('plugins_loaded', array($class, 'localize'));

		// Update check on debug page.
		add_action('admin_notices', array($class, 'debug_notice'));

		// AJAX hook for disabling contributor lookups.
		add_action('wp_ajax_bm_ajax_disable_contributor_notice', array($class, 'disable_contributor_notice'));

		// And the corresponding warnings.
		add_filter('admin_notices', array($class, 'contributors_changed_notice'));

		// Pull remote contributor information.
		$next = wp_next_scheduled('cron_get_remote_contributors');
		if ('disabled' === get_option('bm_contributor_notice', false)) {
			// Make sure the CRON job is disabled.
			if ($next) {
				wp_unschedule_event($next, 'cron_get_remote_contributors');
			}
		}
		else {
			add_action('cron_get_remote_contributors', array($class, 'cron_get_remote_contributors'));
			if (!$next) {
				wp_schedule_event(time(), 'hourly', 'cron_get_remote_contributors');
			}
		}

		// Register plugins page quick links if we aren't running in
		// Must-Use mode.
		if (!BLOBMIMES_MUST_USE) {
			add_filter('plugin_action_links_' . plugin_basename(BLOBMIMES_INDEX), array($class, 'plugin_action_links'));
		}
	}

Register Actions and Filters

@return void Nothing.


public static function plugin_action_links($links) {
		if (current_user_can('manage_options')) {
			$links[] = '' . __('Debug File Validation', 'blob-mimes') . '';
		}

		$links[] = '' . esc_html__('Documentation', 'blob-mimes') . '';

		return $links;
	}

'<a href="https://github.com/Blobfolio/blob-mimes/tree/master/wp" target="_blank" rel="noopener">'

Plugin Action Links

Add a few links to the plugins page so people can more easily
find what they're looking for.

@param array $links Links.
@return array Links.


public static function get_version() {
		if (is_null(static::$version)) {
			$plugin_data = get_plugin_data(BLOBMIMES_INDEX, false, false);
			if (isset($plugin_data['Version'])) {
				static::$version = $plugin_data['Version'];
			}
			else {
				static::$version = '0.0';
			}
		}

		return static::$version;
	}

public static function get_version ( ) { if ( is_null ( static :: $ version ) ) { $ plugin_data = get_plugin_data ( BLOBMIMES_INDEX , false , false ) ; if ( isset ( $ plugin_data [ 'Version' ] ) ) { static :: $ version = $ plugin_data [ 'Version' ] ; } else { static :: $ version = '0.0' ; } } return static :: $ version ; }

Get Plugin Version

@return string Version.


public static function get_remote_version() {
		if (is_null(static::$remote_version)) {
			$response = plugins_api(
				'plugin_information',
				array('slug'=>'blob-mimes')
			);
			if (
				!is_wp_error($response) &&
				is_a($response, 'stdClass') &&
				isset($response->version)
			) {
				static::$remote_version = $response->version;
				static::$remote_home = $response->homepage;
			}
			else {
				static::$remote_version = '0.0';
			}
		}

		return static::$remote_version;
	}

public static function get_remote_version ( ) { if ( is_null ( static :: $ remote_version ) ) { $ response = plugins_api ( 'plugin_information' , array ( 'slug' => 'blob-mimes' ) ) ; if ( ! is_wp_error ( $ response ) && is_a ( $ response , 'stdClass' ) && isset ( $ response -> version ) ) { static :: $ remote_version = $ response -> version ; static :: $ remote_home = $ response -> homepage ; } else { static :: $ remote_version = '0.0' ; } } return static :: $ remote_version ; }

Get Remote Version

@return string Version.


public static function check_filetype_and_ext($checked, $file, $filename, $mimes) {
		// We don't care what WP has already done.
		$proper_filename = false;

		// Do basic extension validation and MIME mapping.
		$wp_filetype = mime::check_real_filetype($file, $filename, $mimes);
		$ext = $wp_filetype['ext'];
		$type = $wp_filetype['type'];

		// We can't do any further validation without a file to work with.
		if (!@file_exists($file)) {
			return compact('ext', 'type', 'proper_filename');
		}

		// If the type is valid, should we be renaming the file?
		if (false !== $ext && false !== $type) {
			$new_filename = mime::update_filename_extension($filename, $ext);
			if ($filename !== $new_filename) {
				$proper_filename = $new_filename;
			}
		}

		return compact('ext', 'type', 'proper_filename');
	}

Override Upload File Validation

This hooks into wp_check_filetype_and_ext() to improve its
determinations.

@see wp_check_filetype_and_ext()

@param array $checked Previous check status.
@param string $file File path.
@param string $filename File name.
@param array $mimes Mimes.
@return array Checked status.


public static function check_filetype_and_ext_svg($checked, $file, $filename, $mimes) {
		// Only need to do something if the type is SVG.
		if ('image/svg+xml' === $checked['type']) {
			try {
				$contents = @file_get_contents($file);
				$contents = svg::sanitize($contents);

				// Overwrite the contents if we're good.
				if (is_string($contents) && $contents) {
					@file_put_contents($file, $contents);

					// In case it got renamed somewhere along the way.
					if ($checked['proper_filename']) {
						$checked['proper_filename'] = mime::update_filename_extension($checked['proper_filename'], '.svg');
					}
				}
				// Otherwise just fail the download.
				else {
					$checked['type'] = $checked['ext'] = false;
				}
			} catch (\Throwable $e) {
				error_log($e->getMessage());
				$checked['type'] = $checked['ext'] = false;
			} catch (\Exception $e) {
				$checked['type'] = $checked['ext'] = false;
			}
		}

		return $checked;
	}

Sanitize SVG Uploads

This is triggered after our general content-based fixer, so if
something is claiming to be an SVG here, it should actually be
one.

@see wp_check_filetype_and_ext()

@param array $checked Previous check status.
@param string $file File path.
@param string $filename File name.
@param array $mimes Mimes.
@return array Checked status.


protected static function parse_readme_contributors($file) {
		if (!$file || !@is_file($file)) {
			return false;
		}

		require_once (ABSPATH . 'wp-admin/includes/file.php');

		// This can actually be parsed the same way plugin index files
		// are. Neat!
		$headers = get_file_data($file, array('Contributors'=>'Contributors'));
		if (isset($headers['Contributors'])) {
			// These are comma-separated, so let's array-ize them and
			// clean it up a bit.
			$headers['Contributors'] = explode(',', $headers['Contributors']);
			foreach ($headers['Contributors'] as $k=>$v) {
				$headers['contributors'][$k] = trim($v);
				if (!$v) {
					unset($headers['contributors'][$k]);
				}
			}

			// We should have at least one!
			if (count($headers['contributors'])) {
				$headers['contributors'] = array_unique($headers['contributors']);
				sort($headers['contributors']);
				return $headers['contributors'];
			}
		}

		// No go.
		return false;
	}

Parse Readme Contributors

@param string $file File.
@return array|bool Contributors or false.


public static function get_plugin_slug_by_path($path) {
		if (is_string($path) && $path) {
			$slug = $path;
			while (false !== strpos($slug, '/')) {
				$slug = dirname($slug);
			}
			$slug = preg_replace('/\.php$/i', '', $slug);

			return $slug ? $slug : false;
		}

		return false;
	}

public static function get_plugin_slug_by_path ( $ path ) { if ( is_string ( $ path ) && $ path ) { $ slug = $ path ; while ( false !== strpos ( $ slug , '/' ) ) { $ slug = dirname ( $ slug ) ; } $ slug = preg_replace ( '/\.php$/i' , '' , $ slug ) ; return $ slug ? $ slug : false ; } return false ; }

Extract Plugin Slug From Path

@param string $path Path.
@return string|bool Slug or false.


public static function cron_get_remote_contributors() {
		require_once(ABSPATH . 'wp-admin/includes/plugin.php');
		$plugins = get_plugins();
		$out = array();

		// We'll also keep track of plugins that aren't hosted on
		// WP.org. This might change, so we'll periodically rebuild the
		// list.
		$save_invalid = false;
		if (false === ($invalid = get_transient('bm_external_plugins'))) {
			$save_invalid = true;
			$invalid = array();
		}

		foreach ($plugins as $k=>$v) {
			// Can't check it.
			if (
				false === ($slug = static::get_plugin_slug_by_path($k)) ||
				isset($invalid[$slug])
			) {
				continue;
			}

			// The plugins_api() function does not fully support the
			// API spec, so we have to do this manually.
			$url = sprintf(static::PLUGIN_API, $slug);
			$response = wp_remote_get(
				$url,
				array(
					'timeout'=>3,
				)
			);
			if (200 === wp_remote_retrieve_response_code($response)) {
				$body = wp_remote_retrieve_body($response);
				$body = json_decode($body, true);
				if ($body) {
					// If WP returned an error, note the slug so we can
					// avoid checking it in the future.
					if (isset($body['error'])) {
						$invalid[$slug] = true;
						$save_invalid = true;
						continue;
					}

					if (
						isset($body['contributors']) &&
						is_array($body['contributors']) &&
						count($body['contributors'])
					) {
						ksort($body['contributors']);
						$out[$slug] = array_keys($body['contributors']);
					}
				}
			}
		}

		// Save the contributors.
		update_option('bm_remote_contributors', $out);

		// Save the invalid plugins.
		if ($save_invalid) {
			set_transient('bm_external_plugins', $invalid, DAY_IN_SECONDS);
		}
	}

Pull Plugin Contributors

This is a simple CRON job that will pull contributor information
for any installed plugins so we have that data for later
reference.

@return void Nothing.


private function validate()
    {
        $file = $this->file;

        if (!is_file($file)) {
            throw new \RuntimeException(sprintf("'%s' is not a file", $file));
        }

        if (!is_readable($file)) {
            // @codeCoverageIgnoreStart
            throw new \RuntimeException(sprintf("'%s' is not a readable file", $file));
            // @codeCoverageIgnoreEnd
        }
    }

private
function
validate
(
)
{
$
file
=
$
this
->
file
;
if
(
!
is_file
(
$
file
)
)
{
throw
new
\
RuntimeException
(
sprintf
(
"'%s' is not a file"
,
$
file
)
)
;
}
if
(
!
is_readable
(
$
file
)
)
{
// @codeCoverageIgnoreStart
throw
new
\
RuntimeException
(
sprintf
(
"'%s' is not a readable file"
,
$
file
)
)
;
// @codeCoverageIgnoreEnd
}
}

Validates the file passed to see if it is a file and is readable

@throws \RuntimeException If the file passed is not a file
@throws \RuntimeException If the file passed is not readable