public function setZoomControl()
    {
        $args = func_get_args();

        if (isset($args[0]) && ($args[0] instanceof ZoomControl)) {
            $this->zoomControl = $args[0];
            $this->mapOptions['zoomControl'] = true;
        } elseif ((isset($args[0]) && is_string($args[0])) && (isset($args[1]) && is_string($args[1]))) {
            if ($this->zoomControl === null) {
                $this->zoomControl = new ZoomControl();
            }

            $this->zoomControl->setControlPosition($args[0]);
            $this->zoomControl->setZoomControlStyle($args[1]);

            $this->mapOptions['zoomControl'] = true;
        } elseif (!isset($args[0])) {
            $this->zoomControl = null;

            if (isset($this->mapOptions['zoomControl'])) {
                unset($this->mapOptions['zoomControl']);
            }
        } else {
            throw MapException::invalidZoomControl();
        }
    }

public function setZoomControl ( ) { $ args = func_get_args ( ) ; if ( isset ( $ args [ 0 ] ) && ( $ args [ 0 ] instanceof ZoomControl ) ) { $ this -> zoomControl = $ args [ 0 ] ; $ this -> mapOptions [ 'zoomControl' ] = true ; } elseif ( ( isset ( $ args [ 0 ] ) && is_string ( $ args [ 0 ] ) ) && ( isset ( $ args [ 1 ] ) && is_string ( $ args [ 1 ] ) ) ) { if ( $ this -> zoomControl === null ) { $ this -> zoomControl = new ZoomControl ( ) ; } $ this -> zoomControl -> setControlPosition ( $ args [ 0 ] ) ; $ this -> zoomControl -> setZoomControlStyle ( $ args [ 1 ] ) ; $ this -> mapOptions [ 'zoomControl' ] = true ; } elseif ( ! isset ( $ args [ 0 ] ) ) { $ this -> zoomControl = null ; if ( isset ( $ this -> mapOptions [ 'zoomControl' ] ) ) { unset ( $ this -> mapOptions [ 'zoomControl' ] ) ; } } else { throw MapException :: invalidZoomControl ( ) ; } }

Sets the map zoom control.

Available prototypes:
- function setZoomControl(Ivory\GoogleMap\Controls\ZoomControl $zoomControl = null)
- function setZoomControl(string $controlPosition, string $zoomControlStyle)

@throws \Ivory\GoogleMap\Exception\MapException If the zoom control is not valid (prototypes).


public function addMarker(Marker $marker)
    {
        $this->markerCluster->addMarker($marker);

        if ($this->autoZoom) {
            $this->bound->extend($marker);
        }
    }

public function addMarker ( Marker $ marker ) { $ this -> markerCluster -> addMarker ( $ marker ) ; if ( $ this -> autoZoom ) { $ this -> bound -> extend ( $ marker ) ; } }

Add a map marker.

@param \Ivory\GoogleMap\Overlays\Marker $marker The marker to add.


public function addInfoWindow(InfoWindow $infoWindow)
    {
        $this->infoWindows[] = $infoWindow;

        if ($this->autoZoom) {
            $this->bound->extend($infoWindow);
        }
    }

public function addInfoWindow ( InfoWindow $ infoWindow ) { $ this -> infoWindows [ ] = $ infoWindow ; if ( $ this -> autoZoom ) { $ this -> bound -> extend ( $ infoWindow ) ; } }

Add a map info window.

@param \Ivory\GoogleMap\Overlays\InfoWindow $infoWindow The info window to add.


public function addPolyline(Polyline $polyline)
    {
        $this->polylines[] = $polyline;

        if ($this->autoZoom) {
            $this->bound->extend($polyline);
        }
    }

public function addPolyline ( Polyline $ polyline ) { $ this -> polylines [ ] = $ polyline ; if ( $ this -> autoZoom ) { $ this -> bound -> extend ( $ polyline ) ; } }

Add a map polyline.

@param \Ivory\GoogleMap\Overlays\Polyline The polyline to add.


public function addEncodedPolyline(EncodedPolyline $encodedPolyline)
    {
        $this->encodedPolylines[] = $encodedPolyline;

        if ($this->autoZoom) {
            $this->bound->extend($encodedPolyline);
        }
    }

public function addEncodedPolyline ( EncodedPolyline $ encodedPolyline ) { $ this -> encodedPolylines [ ] = $ encodedPolyline ; if ( $ this -> autoZoom ) { $ this -> bound -> extend ( $ encodedPolyline ) ; } }

Adds an encoded polyline to the map.

@param \Ivory\GoogleMap\Overlays\EncodedPolyline $encodedPolyline The encoded polyline to add.


public function addPolygon(Polygon $polygon)
    {
        $this->polygons[] = $polygon;

        if ($this->autoZoom) {
            $this->bound->extend($polygon);
        }
    }

public function addPolygon ( Polygon $ polygon ) { $ this -> polygons [ ] = $ polygon ; if ( $ this -> autoZoom ) { $ this -> bound -> extend ( $ polygon ) ; } }

Add a map polygon.

@param \Ivory\GoogleMap\Overlays\Polygon $polygon The polygon to add.


public function addRectangle(Rectangle $rectangle)
    {
        $this->rectangles[] = $rectangle;

        if ($this->autoZoom) {
            $this->bound->extend($rectangle);
        }
    }

public function addRectangle ( Rectangle $ rectangle ) { $ this -> rectangles [ ] = $ rectangle ; if ( $ this -> autoZoom ) { $ this -> bound -> extend ( $ rectangle ) ; } }

Add a map rectangle to the map.

@param \Ivory\GoogleMap\Overlays\Rectangle $rectangle The rectangle to add.


public function addCircle(Circle $circle)
    {
        $this->circles[] = $circle;

        if ($this->autoZoom) {
            $this->bound->extend($circle);
        }
    }

public function addCircle ( Circle $ circle ) { $ this -> circles [ ] = $ circle ; if ( $ this -> autoZoom ) { $ this -> bound -> extend ( $ circle ) ; } }

Add a circle to the map.

@param \Ivory\GoogleMap\Overlays\Circle $circle The circle to add.


public function addGroundOverlay(GroundOverlay $groundOverlay)
    {
        $this->groundOverlays[] = $groundOverlay;

        if ($this->autoZoom) {
            $this->bound->extend($groundOverlay);
        }
    }

public function addGroundOverlay ( GroundOverlay $ groundOverlay ) { $ this -> groundOverlays [ ] = $ groundOverlay ; if ( $ this -> autoZoom ) { $ this -> bound -> extend ( $ groundOverlay ) ; } }

Add a ground overlay to the map.

@param \Ivory\GoogleMapBundle\Model\Overlays\GroupOverlay $groundOverlay The ground overlay to add.


public function set($value = null, $ttl = null)
    {
        $now = new DateTime();

        // whoever came up with the idea of allowing int AND datetime...
        // so lets convert this to an int (its a time to live, not a date to delete ffs)
        if ($ttl instanceof DateTime) {
            $ttl = $ttl->getTimestamp() - $now->getTimestamp();
        }

        $data = [
            "updated" => $now,
            "value" => $value,
            "key" => $this->key,
            "ttl" => $ttl
        ];

        return false !== file_put_contents($this->filename, serialize($data));
    }

Stores a value into the cache.

The $value argument may be any item that can be serialized by PHP,
although the method of serialization is left up to the Implementing
Library.

Implementing Libraries MAY provide a default TTL if one is not specified.
If no TTL is specified and no default TTL has been set, the TTL MUST
be set to the maximum possible duration of the underlying storage
mechanism, or permanent if possible.

@param mixed $value
The serializable value to be stored.
@param int|DateTime $ttl
- If an integer is passed, it is interpreted as the number of seconds
after which the item MUST be considered expired.
- If a DateTime object is passed, it is interpreted as the point in
time after which the the item MUST be considered expired.
- If no value is passed, a default value MAY be used. If none is set,
the value should be stored permanently or for as long as the
implementation allows.
@return bool
Returns true if the item was successfully saved, or false if there was
an error.


public function delete()
    {
        if (file_exists($this->filename)) {
            unlink($this->filename);
        }
        $this->hit = false;
        $this->value = null;
        return $this;
    }

public function delete ( ) { if ( file_exists ( $ this -> filename ) ) { unlink ( $ this -> filename ) ; } $ this -> hit = false ; $ this -> value = null ; return $ this ; }

Removes the current key from the cache.

@return \Psr\Cache\ItemInterface
The current item.

Removes the current key from the cache .


public function setAvoidHighways($avoidHighways = null)
    {
        if (!is_bool($avoidHighways) && ($avoidHighways !== null)) {
            throw DirectionsException::invalidDirectionsRequestAvoidHighways();
        }

        $this->avoidHighways = $avoidHighways;
    }

public function setAvoidHighways ( $ avoidHighways = null ) { if ( ! is_bool ( $ avoidHighways ) && ( $ avoidHighways !== null ) ) { throw DirectionsException :: invalidDirectionsRequestAvoidHighways ( ) ; } $ this -> avoidHighways = $ avoidHighways ; }

Sets if the the directions request avoids hightways.

@param boolean $avoidHighways TRUE if the directions request avoids hightways else FALSE.

@throws \Ivory\GoogleMap\Exception\DirectionsException If the avoid highways flag is not valid.

Sets if the the directions request avoids hightways .


public function setAvoidTolls($avoidTolls = null)
    {
        if (!is_bool($avoidTolls) && ($avoidTolls !== null)) {
            throw DirectionsException::invalidDirectionsRequestAvoidTolls();
        }

        $this->avoidTolls = $avoidTolls;
    }

public function setAvoidTolls ( $ avoidTolls = null ) { if ( ! is_bool ( $ avoidTolls ) && ( $ avoidTolls !== null ) ) { throw DirectionsException :: invalidDirectionsRequestAvoidTolls ( ) ; } $ this -> avoidTolls = $ avoidTolls ; }

Sets if the the directions request avoids tolls.

@param boolean $avoidTolls TRUE if the directions request avoids tolls else FALSE.

@throws \Ivory\GoogleMap\Exception\DirectionsException If the avoid tolls flag is not valid.

Sets if the the directions request avoids tolls .


public function setDestination()
    {
        $args = func_get_args();

        if (isset($args[0]) && is_string($args[0])) {
            $this->destination = $args[0];
        } elseif (isset($args[0]) && ($args[0] instanceof Coordinate)) {
            $this->destination = $args[0];
        } elseif ((isset($args[0]) && is_numeric($args[0])) && (isset($args[1]) && is_numeric($args[1]))) {
            if ($this->destination === null) {
                $this->destination = new Coordinate();
            }

            $this->destination->setLatitude($args[0]);
            $this->destination->setLongitude($args[1]);

            if (isset($args[2]) && is_bool($args[2])) {
                $this->destination->setNoWrap($args[2]);
            }
        } else {
            throw DirectionsException::invalidDirectionsRequestDestination();
        }
    }

public function setDestination ( ) { $ args = func_get_args ( ) ; if ( isset ( $ args [ 0 ] ) && is_string ( $ args [ 0 ] ) ) { $ this -> destination = $ args [ 0 ] ; } elseif ( isset ( $ args [ 0 ] ) && ( $ args [ 0 ] instanceof Coordinate ) ) { $ this -> destination = $ args [ 0 ] ; } elseif ( ( isset ( $ args [ 0 ] ) && is_numeric ( $ args [ 0 ] ) ) && ( isset ( $ args [ 1 ] ) && is_numeric ( $ args [ 1 ] ) ) ) { if ( $ this -> destination === null ) { $ this -> destination = new Coordinate ( ) ; } $ this -> destination -> setLatitude ( $ args [ 0 ] ) ; $ this -> destination -> setLongitude ( $ args [ 1 ] ) ; if ( isset ( $ args [ 2 ] ) && is_bool ( $ args [ 2 ] ) ) { $ this -> destination -> setNoWrap ( $ args [ 2 ] ) ; } } else { throw DirectionsException :: invalidDirectionsRequestDestination ( ) ; } }

Sets the directions request destination.

Available prototypes:
- function setDestination(string $destination)
- function setDestination(Ivory\GoogleMap\Base\Coordinate $destination)
- function setDestination(double $latitude, double $longitude, boolean $noWrap)

@throws \Ivory\GoogleMap\Exception\DirectionsException If the destination is not valid (prototypes).

Sets the directions request destination .


public function setOptimizeWaypoints($optimizeWaypoints = null)
    {
        if (!is_bool($optimizeWaypoints) && ($optimizeWaypoints !== null)) {
            throw DirectionsException::invalidDirectionsRequestOptimizeWaypoints();
        }

        $this->optimizeWaypoints = $optimizeWaypoints;
    }

Sets if the directions request optimizes waypoints.

@param boolean $optimizeWaypoints TRUE if the directions request optimizes waypoints else FALSE.

@throws \Ivory\GoogleMap\Exception\DirectionsException If the optimize waypoints flag is not valid.

