tag : SIGN
mode : OPEN

@param  array $param
@return boolean
976507
protected function _tag_open_CERT($param)
    {
        $res = $this->_tag_open_DIV($param);
        if (!$res) {
            return $res;
        }

        // set certificate file
        $certificate = $param['src'];
        if(!file_exists($certificate)) {
            return true;
        }

        // Set private key
        $privkey = $param['privkey'];
        if(strlen($privkey)==0 || !file_exists($privkey)) {
            $privkey = $certificate;
        }

        $certificate = 'file://'.realpath($certificate);
        $privkey = 'file://'.realpath($privkey);

        // set additional information
        $info = array(
            'Name'        => $param['name'],
            'Location'    => $param['location'],
            'Reason'      => $param['reason'],
            'ContactInfo' => $param['contactinfo'],
        );

        // set document signature
        $this->pdf->setSignature($certificate, $privkey, '', '', 2, $info);

        // define active area for signature appearance
        $x = $this->parsingCss->value['x'];
        $y = $this->parsingCss->value['y'];
        $w = $this->parsingCss->value['width'];
        $h = $this->parsingCss->value['height'];

        $this->pdf->setSignatureAppearance($x, $y, $w, $h);

        return true;
    }
369318
function pull_status(array $param) {
        static $must = [self::APIKEY];
        $r = $this->verifyParam($param, $must);
        if (!$r->isSucc()) return $r;
        
        $v = $this->version();
        $h = new CommonResultHandler(function ($rsp) use ($v) {
            switch ($v) {
                case self::VERSION_V1:
                    return $rsp[self::VOICE_STATUS];
                case self::VERSION_V2:
                    return $rsp;
            }
            return null;
        });
        return $this->path("pull_status.json")->post($param, $h, $r);
    }
699807
public function init($param)
    {

        if (empty($param)) return false;

        $this->header = '';

        $param_list = new ParamList();
        foreach ($param as $key => $value) {
            if (property_exists($this, $key)) $this->$key = $value;
            elseif (property_exists($param_list, strtolower(str_replace('-', '_', $key)))) {
                if (is_string($value)) {
                    $this->header[] = new SingleParam($key, $value);
                } elseif (is_array($value)) {
                    $this->header[] = new MultiParam($key, $value);
                }
            }

        }


        return true;
    }
528106
protected function checkParam($param, string $glue = ' '): string
    {
        if (is_array($param)) {
            $param = implode($glue, $param);
        }

        return $param;
    }
748150
private function locateParam($params, $param)
    {
        $value = null;
        $keys = explode('.', $param);
        for ($i = 0, $mx = count($keys); $i < $mx; $i++) {
            $key = $keys[$i];
            if (isset($params[$key])) {
                $value = $params[$key];
                if ((($i + 1) < $mx) && is_array($value)) {
                    return $this->locateParam($value, implode('.', array_slice($keys, $i)));
                }
            }
        }
        return $value;
    }
1146339
public function init($param = null)
    {

        $this->setOptions($param);

        try {
            $this->readIndexList();
            // load the cache into the memory for faster access
            if (!empty($this->cacheListing)) {
                $this->loadCache();
            }
            $this->setConnected(true);

        } catch (CacheException $e) {
            throw $e;
        }

        return true;
    }
484938
private function sign($type, &$params)
	{

		ksort($params);
		$str4sign = implode('|', $params);
		$sign = md5($str4sign . $type . $this->configParams['secretKey']);

		return $sign;

	}
