private function getLine(string $content, int $styles = null, int $paddingLength = null):string
    {
        $termCols = $this->countTermCols();

        // title lines
        if ($styles & self::STYLE_TITLE || $styles & self::STYLE_SUBTITLE) {
            $styles |= self::STYLE_BOLD | self::STYLE_CENTER;
            $titleSide = str_pad("", $styles & self::STYLE_TITLE ? 4 : 2, "-");
            $content = ($titleSide ? "$titleSide " : "").strtoupper($content).($titleSide ? " $titleSide" : "");
        }

        // centering
        if ($styles & self::STYLE_CENTER && strlen($content) < $termCols) {
            $leftPadding = ceil(($termCols - strlen($content)) / 2) + strlen($content);
            $content = str_pad(str_pad($content, $leftPadding, " ", STR_PAD_LEFT),
                $termCols, " ");
        }

        // adding padding
        $paddedContent = "";
        $paddingLength = $paddingLength === null ? 2 : $paddingLength + 2;
        $padding = str_pad("", $paddingLength, " ");
        $availableCols = $termCols - $paddingLength * 2;
        // processing the content by line
        foreach (explode("\n", $content) as $contentLine) {
            $paddedLine = "";

            // processing the content word by word
            foreach (explode(" ", $contentLine) as $word) {
                if (strlen("$paddedLine $word") >= $availableCols) {
                    $paddedContent .= (!empty($paddedContent) ? "\n" : "")
                        .$padding
                        .str_pad($paddedLine, $availableCols, " ")
                        .$padding;
                    $paddedLine = "";
                }
                $paddedLine .= "$word ";
            }

            if (!empty($paddedLine)) {
                $paddedContent .= (!empty($paddedContent) ? "\n" : "")
                    .$padding
                    .str_pad($paddedLine, $availableCols, " ")
                    .$padding;
            }
        }

        // applying colors
        if ($this->options & self::OPT_COLORS && $this->termColor instanceof Color) {
            $paddedContent = $this->termColor->bg('red', $this->termColor->apply('white', $paddedContent));
            if ($styles & self::STYLE_BOLD) {
                $paddedContent = $this->termColor->apply('bold', $paddedContent);
            }
            if ($styles & self::STYLE_ITALIC) {
                $paddedContent = $this->termColor->apply('italic', $paddedContent);
            }
        }
        return "$paddedContent\n";
    }

private
function
getLine
(
string
$
content
,
int
$
styles
=
,
int
$
paddingLength
=
)
:
string
{
$
termCols
=
$
this
->
countTermCols
(
)
;
// title lines
if
(
$
styles
&
self
::
STYLE_TITLE
||
$
styles
&
self
::
STYLE_SUBTITLE
)
{
$
styles
|=
self
::
STYLE_BOLD
|
self
::
STYLE_CENTER
;
$
titleSide
=
str_pad
(
""
,
$
styles
&
self
::
STYLE_TITLE
4
:
2
,
"-"
)
;
$
content
=
(
$
titleSide
"$titleSide "
:
""
)
.
strtoupper
(
$
content
)
.
(
$
titleSide
" $titleSide"
:
""
)
;
}
// centering
if
(
$
styles
&
self
::
STYLE_CENTER
&&
strlen
(
$
content
)
<
$
termCols
)
{
$
leftPadding
=
ceil
(
(
$
termCols
strlen
(
$
content
)
)
/
2
)
+
strlen
(
$
content
)
;
$
content
=
str_pad
(
str_pad
(
$
content
,
$
leftPadding
,
" "
,
STR_PAD_LEFT
)
,
$
termCols
,
" "
)
;
}
// adding padding
$
paddedContent
=
""
;
$
paddingLength
=
$
paddingLength
===
2
:
$
paddingLength
+
2
;
$
padding
=
str_pad
(
""
,
$
paddingLength
,
" "
)
;
$
availableCols
=
$
termCols
$
paddingLength
*
2
;
// processing the content by line
foreach
(
explode
(
"\n"
,
$
content
)
as
$
contentLine
)
{
$
paddedLine
=
""
;
// processing the content word by word
foreach
(
explode
(
" "
,
$
contentLine
)
as
$
word
)
{
if
(
strlen
(
"$paddedLine $word"
)
>=
$
availableCols
)
{
$
paddedContent
.=
(
!
empty
(
$
paddedContent
)
"\n"
:
""
)
.
$
padding
.
str_pad
(
$
paddedLine
,
$
availableCols
,
" "
)
.
$
padding
;
$
paddedLine
=
""
;
}
$
paddedLine
.=
"$word "
;
}
if
(
!
empty
(
$
paddedLine
)
)
{
$
paddedContent
.=
(
!
empty
(
$
paddedContent
)
"\n"
:
""
)
.
$
padding
.
str_pad
(
$
paddedLine
,
$
availableCols
,
" "
)
.
$
padding
;
}
}
// applying colors
if
(
$
this
->
options
&
self
::
OPT_COLORS
&&
$
this
->
termColor
instanceof
Color
)
{
$
paddedContent
=
$
this
->
termColor
->
bg
(
'red'
,
$
this
->
termColor
->
apply
(
'white'
,
$
paddedContent
)
)
;
if
(
$
styles
&
self
::
STYLE_BOLD
)
{
$
paddedContent
=
$
this
->
termColor
->
apply
(
'bold'
,
$
paddedContent
)
;
}
if
(
$
styles
&
self
::
STYLE_ITALIC
)
{
$
paddedContent
=
$
this
->
termColor
->
apply
(
'italic'
,
$
paddedContent
)
;
}
}
return
"$paddedContent\n"
;
}

Adds padding and line breaks to the content to make it fit inside the terminal windows with a
proper word cesure.

@param string $content
@param int|null $styles Rendering style (see STYLE_XXX class constants)
@param int|null $paddingLength
@return string

Adds padding and line breaks to the content to make it fit inside the terminal windows with a proper word cesure .


public static function slice(array &$array, int $position, $insert): void
	{
		if (isset($array[$position])) {
			array_splice($array, $position, 0, [$insert]);
		} else {
			$array[$position] = $insert;
		}
	}

public static function slice ( array & $ array , int $ position , $ insert ) : void { if ( isset ( $ array [ $ position ] ) ) { array_splice ( $ array , $ position , 0 , [ $ insert ] ) ; } else { $ array [ $ position ] = $ insert ; } }

Vlozi do pole na dane misto
@param array $array
@param int $position
@param mixed $insert


protected function setRules($ruleAr)
    {
        v::with('Amcms\\Services\\ValidatorRules\\');
        $vObj = v::initValidator();

        if (!is_array($ruleAr)) {
            return $vObj;
        }

        foreach ($ruleAr as $ruleStr) {
            $data = explode(':', trim($ruleStr));
            switch ($data[0]) {
                case 'required':
                    $vObj->notEmpty();
                    break;

                case 'email':
                    $vObj->email();
                    break;

                default:
                    break;
            }
        }

        return $vObj;
    }

protected function setRules ( $ ruleAr ) { v :: with ( 'Amcms\\Services\\ValidatorRules\\' ) ; $ vObj = v :: initValidator ( ) ; if ( ! is_array ( $ ruleAr ) ) { return $ vObj ; } foreach ( $ ruleAr as $ ruleStr ) { $ data = explode ( ':' , trim ( $ ruleStr ) ) ; switch ( $ data [ 0 ] ) { case 'required' : $ vObj -> notEmpty ( ) ; break ; case 'email' : $ vObj -> email ( ) ; break ; default : break ; } } return $ vObj ; }

Create rules chain
@param array $ruleAr string-based rules
@return  Respect\Validation\Validator


public function completeFlow(ClientEntity $client)
    {
        $username = $this->server->getRequestHandler()->getParam('username');
        if (is_null($username)) {
            throw new Exception\InvalidRequestException('username');
        }

        $password = $this->server->getRequestHandler()->getParam('password');
        if (is_null($password)) {
            throw new Exception\InvalidRequestException('password');
        }

        // Check if user's username and password are correct
        $userId = call_user_func($this->getVerifyCredentialsCallback(), $username, $password);

        if ($userId === false) {
            throw new Exception\InvalidCredentialsException();
        }

        // Validate any scopes that are in the request
        $scopeParam = $this->server->getRequestHandler()->getParam('scope');
        $scopes = $this->validateScopes($scopeParam, $client);

        // Create a new session
        $session = new SessionEntity($this->server);
        $session->setOwner('user', $userId);
        $session->associateClient($client);

        // Generate an access token
        $accessToken = new AccessTokenEntity($this->server);
        $accessToken->setId();
        $accessToken->setExpireTime($this->getAccessTokenTTL() + time());

        // Associate scopes with the session and access token
        foreach ($scopes as $scope) {
            $session->associateScope($scope);
        }

        foreach ($session->getScopes() as $scope) {
            $accessToken->associateScope($scope);
        }

        $this->server->getTokenType()->setSession($session);
        $this->server->getTokenType()->setParam('access_token', $accessToken->getId());
        $this->server->getTokenType()->setParam('expires_in', $this->getAccessTokenTTL());

        // Associate a refresh token if set
        if ($this->server->hasGrantType('refresh_token')) {
            $refreshToken = new RefreshTokenEntity($this->server);
            $refreshToken->setId();
            $refreshToken->setExpireTime($this->server->getGrantType('refresh_token')->getRefreshTokenTTL() + time());
            $this->server->getTokenType()->setParam('refresh_token', $refreshToken->getId());
        }

        // Save everything
        $session->save();
        $accessToken->setSession($session);
        $accessToken->save();

        if ($this->server->hasGrantType('refresh_token')) {
            $refreshToken->setAccessToken($accessToken);
            $refreshToken->save();
        }

        return $this->server->getTokenType()->generateResponse();
    }

Complete the password grant

@return array

@throws


public function getObject($objectName, $new = 0)
    {
        if (isset($this->_objectsMap[$objectName]) && $new == 0) {
            return $this->_objectsMap[$objectName];
        }

        $obj = $this->constructObject($objectName);
        if (!$obj) {
            return null;
        }
        // save object to cache
        $this->_objectsMap[$objectName] = $obj;
        if ($new != 1) {
            if (method_exists($obj, "loadStatefullVars")) {
                $obj->loadStatefullVars(Openbizx::$app->getSessionContext());
            }
        }

        return $obj;
    }

public
function
getObject
(
$
objectName
,
$
new
=
0
)
{
if
(
isset
(
$
this
->
_objectsMap
[
$
objectName
]
)
&&
$
new
==
0
)
{
return
$
this
->
_objectsMap
[
$
objectName
]
;
}
$
obj
=
$
this
->
constructObject
(
$
objectName
)
;
if
(
!
$
obj
)
{
return
;
}
// save object to cache
$
this
->
_objectsMap
[
$
objectName
]
=
$
obj
;
if
(
$
new
!=
1
)
{
if
(
method_exists
(
$
obj
,
"loadStatefullVars"
)
)
{
$
obj
->
loadStatefullVars
(
Openbizx
::
$
app
->
getSessionContext
(
)
)
;
}
}
return
$
obj
;
}

Get a metadata based object instance.
It returns the instance the internal object map or create a new one and save it in the map.

@param string $objectName name of object that want to get
@return object

Get a metadata based object instance . It returns the instance the internal object map or create a new one and save it in the map .


public function createObject($objName, &$xmlArr = null)
    {
        $obj = $this->constructObject($objName, $xmlArr);
        return $obj;
    }

public function createObject ( $ objName , & $ xmlArr = null ) { $ obj = $ this -> constructObject ( $ objName , $ xmlArr ) ; return $ obj ; }

Create a new metadata based object instance

@param string $objName name of object will be create
@param array $xmlArr propery array of object
@return object


public function register($prefix, $path, $ext=null) {
        $this->_prefix = $prefix;
        $this->_path = $path;
        if ($ext == null) {
            $this->_ext[] = array('xml');
        } else if (is_array($ext)) {
            $this->_ext[] = $ext;
        } else if (is_string($ext)) {
            $ext[] = array($ext);
        }
    }

public function register ( $ prefix , $ path , $ ext = null ) { $ this -> _prefix = $ prefix ; $ this -> _path = $ path ; if ( $ ext == null ) { $ this -> _ext [ ] = array ( 'xml' ) ; } else if ( is_array ( $ ext ) ) { $ this -> _ext [ ] = $ ext ; } else if ( is_string ( $ ext ) ) { $ ext [ ] = array ( $ ext ) ; } }

Register Prefix, location and extension of MetaObject