Sets if the directions request optimizes waypoints .


public function setOrigin()
    {
        $args = func_get_args();

        if (isset($args[0]) && is_string($args[0])) {
            $this->origin = $args[0];
        } elseif (isset($args[0]) && ($args[0] instanceof Coordinate)) {
            $this->origin = $args[0];
        } elseif ((isset($args[0]) && is_numeric($args[0])) && (isset($args[1]) && is_numeric($args[1]))) {
            if ($this->origin === null) {
                $this->origin = new Coordinate();
            }

            $this->origin->setLatitude($args[0]);
            $this->origin->setLongitude($args[1]);

            if (isset($args[2]) && is_bool($args[2])) {
                $this->origin->setNoWrap($args[2]);
            }
        } else {
            throw DirectionsException::invalidDirectionsRequestOrigin();
        }
    }

public function setOrigin ( ) { $ args = func_get_args ( ) ; if ( isset ( $ args [ 0 ] ) && is_string ( $ args [ 0 ] ) ) { $ this -> origin = $ args [ 0 ] ; } elseif ( isset ( $ args [ 0 ] ) && ( $ args [ 0 ] instanceof Coordinate ) ) { $ this -> origin = $ args [ 0 ] ; } elseif ( ( isset ( $ args [ 0 ] ) && is_numeric ( $ args [ 0 ] ) ) && ( isset ( $ args [ 1 ] ) && is_numeric ( $ args [ 1 ] ) ) ) { if ( $ this -> origin === null ) { $ this -> origin = new Coordinate ( ) ; } $ this -> origin -> setLatitude ( $ args [ 0 ] ) ; $ this -> origin -> setLongitude ( $ args [ 1 ] ) ; if ( isset ( $ args [ 2 ] ) && is_bool ( $ args [ 2 ] ) ) { $ this -> origin -> setNoWrap ( $ args [ 2 ] ) ; } } else { throw DirectionsException :: invalidDirectionsRequestOrigin ( ) ; } }

Sets the directions request origin.

Available prototypes:
- function setOrigin(string $destination)
- function setOrigin(Ivory\GoogleMap\Base\Coordinate $destination)
- function setOrigin(double $latitude, double $longitude, boolean $noWrap)

@throws \Ivory\GoogleMap\Exception\DirectionsException If the origin is not valid (prototypes).


public function setProvideRouteAlternatives($provideRouteAlternatives = null)
    {
        if (!is_bool($provideRouteAlternatives) && ($provideRouteAlternatives !== null)) {
            throw DirectionsException::invalidDirectionsRequestProvideRouteAlternatives();
        }

        $this->provideRouteAlternatives = $provideRouteAlternatives;
    }

Sets if the directions request provides route alternatives.

@param boolean $provideRouteAlternatives TRUE if the directions request provides route alternatives else FALSE.

@throws \Ivory\GoogleMap\Exception\DirectionsException If the provide route alternatives flag is not valid.

Sets if the directions request provides route alternatives .


public function setRegion($region = null)
    {
        if ((!is_string($region) || (strlen($region) !== 2)) && ($region !== null)) {
            throw DirectionsException::invalidDirectionsRequestRegion();
        }

        $this->region = $region;
    }

public function setRegion ( $ region = null ) { if ( ( ! is_string ( $ region ) || ( strlen ( $ region ) !== 2 ) ) && ( $ region !== null ) ) { throw DirectionsException :: invalidDirectionsRequestRegion ( ) ; } $ this -> region = $ region ; }

Sets the directions request region.

@param string $region The directions request region.

@throws \Ivory\GoogleMap\Exception\DirectionsException If the region is not valid.


public function setLanguage($language = null)
    {
        if ((!is_string($language) || ((strlen($language) !== 2) && (strlen($language) !== 5))) && ($language !== null)) {
            throw DirectionsException::invalidDirectionsRequestLanguage();
        }

        $this->language = $language;
    }

public function setLanguage ( $ language = null ) { if ( ( ! is_string ( $ language ) || ( ( strlen ( $ language ) !== 2 ) && ( strlen ( $ language ) !== 5 ) ) ) && ( $ language !== null ) ) { throw DirectionsException :: invalidDirectionsRequestLanguage ( ) ; } $ this -> language = $ language ; }

Sets the directions request language.

@param string $language The directions request language.

@throws \Ivory\GoogleMap\Exception\DirectionsException If the language is not valid.


public function setTravelMode($travelMode = null)
    {
        if (!in_array($travelMode, TravelMode::getTravelModes()) && ($travelMode !== null)) {
            throw DirectionsException::invalidDirectionsRequestTravelMode();
        }

        $this->travelMode = $travelMode;
    }

public function setTravelMode ( $ travelMode = null ) { if ( ! in_array ( $ travelMode , TravelMode :: getTravelModes ( ) ) && ( $ travelMode !== null ) ) { throw DirectionsException :: invalidDirectionsRequestTravelMode ( ) ; } $ this -> travelMode = $ travelMode ; }

Sets the directions request travel mode.

@param string $travelMode The directions request travel mode.

@throws \Ivory\GoogleMap\Exception\DirectionsException If the travel mode is not valid.

Sets the directions request travel mode .


public function setUnitSystem($unitSystem = null)
    {
        if (!in_array($unitSystem, UnitSystem::getUnitSystems()) && ($unitSystem !== null)) {
            throw DirectionsException::invalidDirectionsRequestUnitSystem();
        }

        $this->unitSystem = $unitSystem;
    }

public function setUnitSystem ( $ unitSystem = null ) { if ( ! in_array ( $ unitSystem , UnitSystem :: getUnitSystems ( ) ) && ( $ unitSystem !== null ) ) { throw DirectionsException :: invalidDirectionsRequestUnitSystem ( ) ; } $ this -> unitSystem = $ unitSystem ; }

Sets  the directions request unit system.

@param string $unitSystem The directions request unit system.

@throws \Ivory\GoogleMap\Exception\DirectionsException If the unit system is not valid.

Sets the directions request unit system .


public function setWaypoints(array $waypoints = array())
    {
        $this->waypoints = array();

        foreach ($waypoints as $waypoint) {
            $this->addWaypoint($waypoint);
        }
    }

public function setWaypoints ( array $ waypoints = array ( ) ) { $ this -> waypoints = array ( ) ; foreach ( $ waypoints as $ waypoint ) { $ this -> addWaypoint ( $ waypoint ) ; } }

Sets the directions request waypoints.

@param array $waypoints The directions request waypoints.


public function addWaypoint()
    {
        $args = func_get_args();

        if (isset($args[0]) && ($args[0] instanceof DirectionsWaypoint)) {
            $this->waypoints[] = $args[0];
        } elseif ((isset($args[0]) && is_numeric($args[0])) && (isset($args[1]) && is_numeric($args[1]))) {
            $waypoint = new DirectionsWaypoint();
            $waypoint->setLocation($args[0], $args[1]);

            if (isset($args[2]) && is_bool($args[2])) {
                $waypoint->getLocation()->setNoWrap($args[2]);
            }

            $this->waypoints[] = $waypoint;
        } elseif (isset($args[0]) && (is_string($args[0]) || ($args[0] instanceof Coordinate))) {
            $waypoint = new DirectionsWaypoint();
            $waypoint->setLocation($args[0]);

            $this->waypoints[] = $waypoint;
        } else {
            throw DirectionsException::invalidDirectionsRequestWaypoint();
        }
    }

public function addWaypoint ( ) { $ args = func_get_args ( ) ; if ( isset ( $ args [ 0 ] ) && ( $ args [ 0 ] instanceof DirectionsWaypoint ) ) { $ this -> waypoints [ ] = $ args [ 0 ] ; } elseif ( ( isset ( $ args [ 0 ] ) && is_numeric ( $ args [ 0 ] ) ) && ( isset ( $ args [ 1 ] ) && is_numeric ( $ args [ 1 ] ) ) ) { $ waypoint = new DirectionsWaypoint ( ) ; $ waypoint -> setLocation ( $ args [ 0 ] , $ args [ 1 ] ) ; if ( isset ( $ args [ 2 ] ) && is_bool ( $ args [ 2 ] ) ) { $ waypoint -> getLocation ( ) -> setNoWrap ( $ args [ 2 ] ) ; } $ this -> waypoints [ ] = $ waypoint ; } elseif ( isset ( $ args [ 0 ] ) && ( is_string ( $ args [ 0 ] ) || ( $ args [ 0 ] instanceof Coordinate ) ) ) { $ waypoint = new DirectionsWaypoint ( ) ; $ waypoint -> setLocation ( $ args [ 0 ] ) ; $ this -> waypoints [ ] = $ waypoint ; } else { throw DirectionsException :: invalidDirectionsRequestWaypoint ( ) ; } }

Adds a waypoint to the directions request.

Available prototypes:
- function addWaypoint(Ivory\GoogleMap\Services\Directions\DirectionsWaypoint $waypoint)
- function addWaypoint(string $location)
- function addWaypoint(double $latitude, double $longitude, boolean $noWrap)
- function addWaypoint(Ivory\GoogleMap\Base\Coordinate $location)

@throws \Ivory\GoogleMap\Exception\DirectionsException If the waypoint is not valid (prototypes).

Adds a waypoint to the directions request .


public function isValid()
    {
        $isValid = $this->hasDestination() && $this->hasOrigin();

        for ($i = 0; $isValid && ($i < count($this->waypoints)); $i++) {
            $isValid = $this->waypoints[$i]->isValid();
        }

        if ($this->getTravelMode() === TravelMode::TRANSIT) {
            $isValid = $this->hasArrivalTime() || $this->hasDepartureTime();
        }

        return $isValid;
    }

public function isValid ( ) { $ isValid = $ this -> hasDestination ( ) && $ this -> hasOrigin ( ) ; for ( $ i = 0 ; $ isValid && ( $ i < count ( $ this -> waypoints ) ) ; $ i ++ ) { $ isValid = $ this -> waypoints [ $ i ] -> isValid ( ) ; } if ( $ this -> getTravelMode ( ) === TravelMode :: TRANSIT ) { $ isValid = $ this -> hasArrivalTime ( ) || $ this -> hasDepartureTime ( ) ; } return $ isValid ; }

Checks if the directions request is valid.

@return boolean TRUE if the directions request is valid else FALSE.

Checks if the directions request is valid .


public function postJson(string $url, $data, array $args = []): \StdClass
    {
        return $this->submitJson($url, $data, array_merge($args, ['method' => 'POST']));
    }

public function postJson ( string $ url , $ data , array $ args = [ ] ) : \ StdClass { return $ this -> submitJson ( $ url , $ data , array_merge ( $ args , [ 'method' => 'POST' ] ) ) ; }

POST JSON data.

@since 170124.74961 Initial release.

@param string $url  API URL.
@param mixed  $data Data to POST.
@param array  $args Additional args.

@return \StdClass Including a boolean `success` property.


public function logIssue($data = [], string $note = '', string $event = ''): Exception
    {
        if (func_num_args() === 1 && is_string($data)) {
            $note = $data; // Use data as note.
            $data = []; // Data empty in this case.
        }
        $event = $event ?: $this->traceLogEventTrigger();

        if (mb_strpos($event, '#') === false) {
            $event .= '#issue';
        } // Assume this is an issue.

        $this->maybeLog($data, $note, $event);

        return new Exception($note ? $note : $event);
    }

public
function
logIssue
(
$
data
=
[
]
,
string
$
note
=
''
,
string
$
event
=
''
)
:
Exception
{
if
(
func_num_args
(
)
===
1
&&
is_string
(
$
data
)
)
{
$
note
=
$
data
;
// Use data as note.
$
data
=
[
]
;
// Data empty in this case.
}
$
event
=
$
event
:
$
this
->
traceLogEventTrigger
(
)
;
if
(
mb_strpos
(
$
event
,
'#'
)
===
false
)
{
$
event
.=
'#issue'
;
}
// Assume this is an issue.
$
this
->
maybeLog
(
$
data
,
$
note
,
$
event
)
;
return
new
Exception
(
$
note
$
note
:
$
event
)
;
}

Log issue & generate exception.

@since 160522 Debugging utilities.

@param mixed  $data  Data to log (e.g., {@link vars()}).
@param string $note  A brief note or description of the issue.
@param string $event Event name (e.g., {@link __METHOD__}).

@return Exception An exception ready to be thrown.

@internal If only one parameter is passed and it's a string, it's treated as the `$note`.


public function logReview($data = [], string $note = '', string $event = ''): int
    {
        if (func_num_args() === 1 && is_string($data)) {
            $note = $data; // Use data as note.
            $data = []; // Data empty in this case.
        }
        $event = $event ?: $this->traceLogEventTrigger();

        if (mb_strpos($event, '#') === false) {
            $event .= '#review';
        } // Assume this is for review.

        return $this->maybeLog($data, $note, $event);
    }

