Ejemplo n.º 1
0
 /**
  * Creates a new HttpRequest object based on the given data
  * @param array $requestData Data of the HTTP request
  * @return HttpRequest
  */
 public static function create(array $requestData = array())
 {
     $defaultValues = array('REQUEST_TIME' => time(), 'SERVER_PORT' => null, 'SERVER_NAME' => null, 'QUERY_STRING' => null, 'REMOTE_ADDR' => null, 'HTTP_USER_AGENT' => null, 'HTTPS' => null, 'REQUEST_URI' => null, 'HTTP_ACCEPT_LANGUAGE' => null, 'HTTP_ACCEPT_ENCODING' => null, 'REQUEST_METHOD' => null);
     $requestData = array_merge($defaultValues, $requestData);
     $httpRequest = new HttpRequest();
     $protocol = null;
     if ($requestData['HTTPS'] !== null) {
         $protocol = $requestData['HTTPS'] === 'on' ? HttpRequest::PROTOCOL_HTTPS : HttpRequest::PROTOCOL_HTTP;
     }
     $uri = StringUtils::startsWith($requestData['REQUEST_URI'], self::$basePath) ? StringUtils::afterFirst($requestData['REQUEST_URI'], self::$basePath) : $requestData['REQUEST_URI'];
     $path = StringUtils::beforeLast($uri, '?');
     $languages = array();
     $langRates = array_filter(explode(',', $requestData['HTTP_ACCEPT_LANGUAGE']));
     foreach ($langRates as $lr) {
         list($langCode, $importance) = array_pad(preg_split('/;(?:q=)?/', $lr), 2, 1.0);
         $languages[$langCode] = (double) $importance;
     }
     $acceptedEncoding = array_filter(array_map('trim', explode(',', $requestData['HTTP_ACCEPT_ENCODING'])));
     $requestTime = new \DateTime();
     $requestTime->setTimestamp($requestData['REQUEST_TIME']);
     $httpRequest->setHost($requestData['SERVER_NAME']);
     $httpRequest->setPath($path);
     $httpRequest->setPort($requestData['SERVER_PORT']);
     $httpRequest->setProtocol($protocol);
     $httpRequest->setQuery($requestData['QUERY_STRING']);
     $httpRequest->setURI($uri);
     $httpRequest->setRequestTime($requestTime);
     $httpRequest->setAcceptedEncodings($acceptedEncoding);
     $httpRequest->setRequestMethod($requestData['REQUEST_METHOD']);
     $httpRequest->setUserAgent($requestData['HTTP_USER_AGENT']);
     $httpRequest->setAcceptedLanguages($languages);
     $httpRequest->setRemoteAddress($requestData['REMOTE_ADDR']);
     $headers = array();
     foreach ($_SERVER as $name => $value) {
         if (StringUtils::startsWith($name, 'HTTP_') === true) {
             $name = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))));
             $headers[$name] = $value;
         } elseif ($name == 'CONTENT_TYPE') {
             $headers['Content-Type'] = $value;
         } elseif ($name == 'CONTENT_LENGTH') {
             $headers['Content-Length'] = $value;
         }
     }
     $httpRequest->setHeaders($headers);
     return $httpRequest;
 }