@param string $prefix prefix of metaobject, like "Contact" for "Contact.form.ContactForm"
@param string $path location of metaobject with $prefix
@param array|string $ext array of string, collection of extension that support by prefix
@return null
@since OpenbizX CubiX

Register Prefix location and extension of MetaObject


public function Authenticate($code, $scope = null)
    {
        if (!empty($code)) {
            $this->AddParams(array(
                'code' => $code,
                'client_secret' => $this->config['client_secret'],
                'grant_type' => 'authorization_code',
                'redirect_uri' => $this->config['redirect_uri']
            ));

            return $this->Post($this->config['oauth_token_uri']);
        }
    }

public function Authenticate ( $ code , $ scope = null ) { if ( ! empty ( $ code ) ) { $ this -> AddParams ( array ( 'code' => $ code , 'client_secret' => $ this -> config [ 'client_secret' ] , 'grant_type' => 'authorization_code' , 'redirect_uri' => $ this -> config [ 'redirect_uri' ] ) ) ; return $ this -> Post ( $ this -> config [ 'oauth_token_uri' ] ) ; } }

Gets the access token from an oAuth request
@access public
@param string $code The authorization code returned by the oAuth call
@param string $scope The scope of the oAuth request
@return Response


public function Feed(Array $params = array())
    {
        if (!empty($params))
            $this->AddParams($params);

        return $this->Get($this->buildUrl('self/feed/'));
    }

public function Feed ( Array $ params = array ( ) ) { if ( ! empty ( $ params ) ) $ this -> AddParams ( $ params ) ; return $ this -> Get ( $ this -> buildUrl ( 'self/feed/' ) ) ; }

Gets a users feed
@access public
@param string $token An access token
@param Array $params An associative array of key/value pairs to pass to the API.
@return Response


public function Liked(Array $params = array())
	{
		if (!empty($params))
			$this->AddParams($params);
		return $this->Get($this->buildUrl('self/media/liked/'));
	}

public function Liked ( Array $ params = array ( ) ) { if ( ! empty ( $ params ) ) $ this -> AddParams ( $ params ) ; return $ this -> Get ( $ this -> buildUrl ( 'self/media/liked/' ) ) ; }

Gets media liked by the current user
@access public
@param Array $params An associative array of key/value pairs to pass to the API
@return Response


protected function SetRelationship($user_id, $action)
    {
        $this->AddParam('action', $action);
        return $this->Post($this->buildUrl($user_id . '/relationship'));
    }

protected function SetRelationship ( $ user_id , $ action ) { $ this -> AddParam ( 'action' , $ action ) ; return $ this -> Post ( $ this -> buildUrl ( $ user_id . '/relationship' ) ) ; }

Sets a relationship between a particular user and the currently authenticated user
@access public
@param int $user_id A user ID
@param Array $token An associative array of key/value pairs to pass to the API
@return Response


public function setProperties($properties){
    // Update object with incoming values, if any
    if(!empty($properties)){
      foreach($properties as $key => $val){
        $this->$key = $val;
      }
    }
  }

Set object properties

@Param   Array   $properties   Properties to set
@Return  Void


public function findAll($page = 1, $perPage = 0)
  {
    $this->db->select()
             ->from($this->getSource());

    if(is_numeric($perPage) && $perPage > 0){
      $this->db->limit($perPage);

      if(is_numeric($page) && $page > 1){
        $offset = $this->paging->getOffset($page, $perPage);
        $this->db->offset($offset);
      }
    }

    $this->db->execute();
    $this->db->setFetchModeClass(__CLASS__);
    return $this->db->fetchAll();
  }

public function findAll ( $ page = 1 , $ perPage = 0 ) { $ this -> db -> select ( ) -> from ( $ this -> getSource ( ) ) ; if ( is_numeric ( $ perPage ) && $ perPage > 0 ) { $ this -> db -> limit ( $ perPage ) ; if ( is_numeric ( $ page ) && $ page > 1 ) { $ offset = $ this -> paging -> getOffset ( $ page , $ perPage ) ; $ this -> db -> offset ( $ offset ) ; } } $ this -> db -> execute ( ) ; $ this -> db -> setFetchModeClass ( __CLASS__ ) ; return $ this -> db -> fetchAll ( ) ; }

Find and return all

@param  	  int	      $page				Wich page paging are at
@param  	  int	      $perPage		Threads per page
@return    object                Object of database rows


public function countAll(){
	  $this->db->select('COUNT(id) as countRows')
	           ->from($this->getSource());

    $this->db->execute();
    $this->db->setFetchModeClass(__CLASS__);
    $row = $this->db->fetchOne();
    return $row->countRows;
  }

public
function
countAll
(
)
{
$
this
->
db
->
select
(
'COUNT(id) as countRows'
)
->
from
(
$
this
->
getSource
(
)
)
;
$
this
->
db
->
execute
(
)
;
$
this
->
db
->
setFetchModeClass
(
__CLASS__
)
;
$
row
=
$
this
->
db
->
fetchOne
(
)
;
return
$
row
->
countRows
;
}

Count all rows in database table

@return  int   $row->countRows   Count of rows


public function find($id = 0){
    $this->db->select()
             ->from($this->getSource())
             ->where("id = ?");

    $this->db->execute([$id]);
    return $this->db->fetchInto($this);
  }

public
function
find
(
$
id
=
0
)
{
$
this
->
db
->
select
(
)
->
from
(
$
this
->
getSource
(
)
)
->
where
(
"id = ?"
)
;
$
this
->
db
->
execute
(
[
$
id
]
)
;
return
$
this
->
db
->
fetchInto
(
$
this
)
;
}

Find and return specific row

@Param   Int   $id   Row index
@return  this


public function create($values = []){
    $keys   = array_keys($values);
    $values = array_values($values);

    $this->db->insert(
      $this->getSource(),
      $keys
    );

    $res = $this->db->execute($values);

    $this->id = $this->db->lastInsertId();

    return $res;
  }

public function create ( $ values = [ ] ) { $ keys = array_keys ( $ values ) ; $ values = array_values ( $ values ) ; $ this -> db -> insert ( $ this -> getSource ( ) , $ keys ) ; $ res = $ this -> db -> execute ( $ values ) ; $ this -> id = $ this -> db -> lastInsertId ( ) ; return $ res ; }

Create new row

@Param   Array     $values     Key/values to save
@Return  Boolean   True/false  If saving went okey


public function query($columns = "*"){
    $this->db->select($columns)
             ->from($this->getSource());

    return $this;
  }

public function query ( $ columns = "*" ) { $ this -> db -> select ( $ columns ) -> from ( $ this -> getSource ( ) ) ; return $ this ; }

Build a select-query

@Param   String    $columns   Columns to select
@Return  Object    $this


public function execute($params = []){
    $this->db->execute($this->db->getSQL(), $params);
    $this->db->setFetchModeClass(__CLASS__);

    return $this->db->fetchAll();
  }

public function execute ( $ params = [ ] ) { $ this -> db -> execute ( $ this -> db -> getSQL ( ) , $ params ) ; $ this -> db -> setFetchModeClass ( __CLASS__ ) ; return $ this -> db -> fetchAll ( ) ; }

Execute the query built

@Param   String    $query    Custom query
@Return  Object    $this


protected function canProceed($name, $args)
    {
        $condition = $this->condition;

        return $condition instanceof \Closure
            ? $condition($this, $name, ...$args)
            : $condition;
    }

protected function canProceed ( $ name , $ args ) { $ condition = $ this -> condition ; return $ condition instanceof \ Closure ? $ condition ( $ this , $ name , ... $ args ) : $ condition ; }

Check if it can proceed with callback

@param mixed $name
@param mixed $args

@return bool|mixed


protected function createLink($content, $href = '#', $title = null) {
    $content = (string) $content;
    $href    = (string) $href;
    $title   = (string) $title;

    if (empty($title)) {
      $title = $content;
    }

    $link = GeneralUtility::makeInstance('TYPO3\CMS\Fluid\Core\ViewHelper\TagBuilder');
    $link->setTagName('a');
    $link->addAttribute('href', $href);
    $link->addAttribute('title', $title);
    $link->setContent($content);

    return $link;
  }

Creates a link.

@param string $content The content of the link
@param string $href The optional href attribute of the link, defaults to `#`
@param string $title The optional title attribute of the link
@return \TYPO3\CMS\Fluid\Core\ViewHelper\TagBuilder The link


public function pickToParent($recId=null)
    {
    	if ($recId==null || $recId=='')
            $recId = Openbizx::$app->getClientProxy()->getFormInputs('_selectedId');

        $selIds = Openbizx::$app->getClientProxy()->getFormInputs('row_selections', false);
        if ($selIds == null)
            $selIds[] = $recId;

        // if no parent elem or picker map, call AddToParent
        if (!$this->parentFormElemName)
        {
            $this->addToParent($selIds);
        }

        // if has parent elem and picker map, call JoinToParent
        if ($this->parentFormElemName && $this->pickerMap)
        {
            $this->joinToParent($selIds);
        }

    }

Pick data to parent form

@param <type> $recId
@return void
@access remote


protected function _parsePickerMap($pickerMap)
    {
        $returnList = array();
        $pickerList = explode(",", $pickerMap);
        foreach ($pickerList as $pair)
        {
            $controlMap = explode(":", $pair);
            $controlMap[0] = trim($controlMap[0]);
            $controlMap[1] = trim($controlMap[1]);
            $returnList[] = $controlMap;
        }
        return $returnList;
    }

protected function _parsePickerMap ( $ pickerMap ) { $ returnList = array ( ) ; $ pickerList = explode ( "," , $ pickerMap ) ; foreach ( $ pickerList as $ pair ) { $ controlMap = explode ( ":" , $ pair ) ; $ controlMap [ 0 ] = trim ( $ controlMap [ 0 ] ) ; $ controlMap [ 1 ] = trim ( $ controlMap [ 1 ] ) ; $ returnList [ ] = $ controlMap ; } return $ returnList ; }

Parse Picker Map into an array

@param string $pickerMap pickerMap defined in metadata
@return array picker map array


private function convertArrayOfReflectionToSelf(array $reflectionClasses): array
    {
        $return = [];
        foreach ($reflectionClasses as $key => $reflectionClass) {
            $return[$key] = self::constructFromReflectionClass($reflectionClass);
        }

        return $return;
    }

private function convertArrayOfReflectionToSelf ( array $ reflectionClasses ) : array { $ return = [ ] ; foreach ( $ reflectionClasses as $ key => $ reflectionClass ) { $ return [ $ key ] = self :: constructFromReflectionClass ( $ reflectionClass ) ; } return $ return ; }

Take an array of raw \ReflectionClass objects and return an array of self

@param array $reflectionClasses

@return array|self[]
@throws \ReflectionException

Take an array of raw \ ReflectionClass objects and return an array of self


private function _initSetup()
    {
        unset($this->columnFieldMap);
        $this->columnFieldMap = array();
        unset($this->keyFieldColumnMap);
        $this->keyFieldColumnMap = array();
        $i = 0;
        // generate column index if the column is one of the basetable (column!="")
        foreach ($this->varValue as $key => $field) {  // $key is fieldname, $field is fieldobj
            ////////////////////////////////////////////////////////////////////
            // TODO: join fields and nonjoin fields may have same column name
            ////////////////////////////////////////////////////////////////////
            if (isset($field->column) && !isset($field->join) ) {  // ignore the joined field column
                $this->columnFieldMap[$field->column] = $key;
            }
            if (isset($field->column) || isset($field->sqlExpression)) {
                $field->index = $i++;
            }
        }
        // create key field column map to support composite key
        if (isset($this->varValue["Id"]) && $this->varValue["Id"]->column) {
            $keycols = explode(",", $this->varValue["Id"]->column);
            foreach ($keycols as $col) {
                $field = $this->getFieldByColumn($col);  // main table
                $this->keyFieldColumnMap[$field] = $col;
            }
        }
    }

Do some initial setup work

@return void


public function getFieldByColumn($column, $table = null)
    {
        // TODO: 2 columns can have the same name in case of joined fields
        if (isset($this->columnFieldMap[$column])) {
            return $this->columnFieldMap[$column];
        }
        return null;
    }

Get fielf by column name

@param string $column column name
@param string $table table name
@return BizField instant of {@link BizField}