public
function
logReview
(
$
data
=
[
]
,
string
$
note
=
''
,
string
$
event
=
''
)
:
int
{
if
(
func_num_args
(
)
===
1
&&
is_string
(
$
data
)
)
{
$
note
=
$
data
;
// Use data as note.
$
data
=
[
]
;
// Data empty in this case.
}
$
event
=
$
event
:
$
this
->
traceLogEventTrigger
(
)
;
if
(
mb_strpos
(
$
event
,
'#'
)
===
false
)
{
$
event
.=
'#review'
;
}
// Assume this is for review.
return
$
this
->
maybeLog
(
$
data
,
$
note
,
$
event
)
;
}

Log for review.

@since 160522 Debugging utilities.

@param mixed  $data  Data to log (e.g., {@link vars()}).
@param string $note  A brief note or description of the issue.
@param string $event Event name (e.g., {@link __METHOD__}).

@return int Total number of bytes written.

@internal If only one parameter is passed and it's a string, it's treated as the `$note`.


protected function writeLogFileLines(string $event, array $lines): int
    {
        if (!$lines) { // No lines?
            return 0; // Stop; nothing to do here.
        }
        $this->prepareLogsDir(); // Prepares (and secures).

        if (mb_strpos($event, '#') !== false) {
            $file_name = mb_strstr($event, '#');
            $file_name = $this->c::nameToSlug($file_name);
            $file_name .= '.log'; // Add extension now.
        }
        $file_name    = $file_name ?: 'debug.log';
        $process_file = $this->logs_dir.'/process.'.$file_name;
        $file         = $this->logs_dir.'/'.$file_name;

        $this->maybeRotateLogFiles($file);

        $entry = implode("\n", $lines)."\n\n".str_repeat('-', 3)."\n\n";

        if (!isset($this->first_process_writes[$process_file])) {
            $this->first_process_writes[$process_file] = -1;
            @unlink($process_file); // First-process write.
        } // ↑ Empty file on the first write in each process.

        file_put_contents($process_file, $entry, LOCK_EX | FILE_APPEND);
        return (int) file_put_contents($file, $entry, LOCK_EX | FILE_APPEND);
    }

Write lines to log file.

@since 160522 Debugging utilities.

@param string $event Event name.
@param array  $lines Log entry lines.

@return int Total number of bytes written.


protected function cleanLogEvent(string $event): string
    {
        if (($classes_pos = mb_strripos($event, '\\Classes\\')) !== false) {
            $event = mb_substr($event, $classes_pos + 9);
        } // This chops off `*\Classes\` from `__METHOD__`.
        $event = str_replace($this->App->namespace, '', $event);

        return $event = $this->c::mbTrim($event, '', '\\');
    }

Cleans log event name.

@since 160522 Debugging utilities.

@param string $event Log event name.

@return string Cleaned log event name.


protected function maybeRotateLogFiles(string $file)
    {
        if (!$file || !is_file($file)) {
            return; // Nothing to do at this time.
        } elseif (filesize($file) < $this->max_log_file_size) {
            return; // Nothing to do at this time.
        } // Only rotate when log file becomes large.

        rename($file, $this->uniqueSuffixLogFile($file));

        foreach ($this->c::dirRegexRecursiveIterator($this->logs_dir, '/\.log$/ui') as $_Resource) {
            if ($_Resource->isFile() && $_Resource->getMTime() < $this->max_log_file_age) {
                unlink($_Resource->getPathname());
            }
        } // unset($_Resource); // Housekeeping.
    }

Maybe rotate log files.

@since 160522 Debugging utilities.

@param string $file Absolute file path.


public function response(string $url, array $args = []): \StdClass
    {
        return $this->curl($url, array_merge($args, ['return' => 'object']));
    }

public function response ( string $ url , array $ args = [ ] ) : \ StdClass { return $ this -> curl ( $ url , array_merge ( $ args , [ 'return' => 'object' ] ) ) ; }

Remote HTTP communication.

@param string $url  A URL to connect to.
@param array  $args Connection arguments.

@return \StdClass Always returns a full response.


public function parse(string $source): Contracts\Document
    {
        $content = $this->parseContent($source);
        $metadata = $this->parseMetadata($this->parseHeader($source));

        return $this->buildDocument($content, $metadata);
    }

public function parse ( string $ source ) : Contracts \ Document { $ content = $ this -> parseContent ( $ source ) ; $ metadata = $ this -> parseMetadata ( $ this -> parseHeader ( $ source ) ) ; return $ this -> buildDocument ( $ content , $ metadata ) ; }

Parse a markdown document with metadata.

@param  string  $source

@return \Kurenai\Contracts\Document

Parse a markdown document with metadata .


public function buildDocument(string $content, array $metadata): Contracts\Document
    {
        $document = $this->documentResolver;
        $document->setContent($content);
        $document->set($metadata);

        return $document;
    }

public function buildDocument ( string $ content , array $ metadata ) : Contracts \ Document { $ document = $ this -> documentResolver ; $ document -> setContent ( $ content ) ; $ document -> set ( $ metadata ) ; return $ document ; }

Build a Document from the parsed data.

@param  string  $content
@param  array   $metadata

@return \Kurenai\Contracts\Document


public function parseSection(string $source, int $offset): string
    {
        $sections = preg_split(self::SECTION_SPLITTER, $source, 2);

        if (count($sections) != 2) {
            throw new TooFewSectionsException();
        }

        return trim($sections[$offset]);
    }

public function parseSection ( string $ source , int $ offset ) : string { $ sections = preg_split ( self :: SECTION_SPLITTER , $ source , 2 ) ; if ( count ( $ sections ) != 2 ) { throw new TooFewSectionsException ( ) ; } return trim ( $ sections [ $ offset ] ) ; }

Parse a dection of the document.

@param  string  $source
@param  int  $offset

@throws \Kurenai\Exceptions\TooFewSectionsException

@return string


public function parseMetadata(string $source): array
    {
        $yaml = Yaml::parse($source);

        if (! is_array($yaml)) {
            throw new ParseException('The YAML value does not appear to be valid UTF-8.', -1, null, null);
        }

        return $yaml;
    }

Parse metadata into an array.

@param  string  $source

@return array


public function queryVar(string $key): string
    {
        if (isset($this->query_vars[$key])) {
            return $this->query_vars[$key];
        }
        $value = ''; // Initialize.

        if (isset($_REQUEST[$key])) {
            $value = (string) $_REQUEST[$key];
            $value = $this->c::unslash($value);
            $value = $this->c::mbTrim($value);
        } elseif (isset($this->rewrite_query_vars[$key])) {
            $value = $this->rewrite_query_vars[$key];
        }
        return $this->query_vars[$key] = $value;
    }

public
function
queryVar
(
string
$
key
)
:
string
{
if
(
isset
(
$
this
->
query_vars
[
$
key
]
)
)
{
return
$
this
->
query_vars
[
$
key
]
;
}
$
value
=
''
;
// Initialize.
if
(
isset
(
$
_REQUEST
[
$
key
]
)
)
{
$
value
=
(
string
)
$
_REQUEST
[
$
key
]
;
$
value
=
$
this
->
c
::
unslash
(
$
value
)
;
$
value
=
$
this
->
c
::
mbTrim
(
$
value
)
;
}
elseif
(
isset
(
$
this
->
rewrite_query_vars
[
$
key
]
)
)
{
$
value
=
$
this
->
rewrite_query_vars
[
$
key
]
;
}
return
$
this
->
query_vars
[
$
key
]
=
$
value
;
}

Parse route.

@since 161008 Route.

@param string $key Query var key.

@return string Parsed route contents.


protected function get(string $file, array $vars = [], string $dir = ''): string
    {
        $template_vars = $this->vars; // Route vars as template vars.

        if (isset($template_vars[$file])) { // File-specific vars?
            $template_vars = array_replace_recursive($template_vars, $template_vars[$file]);
        }
        $template_vars = array_replace_recursive($template_vars, $vars);
        $Template      = $this->c::getTemplate($file, $dir, ['Route' => $this]);

        return $Template->parse($template_vars);
    }

protected
function
get
(
string
$
file
,
array
$
vars
=
[
]
,
string
$
dir
=
''
)
:
string
{
$
template_vars
=
$
this
->
vars
;
// Route vars as template vars.
if
(
isset
(
$
template_vars
[
$
file
]
)
)
{
// File-specific vars?
$
template_vars
=
array_replace_recursive
(
$
template_vars
,
$
template_vars
[
$
file
]
)
;
}
$
template_vars
=
array_replace_recursive
(
$
template_vars
,
$
vars
)
;
$
Template
=
$
this
->
c
::
getTemplate
(
$
file
,
$
dir
,
[
'Route'
=>
$
this
]
)
;
return
$
Template
->
parse
(
$
template_vars
)
;
}

Get a template.

@since 161008 Route.

@param string $file Relative to templates dir.
@param array  $vars Template vars for the include.
@param string $dir  From a specific directory?

@return string Parsed template contents.


public function getRemote(array $args = []): TwitterOAuth
    {
        $default_args = $this->default_credentials;

        $args += $default_args;
        $hash = $this->remoteHash($args);

        if (isset($this->remotes[$hash])) {
            return $this->remotes[$hash];
        }
        return $this->remotes[$hash] = new TwitterOAuth(
            (string) $args['consumer_key'],
            (string) $args['consumer_secret'],
            (string) $args['access_token'],
            (string) $args['access_token_secret']
        );
    }

public function getRemote ( array $ args = [ ] ) : TwitterOAuth { $ default_args = $ this -> default_credentials ; $ args += $ default_args ; $ hash = $ this -> remoteHash ( $ args ) ; if ( isset ( $ this -> remotes [ $ hash ] ) ) { return $ this -> remotes [ $ hash ] ; } return $ this -> remotes [ $ hash ] = new TwitterOAuth ( ( string ) $ args [ 'consumer_key' ] , ( string ) $ args [ 'consumer_secret' ] , ( string ) $ args [ 'access_token' ] , ( string ) $ args [ 'access_token_secret' ] ) ; }

Get remote connection.

@since 17xxxx Twitter utils.

@param array $args Credentials.

@return TwitterOAuth Remote instance.


protected function remoteHash(array $args = []): string
    {
        $default_args = $this->default_credentials;

        $args += $default_args;
        $args        = array_intersect_key($args, $default_args);
        $args        = array_map('strval', $args);
        return $hash = sha1(serialize($args));
    }

protected function remoteHash ( array $ args = [ ] ) : string { $ default_args = $ this -> default_credentials ; $ args += $ default_args ; $ args = array_intersect_key ( $ args , $ default_args ) ; $ args = array_map ( 'strval' , $ args ) ; return $ hash = sha1 ( serialize ( $ args ) ) ; }

Get remote hash.

@since 17xxxx Twitter utils.

@param array $args Credentials.

@return string Remote hash.


public function toAscii($value)
    {
        if (is_array($value) || is_object($value)) {
            foreach ($value as $_key => &$_value) {
                $_value = $this->toAscii($_value);
            } // unset($_key, $_value);
            return $value;
        }
        if (!($string = (string) $value)) {
            return $string; // Nothing to do.
        }
        return (string) transliterator_transliterate('Any-Latin; Latin-ASCII', $string);
    }

public
function
toAscii
(
$
value
)
{
if
(
is_array
(
$
value
)
||
is_object
(
$
value
)
)
{
foreach
(
$
value
as
$
_key
=>
&
$
_value
)
{
$
_value
=
$
this
->
toAscii
(
$
_value
)
;
}
// unset($_key, $_value);
return
$
value
;
}
if
(
!
(
$
string
=
(
string
)
$
value
)
)
{
return
$
string
;
// Nothing to do.
}
return
(
string
)
transliterator_transliterate
(
'Any-Latin; Latin-ASCII'
,
$
string
)
;
}

Convert to ASCII.

@since 150424 Multibyte support.

@param mixed $value Any input value.

@return string|array|object Output value.


public static function getDistanceMatrixStatus()
    {
        return array(
            self::INVALID_REQUEST,
            self::MAX_DIMENSIONS_EXCEEDED,
            self::MAX_ELEMENTS_EXCEEDED,
            self::OK,
            self::OVER_QUERY_LIMIT,
            self::REQUEST_DENIED,
            self::UNKNOWN_ERROR,
        );
    }

public static function getDistanceMatrixStatus ( ) { return array ( self :: INVALID_REQUEST , self :: MAX_DIMENSIONS_EXCEEDED , self :: MAX_ELEMENTS_EXCEEDED , self :: OK , self :: OVER_QUERY_LIMIT , self :: REQUEST_DENIED , self :: UNKNOWN_ERROR , ) ; }

Gets the available distance matrix status.

@return array The available distance matrix status.

Gets the available distance matrix status .