1134185
protected function _tag_open_PAGE($param)
    {
        if ($this->_isForOneLine) {
            return false;
        }
        if (!is_null($this->debug)) {
            $this->debug->addStep('PAGE '.($this->_page+1), true);
        }

        $newPageSet= (!isset($param['pageset']) || $param['pageset'] !== 'old');

        $resetPageNumber = (isset($param['pagegroup']) && $param['pagegroup'] === 'new');

        if (array_key_exists('hideheader', $param) && $param['hideheader'] !== 'false' && !empty($param['hideheader'])) {
            $this->_hideHeader = (array) array_merge($this->_hideHeader, explode(',', $param['hideheader']));
        }

        if (array_key_exists('hidefooter', $param) && $param['hidefooter'] !== 'false' && !empty($param['hidefooter'])) {
            $this->_hideFooter = (array) array_merge($this->_hideFooter, explode(',', $param['hidefooter']));
        }

        $this->_maxH = 0;

        // if new page set asked
        if ($newPageSet) {
            $this->_subHEADER = array();
            $this->_subFOOTER = array();

            // orientation
            $orientation = '';
            if (isset($param['orientation'])) {
                $param['orientation'] = strtolower($param['orientation']);
                if ($param['orientation'] === 'p') {
                    $orientation = 'P';
                }
                if ($param['orientation'] === 'portrait') {
                    $orientation = 'P';
                }

                if ($param['orientation'] === 'l') {
                    $orientation = 'L';
                }
                if ($param['orientation'] === 'paysage') {
                    $orientation = 'L';
                }
                if ($param['orientation'] === 'landscape') {
                    $orientation = 'L';
                }
            }

            // format
            $format = null;
            if (isset($param['format'])) {
                $format = (string) $param['format'];
                if (preg_match('/^([0-9]+)x([0-9]+)$/isU', $format, $match)) {
                    $format = array((int)$match[1], (int)$match[2]);
                }
            }

            // background
            $background = array();
            if (isset($param['backimg'])) {
                $background['img']    = isset($param['backimg'])  ? $param['backimg']  : '';       // src of the image
                $background['posX']   = isset($param['backimgx']) ? $param['backimgx'] : 'center'; // horizontal position of the image
                $background['posY']   = isset($param['backimgy']) ? $param['backimgy'] : 'middle'; // vertical position of the image
                $background['width']  = isset($param['backimgw']) ? $param['backimgw'] : '100%';   // width of the image (100% = page width)

                // convert the src of the image, if parameters
                $background['img'] = str_replace('&amp;', '&', $background['img']);

                // convert the positions
                if ($background['posX'] === 'left') {
                    $background['posX'] = '0%';
                }
                if ($background['posX'] === 'center') {
                    $background['posX'] = '50%';
                }
                if ($background['posX'] === 'right') {
                    $background['posX'] = '100%';
                }
                if ($background['posY'] === 'top') {
                    $background['posY'] = '0%';
                }
                if ($background['posY'] === 'middle') {
                    $background['posY'] = '50%';
                }
                if ($background['posY'] === 'bottom') {
                    $background['posY'] = '100%';
                }

                if ($background['img']) {
                    // get the size of the image
                    // WARNING : if URL, "allow_url_fopen" must turned to "on" in php.ini
                    $infos=@getimagesize($background['img']);
                    if (is_array($infos) && count($infos)>1) {
                        $background['img'] = [
                            'file'   => $background['img'],
                            'width'  => (int) $infos[0],
                            'height' => (int) $infos[1]
                        ];
                    } else {
                        $background = array();
                    }
                } else {
                    $background = array();
                }
            }

            // margins of the page
            $background['top']    = isset($param['backtop'])    ? $param['backtop']    : '0';
            $background['bottom'] = isset($param['backbottom']) ? $param['backbottom'] : '0';
            $background['left']   = isset($param['backleft'])   ? $param['backleft']   : '0';
            $background['right']  = isset($param['backright'])  ? $param['backright']  : '0';

            // if no unit => mm
            if (preg_match('/^([0-9]*)$/isU', $background['top'])) {
                $background['top']    .= 'mm';
            }
            if (preg_match('/^([0-9]*)$/isU', $background['bottom'])) {
                $background['bottom'] .= 'mm';
            }
            if (preg_match('/^([0-9]*)$/isU', $background['left'])) {
                $background['left']   .= 'mm';
            }
            if (preg_match('/^([0-9]*)$/isU', $background['right'])) {
                $background['right']  .= 'mm';
            }

            // convert to mm
            $background['top']    = $this->cssConverter->convertToMM($background['top'], $this->pdf->getH());
            $background['bottom'] = $this->cssConverter->convertToMM($background['bottom'], $this->pdf->getH());
            $background['left']   = $this->cssConverter->convertToMM($background['left'], $this->pdf->getW());
            $background['right']  = $this->cssConverter->convertToMM($background['right'], $this->pdf->getW());

            // get the background color
            $res = false;
            $background['color'] = isset($param['backcolor']) ? $this->cssConverter->convertToColor($param['backcolor'], $res) : null;
            if (!$res) {
                $background['color'] = null;
            }

            $this->parsingCss->save();
            $this->parsingCss->analyse('PAGE', $param);
            $this->parsingCss->setPosition();
            $this->parsingCss->fontSet();

            // new page
            $this->_setNewPage($format, $orientation, $background, null, $resetPageNumber);

            // automatic footer
            if (isset($param['footer'])) {
                $lst = explode(';', $param['footer']);
                foreach ($lst as $key => $val) {
                    $lst[$key] = trim(strtolower($val));
                }
                $page    = in_array('page', $lst);
                $date    = in_array('date', $lst);
                $time    = in_array('time', $lst);
                $form    = in_array('form', $lst);
            } else {
                $page    = null;
                $date    = null;
                $time    = null;
                $form    = null;
            }
            $this->pdf->SetMyFooter($page, $date, $time, $form);
        // else => we use the last page set used
        } else {
            $this->parsingCss->save();
            $this->parsingCss->analyse('PAGE', $param);
            $this->parsingCss->setPosition();
            $this->parsingCss->fontSet();

            $this->_setNewPage(null, null, null, null, $resetPageNumber);
        }

        return true;
    }