Ejemplo n.º 2
0
 public function testAfterFirst()
 {
     $this->assertSame(StringUtils::afterFirst('foo/bar', '/'), 'bar', 'Test 1');
     $this->assertSame(StringUtils::afterFirst('foo/', '/'), '', 'Test 2');
 }
    /**
     * Generates the HTML config form for the element
     * 
     * @param BackendController $backendController
     * @param int $pageID The current pages ID
     *
     * @return string The config box as HTML
     * @throws CMSException
     * @throws \Exception
     */
    public function generateConfigBox(BackendController $backendController, $pageID)
    {
        $lang = $backendController->getLocaleHandler()->getLanguage();
        $configFilePath = $backendController->getCore()->getSiteRoot() . 'settings' . DIRECTORY_SEPARATOR . 'elements' . DIRECTORY_SEPARATOR;
        $configFile = $configFilePath . $this->identifier . '.config.json';
        if (file_exists($configFile) === false) {
            throw new CMSException('No settings found for this module: ' . $this->identifier);
        }
        try {
            $jsonConfig = JsonUtils::decode(file_get_contents($configFile));
            if (!isset($jsonConfig->settings)) {
                return 500;
            }
        } catch (\Exception $e) {
            throw $e;
        }
        $modIDStr = 'mod-' . $this->ID . '-' . $pageID;
        $boxHtml = '<form method="post" class="mod-config-form" element="' . $modIDStr . '"><fieldset><legend>Element specific</legend>';
        foreach ($jsonConfig->settings as $key => $entry) {
            $fld = null;
            $hintHtml = isset($entry->hint) ? '<abbr title="' . $entry->hint->{$lang} . '">?</abbr>' : null;
            $settingValue = isset($this->settings->{$key}) ? $this->settings->{$key} : null;
            $idStr = 'mod-' . $this->ID . '-' . $pageID . '-' . $key;
            $requiredHtml = $entry->required ? '<em title="required">*</em>' : null;
            $requiredAttr = $entry->required ? ' required' : null;
            if (in_array($entry->type, array('select', 'option', 'select-multi', 'multi-option'))) {
                $multiple = null;
                $multiBrackets = null;
                if (in_array($entry->type, array('select-multi', 'multi-option'))) {
                    $multiple = ' multiple';
                    $multiBrackets = '[]';
                }
                $fld .= '<dl><dt><label for="' . $idStr . '">' . $entry->label->{$lang} . $requiredHtml . '</label></dt>
				<dd><select name="' . $key . $multiBrackets . '" id="' . $idStr . '"' . $requiredAttr . $multiple . '>';
                $values = $this->getValues($entry->options, $backendController);
                foreach ($values as $optKey => $optVal) {
                    if (in_array($entry->type, array('select-multi', 'multi-option'))) {
                        $selected = in_array($optKey, $this->settings->{$key}) ? ' selected' : null;
                    } else {
                        $selected = $this->settings->{$key} == $optKey ? ' selected' : null;
                    }
                    $fld .= '<option value="' . $optKey . '"' . $selected . '>' . $optVal . '</option>';
                }
                $fld .= '</select>' . $hintHtml . '</dd></dl>';
            } elseif (in_array($entry->type, array('input', 'email', 'number', 'url', 'regex', 'string', 'text', 'file'))) {
                $dataAttrs = null;
                if (in_array($entry->type, array('input', 'text', 'string', 'number', 'regex'))) {
                    $typeStr = 'text';
                    $dataAttrs = ' data-type="string"';
                } elseif ($entry->type === 'file') {
                    $typeStr = 'text';
                    $dataAttrs = ' class="filechooser"';
                } else {
                    $typeStr = $entry->type;
                    $dataAttrs = ' data-type="' . $entry->type . '"';
                }
                if ($entry->type === 'regex' && isset($entry->regex)) {
                    $dataAttrs = ' data-type="regex" regex="' . $entry->regex . '"';
                }
                if ($entry->type === 'number') {
                    $minStr = isset($entry->min) ? ' min="' . $entry->min . '"' : null;
                    $maxStr = isset($entry->max) ? ' max="' . $entry->max . '"' : null;
                    if ($minStr !== null || $maxStr !== null) {
                        $dataAttrs = $minStr . $maxStr;
                    }
                }
                if (in_array($entry->type, array('input', 'text', 'string'))) {
                    $minStr = isset($entry->minLength) ? ' minlength="' . $entry->minLength . '"' : null;
                    $maxStr = isset($entry->maxLength) ? ' maxlength="' . $entry->maxLength . '"' : null;
                    if ($minStr !== null || $maxStr !== null) {
                        $dataAttrs = $minStr . $maxStr;
                    }
                }
                $sizeClass = StringUtils::afterFirst($entry->type, '-');
                $sizeClassStr = $sizeClass !== '' ? ' class="' . $sizeClass . '"' : null;
                $fld .= '<dl><dt><label for="' . $idStr . '">' . $entry->label->{$lang} . $requiredHtml . '</label></dt>
				<dd><input type="' . $typeStr . '" name="' . $key . '" id="' . $idStr . '" value="' . $settingValue . '"' . $sizeClassStr . '' . $requiredAttr . '' . $dataAttrs . '>' . $hintHtml . '</dd></dl>';
            } elseif (in_array($entry->type, array('radio', 'multi-checkbox'))) {
                $values = $this->getValues($entry->options, $backendController);
                $type = null;
                $multiBrackets = in_array($entry->type, array('multi-checkbox')) ? '[]' : null;
                $selectedArr = is_array($this->settings->{$key}) ? $this->settings->{$key} : array($this->settings->{$key});
                if ($entry->type === 'radio') {
                    $type = 'radio';
                } elseif ($entry->type === 'multi-checkbox') {
                    $type = 'checkbox';
                }
                $fld .= '<dl><dt>' . $entry->label->{$lang} . '</dt>
				<dd><ul>';
                foreach ($values as $optKey => $optVal) {
                    $checked = in_array($optKey, $selectedArr) ? ' checked' : null;
                    $fld .= '<li><label><input type="' . $type . '" name="' . $key . $multiBrackets . '" value="' . $optKey . '"' . $checked . '>' . $optVal . '</label></li>';
                }
                $fld .= '</ul></dd></dl>';
            } elseif ($entry->type == 'toggle') {
                $checked = $this->settings->{$key} == 1 ? ' checked' : null;
                $fld .= '<dl><dt><label for="' . $idStr . '">' . $entry->label->{$lang} . $requiredHtml . '</label></dt>
				<dd><input type="checkbox" name="' . $key . '" id="' . $idStr . '" value="1"' . $requiredAttr . $checked . '>' . $hintHtml . '</dd></dl>';
            } elseif ($entry->type === 'wysiwyg') {
                $fld .= '<dl><dt><label for="' . $idStr . '">' . $entry->label->{$lang} . $requiredHtml . '</label></dt>
				<dd><textarea class="ckeditor" name="' . $key . '" id="' . $idStr . '"' . $requiredAttr . '>' . $settingValue . '</textarea>' . $hintHtml . '</dd></dl>';
            } else {
                throw new CMSException('Unknow settings data-type: ' . $entry->type);
            }
            $boxHtml .= $fld;
        }
        $boxHtml .= '</fieldset><fieldset><legend>General</legend>
			<dl><dt>Pass on</dt>
				<dd><ul>
					<li><label><input type="checkbox" value="1">Override children\'s settings</label></li>
				</ul></dd>
			</dl>';
        if ($this->settingsSelf) {
            $boxHtml .= '<dl>
				<dt>Delete</dt>
				<dd><ul>
					<li><label><input name="delete_settings" type="checkbox" value="1">Delete specific element settings on this page</label></li>
				</ul></dd>
			</dl>';
        }
        $boxHtml .= '</fieldset></form>
		<script src="/js/ckeditor/ckeditor.js"></script>
		<script src="/js/ckeditor/config.js"></script>
		<script src="/js/jquery.filechooser.js"></script>
		<script src="/js/cms.settingsbox.js"></script>';
        return $boxHtml;
    }