public function stripLeading($value, $trim = true)
    {
        if (is_array($value) || is_object($value)) {
            foreach ($value as $_key => &$_value) {
                $_value = $this->stripLeading($_value, $trim);
            } // unset($_key, $_value);
            return $value;
        }
        if (!($string = (string) $value)) {
            return $string; // Nothing to do.
        }
        if ($trim === true) { // Default (trim).

            $_string            = $string; // Temporary copy.
            $string             = ''; // Reinitialize; rebuilding below.
            $_line_based_pieces = preg_split('/(['."\r\n".']+)/u', $_string, -1, PREG_SPLIT_DELIM_CAPTURE);

            foreach ($_line_based_pieces as $_index => $_piece) {
                if (!preg_match('/^\s*$/u', $_piece)) {
                    $string = implode(array_slice($_line_based_pieces, $_index));
                    break; // Found the first line that's not just whitespace.
                }
            } // unset($_string, $_line_based_pieces, $_piece); // Housekeeping.
            $string = $this->c::mbRTrim($string); // Now ditch any trailing whitespace.
            //
        } elseif ($trim === 'html-trim') { // HTML trimming in this case.

            $_string            = $string; // Temporary copy.
            $string             = ''; // Reinitialize; rebuilding below.
            $_line_based_pieces = preg_split('/(['."\r\n".']+)/u', $_string, -1, PREG_SPLIT_DELIM_CAPTURE);

            if (($html_whitespace = &$this->cacheKey(__FUNCTION__.'_html_whitespace')) === null) {
                $html_whitespace = implode('|', $this::HTML_WHITESPACE);
            }
            foreach ($_line_based_pieces as $_index => $_piece) {
                if (!preg_match('/^(?:'.$html_whitespace.')*$/u', $_piece)) {
                    $string = implode(array_slice($_line_based_pieces, $_index));
                    break; // Found the first line that's not just whitespace.
                }
            } // unset($_string, $_line_based_pieces, $_piece); // Housekeeping.
            $string = $this->c::htmlRTrim($string); // Now ditch any trailing whitespace.
        }
        if (!$string || !preg_match('/^(?<indentation>['."\t".' ]+)/u', $string, $_m)) {
            return $string; // Empty, or no indentation. Nothing to do.
        }
        return $string = preg_replace('/^'.$_m['indentation'].'/um', '', $string);
    }

Strip leading indents.

@since 160720 Indent utils.

@param mixed       $value Any input value.
@param bool|string $trim  Trim to find first line?
If `true`, regular trimming applies.
If `'html-trim'`, HTML trimming applies.

@return string|array|object Stripped value(s).


public function setSteps(array $steps)
    {
        $this->steps = array();

        foreach ($steps as $step) {
            $this->addStep($step);
        }
    }

public function setSteps ( array $ steps ) { $ this -> steps = array ( ) ; foreach ( $ steps as $ step ) { $ this -> addStep ( $ step ) ; } }

Sets the leg steps.

@param array $steps The leg steps.


public function route()
    {
        $args = func_get_args();

        if (isset($args[0]) && ($args[0] instanceof DirectionsRequest)) {
            $directionsRequest = $args[0];
        } elseif ((isset($args[0]) && is_string($args[0])) && (isset($args[1]) && is_string($args[1]))) {
            $directionsRequest = new DirectionsRequest();

            $directionsRequest->setOrigin($args[0]);
            $directionsRequest->setDestination($args[1]);
        } else {
            throw DirectionsException::invalidDirectionsRequestParameters();
        }

        if (!$directionsRequest->isValid()) {
            throw DirectionsException::invalidDirectionsRequest();
        }

        $response = $this->send($this->generateUrl($directionsRequest));
        $directionsResponse = $this->buildDirectionsResponse($this->parse($response->getBody()));

        return $directionsResponse;
    }

public function route ( ) { $ args = func_get_args ( ) ; if ( isset ( $ args [ 0 ] ) && ( $ args [ 0 ] instanceof DirectionsRequest ) ) { $ directionsRequest = $ args [ 0 ] ; } elseif ( ( isset ( $ args [ 0 ] ) && is_string ( $ args [ 0 ] ) ) && ( isset ( $ args [ 1 ] ) && is_string ( $ args [ 1 ] ) ) ) { $ directionsRequest = new DirectionsRequest ( ) ; $ directionsRequest -> setOrigin ( $ args [ 0 ] ) ; $ directionsRequest -> setDestination ( $ args [ 1 ] ) ; } else { throw DirectionsException :: invalidDirectionsRequestParameters ( ) ; } if ( ! $ directionsRequest -> isValid ( ) ) { throw DirectionsException :: invalidDirectionsRequest ( ) ; } $ response = $ this -> send ( $ this -> generateUrl ( $ directionsRequest ) ) ; $ directionsResponse = $ this -> buildDirectionsResponse ( $ this -> parse ( $ response -> getBody ( ) ) ) ; return $ directionsResponse ; }

Routes the given request.

Available prototypes:
- function route(string $origin, string $destination)
- function route(Ivory\GoogleMap\Services\Directions\DirectionsRequest $request)

@throws \Ivory\GoogleMap\Exception\DirectionsException If the request is not valid (prototypes).


protected function buildDirectionsResponse(\stdClass $directionsResponse)
    {
        $routes = $this->buildDirectionsRoutes($directionsResponse->routes);
        $status = $directionsResponse->status;

        return new DirectionsResponse($routes, $status);
    }

protected function buildDirectionsResponse ( \ stdClass $ directionsResponse ) { $ routes = $ this -> buildDirectionsRoutes ( $ directionsResponse -> routes ) ; $ status = $ directionsResponse -> status ; return new DirectionsResponse ( $ routes , $ status ) ; }

Builds the directions response according to the normalized directions API results.

@param \stdClass $directionsResponse The normalied directions response.

@return \Ivory\GoogleMap\Services\Directions\DirectionsResponse The builded directions response.

Builds the directions response according to the normalized directions API results .


protected function buildDirectionsRoutes(array $directionsRoutes)
    {
        $results =  array();
        foreach ($directionsRoutes as $directionsRoute) {
            $results[] = $this->buildDirectionsRoute($directionsRoute);
        }

        return $results;
    }

protected function buildDirectionsRoutes ( array $ directionsRoutes ) { $ results = array ( ) ; foreach ( $ directionsRoutes as $ directionsRoute ) { $ results [ ] = $ this -> buildDirectionsRoute ( $ directionsRoute ) ; } return $ results ; }

Builds the directions routes according to the normalized directions API routes.

@param \stdClass $directionsRoutes The normalized directions routes.

@return array The builded directions routes.

Builds the directions routes according to the normalized directions API routes .


protected function buildDirectionsRoute(\stdClass $directionsRoute)
    {
        $bound = new Bound(
            new Coordinate($directionsRoute->bounds->southwest->lat, $directionsRoute->bounds->southwest->lng),
            new Coordinate($directionsRoute->bounds->northeast->lat, $directionsRoute->bounds->northeast->lng)
        );

        // @see https://github.com/egeloen/IvoryGoogleMapBundle/issues/72
        // @codeCoverageIgnoreStart
        if (!isset($directionsRoute->copyrights)) {
            $directionsRoute->copyrights = '';
        }

        if (!isset($directionsRoute->summary)) {
            $directionsRoute->summary = '';
        }
        // @codeCoverageIgnoreEnd

        $summary = $directionsRoute->summary;
        $copyrights = $directionsRoute->copyrights;

        $directionsLegs = $this->buildDirectionsLegs($directionsRoute->legs);
        $overviewPolyline = new EncodedPolyline($directionsRoute->overview_polyline->points);

        // The warnings & waypoint_order properties can not be defined in the xml format.
        if (!isset($directionsRoute->warnings)) {
            $directionsRoute->warnings = array();
        }

        if (!isset($directionsRoute->waypoint_order)) {
            $directionsRoute->waypoint_order = array();
        }

        $warnings = $directionsRoute->warnings;
        $waypointOrder = $directionsRoute->waypoint_order;

        return new DirectionsRoute(
            $bound,
            $copyrights,
            $directionsLegs,
            $overviewPolyline,
            $summary,
            $warnings,
            $waypointOrder
        );
    }

Builds the directions route according to the normalized directions API route.

@param \stdClass $directionsRoute The normalized directions route.

@return \Ivory\GoogleMap\Services\Directions\DirectionsRoute The builded directions route.

Builds the directions route according to the normalized directions API route .


protected function buildDirectionsLegs(array $directionsLegs)
    {
        $results =  array();
        foreach ($directionsLegs as $directionsLeg) {
            $results[] = $this->buildDirectionsLeg($directionsLeg);
        }

        return $results;
    }

protected function buildDirectionsLegs ( array $ directionsLegs ) { $ results = array ( ) ; foreach ( $ directionsLegs as $ directionsLeg ) { $ results [ ] = $ this -> buildDirectionsLeg ( $ directionsLeg ) ; } return $ results ; }

Builds the directions legs according to the normalized directions API legs.

@param array $directionsLegs The normalized directions legs.

@return array The builded directions legs.

Builds the directions legs according to the normalized directions API legs .


protected function buildDirectionsLeg(\stdClass $directionsLeg)
    {
        $distance = new Distance($directionsLeg->distance->text, $directionsLeg->distance->value);
        $duration = new Duration($directionsLeg->duration->text, $directionsLeg->duration->value);
        $endAddress = $directionsLeg->end_address;
        $endLocation = new Coordinate($directionsLeg->end_location->lat, $directionsLeg->end_location->lng);
        $startAddress = $directionsLeg->start_address;
        $startLocation = new Coordinate($directionsLeg->start_location->lat, $directionsLeg->start_location->lng);
        $steps = $this->buildDirectionsSteps($directionsLeg->steps);

        // The via_waypoint property can not be defined in the xml format.
        if (!isset($directionsLeg->via_waypoint)) {
            $directionsLeg->via_waypoint = array();
        }

        $viaWaypoint = $directionsLeg->via_waypoint;

        return new DirectionsLeg(
            $distance,
            $duration,
            $endAddress,
            $endLocation,
            $startAddress,
            $startLocation,
            $steps,
            $viaWaypoint
        );
    }

Buildd the directions leg according to the normalized directions API leg.

@param \stdClass $directionsLeg The normalized directions leg.

@return \Ivory\GoogleMap\Services\Directions\DirectionsLeg The builded directions leg.

Buildd the directions leg according to the normalized directions API leg .


protected function buildDirectionsSteps(array $directionsSteps)
    {
        $results =  array();
        foreach ($directionsSteps as $directionsStep) {
            $results[] = $this->buildDirectionsStep($directionsStep);
        }

        return $results;
    }

protected function buildDirectionsSteps ( array $ directionsSteps ) { $ results = array ( ) ; foreach ( $ directionsSteps as $ directionsStep ) { $ results [ ] = $ this -> buildDirectionsStep ( $ directionsStep ) ; } return $ results ; }

Builds the directions steps according to the normalized directions API steps.

@param array $directionsSteps The normalized directions steps.

@return array The builded directions steps.

Builds the directions steps according to the normalized directions API steps .


protected function buildDirectionsStep(\stdClass $directionsStep)
    {
        $distance = new Distance($directionsStep->distance->text, $directionsStep->distance->value);
        $duration = new Duration($directionsStep->duration->text, $directionsStep->duration->value);
        $endLocation = new Coordinate($directionsStep->end_location->lat, $directionsStep->end_location->lng);
        $instructions = $directionsStep->html_instructions;
        $encodedPolyline = new EncodedPolyline($directionsStep->polyline->points);
        $startLocation = new Coordinate($directionsStep->start_location->lat, $directionsStep->start_location->lng);
        $travelMode = $directionsStep->travel_mode;

        return new DirectionsStep(
            $distance,
            $duration,
            $endLocation,
            $instructions,
            $encodedPolyline,
            $startLocation,
            $travelMode
        );
    }

protected function buildDirectionsStep ( \ stdClass $ directionsStep ) { $ distance = new Distance ( $ directionsStep -> distance -> text , $ directionsStep -> distance -> value ) ; $ duration = new Duration ( $ directionsStep -> duration -> text , $ directionsStep -> duration -> value ) ; $ endLocation = new Coordinate ( $ directionsStep -> end_location -> lat , $ directionsStep -> end_location -> lng ) ; $ instructions = $ directionsStep -> html_instructions ; $ encodedPolyline = new EncodedPolyline ( $ directionsStep -> polyline -> points ) ; $ startLocation = new Coordinate ( $ directionsStep -> start_location -> lat , $ directionsStep -> start_location -> lng ) ; $ travelMode = $ directionsStep -> travel_mode ; return new DirectionsStep ( $ distance , $ duration , $ endLocation , $ instructions , $ encodedPolyline , $ startLocation , $ travelMode ) ; }

Builds the directions step according to the normalized directions API step.

@param \stdClass $directionsStep The normalized directions step.

@return \Ivory\GoogleMap\Services\Directions\DirectionsStep The builded directions step.

Builds the directions step according to the normalized directions API step .