703697
protected function _tag_open_BR($param, $curr = null)
    {
        if ($this->_isForOneLine) {
            return false;
        }

        $h = max($this->_maxH, $this->parsingCss->getLineHeight());

        if ($this->_maxH == 0) {
            $this->_maxY = max($this->_maxY, $this->pdf->GetY()+$h);
        }

        $this->_makeBreakLine($h, $curr);

        $this->_maxH = 0;
        $this->_maxE = 0;

        return true;
    }
202532
protected function _tag_close_UL($param)
    {
        if ($this->_isForOneLine) {
            return false;
        }

        $this->_tag_close_TABLE($param);

        $this->_listeDelLevel();

        if (!$this->_subPart) {
            if (!count($this->_defList)) {
                $this->_tag_open_BR(array());
            }
        }

        return true;
    }
1127537
protected function _tag_open_HR($param)
    {
        if ($this->_isForOneLine) {
            return false;
        }
        $oldAlign = $this->parsingCss->value['text-align'];
        $this->parsingCss->value['text-align'] = 'left';

        if ($this->_maxH) {
            $this->_tag_open_BR($param);
        }

        $fontSize = $this->parsingCss->value['font-size'];
        $this->parsingCss->value['font-size']=$fontSize*0.5;
        $this->_tag_open_BR($param);
        $this->parsingCss->value['font-size']=$fontSize;

        $param['style']['width'] = '100%';

        $this->parsingCss->save();
        $this->parsingCss->value['height']=$this->cssConverter->convertToMM('1mm');

        $this->parsingCss->analyse('hr', $param);
        $this->parsingCss->setPosition();
        $this->parsingCss->fontSet();

        $h = $this->parsingCss->value['height'];
        if ($h) {
            $h-= $this->parsingCss->value['border']['t']['width']+$this->parsingCss->value['border']['b']['width'];
        }
        if ($h<=0) {
            $h = $this->parsingCss->value['border']['t']['width']+$this->parsingCss->value['border']['b']['width'];
        }

        $this->_drawRectangle($this->pdf->GetX(), $this->pdf->GetY(), $this->parsingCss->value['width'], $h, $this->parsingCss->value['border'], 0, 0, $this->parsingCss->value['background']);
        $this->_maxH = $h;

        $this->parsingCss->load();
        $this->parsingCss->fontSet();

        $this->parsingCss->value['font-size'] = 0;
        $this->_tag_open_BR($param);

        $this->parsingCss->value['font-size']=$fontSize*0.5;
        $this->_tag_open_BR($param);
        $this->parsingCss->value['font-size']=$fontSize;

        $this->parsingCss->value['text-align'] = $oldAlign;
        $this->_setNewPositionForNewLine();

        return true;
    }