public function getKeySearchRule($isUseOldValue = false, $isUseColumnName = false)
    {
        $keyFields = $this->getKeyFields();
        $retStr = "";
        foreach ($keyFields as $fieldName => $fieldObj) {
            if ($retStr != "")
                $retStr .= " AND ";
            $lhs = $isUseColumnName ? $fieldObj->column : "[$fieldName]";
            $rhs = $isUseOldValue ? $fieldObj->oldValue : $fieldObj->value;
            if ($rhs == "")
                $retStr .= "(" . $lhs . "='" . $rhs . "' or " . $lhs . " is null)";
            else
                $retStr .= $lhs . "='" . $rhs . "'";
        }
        return $retStr;
    }

public
function
getKeySearchRule
(
$
isUseOldValue
=
false
,
$
isUseColumnName
=
false
)
{
$
keyFields
=
$
this
->
getKeyFields
(
)
;
$
retStr
=
""
;
foreach
(
$
keyFields
as
$
fieldName
=>
$
fieldObj
)
{
if
(
$
retStr
!=
""
)
$
retStr
.=
" AND "
;
$
lhs
=
$
isUseColumnName
$
fieldObj
->
column
:
"[$fieldName]"
;
$
rhs
=
$
isUseOldValue
$
fieldObj
->
oldValue
:
$
fieldObj
->
value
;
if
(
$
rhs
==
""
)
$
retStr
.=
"("
.
$
lhs
.
"='"
.
$
rhs
.
"' or "
.
$
lhs
.
" is null)"
;
else
$
retStr
.=
$
lhs
.
"='"
.
$
rhs
.
"'"
;
}
return
$
retStr
;
}

Get key search rule.
The key search rule is used to find a single record by given key values

@param boolean $isUseOldValue true if old key value is used in the search rule
@param boolean $isUseColumnName true if column name is used in the search rule, false if [field] is used
@return string search rule

Get key search rule . The key search rule is used to find a single record by given key values


public function setRecordArr($recArr)
    {
        if (!$recArr) {
            return;
        }
        foreach ($this->varValue as $key => $field) {
            if ( isset($recArr[$key]) ) {
                $recArr[$key] = $field->setValue($recArr[$key]);
            }
        }
    }

public function setRecordArr ( $ recArr ) { if ( ! $ recArr ) { return ; } foreach ( $ this -> varValue as $ key => $ field ) { if ( isset ( $ recArr [ $ key ] ) ) { $ recArr [ $ key ] = $ field -> setValue ( $ recArr [ $ key ] ) ; } } }

Set record array to internal data structure

@param array $recArr record array
@return void


final public function saveOldRecord(&$inputArr)
    {
        if (!$inputArr)
            return;
        foreach ($inputArr as $key => $value) {
            $bizField = $this->varValue[$key];
            if (!$bizField)
                continue;
            $bizField->saveOldValue($value);
        }
    }

final public function saveOldRecord ( & $ inputArr ) { if ( ! $ inputArr ) return ; foreach ( $ inputArr as $ key => $ value ) { $ bizField = $ this -> varValue [ $ key ] ; if ( ! $ bizField ) continue ; $ bizField -> saveOldValue ( $ value ) ; } }

Save old recrod,
used in update record when old record value is needed in the action

@param array $inputArr old record array
@return avoid

Save old recrod used in update record when old record value is needed in the action


final public function getRecordArr($sqlArr = null)
    {
        if ($sqlArr) {
            $this->_setSqlRecord($sqlArr);
        }
        $recArr = array();
        foreach ($this->varValue as $key => $field) {
            if ($field->encrypted == 'Y') {
                $svcobj = Openbizx::getService(CRYPT_SERVICE);
                $value = $svcobj->decrypt($field->getValue());
                $recArr[$key] = $value;
            } else {
                $recArr[$key] = $field->getValue();
            }
        }
        return $recArr;
    }

final public function getRecordArr ( $ sqlArr = null ) { if ( $ sqlArr ) { $ this -> _setSqlRecord ( $ sqlArr ) ; } $ recArr = array ( ) ; foreach ( $ this -> varValue as $ key => $ field ) { if ( $ field -> encrypted == 'Y' ) { $ svcobj = Openbizx :: getService ( CRYPT_SERVICE ) ; $ value = $ svcobj -> decrypt ( $ field -> getValue ( ) ) ; $ recArr [ $ key ] = $ value ; } else { $ recArr [ $ key ] = $ field -> getValue ( ) ; } } return $ recArr ; }

Get record array by converting input indexed-Value array to Field-Value pairs

@param array $sqlArr column value pair array
@return array record array

Get record array by converting input indexed - Value array to Field - Value pairs


public function convertSqlArrToRecArr($sqlArr)
    {
        $recArr = array();
        /* @var $field BizField */
        foreach ($this->varValue as $key => $field) {
            if ($field->column || $field->sqlExpression) {
                $recArr[$key] = $sqlArr[$field->index];
            } else {
                $recArr[$key] = "";
            }
        }
        return $recArr;
    }

public
function
convertSqlArrToRecArr
(
$
sqlArr
)
{
$
recArr
=
array
(
)
;
/* @var $field BizField */
foreach
(
$
this
->
varValue
as
$
key
=>
$
field
)
{
if
(
$
field
->
column
||
$
field
->
sqlExpression
)
{
$
recArr
[
$
key
]
=
$
sqlArr
[
$
field
->
index
]
;
}
else
{
$
recArr
[
$
key
]
=
""
;
}
}
return
$
recArr
;
}

Conver sql array to record array

@param array $sqlArr indexed-value pair array
@return array field-value record array


private function _setSqlRecord($sqlArr)
    {
        foreach ($this->varValue as $key => $field) {
            if ($field->column || $field->sqlExpression) {
                $field->setValue($sqlArr[$field->index]);
            }
        }
        if (isset($this->varValue["Id"]))
            $this->varValue["Id"]->setValue($this->getKeyValue());
    }

private function _setSqlRecord ( $ sqlArr ) { foreach ( $ this -> varValue as $ key => $ field ) { if ( $ field -> column || $ field -> sqlExpression ) { $ field -> setValue ( $ sqlArr [ $ field -> index ] ) ; } } if ( isset ( $ this -> varValue [ "Id" ] ) ) $ this -> varValue [ "Id" ] -> setValue ( $ this -> getKeyValue ( ) ) ; }

Set sql record array to internal data

@param array $sqlArr indexed-value array from sql result
@return avoid


public function getJoinInputRecord($join)
    {
        $inputFields = $this->inputFields;  // Added by Jixian on 2009-02-15 for implement onSaveDataObj
        $recArr = array();
        foreach ($this->varValue as $key => $value) {
            // do not consider joined columns
            // Added by Jixian on 2009-02-15 for implement onSaveDataObj
            /*
             * It's the time to consider about joined columns
             */

            $field = $value;

            if ($field->join == $join) {
                $recArr[$key] = $value;
            }
        }
        return $recArr;
    }

Get join input record

@param <type> $join
@return array


public function getJoinSearchRule($tableJoin, $isUseOldValue = false)
    {
        $joinFieldName = $this->getFieldByColumn($tableJoin->columnRef, $tableJoin->table);
        $joinField = $this->varValue[$joinFieldName];
        $rhs = $isUseOldValue ? $joinField->oldValue : $joinField->value;
        $retStr = $tableJoin->column . "='" . $rhs . "'";
        return $retStr;
    }

public function getJoinSearchRule ( $ tableJoin , $ isUseOldValue = false ) { $ joinFieldName = $ this -> getFieldByColumn ( $ tableJoin -> columnRef , $ tableJoin -> table ) ; $ joinField = $ this -> varValue [ $ joinFieldName ] ; $ rhs = $ isUseOldValue ? $ joinField -> oldValue : $ joinField -> value ; $ retStr = $ tableJoin -> column . "='" . $ rhs . "'" ; return $ retStr ; }

Get join search rule

NOTE: Added by Jixian on 2009-02-16 for implement onSaveDataObj

@param TableJoin $tableJoin
@param boolean $isUseOldValue
@return string