public function lighten($pct)
    {
        $lightness = $this->lightness() + $pct;
        $lightness = $lightness > 100 ? 100 : $lightness;

        return $this->withLightness($lightness);
    }

public function lighten ( $ pct ) { $ lightness = $ this -> lightness ( ) + $ pct ; $ lightness = $ lightness > 100 ? 100 : $ lightness ; return $ this -> withLightness ( $ lightness ) ; }

Lighten the color.

@param int $pct

@return static


public function darken($pct)
    {
        $lightness = $this->lightness() - $pct;
        $lightness = $lightness < 0 ? 0 : $lightness;

        return $this->withLightness($lightness);
    }

public function darken ( $ pct ) { $ lightness = $ this -> lightness ( ) - $ pct ; $ lightness = $ lightness < 0 ? 0 : $ lightness ; return $ this -> withLightness ( $ lightness ) ; }

Darken the color.

@param int $pct

@return static


public function saturate($pct)
    {
        $saturation = $this->saturation() + $pct;
        $saturation = $saturation > 100 ? 100 : $saturation;

        return $this->withSaturation($saturation);
    }

public function saturate ( $ pct ) { $ saturation = $ this -> saturation ( ) + $ pct ; $ saturation = $ saturation > 100 ? 100 : $ saturation ; return $ this -> withSaturation ( $ saturation ) ; }

Saturate the color.

@param int $pct

@return static


public function desaturate($pct)
    {
        $saturation = $this->saturation() - $pct;
        $saturation = $saturation < 0 ? 0 : $saturation;

        return $this->withSaturation($saturation);
    }

public function desaturate ( $ pct ) { $ saturation = $ this -> saturation ( ) - $ pct ; $ saturation = $ saturation < 0 ? 0 : $ saturation ; return $ this -> withSaturation ( $ saturation ) ; }

Desaturate the color.

@param int $pct

@return static


public function mix(HSL $color)
    {
        return new self(...mixHSL(
            $this->hue(),
            $this->saturation(),
            $this->lightness(),
            $color->hue(),
            $color->saturation(),
            $color->lightness()
        ));
    }

public function mix ( HSL $ color ) { return new self ( ... mixHSL ( $ this -> hue ( ) , $ this -> saturation ( ) , $ this -> lightness ( ) , $ color -> hue ( ) , $ color -> saturation ( ) , $ color -> lightness ( ) ) ) ; }

Get the mix between this and the given color.

@param HSL $color

@return static

Get the mix between this and the given color .


public function start(string $name = '', array $options = [])
    {
        if (session_status() !== \PHP_SESSION_NONE) {
            throw $this->c::issue('Expecting inactive session.');
        } // Expecting inactive so we can start below.

        if ($name) {
            session_name($name);
        }
        $options += [ // Defaults.
            'use_strict_mode'        => true,
            'use_trans_sid'          => false,

            'sid_length'             => 64,
            'sid_bits_per_character' => 6,

            'use_cookies'            => true,
            'use_only_cookies'       => true,
            'cookie_lifetime'        => 0,
            'cookie_path'            => '/',
            'cookie_secure'          => true,
            'cookie_httponly'        => true,

            'gc_maxlifetime'         => 86400,
            'cache_limiter'          => 'nocache',

            'read_and_close' => false,
        ];
        if (!session_start($options)) {
            throw $this->c::issue('Unable to start session.');
        }
    }

Start session.

@since 17xxxx Session utils.

@param string $name    Session name.
@param array  $options Session options.


public function isValid(string $version): bool
    {
        if (!$version) {
            return false; // Nope.
        }
        return (bool) preg_match($this::WS_VERSION_REGEX_VALID, $version);
    }

public
function
isValid
(
string
$
version
)
:
bool
{
if
(
!
$
version
)
{
return
false
;
// Nope.
}
return
(
bool
)
preg_match
(
$
this
::
WS_VERSION_REGEX_VALID
,
$
version
)
;
}

Is it a valid WS version?

@since 150424 Initial release.

@param string $version Input version.

@return bool `TRUE` if valid.


public function isValidDev(string $version): bool
    {
        if (!$version) {
            return false; // Nope.
        }
        return (bool) preg_match($this::WS_VERSION_REGEX_VALID_DEV, $version);
    }

public
function
isValidDev
(
string
$
version
)
:
bool
{
if
(
!
$
version
)
{
return
false
;
// Nope.
}
return
(
bool
)
preg_match
(
$
this
::
WS_VERSION_REGEX_VALID_DEV
,
$
version
)
;
}

Is it a valid WS dev version?

@since 150424 Initial release.

@param string $version Input version.

@return bool `TRUE` if valid.


public function isValidStable(string $version): bool
    {
        if (!$version) {
            return false; // Nope.
        }
        return (bool) preg_match($this::WS_VERSION_REGEX_VALID_STABLE, $version);
    }

public
function
isValidStable
(
string
$
version
)
:
bool
{
if
(
!
$
version
)
{
return
false
;
// Nope.
}
return
(
bool
)
preg_match
(
$
this
::
WS_VERSION_REGEX_VALID_STABLE
,
$
version
)
;
}

Is it a valid WS stable version?

@since 150424 Initial release.

@param string $version Input version.

@return bool `TRUE` if valid.


public function date(string $version, string $format = 'F jS, Y'): string
    {
        if (!$format) {
            return ''; // Not possible.
        } elseif (!($time = $this->time($version))) {
            return ''; // Not possible.
        }
        return date($format, $time);
    }

public
function
date
(
string
$
version
,
string
$
format
=
'F jS, Y'
)
:
string
{
if
(
!
$
format
)
{
return
''
;
// Not possible.
}
elseif
(
!
(
$
time
=
$
this
->
time
(
$
version
)
)
)
{
return
''
;
// Not possible.
}
return
date
(
$
format
,
$
time
)
;
}

WS version to date.

@since 150424 Initial release.

@param string $version Input version.
@param string $format  Any valid date format string.

@return string Date string, else empty string on failure.


public function time(string $version): int
    {
        if (!$version) {
            return 0; // Not possible.
        } elseif (!$this->isValid($version)) {
            return 0; // Invalid version.
        }
        $Y = substr(date('Y'), 0, 2).substr($version, 0, 2);
        $m = substr($version, 2, 2); // Month.
        $d = substr($version, 4, 2); // Day.

        $time = strtotime($Y.'-'.$m.'-'.$d.' 12:00 am');

        if (preg_match('/^[0-9]{6}\.([0-9]+)/u', $version, $_m)) {
            $time += $_m[1]; // Seconds into current day.
        } // unset($_m); // Housekeeping.

        return $time;
    }

public
function
time
(
string
$
version
)
:
int
{
if
(
!
$
version
)
{
return
0
;
// Not possible.
}
elseif
(
!
$
this
->
isValid
(
$
version
)
)
{
return
0
;
// Invalid version.
}
$
Y
=
substr
(
date
(
'Y'
)
,
0
,
2
)
.
substr
(
$
version
,
0
,
2
)
;
$
m
=
substr
(
$
version
,
2
,
2
)
;
// Month.
$
d
=
substr
(
$
version
,
4
,
2
)
;
// Day.
$
time
=
strtotime
(
$
Y
.
'-'
.
$
m
.
'-'
.
$
d
.
' 12:00 am'
)
;
if
(
preg_match
(
'/^[0-9]{6}\.([0-9]+)/u'
,
$
version
,
$
_m
)
)
{
$
time
+=
$
_m
[
1
]
;
// Seconds into current day.
}
// unset($_m); // Housekeeping.
return
$
time
;
}

WS version to time.

@since 150424 Initial release.

@param string $version Input version.

@return int Timestamp, else `0` on failure.


public function withNoCache(): self
    {
        $clone = $this->withoutHeader('last-modified');

        foreach ($this->App->c::noCacheHeadersArray() as $_header => $_value) {
            $clone = $clone->withHeader($_header, $_value);
        } // unset($_header, $_value);

        return $clone; // Response.
    }

public
function
withNoCache
(
)
:
self
{
$
clone
=
$
this
->
withoutHeader
(
'last-modified'
)
;
foreach
(
$
this
->
App
->
c
::
noCacheHeadersArray
(
)
as
$
_header
=>
$
_value
)
{
$
clone
=
$
clone
->
withHeader
(
$
_header
,
$
_value
)
;
}
// unset($_header, $_value);
return
$
clone
;
// Response.
}

With no-cache headers.

@since 17xxxx Response utils.

@return Response w/ no-cache headers.


public function withSuccess(int $status, $data, bool $as_json = null): self
    {
        $is_data_array = is_array($data);

        if (!isset($as_json) && $is_data_array) {
            $as_json = $this->App->c::isApi() || $this->App->c::isAjax();
        }
        if ($as_json) { // Format as JSON?
            $content_type = 'application/json';
            $data         = $is_data_array ? $data : [];
            $content      = json_encode(['success' => true] + $data, JSON_PRETTY_PRINT);
        } else {
            $content      = is_string($data) ? $data : '';
            $content_type = 'text/'.($this->App->c::isHtml($content, true) ? 'html' : 'plain');
        }
        $clone = $this->withStatus($status);
        $clone = $clone->withHeader('content-type', $content_type.'; charset=utf-8');

        $Body         = $this->App->c::createReponseBody($content);
        return $clone = $clone->withBody($Body);
    }

public
function
withSuccess
(
int
$
status
,
$
data
,
bool
$
as_json
=
)
:
self
{
$
is_data_array
=
is_array
(
$
data
)
;
if
(
!
isset
(
$
as_json
)
&&
$
is_data_array
)
{
$
as_json
=
$
this
->
App
->
c
::
isApi
(
)
||
$
this
->
App
->
c
::
isAjax
(
)
;
}
if
(
$
as_json
)
{
// Format as JSON?
$
content_type
=
'application/json'
;
$
data
=
$
is_data_array
$
data
:
[
]
;
$
content
=
json_encode
(
[
'success'
=>
true
]
+
$
data
,
JSON_PRETTY_PRINT
)
;
}
else
{
$
content
=
is_string
(
$
data
)
$
data
:
''
;
$
content_type
=
'text/'
.
(
$
this
->
App
->
c
::
isHtml
(
$
content
,
true
)
'html'
:
'plain'
)
;
}
$
clone
=
$
this
->
withStatus
(
$
status
)
;
$
clone
=
$
clone
->
withHeader
(
'content-type'
,
$
content_type
.
'; charset=utf-8'
)
;
$
Body
=
$
this
->
App
->
c
::
createReponseBody
(
$
content
)
;
return
$
clone
=
$
clone
->
withBody
(
$
Body
)
;
}

Success response.

@since 17xxxx Response utils.

@param int          $status  Status.
@param array|string $data    Props/markup.
@param bool         $as_json As JSON?

@return Response w/ success response.


public function withError(int $status, $data, bool $as_json = null): self
    {
        $is_data_error = $data && $this->App->c::isError($data);

        if (!isset($as_json) && $is_data_error) {
            $as_json = $this->App->c::isApi() || $this->App->c::isAjax();
        }
        if ($as_json) { // Format as JSON?
            $data         = $is_data_error ? $data : null;
            $Error        = $data ?: $this->App->c::error();
            $content_type = 'application/json';
            $content      = json_encode([
                'success' => false,
                'error'   => [
                    'code'    => $status,
                    'slug'    => $Error->slug(),
                    'message' => $Error->message(),
                ],
            ], JSON_PRETTY_PRINT);
        } else {
            $data         = is_string($data) ? $data : '';
            $content      = $data ?: $this->App->c::statusHeaderMessage($status);
            $content_type = 'text/'.($this->App->c::isHtml($content, true) ? 'html' : 'plain');
        }
        $clone = $this->withStatus($status);
        $clone = $clone->withHeader('content-type', $content_type.'; charset=utf-8');

        $Body         = $this->App->c::createReponseBody($content);
        return $clone = $clone->withBody($Body);
    }

public
function
withError
(
int
$
status
,
$
data
,
bool
$
as_json
=
)
:
self
{
$
is_data_error
=
$
data
&&
$
this
->
App
->
c
::
isError
(
$
data
)
;
if
(
!
isset
(
$
as_json
)
&&
$
is_data_error
)
{
$
as_json
=
$
this
->
App
->
c
::
isApi
(
)
||
$
this
->
App
->
c
::
isAjax
(
)
;
}
if
(
$
as_json
)
{
// Format as JSON?
$
data
=
$
is_data_error
$
data
:
;
$
Error
=
$
data
:
$
this
->
App
->
c
::
error
(
)
;
$
content_type
=
'application/json'
;
$
content
=
json_encode
(
[
'success'
=>
false
,
'error'
=>
[
'code'
=>
$
status
,
'slug'
=>
$
Error
->
slug
(
)
,
'message'
=>
$
Error
->
message
(
)
,
]
,
]
,
JSON_PRETTY_PRINT
)
;
}
else
{
$
data
=
is_string
(
$
data
)
$
data
:
''
;
$
content
=
$
data
:
$
this
->
App
->
c
::
statusHeaderMessage
(
$
status
)
;
$
content_type
=
'text/'
.
(
$
this
->
App
->
c
::
isHtml
(
$
content
,
true
)
'html'
:
'plain'
)
;
}
$
clone
=
$
this
->
withStatus
(
$
status
)
;
$
clone
=
$
clone
->
withHeader
(
'content-type'
,
$
content_type
.
'; charset=utf-8'
)
;
$
Body
=
$
this
->
App
->
c
::
createReponseBody
(
$
content
)
;
return
$
clone
=
$
clone
->
withBody
(
$
Body
)
;
}