Ejemplo n.º 4
0
 /**
  * @param array $sqlParams The params for the SQL query of the renderer
  *
  * @return string The rendered HTML table
  *
  * @throws \Exception
  */
 public function display(array $sqlParams = array())
 {
     $this->appendTableActions();
     $textSearch = array();
     $filterForm = false;
     foreach ($this->columns as $c) {
         /** @var Column $c */
         if (!$c->isFilterable()) {
             continue;
         }
         $filterForm = true;
         if ($this->filtersApplied === false) {
             break;
         }
         if ($c->getFilterable()->type === 'text') {
             $keywordGroupQueryStr = null;
             foreach ($this->keywords as $k) {
                 $compareWord = 'LIKE';
                 $prefix = ' OR ';
                 if (StringUtils::startsWith($k, '+')) {
                     $k = substr($k, 1);
                     $compareWord = 'LIKE';
                     $prefix = ' AND ';
                 } elseif (StringUtils::startsWith($k, '-')) {
                     $k = substr($k, 1);
                     $compareWord = 'NOT LIKE';
                     $prefix = ' AND ';
                 }
                 $keywordGroupQueryStr .= ($keywordGroupQueryStr !== null ? $prefix : null) . ($c->getSortSelector() === null ? $c->getSQLColumn() : $c->getSortSelector()) . " " . $compareWord . " ?";
                 $sqlParams[] = '%' . $k . '%';
             }
             if ($keywordGroupQueryStr === null) {
                 continue;
             }
             $textSearch[] = '(' . $keywordGroupQueryStr . ')';
         }
     }
     $hasColumnFilter = false;
     $columnFilterHtml = '<tr class="column-filters">';
     $columnFilterSql = array();
     foreach ($this->columns as $c) {
         if ($c->getColumnFilter() === null) {
             $columnFilterHtml .= '<th class="no-filter">&nbsp;</th>';
             continue;
         }
         $selection = isset($_SESSION['table'][$this->tableName]['filter'][$c->getColumnFilter()->getFilterName()]) ? $_SESSION['table'][$this->tableName]['filter'][$c->getColumnFilter()->getFilterName()] : null;
         $hasColumnFilter = true;
         $columnFilterHtml .= '<th>' . $c->getColumnFilter()->renderHtml($selection) . '</th>';
         if (($filterSql = $c->getColumnFilter()->renderSql($c->getSortSelector() !== null ? $c->getSortSelector() : $c->getSQLColumn(), $selection)) !== null) {
             $columnFilterSql[] = $filterSql;
             $sqlParams = array_merge($sqlParams, (array) $selection);
         }
     }
     if ($this->options !== null) {
         $columnFilterHtml .= "\t\t<th class=\"no-filter\">&nbsp;</th>\n";
     }
     $columnFilterHtml .= '</tr>';
     $searchHtml = null;
     $filterInfo = null;
     if ($filterForm === true) {
         $searchHtml = '<div class="table-data-search"><input type="hidden" name="table" value="' . $this->tableName . '"><input type="text" name="filter[keywords]" value="' . str_replace('"', '&quot;', $this->keywordStr) . '" placeholder="' . $this->getText('Keywords') . '"><button type="submit">' . $this->getText('Go') . '</button></div>';
     }
     $whereConds = array();
     if (count($textSearch) > 0) {
         $whereConds[] = '(' . implode(' OR ', $textSearch) . ')';
         $keywordsHtml = array();
         foreach ($this->keywords as $k) {
             $keywordsHtml[] = '<span class="' . $this->cssClass . '-keyword">' . $k . '</span>';
         }
         $filterInfo = ' (' . $this->getText('Result is filtered by keywords') . ': ' . implode(null, $keywordsHtml) . ')';
     }
     if ($this->filtersApplied) {
         $filterInfo .= ' (<a href="?table=' . $this->tableName . '&amp;resetfilters" class="table-reset-filters">' . $this->getText('reset filters') . '</a>)';
     }
     // filter
     foreach ($columnFilterSql as $filterSql) {
         $whereConds[] = '(' . $filterSql . ')';
     }
     if (count($whereConds) > 0) {
         $this->sqlQuery .= ' WHERE ' . implode(' AND ', $whereConds);
     }
     if ($this->sortable !== null) {
         $this->sqlQuery .= ' ORDER BY ' . $this->sortable['sort'];
     } elseif ($this->orderBy !== null && isset($this->columns[$this->orderBy['column']]) === true) {
         $this->sqlQuery .= ' ORDER BY ' . $this->columns[$this->orderBy['column']]->getSortSelector() . ' ' . $this->orderBy['sort'];
     }
     if (preg_match('/[\\s\\)]+FROM(?![^\\(]*\\)).*/ims', $this->sqlQuery, $fromMatches) === 0) {
         throw new TableRendererException('No FROM found in query: ' . $this->sqlQuery);
     }
     $this->stmnt = $this->db->prepare("SELECT COUNT(*) total_records " . $fromMatches[0]);
     $this->stmntLimited = $this->db->prepare($this->sqlQuery . " LIMIT ?,?");
     $res = $this->db->select($this->stmnt, $sqlParams);
     $entriesCount = $res[0]->total_records;
     $resStart = ($this->currentPage - 1) * $this->pageLimit;
     if ($resStart > $entriesCount) {
         $resStart = 0;
     }
     $sqlParams[] = $resStart;
     $sqlParams[] = $this->pageLimit;
     $resLimited = $this->db->select($this->stmntLimited, $sqlParams);
     $dataUriAttr = $this->ajaxUri !== null ? ' class="table-renderer-ajax" data-uri="' . $this->ajaxUri . '"' : null;
     $tableHtml = '<div id="' . $this->tableName . '" ' . $dataUriAttr . '><form method="post" action="?table=' . $this->tableName . '#' . $this->tableName . '" class="' . $this->cssClass . '-filters">';
     /*if($entriesCount <= 0)
     		return $tableHtml . $searchHtml . '<p class="' . $this->cssClass . '-info">' . $this->getText('No entries found.') . $filterInfo . '</p>';*/
     if ($this->columns === null) {
         $this->columns = $this->getColumnsByQuery($res);
     }
     $tableHtml .= $searchHtml;
     // PAGINATION
     $numPages = ceil($entriesCount / $this->pageLimit);
     $tableHtml .= '<div class="table-pagination-wrapper">';
     if ($numPages > 1) {
         $tableHtml .= '<ul class="' . $this->cssClass . '-pagination">';
         for ($i = 1; $i <= $numPages; ++$i) {
             $active = $i == $this->currentPage ? ' class="active"' : null;
             $tableHtml .= '<li><a href="?table=' . $this->tableName . '&amp;page=' . $i . '#' . $this->tableName . '"' . $active . '>' . $i . '</a></li>';
         }
         $tableHtml .= '</ul>';
     }
     $tableHtml .= '</div>';
     if ($this->displayInfo === true) {
         $tableHtml .= "<p class=\"" . $this->cssClass . "-info\">" . sprintf($this->getText('There is <b>%d</b> entry.', 'There are <b>%d</b> entries.', $entriesCount), $entriesCount) . $filterInfo . "</p>\n";
     }
     $tableHtml .= "<table class=\"" . $this->cssClass . "\">\n\t<thead>\n\t<tr>\n";
     if ($this->selectable === true) {
         $tableHtml .= "\t\t<th class=\"header-selectable\">&nbsp;</th>\n";
     }
     if ($this->reorder === true) {
         $tableHtml .= "\t\t<th class=\"header-reorder\">&nbsp;</th>\n";
     }
     foreach ($this->columns as $col) {
         /** @var Column $col */
         if ($col->isHidden() === true) {
             continue;
         }
         if ($this->sortable === null && $col->isSortable()) {
             $sortStr = $this->orderBy !== null && $this->orderBy['column'] == $col->getSQLColumn() && $this->orderBy['sort'] == 'ASC' ? 'DESC' : 'ASC';
             $sortClass = null;
             $sortFontIcon = '<i class="fa fa-sort"></i>';
             if ($this->orderBy !== null && $this->orderBy['column'] == $col->getSQLColumn()) {
                 $sortFontIcon = '<i class="fa ' . ($this->orderBy['sort'] === 'ASC' ? 'fa-caret-up' : 'fa-caret-down') . '"></i>';
                 $sortClass = ' class="active-' . strtolower($this->orderBy['sort']) . '"';
             }
             $label = '<a href="?table=' . $this->tableName . '&amp;sort=' . $col->getSQLColumn() . '-' . $sortStr . '#' . $this->tableName . '"' . $sortClass . '>' . $col->getLabel() . $sortFontIcon . '</a>';
         } else {
             $label = $col->getLabel();
         }
         $tableHtml .= "\t\t<th>" . $label . "</th>\n";
     }
     if ($this->options !== null) {
         $tableHtml .= "\t\t<th>&nbsp;</th>\n";
     }
     $tableHtml .= '</tr>';
     if ($hasColumnFilter) {
         $tableHtml .= $columnFilterHtml;
     }
     $sortableClass = $this->sortable !== null ? ' class="sortable-table"' : null;
     $tableHtml .= "\t</thead>\n\t<tbody" . $sortableClass . ">\n";
     $optsHtml = $this->getOptsAsHtml();
     $i = 0;
     foreach ($resLimited as $r) {
         $class = $i % 2 == 0 ? 'odd' : 'even';
         $entryID = null;
         if ($this->sortable !== null) {
             $kcArr = array();
             foreach ($this->sortable['key'] as $kc) {
                 $kcArr[] = $r->{$kc};
             }
             $entryID = 'id="sort-' . implode('-', $kcArr) . '" ';
         }
         $tableHtml .= "\t<tr " . $entryID . "class=\"" . $class . "\">\n";
         if ($this->selectable === true) {
             $tableHtml .= '<td class="selectable" style="vertical-align: middle;"><input type="checkbox" value="" name="' . $this->tableName . '[]"></td>';
         }
         if ($this->reorder === true) {
             $tableHtml .= '<td class="reorder"><span>' . $this->getText('move') . '</span></td>';
         }
         foreach ($this->columns as $col) {
             /** @var Column $col */
             if ($col->isHidden() === true) {
                 continue;
             }
             // @TODO Generate sql query don't give it as param in constructor so we can move this code to trash
             $sqlColumnIdentifier = StringUtils::afterFirst($col->getSQLColumn(), '.');
             if ($sqlColumnIdentifier === '') {
                 $sqlColumnIdentifier = $col->getSQLColumn();
             }
             $value = $col->getSQLColumn() !== null ? $r->{$sqlColumnIdentifier} : null;
             foreach ($col->getDecorators() as $d) {
                 /** @var  ColumnDecorator $d */
                 $value = $d->modify($value, $r, $col->getSQLColumn(), $this);
             }
             if ($col->isFilterable() && $this->filtersApplied) {
                 foreach ($this->keywords as $k) {
                     if (StringUtils::startsWith($k, '+') || StringUtils::startsWith($k, '-')) {
                         $k = substr($k, 1);
                     }
                     $k = str_replace(array('/', '(', ')'), array('\\/', '\\(', '\\)'), $k);
                     // regex look behind if we're not in a html tag
                     $value = preg_replace('/(?![^<]*>)(' . $k . ')/ims', '<span class="' . $this->cssClass . '-highlighted">$1</span>', $value);
                 }
             }
             $cssClassesAttr = count($col->getCssClasses()) > 0 ? ' class="' . implode(' ', $col->getCssClasses()) . '"' : null;
             $tableHtml .= "\t\t<td" . $cssClassesAttr . ">" . $value . "</td>\n";
         }
         $tableHtml .= $this->prepareOptLink($optsHtml, $r);
         $tableHtml .= "\t</tr>\n";
         ++$i;
     }
     $tableHtml .= '</tbody></table>';
     if ($this->selectable === true) {
         $tableHtml .= '<p><a href="">delete</a> or <a href="">edit</a> choosen ones </p>';
     }
     return $tableHtml . '</form></div>';
 }