public function getMethod(): string
  {
    if (isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']))
    {
      return strtoupper($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']);
    }

    if (isset($_SERVER['REQUEST_METHOD']))
    {
      return strtoupper($_SERVER['REQUEST_METHOD']);
    }

    return 'GET';
  }

public function getMethod ( ) : string { if ( isset ( $ _SERVER [ 'HTTP_X_HTTP_METHOD_OVERRIDE' ] ) ) { return strtoupper ( $ _SERVER [ 'HTTP_X_HTTP_METHOD_OVERRIDE' ] ) ; } if ( isset ( $ _SERVER [ 'REQUEST_METHOD' ] ) ) { return strtoupper ( $ _SERVER [ 'REQUEST_METHOD' ] ) ; } return 'GET' ; }

Returns the method of the current request.

@return string

@api
@since 1.0.0

Returns the method of the current request .


public function getRequestUri(): string
  {
    if (isset($_SERVER['REQUEST_URI']))
    {
      $requestUri = $_SERVER['REQUEST_URI'];
      if ($requestUri!=='' && $requestUri[0]!=='/')
      {
        $requestUri = preg_replace('/^(http|https):\/\/[^\/]+/i', '', $requestUri);
      }

      return $requestUri;
    }

    throw new \LogicException('Unable to resolve requested URI');
  }

public
function
getRequestUri
(
)
:
string
{
if
(
isset
(
$
_SERVER
[
'REQUEST_URI'
]
)
)
{
$
requestUri
=
$
_SERVER
[
'REQUEST_URI'
]
;
if
(
$
requestUri
!==
''
&&
$
requestUri
[
0
]
!==
'/'
)
{
$
requestUri
=
preg_replace
(
'/^(http|https):\/\/[^\/]+/i'
,
''
,
$
requestUri
)
;
}
return
$
requestUri
;
}
throw
new
\
LogicException
(
'Unable to resolve requested URI'
)
;
}

Returns the requested relative URL after. It includes the query part if any.

@return string

@api
@since 1.0.0

Returns the requested relative URL after . It includes the query part if any .


public function getOptions(ServiceLocatorInterface $sl, $key, $name = null)
    {
        if ($name === null) {
            $name = $this->getName();
        }

        $options = $sl->get('Configuration');
        $options = $options['doctrine'];
        if ($mappingType = $this->getMappingType()) {
            $options = $options[$mappingType];
        }
        $options = isset($options[$key][$name]) ? $options[$key][$name] : null;

        if (null === $options) {
            throw new RuntimeException(
                sprintf(
                    'Options with name "%s" could not be found in "doctrine.%s".',
                    $name,
                    $key
                )
            );
        }

        $optionsClass = $this->getOptionsClass();

        return new $optionsClass($options);
    }

Gets options from configuration based on name.

@param  ServiceLocatorInterface      $sl
@param  string                       $key
@param  null|string                  $name
@return \Zend\Stdlib\AbstractOptions
@throws \RuntimeException

Gets options from configuration based on name .


public function make()
    {
        if( !$this->instance ){
            $this->instance = call_user_func($this->builder);
        }

        return $this->instance;
    }

public function make ( ) { if ( ! $ this -> instance ) { $ this -> instance = call_user_func ( $ this -> builder ) ; } return $ this -> instance ; }

Get or make the singleton instance.

@return mixed


public function issueAccessToken()
    {
        $grantType = $this->requestHandler->getParam('grant_type');
        if (is_null($grantType)) {
            throw new Exception\InvalidRequestException('grant_type');
        }

        // Ensure grant type is one that is recognised and is enabled
        if (!in_array($grantType, array_keys($this->grantTypes))) {
            throw new Exception\UnsupportedGrantTypeException($grantType);
        }

        // Complete the flow
        return $this->getGrantType($grantType)->grant();
    }

Issue an access token

@return array Authorise request parameters

@throws


public function format(IReport $report)
    {
        $output = '';
        $params = $this->getParameters();

        $file = $params->get('location', 'environaut-config.sh');
        $groups = $params->get('groups');

        if (is_writable($file)) {
            $output .= '<comment>Overwriting</comment> ';
        } else {
            $output .= 'Writing ';
        }

        if (empty($groups)) {
            $output .= 'all groups ';
        } else {
            $output .= 'group(s) "' . implode(', ', $groups) . '" ';
        }

        $output .= 'to file "<comment>' . $file . '</comment>"...';

        $default_template = <<<EOT
%settings\$s
EOT;

        $template = $params->get('template', $default_template);

        $all_settings = $report->getSettingsAsArray($groups);

        $grouped_settings = array();
        $content = '';

        foreach ($all_settings as $setting) {
            $name = $this->makeShellVariableName($setting['name'], $setting['group']);
            $value = $this->mapValue($setting['value']);

            $content .= $name . "='" . $value ."'\n";
        }

        $content = self::vksprintf($template, array('settings' => $content));

        $ok = file_put_contents($file, $content, LOCK_EX);

        if ($ok !== false) {
            $output .= '<info>ok</info>.';
        } else {
            $output .= '<error>FAILED</error>.';
        }

        return $output;
    }

Writes all or specific groups of settings as a shell file and
returns a message with some information about that.

@param IReport $report report to take results (and settings) from

@return string messages for CLI output

Writes all or specific groups of settings as a shell file and returns a message with some information about that .


public function decode($file)
    {
        $contents = $this->getFileContents($file);

        $result = array();
        if ($contents != "") {
            $result = json_decode($contents, true);
        }

        return $result;
    }

public function decode ( $ file ) { $ contents = $ this -> getFileContents ( $ file ) ; $ result = array ( ) ; if ( $ contents != "" ) { $ result = json_decode ( $ contents , true ) ; } return $ result ; }

Decodes the json contents readed from the given file, into an array

@param  string $file
@return array

Decodes the json contents readed from the given file into an array


public function validate($totp, $key, $stamp = null)
    {
        if ($stamp === null) {
            $stamp = $this->timeManager->getCurrentStamp();
        }

        if (!preg_match('/^[0-9]{6}$/', $totp)) {
            return false;
        }
        $totp = intval($totp);

        // Search the stamp corresponding to the totp provided
        for ($st = $stamp - $this->window; $st <= $stamp + $this->window; ++$st) {
            if (($res = TOTPGenerator::generate($st, $key)) == $totp) {
                return $st;
            }
        }

        return false;
    }

Check if a totp corresponds to a key and a stamp.

@param string $key
@param int    $totp

@return bool Return true if the totp corresponds to the key and the stamp provided

Check if a totp corresponds to a key and a stamp .


public function actionIndex()
    {
        Url::remember('', 'actions-redirect');
        $searchModel = new CommentSearch();
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);

        return $this->render('index', [
            'searchModel' => $searchModel,
            'dataProvider' => $dataProvider,
        ]);
    }

public function actionIndex ( ) { Url :: remember ( '' , 'actions-redirect' ) ; $ searchModel = new CommentSearch ( ) ; $ dataProvider = $ searchModel -> search ( Yii :: $ app -> request -> queryParams ) ; return $ this -> render ( 'index' , [ 'searchModel' => $ searchModel , 'dataProvider' => $ dataProvider , ] ) ; }


protected function _doUpdate($inputRecord, $currentRecord)
    {
        $dataRec = new DataRecord($currentRecord, $this->getDataObj());

        foreach ($inputRecord as $k => $v){
           	$dataRec[$k] = $v; // or $dataRec->$k = $v;
        }

        try
        {
            $dataRec->save();
        }
        catch (Openbizx\Validation\Exception $e)
        {
            $errElements = $this->getErrorElements($e->errors);
        	if(count($e->errors)==count($errElements)){
            	$this->formHelper->processFormObjError($errElements);
            }else{
            	$errmsg = implode("<br />",$e->errors);
		        Openbizx::$app->getClientProxy()->showErrorMessage($errmsg);
            }
            return false;
        }
        catch (Openbizx\Data\Exception $e)
        {
            $this->processDataException($e);
            return false;
        }
		$this->activeRecord = null;
        $this->getActiveRecord($dataRec["Id"]);

        //$this->runEventLog();
        return true;
    }

protected
function
_doUpdate
(
$
inputRecord
,
$
currentRecord
)
{
$
dataRec
=
new
DataRecord
(
$
currentRecord
,
$
this
->
getDataObj
(
)
)
;
foreach
(
$
inputRecord
as
$
k
=>
$
v
)
{
$
dataRec
[
$
k
]
=
$
v
;
// or $dataRec->$k = $v;
}
try
{
$
dataRec
->
save
(
)
;
}
catch
(
Openbizx
\
Validation
\
Exception
$
e
)
{
$
errElements
=
$
this
->
getErrorElements
(
$
e
->
errors
)
;
if
(
count
(
$
e
->
errors
)
==
count
(
$
errElements
)
)
{
$
this
->
formHelper
->
processFormObjError
(
$
errElements
)
;
}
else
{
$
errmsg
=
implode
(
"<br />"
,
$
e
->
errors
)
;
Openbizx
::
$
app
->
getClientProxy
(
)
->
showErrorMessage
(
$
errmsg
)
;
}
return
false
;
}
catch
(
Openbizx
\
Data
\
Exception
$
e
)
{
$
this
->
processDataException
(
$
e
)
;
return
false
;
}
$
this
->
activeRecord
=
;
$
this
->
getActiveRecord
(
$
dataRec
[
"Id"
]
)
;
//$this->runEventLog();
return
true
;
}

Do update record

@param array $inputRecord
@param array $currentRecord
@return void


public function execute($request, $response, $args)
    {
        $this->request = $request;
        $this->response = $response;
        // dd($request);

        // dd($this->modx->db);

        // URL to resource ID
        $this->resourceId = $this->dispatchRoute();
        if (!$this->resourceId) {
            return null;
        }

        // пока нет БД и кода, всегда возвращаем null
        return null;
    }

Main entry point
@return null|Response MODX parser result


protected function implode(array $list, string $conjunction = "or")
    {
        $last = array_pop($list) ?: "null";
        if ($list) {
            $glue = count($list) > 1 ? ", " : " ";
            return implode($glue, $list) . ', ' .$conjunction . ' ' . $last;
        }
        return $last;
    }

protected
function
implode
(
array
$
list
,
string
$
conjunction
=
"or"
)
{
$
last
=
array_pop
(
$
list
)
:
"null"
;
if
(
$
list
)
{
$
glue
=
count
(
$
list
)
>
1
", "
:
" "
;
return
implode
(
$
glue
,
$
list
)
.
', '
.
$
conjunction
.
' '
.
$
last
;
}
return
$
last
;
}

A natural language version of implode.

@param array $list
@param string $conjunction
@return mixed|string


function renderCSV ($objName)
    {
        $this->render($objName, ",", "csv");

        //Log This Export
        Openbizx::$app->getLog()->log(LOG_INFO, "ExcelService", "Export CSV file.");
    }

function
renderCSV
(
$
objName
)
{
$
this
->
render
(
$
objName
,
","
,
"csv"
)
;
//Log This Export
Openbizx
::
$
app
->
getLog
(
)
->
log
(
LOG_INFO
,
"ExcelService"
,
"Export CSV file."
)
;
}

Render the excel output with CSV format

@param string $objName object name which is the bizform name
@return void


protected function render($objName, $separator=",", $ext="csv")
    {
        ob_end_clean();
        header("Pragma: public");
        header("Expires: 0");
        header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
        header("Cache-Control: public");
        header("Content-Description: File Transfer");
        header("Content-Type: application/vnd.ms-excel");
        header("Content-Disposition: filename=" . $objName."_".date('Y-m-d') . "." . $ext);
        header("Content-Transfer-Encoding: binary");

        $dataTable = $this->getDataTable($objName);
        foreach ($dataTable as $row)
        {
            $line = "";
            foreach ($row as $cell) {
                $txt = $this->strip_cell($cell);
                //if (!empty($txt))
				//Changed condition from empty()to is_null() to allow null fields from being truncated out when csv generated (cyril ogana 2011-11-11)
				//TODO: Need to add condition to leave out fields which have no column name e.g. the first field which has rowcheckboxes?
				if (!is_null($txt))
                    $line .= "\"" . $txt . "\"$separator";
            }
            $line = rtrim($line, $separator);
            $line = iconv("UTF-8","GB2312//IGNORE",$line);
            echo rtrim($line) . "\n";
        }
    }

Render excel data

@param string $objName object form name
@param string $separator sparator between column
@param string $ext file extension
@return void


protected function getDataTable($objName)
    {
        /* @var $formObj EasyForm */
        $formObj = Openbizx::getObject($objName); // get the existing EasyForm|BizForm object

        // if BizForm, call BizForm::renderTable
        if ($formObj instanceof BizForm)
        {
            $dataTable = $formObj->renderTable();
        }
        // if EasyForm, call EasyForm->DataPanel::renderTable
        if ($formObj instanceof EasyForm)
        {
            $recordSet = $formObj->fetchDataSet();
            $dataSet = $formObj->dataPanel->renderTable($recordSet);
            foreach ($dataSet['elems'] as $elem)
            {
                $labelRow[] = $elem['label'];
            }
            $dataTable = array_merge(array($labelRow), $dataSet['data']);
        }

        return $dataTable;

    }

Get raw data to display in the spreadsheet. header and data table

@param string $objName
@return array

Get raw data to display in the spreadsheet . header and data table


public function loadStatefullVars($sessionContext)
    {
        if ($this->stateless == "Y")
            return;
        $sessionContext->loadObjVar($this->objectName, "RecordId", $this->recordId);
        $sessionContext->loadObjVar($this->objectName, "SearchRule", $this->searchRule);
        $sessionContext->loadObjVar($this->objectName, "SortRule", $this->sortRule);
        $sessionContext->loadObjVar($this->objectName, "OtherSqlRule", $this->otherSQLRule);
        $sessionContext->loadObjVar($this->objectName, "Association", $this->association);
    }

public function loadStatefullVars ( $ sessionContext ) { if ( $ this -> stateless == "Y" ) return ; $ sessionContext -> loadObjVar ( $ this -> objectName , "RecordId" , $ this -> recordId ) ; $ sessionContext -> loadObjVar ( $ this -> objectName , "SearchRule" , $ this -> searchRule ) ; $ sessionContext -> loadObjVar ( $ this -> objectName , "SortRule" , $ this -> sortRule ) ; $ sessionContext -> loadObjVar ( $ this -> objectName , "OtherSqlRule" , $ this -> otherSQLRule ) ; $ sessionContext -> loadObjVar ( $ this -> objectName , "Association" , $ this -> association ) ; }

Get session variables data of this object

@param \Openbizx\Web\SessionContext $sessionContext
@return void


public function getProperty($propertyName)
    {
        $ret = parent::getProperty($propertyName);
        if ($ret !== null)
            return $ret;

        // get control object if propertyName is "Control[ctrlname]"
        $pos1 = strpos($propertyName, "[");
        $pos2 = strpos($propertyName, "]");

        if ($pos1 > 0 && $pos2 > $pos1) {
            $propType = substr($propertyName, 0, $pos1);
            $fieldName = substr($propertyName, $pos1 + 1, $pos2 - $pos1 - 1);
            /* if ($propType == "param") {   // get parameter
              return $this->parameters->get($ctrlname);
              } */
            return $this->getField($fieldName);
        }
    }

Get object property

@param string $propertyName
@return BizField|string|mixed


public function getActiveRecord()
    {
        if ($this->recordId == null || $this->recordId == "") {
            return null;
        }
        if ($this->currentRecord == null) {
            // query on $recordId
            $records = $this->directFetch("[Id]='" . $this->recordId . "'", 1);
            if (count($records) == 1) {
                $this->currentRecord = $records[0];
                $this->recordId = $this->currentRecord["Id"];
            } else {
                $this->currentRecord = null;
            }
        }

        return $this->currentRecord;
    }

public
function
getActiveRecord
(
)
{
if
(
$
this
->
recordId
==
||
$
this
->
recordId
==
""
)
{
return
;
}
if
(
$
this
->
currentRecord
==
)
{
// query on $recordId
$
records
=
$
this
->
directFetch
(
"[Id]='"
.
$
this
->
recordId
.
"'"
,
1
)
;
if
(
count
(
$
records
)
==
1
)
{
$
this
->
currentRecord
=
$
records
[
0
]
;
$
this
->
recordId
=
$
this
->
currentRecord
[
"Id"
]
;
}
else
{
$
this
->
currentRecord
=
;
}
}
return
$
this
->
currentRecord
;
}

Get the active record

@todo throw Openbizx\Data\Exception
@return array - record array


public function setActiveRecordId($recordId)
    {
        if ($this->recordId != $recordId) {
            $this->recordId = $recordId;
            $this->currentRecord = null;
        }
    }

public function setActiveRecordId ( $ recordId ) { if ( $ this -> recordId != $ recordId ) { $ this -> recordId = $ recordId ; $ this -> currentRecord = null ; } }

Set the active record according to the record id
@param mixed $recordId record id
@return void


public function fetch()
    {
        $dataSet = new DataSet($this);
        $this->_fetch4countQuery = null;
        $resultSet = $this->_run_search($this->queryLimit);  // regular search or page search
        if ($resultSet !== null) {
            $i = 0;
            while ($recArray = $this->_fetch_record($resultSet)) {
                $dataSet[$i++] = $recArray;
            }
        } else {
            return null;
        }
        return $dataSet;
    }

public
function
fetch
(
)
{
$
dataSet
=
new
DataSet
(
$
this
)
;
$
this
->
_fetch4countQuery
=
;
$
resultSet
=
$
this
->
_run_search
(
$
this
->
queryLimit
)
;
// regular search or page search
if
(
$
resultSet
!==
)
{
$
i
=
0
;
while
(
$
recArray
=
$
this
->
_fetch_record
(
$
resultSet
)
)
{
$
dataSet
[
$
i
++
]
=
$
recArray
;
}
}
else
{
return
;
}
return
$
dataSet
;
}

Fetches SQL result rows as a sequential array according the query rules set before.

@return DataSet array of records

Fetches SQL result rows as a sequential array according the query rules set before .


public function directFetch($searchRule = "", $count = -1, $offset = 0, $sortRule = "")
    {

        //Openbizx::$app->getClientProxy()->showClientAlert(__METHOD__ .'-'. __LINE__ . ' msg: $searchRule : '.$searchRule);

        $curRecord = $this->currentRecord;
        $recId = $this->recordId;
        $this->currentRecord = null;

        $oldSearchRule = $this->searchRule;
        $this->clearSearchRule();
        $this->setSearchRule($searchRule);

        $oldSortRule = $this->sortRule;
        $this->clearSortRule();
        if ($sortRule) {
            $this->setSortRule($sortRule);
        } else {
            $this->setSortRule($this->sortRule);
        }

        $limit = ($count == -1) ? null : array('count' => $count, 'offset' => $offset);

        $dataSet = new DataSet($this);
        $resultSet = $this->_run_search($limit);
        if ($resultSet !== null) {
            $i = 0;
            while ($recArray = $this->_fetch_record($resultSet)) {
                $dataSet[$i++] = $recArray;
            }
        }

        $this->sortRule = $oldSortRule;
        $this->searchRule = $oldSearchRule;
        $this->currentRecord = $curRecord;
        $this->recordId = $recId;

        if (count($dataSet) == 0) {
            return new DataSet(null);
        }
        return $dataSet;
    }

Fetches SQL result rows as a sequential array without using query rules set before.

@param string $searchRule the search rule string
@param int $count number of records to return
@param int $offset the starting point of the return records
@return DataSet set of records

Fetches SQL result rows as a sequential array without using query rules set before .


public function fetchRecords($searchRule, &$resultRecords, $count = -1, $offset = 0, $clearSearchRule = true, $noAssociation = false)
    {
        if ($count == 0)
            return;
        $curRecord = $this->currentRecord;
        $recId = $this->recordId;
        $oldSearchRule = $this->searchRule;
        $this->currentRecord = null;
        if ($clearSearchRule)
            $this->clearSearchRule();
        $this->setSearchRule($searchRule);
        if ($noAssociation) {
            $oldAssociation = $this->association;
            $this->association = null;
        }
        $limit = ($count == -1) ? null : array('count' => $count, 'offset' => $offset);

        $resultRecords = array();

        $resultSet = $this->_run_search($limit);
        if ($resultSet !== null) {
            while ($recArray = $this->_fetch_record($resultSet)) {
                $resultRecords[] = $recArray;
            }
        }
        if ($noAssociation) {
            $this->association = $oldAssociation;
        }
        $this->searchRule = $oldSearchRule;
        $this->currentRecord = $curRecord;
        $this->recordId = $recId;
        return true;
    }

public function fetchRecords ( $ searchRule , & $ resultRecords , $ count = - 1 , $ offset = 0 , $ clearSearchRule = true , $ noAssociation = false ) { if ( $ count == 0 ) return ; $ curRecord = $ this -> currentRecord ; $ recId = $ this -> recordId ; $ oldSearchRule = $ this -> searchRule ; $ this -> currentRecord = null ; if ( $ clearSearchRule ) $ this -> clearSearchRule ( ) ; $ this -> setSearchRule ( $ searchRule ) ; if ( $ noAssociation ) { $ oldAssociation = $ this -> association ; $ this -> association = null ; } $ limit = ( $ count == - 1 ) ? null : array ( 'count' => $ count , 'offset' => $ offset ) ; $ resultRecords = array ( ) ; $ resultSet = $ this -> _run_search ( $ limit ) ; if ( $ resultSet !== null ) { while ( $ recArray = $ this -> _fetch_record ( $ resultSet ) ) { $ resultRecords [ ] = $ recArray ; } } if ( $ noAssociation ) { $ this -> association = $ oldAssociation ; } $ this -> searchRule = $ oldSearchRule ; $ this -> currentRecord = $ curRecord ; $ this -> recordId = $ recId ; return true ; }

Run query and get the query results without affecting DataObject internal state
by default it gets number of records starting from the first row.
if pageNum > 0, it gets number of records starting from the first row of the page

@param $searchRule search rule applied on the query
@param $resultRecord returned result record array
@param $recNum number of records to be returned. if -1, all query results returned
@param $clearSearchRule indicates if search rule need to be cleared before query
@param $noAssociation indicates if current association condition is not used in query
@return boolean - if return false, the caller can call GetErrorMessage to get the error.

@todo Why use parameter as result, fetch word mean the function return value by return keyword.
Need to change parameter and result methodology.

Run query and get the query results without affecting DataObject internal state by default it gets number of records starting from the first row . if pageNum > 0 it gets number of records starting from the first row of the page


public function count()
    {
        // get database connection
        $db = $this->getDBConnection("READ");
        if ($this->_fetch4countQuery) {
            $querySQL = $this->_fetch4countQuery;
        } else {
            $querySQL = $this->getSQLHelper()->buildQuerySQL($this);
        }
        $this->_fetch4countQuery = null;
        return $this->_getNumberRecords($db, $querySQL);
    }

public
function
count
(
)
{
// get database connection
$
db
=
$
this
->
getDBConnection
(
"READ"
)
;
if
(
$
this
->
_fetch4countQuery
)
{
$
querySQL
=
$
this
->
_fetch4countQuery
;
}
else
{
$
querySQL
=
$
this
->
getSQLHelper
(
)
->
buildQuerySQL
(
$
this
)
;
}
$
this
->
_fetch4countQuery
=
;
return
$
this
->
_getNumberRecords
(
$
db
,
$
querySQL
)
;
}

Count the number of record according to the search results set before.
It ignores limit setting

@return int number of records

Count the number of record according to the search results set before . It ignores limit setting


protected function _run_search($limit = null)
    {
        // get database connection
        $db = $this->getDBConnection("READ");
        $querySQL = $this->getSQLHelper()->buildQuerySQL($this);
        $this->_fetch4countQuery = $querySQL;
        if ($limit && count($limit) > 0 && $limit['count'] > 0) {
            $sql = $db->limit($querySQL, $limit['count'], $limit['offset']);
        } else {
            $sql = $querySQL;
        }

        try {
            if ($this->cacheLifeTime > 0) {
                $cache_id = md5($this->objectName . $sql . serialize($bindValues));
                //try to process cache service.
                $cacheSvc = Openbizx::getService(CACHE_SERVICE, 1);
                $cacheSvc->init($this->objectName, $this->cacheLifeTime);
                if ($cacheSvc->test($cache_id)) {
                    //Openbizx::$app->getLog()->log(LOG_DEBUG, "DATAOBJ", "Cache Hit. Query Sql = ".$sql);
                    $resultSetArray = $cacheSvc->load($cache_id);
                } else {
                    Openbizx::$app->getLog()->log(LOG_DEBUG, "DATAOBJ", "Query Sql = " . $sql);
                    $resultSet = $db->query($sql);
                    $resultSetArray = $resultSet->fetchAll();
                    $cacheSvc->save($resultSetArray, $cache_id);
                }
            } else {
                Openbizx::$app->getLog()->log(LOG_DEBUG, "DATAOBJ", "Query Sql = " . $sql);
                $resultSet = $db->query($sql);
                $resultSetArray = $resultSet->fetchAll();
            }
        } catch (Exception $e) {
            Openbizx::$app->getLog()->log(LOG_ERR, "DATAOBJ", "Query Error: " . $e->getMessage());
            $this->errorMessage = $this->getMessage("DATA_ERROR_QUERY") . ": " . $sql . ". " . $e->getMessage();
            throw new \Openbizx\Data\Exception($this->errorMessage);
            return null;
        }
        return $resultSetArray;
    }

Run query with current search rule and returns PDO statement

@param array $limit - if limit is not null, do the limit search
@return PDOStatement


private function _getNumberRecords($db, $sql)
    {
        $has_subquery = false;
        if (preg_match("/\(\s*?SELECT\s*?.+\)/si", $sql)) {
            $has_subquery = true;
        }
        if (preg_match("/^\s*SELECT\s+DISTINCT/is", $sql) || preg_match('/\s+GROUP\s+BY\s+/is', $sql)) {
            // ok, has SELECT DISTINCT or GROUP BY so see if we can use a table alias
            $rewritesql = preg_replace('/(\sORDER\s+BY\s.*)/is', '', $sql);
            $rewritesql = "SELECT COUNT(*) FROM ($rewritesql) _TABLE_ALIAS_";
        } elseif ($has_subquery == false) {
            // now replace SELECT ... FROM with SELECT COUNT(*) FROM
            $rewritesql = preg_replace('/\s*?SELECT\s.*?\s+FROM\s/is', 'SELECT COUNT(*) FROM ', $sql);
            // Because count(*) and 'order by' fails with mssql, access and postgresql.
            // Also a good speedup optimization - skips sorting!
            $rewritesql = preg_replace('/(\sORDER\s+BY\s.*)/is', '', $rewritesql);
        } else {
            $rewritesql = $sql;
        }

        try {
            if ($this->cacheLifeTime > 0) {
                $cache_id = md5($this->objectName . $rewritesql . serialize($bindValues));
                //try to process cache service.
                $cacheSvc = Openbizx::getService(CACHE_SERVICE);
                $cacheSvc->init($this->objectName, $this->cacheLifeTime);
                if ($cacheSvc->test($cache_id)) {
                    //Openbizx::$app->getLog()->log(LOG_DEBUG, "DATAOBJ", ". Query Sql = ".$rewritesql);
                    $resultArray = $cacheSvc->load($cache_id);
                } else {
                    Openbizx::$app->getLog()->log(LOG_DEBUG, "DATAOBJ", "Query Sql = " . $rewritesql);
                    $result = $db->query($rewritesql);
                    $resultArray = $result->fetch();
                    $cacheSvc->save($resultArray, $cache_id);
                }
            } else {
                Openbizx::$app->getLog()->log(LOG_DEBUG, "DATAOBJ", "Query Sql = " . $rewritesql);
                $resultSet = $db->query($rewritesql);
                $resultArray = $resultSet->fetch();
            }
        } catch (Exception $e) {
            Openbizx::$app->getLog()->log(LOG_ERR, "DATAOBJ", "Query Error: " . $e->getMessage());
            $this->errorMessage = $this->getMessage("DATA_ERROR_QUERY") . ": Rewrite:" . $rewritesql . ". Raw:" . $sql . ". " . $e->getMessage();
            throw new \Openbizx\Data\Exception($this->errorMessage);
            return 0;
        }

        if ($has_subquery) {
            $record_count = (int) $resultSet->rowCount();
        } else {
            $record_count = (int) $resultArray[0];
        }
        return (string) $record_count;
    }

Get the number of records according the Select SQL

@param object $db database connection
@param string $sql SQL string
@return int number of records


protected function _fetch_record(&$resultSet)
    {
        if (!is_array($resultSet)) {
            return null;
        }
        $sqlArr = current($resultSet);
        if ($sqlArr) {
            $this->currentRecord = $this->bizRecord->convertSqlArrToRecArr($sqlArr);
            $this->currentRecord = $this->bizRecord->getRecordArr($sqlArr);
            $this->recordId = $this->currentRecord["Id"];
            next($resultSet);
        } else {
            return null;
        }
        return $this->currentRecord;
    }

protected function _fetch_record ( & $ resultSet ) { if ( ! is_array ( $ resultSet ) ) { return null ; } $ sqlArr = current ( $ resultSet ) ; if ( $ sqlArr ) { $ this -> currentRecord = $ this -> bizRecord -> convertSqlArrToRecArr ( $ sqlArr ) ; $ this -> currentRecord = $ this -> bizRecord -> getRecordArr ( $ sqlArr ) ; $ this -> recordId = $ this -> currentRecord [ "Id" ] ; next ( $ resultSet ) ; } else { return null ; } return $ this -> currentRecord ; }

Get record from result setand move the cursor to next row

@return array record array


protected function addSCKeyScript()
    {
        $keyMap = $this->getSCKeyFuncMap();
        if (count($keyMap) == 0) {
            return "";
        }
        Openbizx::$app->getClientProxy()->appendScripts("shortcut", "shortcut.js");
        $str = "<script>\n";
        $formObj = $this->getFormObj();

        if (!$formObj->removeall_sck) {
            $str .= " shortcut.removeall(); \n";
            $formObj->removeall_sck = true;
        }

        foreach ($keyMap as $key => $func) {
            $str .= " shortcut.remove(\"$key\"); \n";
        }

        $str .= " shortcut.add(\"$key\",function() { $func }); \n";
        $str .= "</script>\n";
        return $str;
    }

Add sort-cut key scripts

@return string


public function config(string $key, $default = null)
    {
        return $this->container->get(Config::class)->get($key, $default);
    }

public function config ( string $ key , $ default = null ) { return $ this -> container -> get ( Config :: class ) -> get ( $ key , $ default ) ; }

Get a config key

@param string $key
@param mixed $default
@return mixed


public function bootstrap(): void
    {
        foreach( $this->config('bootstrap', []) as $file ){
            $bootstrap = require_once(path($file));
            $bootstrap($this);
        }
    }

public function bootstrap ( ) : void { foreach ( $ this -> config ( 'bootstrap' , [ ] ) as $ file ) { $ bootstrap = require_once ( path ( $ file ) ) ; $ bootstrap ( $ this ) ; } }


protected function authDBUser($userName, $password)
    {
        $boAuth = Openbizx::getObject($this->authticationDataObj);
        if (!$boAuth)
            return false;
        $searchRule = "[login]='$userName'";
        $recordList = array();
        $boAuth->fetchRecords($searchRule, $recordList, 1);

        $encType 	 = $recordList[0]["enctype"];
        $realPassword = $recordList[0]["password"];
        if ($this->checkPassword($encType,$password,$realPassword))
            return true;

        return false;
    }

protected function authDBUser ( $ userName , $ password ) { $ boAuth = Openbizx :: getObject ( $ this -> authticationDataObj ) ; if ( ! $ boAuth ) return false ; $ searchRule = "[login]='$userName'" ; $ recordList = array ( ) ; $ boAuth -> fetchRecords ( $ searchRule , $ recordList , 1 ) ; $ encType = $ recordList [ 0 ] [ "enctype" ] ; $ realPassword = $ recordList [ 0 ] [ "password" ] ; if ( $ this -> checkPassword ( $ encType , $ password , $ realPassword ) ) return true ; return false ; }

Authenticate User that stored in database

@param string $userName
@param string $password
@return boolean


protected function setRequest($request): void
    {
        if (is_null($this->path)) {
            throw \AWonderPHP\FileWrapper\NullPropertyException::propertyIsNull('path');
        }
        if (! is_null($request)) {
            if (! is_string($request)) {
                throw \AWonderPHP\FileWrapper\TypeErrorException::requestWrongType($request);
            }
            $request = trim(basename($request));
            if (strlen($request) === 0) {
                $request = null;
            }
        }
        if (is_null($request)) {
            $request = trim(basename($this->path));
        }
        $this->request = $request;
    }

protected function setRequest ( $ request ) : void { if ( is_null ( $ this -> path ) ) { throw \ AWonderPHP \ FileWrapper \ NullPropertyException :: propertyIsNull ( 'path' ) ; } if ( ! is_null ( $ request ) ) { if ( ! is_string ( $ request ) ) { throw \ AWonderPHP \ FileWrapper \ TypeErrorException :: requestWrongType ( $ request ) ; } $ request = trim ( basename ( $ request ) ) ; if ( strlen ( $ request ) === 0 ) { $ request = null ; } } if ( is_null ( $ request ) ) { $ request = trim ( basename ( $ this -> path ) ) ; } $ this -> request = $ request ; }

Set the request property

@param string|null $request The name of file as user sees it, only matter for file
download.

@psalm-suppress RedundantConditionGivenDocblockType

@return void


protected function setMaxAge($maxage): void
    {
        $now = time();
        if (is_int($maxage)) {
            if ($maxage > $now) {
                $this->maxage = $maxage - $now;
                return;
            }
            if ($maxage >= 0) {
                $this->maxage = $maxage;
                return;
            }
            throw \AWonderPHP\FileWrapper\InvalidArgumentException::negativeMaxAge();
        }
        if ($maxage instanceof \DateInterval) {
            $dt = new \DateTime();
            $dt->add($maxage);
            $ts = $dt->getTimestamp();
            $seconds = $ts - $now;
            if ($seconds >= 0) {
                $this->maxage = $seconds;
                return;
            }
            throw \AWonderPHP\FileWrapper\InvalidArgumentException::negativeMaxAge();
        }
        if (! is_string($maxage)) {
            throw \AWonderPHP\FileWrapper\TypeErrorException::maxageWrongType($maxage);
        }
        if ($tstamp = strtotime($maxage, time())) {
            $seconds = $tstamp - $now;
            if ($seconds >= 0) {
                $this->maxage = $seconds;
                return;
            }
            throw \AWonderPHP\FileWrapper\InvalidArgumentException::negativeMaxAge();
        }
        throw \AWonderPHP\FileWrapper\InvalidArgumentException::invalidDateString();
    }

protected function setMaxAge ( $ maxage ) : void { $ now = time ( ) ; if ( is_int ( $ maxage ) ) { if ( $ maxage > $ now ) { $ this -> maxage = $ maxage - $ now ; return ; } if ( $ maxage >= 0 ) { $ this -> maxage = $ maxage ; return ; } throw \ AWonderPHP \ FileWrapper \ InvalidArgumentException :: negativeMaxAge ( ) ; } if ( $ maxage instanceof \ DateInterval ) { $ dt = new \ DateTime ( ) ; $ dt -> add ( $ maxage ) ; $ ts = $ dt -> getTimestamp ( ) ; $ seconds = $ ts - $ now ; if ( $ seconds >= 0 ) { $ this -> maxage = $ seconds ; return ; } throw \ AWonderPHP \ FileWrapper \ InvalidArgumentException :: negativeMaxAge ( ) ; } if ( ! is_string ( $ maxage ) ) { throw \ AWonderPHP \ FileWrapper \ TypeErrorException :: maxageWrongType ( $ maxage ) ; } if ( $ tstamp = strtotime ( $ maxage , time ( ) ) ) { $ seconds = $ tstamp - $ now ; if ( $ seconds >= 0 ) { $ this -> maxage = $ seconds ; return ; } throw \ AWonderPHP \ FileWrapper \ InvalidArgumentException :: negativeMaxAge ( ) ; } throw \ AWonderPHP \ FileWrapper \ InvalidArgumentException :: invalidDateString ( ) ; }

Sets the maxage property

@param int|string|\DateInterval $maxage The maximum age the client should cache the
file.

@psalm-suppress RedundantConditionGivenDocblockType

@return void


protected function mimeTypoFix($input): string
    {
        if (is_null($this->path)) {
            throw \AWonderPHP\FileWrapper\NullPropertyException::propertyIsNull('path');
        }
        $input = trim($input);
        $mime = $input;
        switch ($input) {
            case 'application/font-woff':
                $mime = 'font/woff';
                break;
            case 'audio/m4a':
                $mime = 'audio/mp4';
                break;
            case 'audio/matroska':
                $mime = 'audio/x-matroska';
                break;
            case 'audio/mp3':
                $mime = 'audio/mpeg';
                break;
            case 'audio/x-aiff':
                $mime = 'audio/aiff';
                break;
            case 'audio/wav':
                $mime = 'audio/x-wav';
                break;
            case 'audio/x-m4a':
                $mime = 'audio/mp4';
                break;
            case 'audio/x-matroska':
                $arr = explode('.', $this->path);
                $ext = strtolower(end($arr));
                switch ($ext) {
                    case 'weba':
                        $mime = 'audio/webm';
                        break;
                }
                break;
            case 'image/jpg':
                $mime = 'image/jpeg';
                break;
            case 'image/tif':
                $mime = 'image/tiff';
                break;
            case 'video/matroska':
                $mime = 'video/x-matroska';
                // test the extension too so no break
            case 'video/x-matroska':
                $arr = explode('.', $this->path);
                $ext = strtolower(end($arr));
                switch ($ext) {
                    case 'mka':
                        $mime = 'audio/x-matroska';
                        break;
                    case 'weba':
                        $mime = 'audio/webm';
                        break;
                    case 'webm':
                        $mime = 'video/webm';
                        break;
                    case 'webm2':
                        $mime = 'video/webm';
                        break;
                }
                break;
            case 'application/octet-stream':
                $arr = explode('.', $this->path);
                $ext = strtolower(end($arr));
                switch ($ext) {
                    case 'opus':
                        $mime = 'audio/ogg';
                        break;
                }
                break;
            case 'text/plain':
                $arr = explode('.', $this->path);
                $ext = strtolower(end($arr));
                switch ($ext) {
                    case 'js':
                        $mime = 'application/javascript';
                        break;
                    case 'css':
                        $mime = 'text/css';
                        break;
                    case 'vtt':
                        $mime = 'text/vtt';
                        break;
                }
                break;
        }
        return $mime;
    }

protected
function
mimeTypoFix
(
$
input
)
:
string
{
if
(
is_null
(
$
this
->
path
)
)
{
throw
\
AWonderPHP
\
FileWrapper
\
NullPropertyException
::
propertyIsNull
(
'path'
)
;
}
$
input
=
trim
(
$
input
)
;
$
mime
=
$
input
;
switch
(
$
input
)
{
case
'application/font-woff'
:
$
mime
=
'font/woff'
;
break
;
case
'audio/m4a'
:
$
mime
=
'audio/mp4'
;
break
;
case
'audio/matroska'
:
$
mime
=
'audio/x-matroska'
;
break
;
case
'audio/mp3'
:
$
mime
=
'audio/mpeg'
;
break
;
case
'audio/x-aiff'
:
$
mime
=
'audio/aiff'
;
break
;
case
'audio/wav'
:
$
mime
=
'audio/x-wav'
;
break
;
case
'audio/x-m4a'
:
$
mime
=
'audio/mp4'
;
break
;
case
'audio/x-matroska'
:
$
arr
=
explode
(
'.'
,
$
this
->
path
)
;
$
ext
=
strtolower
(
end
(
$
arr
)
)
;
switch
(
$
ext
)
{
case
'weba'
:
$
mime
=
'audio/webm'
;
break
;
}
break
;
case
'image/jpg'
:
$
mime
=
'image/jpeg'
;
break
;
case
'image/tif'
:
$
mime
=
'image/tiff'
;
break
;
case
'video/matroska'
:
$
mime
=
'video/x-matroska'
;
// test the extension too so no break
case
'video/x-matroska'
:
$
arr
=
explode
(
'.'
,
$
this
->
path
)
;
$
ext
=
strtolower
(
end
(
$
arr
)
)
;
switch
(
$
ext
)
{
case
'mka'
:
$
mime
=
'audio/x-matroska'
;
break
;
case
'weba'
:
$
mime
=
'audio/webm'
;
break
;
case
'webm'
:
$
mime
=
'video/webm'
;
break
;
case
'webm2'
:
$
mime
=
'video/webm'
;
break
;
}
break
;
case
'application/octet-stream'
:
$
arr
=
explode
(
'.'
,
$
this
->
path
)
;
$
ext
=
strtolower
(
end
(
$
arr
)
)
;
switch
(
$
ext
)
{
case
'opus'
:
$
mime
=
'audio/ogg'
;
break
;
}
break
;
case
'text/plain'
:
$
arr
=
explode
(
'.'
,
$
this
->
path
)
;
$
ext
=
strtolower
(
end
(
$
arr
)
)
;
switch
(
$
ext
)
{
case
'js'
:
$
mime
=
'application/javascript'
;
break
;
case
'css'
:
$
mime
=
'text/css'
;
break
;
case
'vtt'
:
$
mime
=
'text/vtt'
;
break
;
}
break
;
}
return
$
mime
;
}

Fixes common programmer typos and less than precise mime types from fileinfo.so.

@param string $input The MIME type to be checked and possibly fixed.

@return string Either the input MIME type or a correction of it.

Fixes common programmer typos and less than precise mime types from fileinfo . so .


protected function validMimeType($input): void
    {
        if (is_null($this->path)) {
            throw \AWonderPHP\FileWrapper\NullPropertyException::propertyIsNull('path');
        }
        if (! is_null($input)) {
            if (! is_string($input)) {
                throw \AWonderPHP\FileWrapper\TypeErrorException::mimeWrongType($input);
            }
            $input = trim(strtolower($input));
            try {
                $input = $this->mimeTypoFix($input);
            } catch (\ErrorException $e) {
                error_log($e->getMessage());
                $this->internalError = true;
                return;
            }
            if (in_array($input, $this->validMime)) {
                $this->mime = $input;
                return;
            }
        }
        // do what we can
        if ($input == "application/octet-stream") {
            $input = null;
        }
        $error = false;
        if (! is_null($input)) {
            $arr = explode('/', $input);
            if (count($arr) != 2) {
                $error = true;
            } elseif (! in_array($arr[0], array('application',
                                                'audio',
                                                'font',
                                                'image',
                                                'multipart',
                                                'text',
                                                'video'))) {
                $error = true;
            }
            if ($error) {
                if (function_exists('finfo_open')) {
                    if ($finfo = finfo_open(FILEINFO_MIME_TYPE)) {
                        if ($mime = finfo_file($finfo, $this->path)) {
                            try {
                                $this->mime = $this->mimeTypoFix($mime);
                            } catch (\ErrorException $e) {
                                error_log($e->getMessage());
                                $this->internalError = true;
                            }
                            finfo_close($finfo);
                            return;
                        }
                        finfo_close($finfo);
                    }
                }
            }
        }
        if (is_null($input)) {
            $input = 'application/octet-stream';
        }
        $this->mime = $input;
    }

protected
function
validMimeType
(
$
input
)
:
void
{
if
(
is_null
(
$
this
->
path
)
)
{
throw
\
AWonderPHP
\
FileWrapper
\
NullPropertyException
::
propertyIsNull
(
'path'
)
;
}
if
(
!
is_null
(
$
input
)
)
{
if
(
!
is_string
(
$
input
)
)
{
throw
\
AWonderPHP
\
FileWrapper
\
TypeErrorException
::
mimeWrongType
(
$
input
)
;
}
$
input
=
trim
(
strtolower
(
$
input
)
)
;
try
{
$
input
=
$
this
->
mimeTypoFix
(
$
input
)
;
}
catch
(
\
ErrorException
$
e
)
{
error_log
(
$
e
->
getMessage
(
)
)
;
$
this
->
internalError
=
true
;
return
;
}
if
(
in_array
(
$
input
,
$
this
->
validMime
)
)
{
$
this
->
mime
=
$
input
;
return
;
}
}
// do what we can
if
(
$
input
==
"application/octet-stream"
)
{
$
input
=
;
}
$
error
=
false
;
if
(
!
is_null
(
$
input
)
)
{
$
arr
=
explode
(
'/'
,
$
input
)
;
if
(
count
(
$
arr
)
!=
2
)
{
$
error
=
true
;
}
elseif
(
!
in_array
(
$
arr
[
0
]
,
array
(
'application'
,
'audio'
,
'font'
,
'image'
,
'multipart'
,
'text'
,
'video'
)
)
)
{
$
error
=
true
;
}
if
(
$
error
)
{
if
(
function_exists
(
'finfo_open'
)
)
{
if
(
$
finfo
=
finfo_open
(
FILEINFO_MIME_TYPE
)
)
{
if
(
$
mime
=
finfo_file
(
$
finfo
,
$
this
->
path
)
)
{
try
{
$
this
->
mime
=
$
this
->
mimeTypoFix
(
$
mime
)
;
}
catch
(
\
ErrorException
$
e
)
{
error_log
(
$
e
->
getMessage
(
)
)
;
$
this
->
internalError
=
true
;
}
finfo_close
(
$
finfo
)
;
return
;
}
finfo_close
(
$
finfo
)
;
}
}
}
}
if
(
is_null
(
$
input
)
)
{
$
input
=
'application/octet-stream'
;
}
$
this
->
mime
=
$
input
;
}

Sets the MIME type the file will be served with. Does not compensate for all errors in
declared MIME types but will compensate for some.

@param null|string $input A MIME type.

@psalm-suppress RedundantConditionGivenDocblockType

@return void

Sets the MIME type the file will be served with . Does not compensate for all errors in declared MIME types but will compensate for some .


protected function textCheck(): void
    {
        if (is_null($this->mime)) {
            throw \AWonderPHP\FileWrapper\NullPropertyException::propertyIsNull('mime');
        }
        $test = substr($this->mime, 0, 5);
        if ($test === 'text/') {
            $this->istext = true;
            return;
        }
        $test = substr($this->mime, -4);
        if ($test === "+xml") {
            $this->istext = true;
            return;
        }
        if (in_array($this->mime, $this->textMIME)) {
            $this->istext = true;
        }
    }

protected function textCheck ( ) : void { if ( is_null ( $ this -> mime ) ) { throw \ AWonderPHP \ FileWrapper \ NullPropertyException :: propertyIsNull ( 'mime' ) ; } $ test = substr ( $ this -> mime , 0 , 5 ) ; if ( $ test === 'text/' ) { $ this -> istext = true ; return ; } $ test = substr ( $ this -> mime , - 4 ) ; if ( $ test === "+xml" ) { $ this -> istext = true ; return ; } if ( in_array ( $ this -> mime , $ this -> textMIME ) ) { $ this -> istext = true ; } }

Attempts to detect if serving a text file.

@return void

Attempts to detect if serving a text file .


protected function checkFullFile(): void
    {
        if (is_null($this->filesize)) {
            throw \AWonderPHP\FileWrapper\NullPropertyException::propertyIsNull('filesize');
        }
        $this->end = $this->filesize - 1;
        $this->total = $this->filesize;
        if ($this->istext) {
            return;
        }
        if ($this->filesize > $this->chunksize) {
            $this->ranges = 'bytes';
            if (isset($_SERVER['HTTP_RANGE'])) {
                list($size_unit, $range_orig) = explode('=', $_SERVER['HTTP_RANGE'], 2);
                if ($size_unit == 'bytes') {
                    $this->fullfile = false;
                    //below causes noise in log, so do w/ if then instead. Not using extra_ranges anyway
                    //list($range, $extra_ranges) = explode(',', $range_orig, 2);
                    $arr = explode(',', $range_orig, 2);
                    if (isset($arr[1])) {
                        $extra_ranges = $arr[1];
                    } else {
                        $extra_ranges = null;
                    }
                    $range = $arr[0];
                    list($start, $end) = explode('-', $range, 2);
                } else {
                    $this->badrange = true;
                }
                $end = (empty($end)) ? ($this->filesize - 1) : min(abs(intval($end)), ($this->filesize - 1));
                $start = (empty($start) || $end < abs(intval($start))) ? 0 : max(abs(intval($start)), 0);
                if ($start > 0 || $end < ($this->filesize - 1)) {
                    $this->start = $start;
                    $this->end = $end;
                    $this->total = $this->end - $this->start + 1;
                }
            }
        }
    }

Are we serving the full file or just part of it?

@return void


protected function setFileProperties(): void
    {
        if (is_null($this->path)) {
            throw \AWonderPHP\FileWrapper\NullPropertyException::propertyIsNull('path');
        }
        date_default_timezone_set('UTC');
        $this->filesize = filesize($this->path);
        $this->timestamp = filemtime($this->path);
        $this->lastmod = preg_replace('/\+0000$/', 'GMT', date('r', $this->timestamp));
        $inode = fileinode($this->path);
        // The f4a24ef etc strings - my understand in that
        //  because of caching proxies, the Etag needs to be
        //  different for different types of transfer encoding
        //  (e.g. brotli, gzip, deflate) or content could be
        //  delivered to a client that the client can not
        //  decompress.
        // This class assumes only text files will potentially
        //  be further compressed when serving.
        $etagEnd = 'f4a24ef';
        if ($this->istext) {
            if (ini_get('zlib.output_compression')) {
                $accept = 'identity';
                if ($this->minify) {
                    $etagEnd = '3d';
                } else {
                    $etagEnd = '4c';
                }
                if (isset($this->REQHEADERS['accept-encoding'])) {
                    $T = trim(strtolower($this->REQHEADERS['accept-encoding']));
                    if (strpos($T, 'gzip') !== false) {
                        $accept = 'gzip';
                    } elseif (strpos($T, 'deflate') !== false) {
                        $accept = 'deflate';
                    }
                }
                switch ($accept) {
                    case 'gzip':
                        $etagEnd .= '7aa23';
                        break;
                    case 'deflate':
                        $etagEnd .= '98db4';
                        break;
                    default:
                        $etagEnd .= 'c41ca';
                }
            }
        }
        $this->etag = sprintf("%x-%x-%x-%s", $inode, $this->filesize, $this->timestamp, $etagEnd);
        try {
            $this->checkFullFile();
        } catch (\ErrorException $e) {
            error_log($e->getMessage());
            $this->internalError = true;
            return;
        }
    }

Sets class properties needed to generate a unique Etag and to serve the file.

@return void

Sets class properties needed to generate a unique Etag and to serve the file .


protected function cacheCheck()
    {
        if (is_null($this->etag)) {
            throw \AWonderPHP\FileWrapper\NullPropertyException::propertyIsNull('etag');
        }
        if (isset($this->REQHEADERS['if-none-match'])) {
            $reqETAG=trim($this->REQHEADERS['if-none-match'], '\'"');
            if (strcmp($reqETAG, $this->etag) == 0) {
                $this->cacheok=true;
            }
        } elseif (isset($this->REQHEADERS['if-modified-since'])) {
            $reqLMOD=strtotime(trim($this->REQHEADERS['if-modified-since']));
            if ($reqLMOD == $this->timestamp) {
                $this->cacheok=true;
            }
        }
    }

protected function cacheCheck ( ) { if ( is_null ( $ this -> etag ) ) { throw \ AWonderPHP \ FileWrapper \ NullPropertyException :: propertyIsNull ( 'etag' ) ; } if ( isset ( $ this -> REQHEADERS [ 'if-none-match' ] ) ) { $ reqETAG = trim ( $ this -> REQHEADERS [ 'if-none-match' ] , '\'"' ) ; if ( strcmp ( $ reqETAG , $ this -> etag ) == 0 ) { $ this -> cacheok = true ; } } elseif ( isset ( $ this -> REQHEADERS [ 'if-modified-since' ] ) ) { $ reqLMOD = strtotime ( trim ( $ this -> REQHEADERS [ 'if-modified-since' ] ) ) ; if ( $ reqLMOD == $ this -> timestamp ) { $ this -> cacheok = true ; } } }

Is the browser cached version okay?

@return void


protected function readFromFilesystem(): void
    {
        if (is_null($this->path)) {
            throw \AWonderPHP\FileWrapper\NullPropertyException::propertyIsNull('path');
        }
        $chunk = $this->chunksize;
        $sent = 0;
        $fp = fopen($this->path, 'rb');
        fseek($fp, $this->start);
        while (!feof($fp)) {
            if (($this->total - $sent) < $chunk) {
                $chunk = $this->total - $sent;
            }
            print(fread($fp, $chunk));
            flush();
            ob_flush();
            $sent = $sent + $chunk;
            if ($sent >= $this->total) {
                break;
            }
        }
        fclose($fp);
    }

protected function readFromFilesystem ( ) : void { if ( is_null ( $ this -> path ) ) { throw \ AWonderPHP \ FileWrapper \ NullPropertyException :: propertyIsNull ( 'path' ) ; } $ chunk = $ this -> chunksize ; $ sent = 0 ; $ fp = fopen ( $ this -> path , 'rb' ) ; fseek ( $ fp , $ this -> start ) ; while ( ! feof ( $ fp ) ) { if ( ( $ this -> total - $ sent ) < $ chunk ) { $ chunk = $ this -> total - $ sent ; } print ( fread ( $ fp , $ chunk ) ) ; flush ( ) ; ob_flush ( ) ; $ sent = $ sent + $ chunk ; if ( $ sent >= $ this -> total ) { break ; } } fclose ( $ fp ) ; }

Reads the file or portion of binary file from the filesystem and sends it to the
client.

@return void

Reads the file or portion of binary file from the filesystem and sends it to the client .


protected function sendContent(): bool
    {
        if (is_null($this->path)) {
            $this->sendInternalError();
            return false;
        }
        if (is_null($this->request)) {
            $this->sendInternalError();
            return false;
        }
        if (is_null($this->etag)) {
            $this->sendInternalError();
            return false;
        }
        if (is_null($this->mime)) {
            $this->sendInternalError();
            return false;
        }
        if (is_null($this->filesize)) {
            $this->sendInternalError();
            return false;
        }
        //make sure zlib output compression turned off
        ini_set("zlib.output_compression", "Off");

        if ($this->attachment) {
            header('Content-Description: File Transfer');
            header('Content-Disposition: attachment; filename="' . $this->request . '"');
        }
        if ($this->maxage == 0) {
            header('Cache-Control: must-revalidate');
        } else {
            header('Cache-Control: max-age=' . $this->maxage);
        }
        header('Last-Modified: ' . $this->lastmod);
        header('ETag: "' . $this->etag . '"');
        header('Accept-Ranges: ' . $this->ranges);
        if ($this->fullfile) {
            header('Content-Length: ' . $this->filesize);
        } else {
            header('HTTP/1.1 206 Partial Content');
            header('Content-Length: ' . $this->total);
            header('Content-Range: bytes ' . $this->start . '-' . $this->end . '/' . $this->filesize);
        }
        if (! is_null($this->allowOrigin)) {
            header('access-control-allow-origin: ' . $this->allowOrigin);
        }
        header('Content-Type: ' . $this->mime);
        header_remove('X-Powered-By');
        try {
            $this->readFromFilesystem();
        } catch (\Error $e) {
            error_log($e->getMessage());
            $this->sendInternalError();
            return false;
        }
        return true;
    }

Send headers and then the file, for binary file.

@return bool True on success, False on failure.

Send headers and then the file for binary file .


protected function cleanSource($content): string
    {
        if (is_null($this->path)) {
            throw \AWonderPHP\FileWrapper\NullPropertyException::propertyIsNull('path');
        }
        //nuke BOM when we definitely have UTF8
        $bom = pack('H*', 'EFBBBF');
        //DOS to UNIX
        $content = str_replace("\r\n", "\n", $content);
        //Classic Mac to UNIX
        $content = str_replace("\r", "\n", $content);
        if (function_exists('mb_detect_encoding')) {
            if (mb_detect_encoding($content, 'UTF-8', true)) {
                $this->charEnc="UTF-8";
                $content = preg_replace("/^$bom/", '', $content);
            } elseif ($ENC = mb_detect_encoding($content, $this->charsetlist, true)) {
                $this->charEnc=$ENC;
                if (function_exists('iconv')) {
                    if ($new = iconv($ENC, 'UTF-8', $content)) {
                        $this->charEnc="UTF-8";
                        $content = preg_replace("/^$bom/", '', $new);
                    } else {
                      //conversion failed
                        error_log('Could not convert ' . $this->path . ' to UTF-8');
                    }
                }
            } else {
              //we could not detect character encoding
                error_log('Could not identify character encoding for ' . $this->path);
            }
        }
        return($content);
    }

Cleans up line breaks and attempts to convert files to UTF8.

By default this is turned off, extend class to use.

@param string $content The text to be cleaned and converted.

@return string The cleaned content.

Cleans up line breaks and attempts to convert files to UTF8 .


protected function jsminify($content): string
    {
        $JSqueeze = new \Patchwork\JSqueeze();
        return($JSqueeze->squeeze($content, true, false));
    }

protected function jsminify ( $ content ) : string { $ JSqueeze = new \ Patchwork \ JSqueeze ( ) ; return ( $ JSqueeze -> squeeze ( $ content , true , false ) ) ; }

Minify JavaScript. By default turned off, extend class to enable.

@param string $content The content to be minified.

@return string The minified content.

Minify JavaScript . By default turned off extend class to enable .


protected function cssminify($content): string
    {
        $content = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $content);
        $content = str_replace(': ', ':', $content);
        $content = str_replace(array("\r\n", "\r", "\n", "\t"), '', $content);
        $content = preg_replace("/ {2,}/", ' ', $content);
        $content = str_replace(array('} '), '}', $content);
        $content = str_replace(array('{ '), '{', $content);
        $content = str_replace(array('; '), ';', $content);
        $content = str_replace(array(', '), ',', $content);
        $content = str_replace(array(' }'), '}', $content);
        $content = str_replace(array(' {'), '{', $content);
        $content = str_replace(array(' ;'), ';', $content);
        $content = str_replace(array(' ,'), ',', $content);
        return $content;
    }