Error response.

@since 17xxxx Response utils.

@param int          $status  Status.
@param Error|string $data    Error|markup.
@param bool         $as_json As JSON?

@return Response w/ error response.


public function output(array $args = [])
    {
        $default_args = [
            'exit' => false,
        ];
        $args += $default_args; // Merge defaults.
        $args['exit'] = (bool) $args['exit'];

        if ($this->hasNoCache()) {
            $this->App->c::noCacheFlags();
        }
        $status   = $this->getStatusCode();
        $protocol = 'HTTP/'.$this->getProtocolVersion();

        $this->App->c::statusHeader($status, $protocol);

        foreach (array_keys($this->getHeaders()) as $_header) {
            header($_header.': '.$this->getHeaderLine($_header));
        } // unset($_header); // Housekeeping.

        $Body = $this->getBody();
        $Body->rewind(); // Rewind.

        while (!$Body->eof()) {
            echo $Body->read(262144); // 256kbs at a time.
        }
        if ($args['exit']) {
            exit; // Stop here.
        }
    }

public
function
output
(
array
$
args
=
[
]
)
{
$
default_args
=
[
'exit'
=>
false
,
]
;
$
args
+=
$
default_args
;
// Merge defaults.
$
args
[
'exit'
]
=
(
bool
)
$
args
[
'exit'
]
;
if
(
$
this
->
hasNoCache
(
)
)
{
$
this
->
App
->
c
::
noCacheFlags
(
)
;
}
$
status
=
$
this
->
getStatusCode
(
)
;
$
protocol
=
'HTTP/'
.
$
this
->
getProtocolVersion
(
)
;
$
this
->
App
->
c
::
statusHeader
(
$
status
,
$
protocol
)
;
foreach
(
array_keys
(
$
this
->
getHeaders
(
)
)
as
$
_header
)
{
header
(
$
_header
.
': '
.
$
this
->
getHeaderLine
(
$
_header
)
)
;
}
// unset($_header); // Housekeeping.
$
Body
=
$
this
->
getBody
(
)
;
$
Body
->
rewind
(
)
;
// Rewind.
while
(
!
$
Body
->
eof
(
)
)
{
echo
$
Body
->
read
(
262144
)
;
// 256kbs at a time.
}
if
(
$
args
[
'exit'
]
)
{
exit
;
// Stop here.
}
}

Output response.

@since 17xxxx Response utils.

@param array $args Any behavioral args.


public function setLegs(array $legs)
    {
        $this->legs = array();

        foreach ($legs as $leg) {
            $this->addLeg($leg);
        }
    }

public function setLegs ( array $ legs ) { $ this -> legs = array ( ) ; foreach ( $ legs as $ leg ) { $ this -> addLeg ( $ leg ) ; } }

Sets the route legs

@param array $legs The route legs.


public function setWarnings(array $warnings)
    {
        $this->warnings = array();

        foreach ($warnings as $warning) {
            $this->addWarning($warning);
        }
    }

public function setWarnings ( array $ warnings ) { $ this -> warnings = array ( ) ; foreach ( $ warnings as $ warning ) { $ this -> addWarning ( $ warning ) ; } }

Sets the route warnings.

@param array $warnings The route warnings.


public function setWaypointOrder(array $waypointOrder)
    {
        $this->waypointOrder = array();

        foreach ($waypointOrder as $waypointOrder) {
            $this->addWaypointOrder($waypointOrder);
        }
    }

public function setWaypointOrder ( array $ waypointOrder ) { $ this -> waypointOrder = array ( ) ; foreach ( $ waypointOrder as $ waypointOrder ) { $ this -> addWaypointOrder ( $ waypointOrder ) ; } }

Sets the routes waypoint order.

@param array $waypointOrder The route waypoint order.


public function render($zoomControlStyle)
    {
        switch ($zoomControlStyle) {
            case ZoomControlStyle::DEFAULT_:
            case ZoomControlStyle::LARGE:
            case ZoomControlStyle::SMALL:
                return sprintf('google.maps.ZoomControlStyle.%s', strtoupper($zoomControlStyle));
            default:
                throw HelperException::invalidZoomControlStyle();
        }
    }

public function render ( $ zoomControlStyle ) { switch ( $ zoomControlStyle ) { case ZoomControlStyle :: DEFAULT_ : case ZoomControlStyle :: LARGE : case ZoomControlStyle :: SMALL : return sprintf ( 'google.maps.ZoomControlStyle.%s' , strtoupper ( $ zoomControlStyle ) ) ; default : throw HelperException :: invalidZoomControlStyle ( ) ; } }

Renders a zoom control style.

@param string $zoomControlStyle The zoom control style.

@throws \Ivory\GoogleMap\Exception\HelperException If thhe zoom control style is not valid.

@return string The JS output.


public function get(?string $key = null)
    {
        if (is_null($key)) {
            return $this->metadata;
        }

        if (! array_key_exists($key, $this->metadata)) {
            return null;
        }

        return $this->metadata[$key];
    }

public function get ( ? string $ key = null ) { if ( is_null ( $ key ) ) { return $ this -> metadata ; } if ( ! array_key_exists ( $ key , $ this -> metadata ) ) { return null ; } return $ this -> metadata [ $ key ] ; }

Get metadata from the document.

@param  string|null  $key

@return mixed


public function issueToken(Request $Request, Response $Response)
    {
        try { // Handles `/(access|refresh)-token` endpoints.
            $AuthorizationServer = $this->authorizationServer();
            $Response            = $AuthorizationServer->respondToAccessTokenRequest($Request, $Response);
            $Response->output(['exit' => true]);
            //
        } catch (OAuthServerException $Exception) {
            $Response = $Exception->generateHttpResponse($Response);
            $Response->output(['exit' => true]);
            //
        } catch (\Throwable $Exception) {
            $Exception = new OAuthServerException($Exception->getMessage(), 0, 'unknown', 500);
            $Response  = $Exception->generateHttpResponse($Response);
            $Response->output(['exit' => true]);
        }
    }

Issue token.

@since 17xxxx OAuth utils.

@param Request  $Request  Request.
@param Response $Response Response.


public function resourceRequest(Request $Request, Response $Response): Request
    {
        try { // Authenticate resource request.
            $ResourceServer = $this->resourceServer();
            return $Request = $ResourceServer->validateAuthenticatedRequest($Request);
            //
        } catch (OAuthServerException $Exception) {
            $Response = $Exception->generateHttpResponse($Response);
            $Response->output(['exit' => true]);
            //
        } catch (\Throwable $Exception) {
            $Exception = new OAuthServerException($Exception->getMessage(), 0, 'unknown', 500);
            $Response  = $Exception->generateHttpResponse($Response);
            $Response->output(['exit' => true]);
        }
    }

public
function
resourceRequest
(
Request
$
Request
,
Response
$
Response
)
:
Request
{
try
{
// Authenticate resource request.
$
ResourceServer
=
$
this
->
resourceServer
(
)
;
return
$
Request
=
$
ResourceServer
->
validateAuthenticatedRequest
(
$
Request
)
;
//
}
catch
(
OAuthServerException
$
Exception
)
{
$
Response
=
$
Exception
->
generateHttpResponse
(
$
Response
)
;
$
Response
->
output
(
[
'exit'
=>
true
]
)
;
//
}
catch
(
\
Throwable
$
Exception
)
{
$
Exception
=
new
OAuthServerException
(
$
Exception
->
getMessage
(
)
,
0
,
'unknown'
,
500
)
;
$
Response
=
$
Exception
->
generateHttpResponse
(
$
Response
)
;
$
Response
->
output
(
[
'exit'
=>
true
]
)
;
}
}

Filter resource request.

@since 17xxxx OAuth utils.

@param Request  $Request  Request.
@param Response $Response Response.

@return Request w/ `oauth_` attributes.

If access token is valid the following attributes are set:
- `oauth_access_token_id` the access token identifier.
- `oauth_client_id` the client identifier.
- `oauth_user_id` the user identifier represented by the access token.
- `oauth_scopes` an array of string scope identifiers.


protected function accessTokenRepository(): AccessTokenRepository
    {
        if ($this->AccessTokenRepository) {
            return $this->AccessTokenRepository;
        }
        return $this->AccessTokenRepository = $this->App->Di->get(AccessTokenRepository::class);
    }

protected function accessTokenRepository ( ) : AccessTokenRepository { if ( $ this -> AccessTokenRepository ) { return $ this -> AccessTokenRepository ; } return $ this -> AccessTokenRepository = $ this -> App -> Di -> get ( AccessTokenRepository :: class ) ; }

Access token repository.

@since 17xxxx OAuth utils.

@return AccessTokenRepository Repo.


public function add($value)
    {
        if (is_array($value) || is_object($value)) {
            foreach ($value as $_key => &$_value) {
                $_value = $this->add($_value);
            } // unset($_key, $_value);
            return $value;
        }
        $string = (string) $value;

        return addslashes($string);
    }

public
function
add
(
$
value
)
{
if
(
is_array
(
$
value
)
||
is_object
(
$
value
)
)
{
foreach
(
$
value
as
$
_key
=>
&
$
_value
)
{
$
_value
=
$
this
->
add
(
$
_value
)
;
}
// unset($_key, $_value);
return
$
value
;
}
$
string
=
(
string
)
$
value
;
return
addslashes
(
$
string
)
;
}

Add slashes deeply.

@since 150424 Initial release.

@param mixed $value Any input value.

@return string|array|object Slashed value.


public function remove($value)
    {
        if (is_array($value) || is_object($value)) {
            foreach ($value as $_key => &$_value) {
                $_value = $this->remove($_value);
            } // unset($_key, $_value);
            return $value;
        }
        $string = (string) $value;

        return stripslashes($string);
    }

public
function
remove
(
$
value
)
{
if
(
is_array
(
$
value
)
||
is_object
(
$
value
)
)
{
foreach
(
$
value
as
$
_key
=>
&
$
_value
)
{
$
_value
=
$
this
->
remove
(
$
_value
)
;
}
// unset($_key, $_value);
return
$
value
;
}
$
string
=
(
string
)
$
value
;
return
stripslashes
(
$
string
)
;
}

Remove slashes deeply.

@since 150424 Initial release.

@param mixed $value Any input value.

@return string|array|object Unslashed value.


public function render(
        $language = 'en',
        array $libraries = array(),
        $callback = null,
        $api_key = null
    )
    {
        $otherParameters = array();

        if (!empty($libraries)) {
            $otherParameters['libraries'] = implode(',', $libraries);
        }

        $otherParameters['language'] = $language;

        // Google Maps API warning: NoApiKeys https://developers.google.com/maps/documentation/javascript/error-messages#no-api-keys
        if (!is_null($api_key)) {
            $otherParameters['key'] = $api_key;
        }

        $this->jsonBuilder
            ->reset()
            ->setValue('[other_params]', urldecode(http_build_query($otherParameters)));

        if ($callback !== null) {
            $this->jsonBuilder->setValue('[callback]', $callback, false);
        }

        $callbackFunction = 'load_ivory_google_map_api';
        $url = sprintf('//www.google.com/jsapi?callback=%s', $callbackFunction);
        $loader = sprintf('google.load("maps", "3", %s);', $this->jsonBuilder->build());

        $output = array();
        $output[] = '<script type="text/javascript">'.PHP_EOL;
        $output[] = sprintf('function %s () { %s };'.PHP_EOL, $callbackFunction, $loader);
        $output[] = '</script>'.PHP_EOL;
        $output[] = sprintf('<script type="text/javascript" src="%s"></script>'.PHP_EOL, $url);

        $this->loaded = true;

        return implode('', $output);
    }

Renders the API.

@param string  $language  The language.
@param array   $libraries Additionnal libraries.
@param string  $callback  A JS callback.
@param string  $api_key   Google Browser API key for the map

@return string The HTML output.


public function setElements(array $elements)
    {
        $this->elements = array();

        foreach ($elements as $element) {
            $this->addElement($element);
        }
    }

public function setElements ( array $ elements ) { $ this -> elements = array ( ) ; foreach ( $ elements as $ element ) { $ this -> addElement ( $ element ) ; } }

Sets the distance matrix row elements.

@param array $elements The row elements.