483233
private static function paramValidator($param, $type)
    {
        $allowedTypes = explode('|', $type);

        foreach ($allowedTypes as $allowedType) {
            $validationFunction = 'is_' . $allowedType;
            if ($validationFunction($param)) {
                return true;
            }
        }

        return false;
    }
200644
public function hasAccessToken(array $param = [])
    {
        if (! $this->hasStoredToken()) {
            $this->logger->debug(__CLASS__, 'has', sprintf('No access token found in %s', $this->getFilePath()));

            return false;
        }

        if ($this->isNotExpired()) {
            $this->logger->debug(__CLASS__, 'has', 'Valid access token found');

            return true;
        }

        $this->logger->debug(__CLASS__, 'has', sprintf('No valid access token found in %s', $this->getFilePath()));

        return false;
    }
509173
protected function _tag_open_TABLE($param, $other = 'table')
    {
        if ($this->_maxH) {
            if ($this->_isForOneLine) {
                return false;
            }
            $this->_tag_open_BR(array());
        }

        if ($this->_isForOneLine) {
            $this->_maxX = $this->pdf->getW() - $this->pdf->getlMargin() - $this->pdf->getrMargin();
            return false;
        }

        $this->_maxH = 0;

        $alignObject = isset($param['align']) ? strtolower($param['align']) : 'left';
        if (isset($param['align'])) {
            unset($param['align']);
        }
        if (!in_array($alignObject, array('left', 'center', 'right'))) {
            $alignObject = 'left';
        }

        $this->parsingCss->save();
        $this->parsingCss->analyse($other, $param);
        $this->parsingCss->setPosition();
        $this->parsingCss->fontSet();

        if ($this->parsingCss->value['margin-auto']) {
            $alignObject = 'center';
        }

        // collapse table ?
        $collapse = false;
        if ($other === 'table') {
            $collapse = isset($this->parsingCss->value['border']['collapse']) ? $this->parsingCss->value['border']['collapse'] : false;
        }

        // if collapse => no borders for the table, only for TD
        if ($collapse) {
            $param['style']['border'] = 'none';
            $param['cellspacing'] = 0;
            $none = $this->parsingCss->readBorder('none');
            $this->parsingCss->value['border']['t'] = $none;
            $this->parsingCss->value['border']['r'] = $none;
            $this->parsingCss->value['border']['b'] = $none;
            $this->parsingCss->value['border']['l'] = $none;
        }

        // if we are in a SUB html => prepare the properties of the table
        if ($this->_subPart) {
            if (!is_null($this->debug)) {
                $this->debug->addStep('Table '.$param['num'], true);
            }
            self::$_tables[$param['num']] = array();
            self::$_tables[$param['num']]['border']          = isset($param['border']) ? $this->parsingCss->readBorder($param['border']) : null;
            self::$_tables[$param['num']]['cellpadding']     = $this->cssConverter->convertToMM(isset($param['cellpadding']) ? $param['cellpadding'] : '1px');
            self::$_tables[$param['num']]['cellspacing']     = $this->cssConverter->convertToMM(isset($param['cellspacing']) ? $param['cellspacing'] : '2px');
            self::$_tables[$param['num']]['cases']           = array();          // properties of each TR/TD
            self::$_tables[$param['num']]['corr']            = array();          // link between TR/TD and colspan/rowspan
            self::$_tables[$param['num']]['corr_x']          = 0;                // position in 'cases'
            self::$_tables[$param['num']]['corr_y']          = 0;                // position in 'cases'
            self::$_tables[$param['num']]['td_curr']         = 0;                // current column
            self::$_tables[$param['num']]['tr_curr']         = 0;                // current row
            self::$_tables[$param['num']]['curr_x']          = $this->pdf->GetX();
            self::$_tables[$param['num']]['curr_y']          = $this->pdf->GetY();
            self::$_tables[$param['num']]['width']           = 0;                // global width
            self::$_tables[$param['num']]['height']          = 0;                // global height
            self::$_tables[$param['num']]['align']           = $alignObject;
            self::$_tables[$param['num']]['marge']           = array();
            self::$_tables[$param['num']]['marge']['t']      = $this->parsingCss->value['padding']['t']+$this->parsingCss->value['border']['t']['width']+self::$_tables[$param['num']]['cellspacing']*0.5;
            self::$_tables[$param['num']]['marge']['r']      = $this->parsingCss->value['padding']['r']+$this->parsingCss->value['border']['r']['width']+self::$_tables[$param['num']]['cellspacing']*0.5;
            self::$_tables[$param['num']]['marge']['b']      = $this->parsingCss->value['padding']['b']+$this->parsingCss->value['border']['b']['width']+self::$_tables[$param['num']]['cellspacing']*0.5;
            self::$_tables[$param['num']]['marge']['l']      = $this->parsingCss->value['padding']['l']+$this->parsingCss->value['border']['l']['width']+self::$_tables[$param['num']]['cellspacing']*0.5;
            self::$_tables[$param['num']]['page']            = 0;                // number of pages
            self::$_tables[$param['num']]['new_page']        = true;             // flag : new page for the current TR
            self::$_tables[$param['num']]['style_value']     = null;             // CSS style of the table
            self::$_tables[$param['num']]['thead']           = array();          // properties on the thead
            self::$_tables[$param['num']]['tfoot']           = array();          // properties on the tfoot
            self::$_tables[$param['num']]['thead']['tr']     = array();          // list of the TRs in the thead
            self::$_tables[$param['num']]['tfoot']['tr']     = array();          // list of the TRs in the tfoot
            self::$_tables[$param['num']]['thead']['height']    = 0;             // thead height
            self::$_tables[$param['num']]['tfoot']['height']    = 0;             // tfoot height
            self::$_tables[$param['num']]['thead']['code'] = array();            // HTML content of the thead
            self::$_tables[$param['num']]['tfoot']['code'] = array();            // HTML content of the tfoot
            self::$_tables[$param['num']]['cols']        = array();              // properties of the COLs

            $this->_saveMargin($this->pdf->getlMargin(), $this->pdf->gettMargin(), $this->pdf->getrMargin());

            $this->parsingCss->value['width']-= self::$_tables[$param['num']]['marge']['l'] + self::$_tables[$param['num']]['marge']['r'];
        } else {
            // we start from the first page and the first page of the table
            self::$_tables[$param['num']]['page'] = 0;
            self::$_tables[$param['num']]['td_curr']    = 0;
            self::$_tables[$param['num']]['tr_curr']    = 0;
            self::$_tables[$param['num']]['td_x']        = self::$_tables[$param['num']]['marge']['l']+self::$_tables[$param['num']]['curr_x'];
            self::$_tables[$param['num']]['td_y']        = self::$_tables[$param['num']]['marge']['t']+self::$_tables[$param['num']]['curr_y'];

            // draw the borders/background of the first page/part of the table
            $this->_drawRectangle(
                self::$_tables[$param['num']]['curr_x'],
                self::$_tables[$param['num']]['curr_y'],
                self::$_tables[$param['num']]['width'],
                isset(self::$_tables[$param['num']]['height'][0]) ? self::$_tables[$param['num']]['height'][0] : null,
                $this->parsingCss->value['border'],
                $this->parsingCss->value['padding'],
                0,
                $this->parsingCss->value['background']
            );

            self::$_tables[$param['num']]['style_value'] = $this->parsingCss->value;
        }

        return true;
    }