Ejemplo n.º 5
0
 public function reorderElements(DB $db, CmsElement $movedCmsElement, $dropZoneID, array $elementOrder)
 {
     // Remove all from column
     $colNo = (int) StringUtils::afterFirst($dropZoneID, 'column-') + 1;
     $this->logger->debug('-- Reorder module in column: ' . $colNo);
     $stmntRemove = $db->prepare("\n\t\t\tDELETE FROM element_column_layout_module WHERE col = ? AND page_IDFK = ? AND element_column_layout_IDFK = ?\n\t\t");
     $deletedElements = $db->delete($stmntRemove, array($colNo, $this->pageID, $this->ID));
     $this->logger->debug('Deleted ' . $deletedElements . ' elements');
     // Remove the element itself (cause of PK crashes)
     $stmntRemoveOriginal = $db->prepare("\n\t\t\tDELETE FROM element_column_layout_module WHERE element_column_layout_IDFK = ? AND page_IDFK = ? AND element_instance_IDFK = ?\n\t\t");
     $deletedOriginal = $db->delete($stmntRemoveOriginal, array($this->ID, $movedCmsElement->getPageID(), $movedCmsElement->getID()));
     $this->logger->debug('Deleted ' . $deletedOriginal . ' original element');
     // Add the new order
     $stmntInsert = $db->prepare("\n\t\t\tINSERT IGNORE INTO element_column_layout_module\n\t\t\t\tSET element_column_layout_IDFK = ?, page_IDFK = ?, col = ?, element_instance_IDFK = ?, sort = ?\n\t\t");
     $stmntUpdate = $db->prepare("UPDATE cms_element_instance SET parent_mod_IDFK = ? WHERE ID = ?");
     $this->logger->debug('Add those modules', array($elementOrder));
     foreach ($elementOrder as $k => $e) {
         $this->logger->debug('Added module: ' . $e);
         $eParts = explode('-', $e);
         if (isset($eParts[0]) === false) {
             continue;
         }
         $db->update($stmntUpdate, array($this->ID, $eParts[0]));
         $db->insert($stmntInsert, array($this->ID, $this->pageID, $colNo, $eParts[0], $k + 1));
     }
 }