public function render($controlPosition)
    {
        switch ($controlPosition) {
            case ControlPosition::BOTTOM_CENTER:
            case ControlPosition::BOTTOM_LEFT:
            case ControlPosition::BOTTOM_RIGHT:
            case ControlPosition::LEFT_BOTTOM:
            case ControlPosition::LEFT_CENTER:
            case ControlPosition::LEFT_TOP:
            case ControlPosition::RIGHT_BOTTOM:
            case ControlPosition::RIGHT_CENTER:
            case ControlPosition::RIGHT_TOP:
            case ControlPosition::TOP_CENTER:
            case ControlPosition::TOP_LEFT:
            case ControlPosition::TOP_RIGHT:
                return sprintf('google.maps.ControlPosition.%s', strtoupper($controlPosition));
            default:
                throw HelperException::invalidControlPosition();
        }
    }

public function render ( $ controlPosition ) { switch ( $ controlPosition ) { case ControlPosition :: BOTTOM_CENTER : case ControlPosition :: BOTTOM_LEFT : case ControlPosition :: BOTTOM_RIGHT : case ControlPosition :: LEFT_BOTTOM : case ControlPosition :: LEFT_CENTER : case ControlPosition :: LEFT_TOP : case ControlPosition :: RIGHT_BOTTOM : case ControlPosition :: RIGHT_CENTER : case ControlPosition :: RIGHT_TOP : case ControlPosition :: TOP_CENTER : case ControlPosition :: TOP_LEFT : case ControlPosition :: TOP_RIGHT : return sprintf ( 'google.maps.ControlPosition.%s' , strtoupper ( $ controlPosition ) ) ; default : throw HelperException :: invalidControlPosition ( ) ; } }

Renders a control position.

@param string $controlPosition The control position.

@throws \Ivory\GoogleMap\Exception\HelperException If the control position is not valid.

@return The JS output.


public function current(): string
    {
        if (($ip = &$this->cacheKey(__FUNCTION__)) !== null) {
            return $ip; // Already cached this.
        }
        if ($this->c::isCli()) {
            throw $this->c::issue('Not possible in CLI mode.');
        } // @TODO Try detecting IP address in CLI mode.

        $sources = [
            'HTTP_CF_CONNECTING_IP',
            'HTTP_CLIENT_IP',
            'HTTP_X_FORWARDED_FOR',
            'HTTP_X_FORWARDED',
            'HTTP_X_CLUSTER_CLIENT_IP',
            'HTTP_FORWARDED_FOR',
            'HTTP_FORWARDED',
            'HTTP_VIA',
            'REMOTE_ADDR',
        ];
        foreach ($sources as $_source) {
            if (!empty($_SERVER[$_source]) && is_string($_SERVER[$_source])) {
                if (($_valid_public_ip = $this->getValidPublicFrom($_SERVER[$_source]))) {
                    return $ip = $_valid_public_ip; // IPv4 or IPv6 address.
                }
            } // unset($_valid_public_ip); // Housekeeping.
        } // unset($_source); // Housekeeping.

        if (!empty($_SERVER['REMOTE_ADDR'])) {
            return $ip = mb_strtolower((string) $_SERVER['REMOTE_ADDR']);
        }
        return $ip = 'unknown'; // Not possible.
    }

Current visitor's IP address.

@since 150424 Initial release.

@return string Current visitor's IP address.

@internal Supports both IPv4 & IPv6 addresses.


public function region(string $ip): string
    {
        if (($geo = $this->geoData($ip))) {
            return $geo->region;
        }
        return ''; // Failure.
    }

public
function
region
(
string
$
ip
)
:
string
{
if
(
(
$
geo
=
$
this
->
geoData
(
$
ip
)
)
)
{
return
$
geo
->
region
;
}
return
''
;
// Failure.
}

Region code for IP address.

@since 150424 Initial release.

@param string $ip An IP address.

@return string Region code for IP address.


public function country(string $ip): string
    {
        if (!empty($_SERVER['HTTP_CF_IPCOUNTRY']) // Save time.
            && $ip === $_SERVER['HTTP_CF_CONNECTING_IP'] ?? '' && $ip === $this->current()
            && mb_strlen((string) $_SERVER['HTTP_CF_IPCOUNTRY']) === 2) {
            return (string) $_SERVER['HTTP_CF_IPCOUNTRY'];
        } // This saves time by using CloudFlare.

        if (($geo = $this->geoData($ip))) {
            return $geo->country;
        }
        return ''; // Failure.
    }

public
function
country
(
string
$
ip
)
:
string
{
if
(
!
empty
(
$
_SERVER
[
'HTTP_CF_IPCOUNTRY'
]
)
// Save time.
&&
$
ip
===
$
_SERVER
[
'HTTP_CF_CONNECTING_IP'
]
??
''
&&
$
ip
===
$
this
->
current
(
)
&&
mb_strlen
(
(
string
)
$
_SERVER
[
'HTTP_CF_IPCOUNTRY'
]
)
===
2
)
{
return
(
string
)
$
_SERVER
[
'HTTP_CF_IPCOUNTRY'
]
;
}
// This saves time by using CloudFlare.
if
(
(
$
geo
=
$
this
->
geoData
(
$
ip
)
)
)
{
return
$
geo
->
country
;
}
return
''
;
// Failure.
}

Country code for IP address.

@since 150424 Initial release.

@param string $ip An IP address.

@return string Country code for IP address.


public function isAjax(bool $flag = null): bool
    {
        if (isset($flag)) {
            $this->is_ajax = $flag;
        }
        if (!isset($this->is_ajax) && $this->is_wordpress) {
            if (defined('DOING_AJAX') && DOING_AJAX) {
                $this->is_ajax = true; // Via WP constants.
            }
        }
        return (bool) $this->is_ajax;
    }

public
function
isAjax
(
bool
$
flag
=
)
:
bool
{
if
(
isset
(
$
flag
)
)
{
$
this
->
is_ajax
=
$
flag
;
}
if
(
!
isset
(
$
this
->
is_ajax
)
&&
$
this
->
is_wordpress
)
{
if
(
defined
(
'DOING_AJAX'
)
&&
DOING_AJAX
)
{
$
this
->
is_ajax
=
true
;
// Via WP constants.
}
}
return
(
bool
)
$
this
->
is_ajax
;
}

An AJAX request?

@since 160531 Request types.

@param bool|null $flag If setting flag.

@return bool Is an AJAX request?


public function isApi(bool $flag = null): bool
    {
        if (isset($flag)) {
            $this->is_api = $flag;
        }
        if (!isset($this->is_api) && $this->is_wordpress) {
            if ((defined('XMLRPC_REQUEST') && XMLRPC_REQUEST) || (defined('REST_REQUEST') && REST_REQUEST)) {
                $this->is_api = true; // Via WP constants.
            }
        }
        return (bool) $this->is_api;
    }

public
function
isApi
(
bool
$
flag
=
)
:
bool
{
if
(
isset
(
$
flag
)
)
{
$
this
->
is_api
=
$
flag
;
}
if
(
!
isset
(
$
this
->
is_api
)
&&
$
this
->
is_wordpress
)
{
if
(
(
defined
(
'XMLRPC_REQUEST'
)
&&
XMLRPC_REQUEST
)
||
(
defined
(
'REST_REQUEST'
)
&&
REST_REQUEST
)
)
{
$
this
->
is_api
=
true
;
// Via WP constants.
}
}
return
(
bool
)
$
this
->
is_api
;
}

An API request?

@since 160605 Request types.

@param bool|null $flag If setting flag.

@return bool Is an API request?


public function doingRestAction(string $action = null): string
    {
        if (isset($action)) {
            $this->doing_rest_action = $action;
            $this->doingAction($action, true);
        }
        return (string) $this->doing_rest_action;
    }

public function doingRestAction ( string $ action = null ) : string { if ( isset ( $ action ) ) { $ this -> doing_rest_action = $ action ; $ this -> doingAction ( $ action , true ) ; } return ( string ) $ this -> doing_rest_action ; }

Doing a REsT action?

@since 160531 Request types.

@param string|null $action Only to set action.

@return string The REsT action being done.


public function doingAction(string $action = '', bool $flag = null): bool
    {
        if ($action && isset($flag)) {
            $this->doing_actions[$action] = $flag;
        }
        if ($action) {
            return $this->doing_actions[$action] ?? false;
        } else {
            return !empty($this->doing_actions);
        }
    }

public function doingAction ( string $ action = '' , bool $ flag = null ) : bool { if ( $ action && isset ( $ flag ) ) { $ this -> doing_actions [ $ action ] = $ flag ; } if ( $ action ) { return $ this -> doing_actions [ $ action ] ?? false ; } else { return ! empty ( $ this -> doing_actions ) ; } }

Doing an action?

@since 170623.50532 Action utils.

@param string     $action Action to add or check.
@param mixed|null $data   If adding action data.

@return bool True if doing the action.


public static function subscribeNewUser($email,$listid,$confirm = false){
    	$data = [
    			'email_address' => $email,
    			'status' => ($confirm ? 'pending' : 'subscribed'),
    	];
    	if (!empty($merge_fields)) $data['merge_fields'] = $merge_fields;
    	$action = self::$api_version.'/lists/'.$listid.'/members/';

    	return self::send($action, 'POST', $data);

    }

public static function subscribeNewUser ( $ email , $ listid , $ confirm = false ) { $ data = [ 'email_address' => $ email , 'status' => ( $ confirm ? 'pending' : 'subscribed' ) , ] ; if ( ! empty ( $ merge_fields ) ) $ data [ 'merge_fields' ] = $ merge_fields ; $ action = self :: $ api_version . '/lists/' . $ listid . '/members/' ; return self :: send ( $ action , 'POST' , $ data ) ; }

subscribe new user to a given listid
@param $email
@param $listid
@return mixed


public function getMember($email,$listid)
    {
    	$action =  "lists/".$listid."/members/" . md5($email);
   		return self::getData($action);
    }

public function getMember ( $ email , $ listid ) { $ action = "lists/" . $ listid . "/members/" . md5 ( $ email ) ; return self :: getData ( $ action ) ; }

get a user from a given listid with a given email
@param $email
@param $listid
@return mixed


public static function updateUser($listid,$email,$status)
    {
    	$data = [
    			'status' => $status
    	];
    	if (!empty($merge_fields)) $data['merge_fields'] = $merge_fields;
    	$action = self::$api_version.'/lists/'.$listid.'/members/'. md5($email);

    	return self::send($action, 'PATCH', $data);
    }

public static function updateUser ( $ listid , $ email , $ status ) { $ data = [ 'status' => $ status ] ; if ( ! empty ( $ merge_fields ) ) $ data [ 'merge_fields' ] = $ merge_fields ; $ action = self :: $ api_version . '/lists/' . $ listid . '/members/' . md5 ( $ email ) ; return self :: send ( $ action , 'PATCH' , $ data ) ; }

update status user to a given listid to a given email
@param $email
@param $listid
@param $status
@return mixed


public static function deleteUser($listid,$email)
    {
     	$email=md5($email);
    	$action = self::$api_version.'/lists/'.$listid.'/members/'. $email;
    	return self::send($action, 'DELETE', []);
    }

public static function deleteUser ( $ listid , $ email ) { $ email = md5 ( $ email ) ; $ action = self :: $ api_version . '/lists/' . $ listid . '/members/' . $ email ; return self :: send ( $ action , 'DELETE' , [ ] ) ; }

delete a user to a given listid to a given email
@param $email
@param $listid
@return mixed


public function sha1(string $string, float $adjust = 0): string
    {
        $hex        = '#'.mb_substr(sha1($string), 0, 6);
        return $hex = $adjust ? $this->adjustLuminosity($hex, $adjust) : $hex;
    }

public function sha1 ( string $ string , float $ adjust = 0 ) : string { $ hex = '#' . mb_substr ( sha1 ( $ string ) , 0 , 6 ) ; return $ hex = $ adjust ? $ this -> adjustLuminosity ( $ hex , $ adjust ) : $ hex ; }

SHA-1 color generation.

@since 161012 Color utilities.

@param string $string String to hash.
@param float  $adjust See {@link adjusLuminosity()}.

@return string Auto-generated color with X luminosity.


public function adjustLuminosity(string $hex, float $adjust): string
    {
        $hex = $this->cleanHex($hex);

        for ($adjusted_hex = '', $_dec, $_hex, $_i = 0; $_i < 3; ++$_i) {
            $_dec = hexdec(mb_substr($hex, $_i * 2, 2));
            $_hex = dechex(round(min(max(0, $_dec + ($_dec * $adjust)), 255)));
            $adjusted_hex .= $this->c::mbStrPad($_hex, 2, '0', STR_PAD_LEFT);
        } // unset($_dec, $_hex, $_i); // Housekeeping.

        return '#'.$adjusted_hex;
    }

Adjust luminosity.

@since 161010 Color utilities.

@param string $hex    Hex color code to adjust.
@param float  $adjust `-0.5` (50% darker), `0.5` (50% ligher).