protected
function
cssminify
(
$
content
)
:
string
{
$
content
=
preg_replace
(
'!/\*[^*]*\*+([^/][^*]*\*+)*/!'
,
''
,
$
content
)
;
$
content
=
str_replace
(
': '
,
':'
,
$
content
)
;
$
content
=
str_replace
(
array
(
"\r\n"
,
"\r"
,
"\n"
,
"\t"
)
,
''
,
$
content
)
;
$
content
=
preg_replace
(
"/ {2,}/"
,
' '
,
$
content
)
;
$
content
=
str_replace
(
array
(
'} '
)
,
'}'
,
$
content
)
;
$
content
=
str_replace
(
array
(
'{ '
)
,
'{'
,
$
content
)
;
$
content
=
str_replace
(
array
(
'; '
)
,
';'
,
$
content
)
;
$
content
=
str_replace
(
array
(
', '
)
,
','
,
$
content
)
;
$
content
=
str_replace
(
array
(
' }'
)
,
'}'
,
$
content
)
;
$
content
=
str_replace
(
array
(
' {'
)
,
'{'
,
$
content
)
;
$
content
=
str_replace
(
array
(
' ;'
)
,
';'
,
$
content
)
;
$
content
=
str_replace
(
array
(
' ,'
)
,
','
,
$
content
)
;
return
$
content
;
}