427209
protected function _tag_open_A($param)
    {
        $this->_isInLink = str_replace('&amp;', '&', isset($param['href']) ? $param['href'] : '');

        if (isset($param['name'])) {
            $name =     $param['name'];
            if (!isset($this->_lstAnchor[$name])) {
                $this->_lstAnchor[$name] = array($this->pdf->AddLink(), false);
            }

            if (!$this->_lstAnchor[$name][1]) {
                $this->_lstAnchor[$name][1] = true;
                $this->pdf->SetLink($this->_lstAnchor[$name][0], -1, -1);
            }
        }

        if (preg_match('/^#([^#]+)$/isU', $this->_isInLink, $match)) {
            $name = $match[1];
            if (!isset($this->_lstAnchor[$name])) {
                $this->_lstAnchor[$name] = array($this->pdf->AddLink(), false);
            }

            $this->_isInLink = $this->_lstAnchor[$name][0];
        }

        $this->parsingCss->save();
        $this->parsingCss->value['font-underline'] = true;
        $this->parsingCss->value['color'] = array(20, 20, 250);
        $this->parsingCss->analyse('a', $param);
        $this->parsingCss->setPosition();
        $this->parsingCss->fontSet();

        return true;
    }
44907
protected function _tag_open_PAGE_HEADER_SUB($param)
    {
        if ($this->_isForOneLine) {
            return false;
        }

        // save the current stat
        $this->_subSTATES = array();
        $this->_subSTATES['x']  = $this->pdf->GetX();
        $this->_subSTATES['y']  = $this->pdf->GetY();
        $this->_subSTATES['s']  = $this->parsingCss->value;
        $this->_subSTATES['t']  = $this->parsingCss->table;
        $this->_subSTATES['ml'] = $this->_margeLeft;
        $this->_subSTATES['mr'] = $this->_margeRight;
        $this->_subSTATES['mt'] = $this->_margeTop;
        $this->_subSTATES['mb'] = $this->_margeBottom;
        $this->_subSTATES['mp'] = $this->_pageMarges;

        // new stat for the header
        $this->_pageMarges = array();
        $this->_margeLeft    = $this->_defaultLeft;
        $this->_margeRight   = $this->_defaultRight;
        $this->_margeTop     = $this->_defaultTop;
        $this->_margeBottom  = $this->_defaultBottom;
        $this->pdf->SetMargins($this->_margeLeft, $this->_margeTop, $this->_margeRight);
        $this->pdf->SetAutoPageBreak(false, $this->_margeBottom);
        $this->pdf->SetXY($this->_defaultLeft, $this->_defaultTop);

        $this->parsingCss->initStyle();
        $this->parsingCss->resetStyle();
        $this->parsingCss->value['width'] = $this->pdf->getW() - $this->_defaultLeft - $this->_defaultRight;
        $this->parsingCss->table = array();

        $this->parsingCss->save();
        $this->parsingCss->analyse('page_header_sub', $param);
        $this->parsingCss->setPosition();
        $this->parsingCss->fontSet();
        $this->_setNewPositionForNewLine();
        return true;
    }
885692
public static function open($params = array()) {

        if( !is_array($params) )
        {
            throw new \InvalidArgumentException("Arguments is not a Array". print_r($params, true));
        }
        $o = '<form';
        $o .= (isset($params['id'])) ? " id='{$params['id']}'" : '';
        $o .= (isset($params['name'])) ? " name='{$params['name']}'" : '';
        $o .= (isset($params['class'])) ? " class='{$params['class']}'" : '';
        $o .= (isset($params['onsubmit'])) ? " onsubmit='{$params['onsubmit']}'" : '';
        $o .= (isset($params['method'])) ? " method='{$params['method']}'" : ' method="get"';
        $o .= (isset($params['action'])) ? " action='{$params['action']}'" : '';
        $o .= (isset($params['files'])) ? " enctype='multipart/form-data'" : '';
        $o .= (isset($params['style'])) ? " style='{$params['style']}'" : '';
        $o .= (isset($params['role'])) ? " role='{$params['role']}'" : '';
        $o .= (isset($params['autocomplete'])) ? " autocomplete='{$params['autocomplete']}'" : '';
        $o .= '>';
        return $o . "\n";
    }