@return string Adjusted hex color, +- luminosity.

@see https://www.sitepoint.com/javascript-generate-lighter-darker-color/


public function cleanHex(string $hex): string
    {
        $hex = ltrim($hex, '#');

        if (!isset($hex[5])) {
            $hex = preg_replace('/(.)/u', '$1$1', $hex);
            $hex = $this->c::mbStrPad($hex, 6, '0');
        }
        return $hex;
    }

public function cleanHex ( string $ hex ) : string { $ hex = ltrim ( $ hex , '#' ) ; if ( ! isset ( $ hex [ 5 ] ) ) { $ hex = preg_replace ( '/(.)/u' , '$1$1' , $ hex ) ; $ hex = $ this -> c :: mbStrPad ( $ hex , 6 , '0' ) ; } return $ hex ; }

Cleans a hex color.

@since 161010 Color utilities.

@param string $hex Hex color.

@return string Clean hex color.


public function maybeEmptyNumericConfigArrays(array $base, array $merge): array
    {
        if (!$merge) { // Save time. Merge is empty?
            return $base; // Nothing to do here.
        }
        foreach ($base as $_key => &$_value) {
            if (is_array($_value) && array_key_exists($_key, $merge)) {
                if (!$_value || $_value === array_values($_value)) {
                    $_value = []; // Empty numeric arrays.
                } elseif ($merge[$_key] && is_array($merge[$_key])) {
                    $_value = $this->maybeEmptyNumericConfigArrays($_value, $merge[$_key]);
                }
            }
        } // unset($_key, $_value); // Housekeeping.
        return $base; // Return possibly-modified base.
    }

Empty numeric config arrays.

@since 160227 Config utils.

@param array $base  Base array.
@param array $merge Array to merge.

@return array The `$base` w/ possibly-empty numeric arrays.

@internal This method must be capable of running w/o a constructed app.


public function create(array $args = []): Classes\Core\Request
    {
        return $this->App->Di->get(Classes\Core\Request::class, $args);
    }

public function create ( array $ args = [ ] ) : Classes \ Core \ Request { return $ this -> App -> Di -> get ( Classes \ Core \ Request :: class , $ args ) ; }

Create request.

@since 17xxxx Request utilities.

@return Classes\Core\Request Instance.


public function createBody(string $content = null): Classes\Core\RequestBody
    {
        return $this->App->Di->get(Classes\Core\RequestBody::class, compact('content'));
    }

public function createBody ( string $ content = null ) : Classes \ Core \ RequestBody { return $ this -> App -> Di -> get ( Classes \ Core \ RequestBody :: class , compact ( 'content' ) ) ; }

Create request body.

@since 17xxxx Request utilities.

@param string|null $content Body content.

@return Classes\Core\RequestBody Instance.


protected function maybeEmptyNumericArrays(array $array, array ...$merge): array
    {
        if (!$merge) { // Save time. Merge is empty?
            return $base; // Nothing to do here.
        }
        foreach ($array as $_key => &$_value) {
            if (is_array($_value)) {
                foreach ($merge as $_merge) {
                    if (array_key_exists($_key, $_merge)) {
                        if (!$_value || $_value === array_values($_value)) {
                            $_value = []; // Empty.
                        } elseif (is_array($_merge[$_key])) {
                            $_value = $this->maybeEmptyNumericArrays($_value, $_merge[$_key]);
                        }
                    }
                } // unset($_merge); // Housekeeping.
            }
        } // unset($_key, $_value); // Housekeeping.

        return $array;
    }

Empty numeric arrays.

@since 17xxxx Change recursive.

@param array $array    Base array.
@param array ...$merge Array to merge.

@return array w/ possibly-empty numeric arrays.


public function render(Rectangle $rectangle, Map $map)
    {
        $this->jsonBuilder
            ->reset()
            ->setValue('[map]', $map->getJavascriptVariable(), false)
            ->setValue('[bounds]', $rectangle->getBound()->getJavascriptVariable(), false)
            ->setValues($rectangle->getOptions());

        return sprintf(
            '%s = new google.maps.Rectangle(%s);'.PHP_EOL,
            $rectangle->getJavascriptVariable(),
            $this->jsonBuilder->build()
        );
    }

public
function
render
(
Rectangle
$
rectangle
,
Map
$
map
)
{
$
this
->
jsonBuilder
->
reset
(
)
->
setValue
(
'[map]'
,
$
map
->
getJavascriptVariable
(
)
,
false
)
->
setValue
(
'[bounds]'
,
$
rectangle
->
getBound
(
)
->
getJavascriptVariable
(
)
,
false
)
->
setValues
(
$
rectangle
->
getOptions
(
)
)
;
return
sprintf
(
'%s = new google.maps.Rectangle(%s);'
.
PHP_EOL
,
$
rectangle
->
getJavascriptVariable
(
)
,
$
this
->
jsonBuilder
->
build
(
)
)
;
}

Renders a rectangle.

@param \Ivory\GoogleMap\Overlays\Rectangle $rectangle The rectangle.
@param \Ivory\GoogleMap\Map                $map       The map.

@return string The JS output.


public function toHtml(string $parent_element_name, array $array, array $args = []): string
    {
        return $this->__invoke($parent_element_name, $array, array_merge($args, ['type' => 'html']));
    }

public function toHtml ( string $ parent_element_name , array $ array , array $ args = [ ] ) : string { return $ this -> __invoke ( $ parent_element_name , $ array , array_merge ( $ args , [ 'type' => 'html' ] ) ) ; }

Array to HTML markup.

@since 160829.74007 XML conversion utils.

@param string $parent_element_name Parent element name.
@param array  $array               Input array to convert.
@param array  $args                Any additional behavioral args.

@return string HTML (with or w/o a DOCTYPE tag).


protected function convert(\DOMDocument $DOMDocument, \DOMElement $ParentDOMElement, array $array)
    {
        foreach ($array as $_child_key => $_child_value) {
            if (is_string($_child_key)) { // Allows duplicate string keys.
                $_child_key = preg_replace('/^[0-9]+_/u', '', $_child_key);
            }
            if (is_array($_child_value)) { // Nested tag.
                $_ChildDOMElement = $DOMDocument->createElement($_child_key);
                $ParentDOMElement->appendChild($_ChildDOMElement);
                $this->convert($DOMDocument, $_ChildDOMElement, $_child_value);
                //
            } elseif (is_scalar($_child_value)) { // Must be scalar.
                // String keys become attributes; numeric keys text nodes.
                $_child_value = (string) $_child_value; // Force string.

                if (is_string($_child_key)) {
                    $_ChildDOMAttr = $DOMDocument->createAttribute($_child_key);
                    $ParentDOMElement->appendChild($_ChildDOMAttr);
                    $_ChildDOMAttr->value = $this->c::escAttr($_child_value);
                } else {
                    $_ChildDOMText = $DOMDocument->createTextNode($_child_value);
                    $ParentDOMElement->appendChild($_ChildDOMText);
                }
            } else { // Fail on unexpected values.
                throw $this->c::issue('Unexpected non-scalar child value.');
            }
        } // unset($_child_key, $_child_value, $_ChildDOMElement, $_ChildDOMAttr, $_ChildDOMText);
    }

Array to XML handler.

@since 160829.74007 XML conversion utils.

@param \DOMDocument $DOMDocument      Class instance.
@param \DOMElement  $ParentDOMElement Class instance.
@param array        $array            Input array to convert.


protected function renderMarker(Marker $marker, Map $map)
    {
        return sprintf(
            '%s.markers.%s = %s',
            $this->getJsContainerName($map),
            $marker->getJavascriptVariable(),
            $this->markerHelper->render($marker, $map)
        );
    }

protected
function
renderMarker
(
Marker
$
marker
,
Map
$
map
)
{
return
sprintf
(
'%s.markers.%s = %s'
,
$
this
->
getJsContainerName
(
$
map
)
,
$
marker
->
getJavascriptVariable
(
)
,
$
this
->
markerHelper
->
render
(
$
marker
,
$
map
)
)
;
}

Renders a marker with the js map container.

@param \Ivory\GoogleMap\Overlays\Marker $marker The marker.
@param \Ivory\GoogleMap\Map             $map    The map.

@return string The JS output.

Renders a marker with the js map container .


public function license(): string
    {
        $key        = mb_strtoupper($this->c::uuidV4());
        return $key = implode('-', str_split($key, 8));
    }

public function license ( ) : string { $ key = mb_strtoupper ( $ this -> c :: uuidV4 ( ) ) ; return $ key = implode ( '-' , str_split ( $ key , 8 ) ) ; }

License key.

@since 170824.30708 Key generator.

@return string UUID w/ 4 dashed parts (35 uppercase bytes).

@example `CAF0F02F-DFC248C7-B4EF607C-F85C154A`


protected function getLibraries(Map $map)
    {
        $libraries = $map->getLibraries();

        $encodedPolylines = $map->getEncodedPolylines();
        if (!empty($encodedPolylines)) {
            $libraries[] = 'geometry';
        }

        return array_unique($libraries);
    }

protected function getLibraries ( Map $ map ) { $ libraries = $ map -> getLibraries ( ) ; $ encodedPolylines = $ map -> getEncodedPolylines ( ) ; if ( ! empty ( $ encodedPolylines ) ) { $ libraries [ ] = 'geometry' ; } return array_unique ( $ libraries ) ; }

Gets the libraries needed for the map.

@param \Ivory\GoogleMap\Map $map The map.

@return array The map libraries.


public function escapeOrder(string $order): string
    {
        $string = mb_strtoupper($order);
        return in_array($order, ['ASC', 'DESC'], true) ? $order : 'ASC';
    }

public function escapeOrder ( string $ order ) : string { $ string = mb_strtoupper ( $ order ) ; return in_array ( $ order , [ 'ASC' , 'DESC' ] , true ) ? $ order : 'ASC' ; }

Escapes order direction.

@since 160422 SQL utils.

@param string $order Order direction.

@return string Escaped order direction.


public function serializeClosure(\Closure $Closure, bool $faster = false): string
    {
        // NOTE: No marker; i.e., so this can be called stand-alone if necessary.
        return $this->{$faster ? 'ClosureTokenSerializer' : 'ClosureAstSerializer'}->serialize($Closure);
    }

Serialize closure.

@since 160712 Closure utils.

@param \Closure $Closure A closure.
@param bool     $faster  Use faster serializer?

@return string Serialized closure.


public function unserializeClosure(string $string, bool $faster = false): \Closure
    {
        if (mb_strpos($string, $this::CLOSURE) === 0) {
            $string = mb_substr($string, mb_strlen($this::CLOSURE));
        }
        return $this->{$faster ? 'ClosureTokenSerializer' : 'ClosureAstSerializer'}->unserialize($string);
    }

public function unserializeClosure ( string $ string , bool $ faster = false ) : \ Closure { if ( mb_strpos ( $ string , $ this :: CLOSURE ) === 0 ) { $ string = mb_substr ( $ string , mb_strlen ( $ this :: CLOSURE ) ) ; } return $ this -> { $ faster ? 'ClosureTokenSerializer' : 'ClosureAstSerializer' } -> unserialize ( $ string ) ; }

Unserialize closure.

@since 160712 Closure utils.

@param string $string A serialized closure.
@param bool   $faster Used faster serializer?

@return \Closure Unserialized closure.


public function maybeSerialize($value, bool $strict = true): string
    {
        if (!$strict) {
            if (is_string($value)) {
                return $string = $value;
            } elseif (is_bool($value)) {
                return $string = (string) (int) $value;
            } elseif (is_int($value) || is_float($value)) {
                return $string = (string) $value;
            } else { // Serialize.
                return $string = $this->__invoke($value);
            }
        } else { // Default.
            if (is_string($value)) {
                return $string = $value;
            } else { // Serialize.
                return $string = $this->__invoke($value);
            }
        }
    }

public
function
maybeSerialize
(
$
value
,
bool
$
strict
=
true
)
:
string
{
if
(
!
$
strict
)
{
if
(
is_string
(
$
value
)
)
{
return
$
string
=
$
value
;
}
elseif
(
is_bool
(
$
value
)
)
{
return
$
string
=
(
string
)
(
int
)
$
value
;
}
elseif
(
is_int
(
$
value
)
||
is_float
(
$
value
)
)
{
return
$
string
=
(
string
)
$
value
;
}
else
{
// Serialize.
return
$
string
=
$
this
->
__invoke
(
$
value
)
;
}
}
else
{
// Default.
if
(
is_string
(
$
value
)
)
{
return
$
string
=
$
value
;
}
else
{
// Serialize.
return
$
string
=
$
this
->
__invoke
(
$
value
)
;
}
}
}

Maybe serialize value.

@since 150424 Serializer.
@since 170824.30708 `$strict` param (= true).

@param mixed $value  Value to serialize.
@param bool  $strict Enable strict types?

@return string A string (possibly serialized).