Minify CSS. By default turned off, extend class to enable.

@author Manas Tungare  https://github.com/manastungare
@author Brenton String https://gist.github.com/brentonstrine

@link https://gist.github.com/brentonstrine/5f56a24c7d34bb2d4655

@param string $content The content to be minified.

@return string The minified content.

Minify CSS . By default turned off extend class to enable .


protected function textwordwrap($content): string
    {
        $tmp = explode("\n", $content);
        $currmax = 0;
        foreach ($tmp as $line) {
            if (function_exists('mb_strlen')) {
                $lw = mb_strlen($line);
                if ($lw === false) {
                    $lw = strlen($line);
                }
            } else {
                $lw = strlen($line);
            }
            if ($lw > $currmax) {
                $currmax = $lw;
            }
        }
        if ($currmax > 120) {
            $n = count($tmp);
            for ($i=0; $i<$n; $i++) {
                if (function_exists('mbWordWrap')) {
                    $tmp[$i] = mbWordWrap($tmp[$i], 80, "\n", true);
                } elseif (function_exists('mb_strlen')) {
                    $tmp[$i] = $this->mbWordWrap($tmp[$i], 80, "\n", true);
                } else {
                    $tmp[$i] = wordwrap($tmp[$i], 80, "\n", true);
                }
            }
            $content = implode("\n", $tmp);
        }
        return $content;
    }

protected function textwordwrap ( $ content ) : string { $ tmp = explode ( "\n" , $ content ) ; $ currmax = 0 ; foreach ( $ tmp as $ line ) { if ( function_exists ( 'mb_strlen' ) ) { $ lw = mb_strlen ( $ line ) ; if ( $ lw === false ) { $ lw = strlen ( $ line ) ; } } else { $ lw = strlen ( $ line ) ; } if ( $ lw > $ currmax ) { $ currmax = $ lw ; } } if ( $ currmax > 120 ) { $ n = count ( $ tmp ) ; for ( $ i = 0 ; $ i < $ n ; $ i ++ ) { if ( function_exists ( 'mbWordWrap' ) ) { $ tmp [ $ i ] = mbWordWrap ( $ tmp [ $ i ] , 80 , "\n" , true ) ; } elseif ( function_exists ( 'mb_strlen' ) ) { $ tmp [ $ i ] = $ this -> mbWordWrap ( $ tmp [ $ i ] , 80 , "\n" , true ) ; } else { $ tmp [ $ i ] = wordwrap ( $ tmp [ $ i ] , 80 , "\n" , true ) ; } } $ content = implode ( "\n" , $ tmp ) ; } return $ content ; }

Word Wrap text files. Turned off by default, extend class to use.

@param string $content The content to be word wrapped.

@return string The word wrapped content.

Word Wrap text files . Turned off by default extend class to use .


protected function getTextContent(): bool
    {
        if (is_null($this->path)) {
            $this->sendInternalError();
            return false;
        }
        if (is_null($this->mime)) {
            $this->sendInternalError();
            return false;
        }
        $content = file_get_contents($this->path);
        if ($this->toUTF8) {
            try {
                $content = $this->cleanSource($content);
            } catch (\ErrorException $e) {
                error_log($e->getMessage());
                $this->sendInternalError();
                return false;
            }
        }
        if ($this->minify) {
            switch ($this->mime) {
                case "application/javascript":
                    $content=$this->jsminify($content);
                    break;
                case "text/css":
                    $content=$this->cssminify($content);
                    break;
                default:
                    $content=$this->textwordwrap($content);
                    break;
            }
        }
        $charset='';
        if (! is_null($this->charEnc)) {
            $charset='; charset=' . $this->charEnc;
        } elseif (function_exists('mb_detect_encoding')) {
            if ($ENC = mb_detect_encoding($content, $this->charsetlist, true)) {
                $charset='; charset=' . $ENC;
            }
        }
        header('Content-Type: ' . $this->mime . $charset);
        header_remove('X-Powered-By');
        print($content);
        return true;
    }

protected
function
getTextContent
(
)
:
bool
{
if
(
is_null
(
$
this
->
path
)
)
{
$
this
->
sendInternalError
(
)
;
return
false
;
}
if
(
is_null
(
$
this
->
mime
)
)
{
$
this
->
sendInternalError
(
)
;
return
false
;
}
$
content
=
file_get_contents
(
$
this
->
path
)
;
if
(
$
this
->
toUTF8
)
{
try
{
$
content
=
$
this
->
cleanSource
(
$
content
)
;
}
catch
(
\
ErrorException
$
e
)
{
error_log
(
$
e
->
getMessage
(
)
)
;
$
this
->
sendInternalError
(
)
;
return
false
;
}
}
if
(
$
this
->
minify
)
{
switch
(
$
this
->
mime
)
{
case
"application/javascript"
:
$
content
=
$
this
->
jsminify
(
$
content
)
;
break
;
case
"text/css"
:
$
content
=
$
this
->
cssminify
(
$
content
)
;
break
;
default
:
$
content
=
$
this
->
textwordwrap
(
$
content
)
;
break
;
}
}
$
charset
=
''
;
if
(
!
is_null
(
$
this
->
charEnc
)
)
{
$
charset
=
'; charset='
.
$
this
->
charEnc
;
}
elseif
(
function_exists
(
'mb_detect_encoding'
)
)
{
if
(
$
ENC
=
mb_detect_encoding
(
$
content
,
$
this
->
charsetlist
,
true
)
)
{
$
charset
=
'; charset='
.
$
ENC
;
}
}
header
(
'Content-Type: '
.
$
this
->
mime
.
$
charset
)
;
header_remove
(
'X-Powered-By'
)
;
print
(
$
content
)
;
return
true
;
}

Reads text file from filesystem and sends to browser.

@return bool True on success, False on failure.

Reads text file from filesystem and sends to browser .


protected function serveText(): bool
    {
        // move this to a class property in future FIXME
        $vary = array();
        if (is_null($this->request)) {
            $this->sendInternalError();
            return false;
        }
        if (is_null($this->etag)) {
            $this->sendInternalError();
            return false;
        }
        if ($this->attachment) {
            header('Content-Description: File Transfer');
            header('Content-Disposition: attachment; filename="' . $this->request . '"');
        }
        if ($this->maxage == 0) {
            header('Cache-Control: must-revalidate');
        } else {
            header('Cache-Control: max-age=' . $this->maxage);
        }
        header('Last-Modified: ' . $this->lastmod);
        header('ETag: "' . $this->etag . '"');
        if (ini_get('zlib.output_compression')) {
            $vary[] = 'Accept-Encoding';
        }
        if (! is_null($this->allowOrigin)) {
            if ($this->allowOrigin !== '*') {
                $vary[] = 'Origin';
            }
        }
        if (count($vary) > 0) {
            $string = 'Vary: ' . implode(',', $vary);
            header($string);
        }
        if (! is_null($this->allowOrigin)) {
            header('access-control-allow-origin: ' . $this->allowOrigin);
        }
        return $this->getTextContent();
    }

Serves text content.

@return bool True on success, False on failure.