yf_divide_pages class

Common used pager module.

Fileplugins/common/classes/common/yf_divide_pages.class.php
Use_class('divide_pages', 'classes/common/')

Public properties

A site sets them in its config with $PROJECT_CONF['divide_pages']['NAME'] = ...;

PropertyDefaultDescription
$DEFAULT_PER_PAGE 20
$DEFAULT_RENDER_TYPE 'slide'
$DEFAULT_TPLS_PATH 'system/divide_pages/'
$OVERRIDE_DB_OBJECT false
$PAGES_LIMIT
int
0 Global pages limit (to prevent pages flooding). Example: 100 (pages only). set to "0" to disable
$PAGES_PER_BLOCK 10
$SQL_COUNT_REWRITE
bool
true Force to rewrite given SQL to force speed with COUNT(*) operator. Example: module_conf("divide_pages", "SQL_COUNT_REWRITE", false);

Public methods 6

public function get_total_records($sql = '', $num_records = 0, $extra = [])
    public function get_total_records($sql = '', $num_records = 0, $extra = [])
    {
        $sql_callback = ($extra['sql_callback'] ?? null);
        if (is_array($sql)) {
            $total_records = count((array) $sql);
        } elseif (empty($num_records) && ! empty($sql)) {
            $sql = trim($sql);
            $_need_std_num_rows = true;
            // Try to rewrite query for more speed
            if ($this->SQL_COUNT_REWRITE) {
                // Example of callback: function($sql) { return preg_replace('/^SELECT.*FROM/ims', 'SELECT COUNT(*) FROM', ltrim($sql)); }
                if (is_callable($sql_callback)) {
                    $modified_sql = $sql_callback($sql);
                } else {
                    $modified_sql = 'SELECT COUNT(*) AS `0` FROM (' . $sql . ') AS __pager_tmp';
                }
                if ($modified_sql != $sql) {
                    $_need_std_num_rows = false;
                }
                // Simple speed optimization by removing ORDER BY ... from SQL when counting total records
                $modified_sql = preg_replace('/\sORDER BY .*? (ASC|DESC)$/i', '', $modified_sql);
            }
            if (isset($extra['db'])) {
                $db = $extra['db'];
            } elseif (is_object($this->OVERRIDE_DB_OBJECT)) {
                $db = $this->OVERRIDE_DB_OBJECT;
            } else {
                $db = db();
            }
            $total_records = (int) ($_need_std_num_rows ? $db->query_num_rows($sql) : $db->get_one($modified_sql));
        } else {
            $total_records = $num_records;
        }
        return (int) $total_records;
    }

go

public function go($sql = '', $url_path = '', $render_type = '', $records_on_page = 0, $num_records = 0, $tpls_path = '', $add_get_vars = 1, $extra = [])

Divide pages.

    public function go($sql = '', $url_path = '', $render_type = '', $records_on_page = 0, $num_records = 0, $tpls_path = '', $add_get_vars = 1, $extra = [])
    {
        $limited_pages = null;
        if (is_array($url_path)) {
            $extra = $url_path;
            $url_path = '';
        }
        if (empty($url_path)) {
            if ($extra['url_path'] ?? null) {
                $url_path = $extra['url_path'];
            } elseif ($extra['path'] ?? null) {
                $url_path = $extra['path'];
            }
        }
        if ( ! $url_path) {
            $url_path = './?object=' . ($_GET['object'] ?? null) . '&action=' . ($_GET['action'] ?? null) . (isset($_GET['id']) ? '&id=' . ($_GET['id'] ?? null) : '');
        }
        if ( ! ($render_type ?? false) || ! strlen($render_type)) {
            if ($extra['render_type'] ?? null) {
                $render_type = $extra['render_type'];
            } elseif ($extra['type'] ?? null) {
                $render_type = $extra['type'];
            }
        }
        if ( ! $render_type) {
            $render_type = $this->DEFAULT_RENDER_TYPE;
        }
        $requested_page = isset($extra['requested_page']) ? $extra['requested_page'] : ($_GET['page'] ?? null);
        $records_on_page = abs((int) (($extra['records_on_page'] ?? null) ?: $records_on_page));
        $per_page = $records_on_page ?: (MAIN_TYPE_ADMIN ? conf('admin_per_page') : conf('user_per_page'));
        if ( ! $per_page) {
            $per_page = conf('per_page') ?: $this->DEFAULT_PER_PAGE;
        }
        $num_records = abs((int) (($extra['num_records'] ?? null) ?: $num_records));
        $tpls_path = ($extra['tpls_path'] ?? null) ?: $tpls_path;
        if ( ! strlen($tpls_path)) {
            $tpls_path = $this->DEFAULT_TPLS_PATH;
        }
        $add_get_vars = isset($extra['add_get_vars']) ? $extra['add_get_vars'] : ($add_get_vars ?: 1);

        $total_records = (int) $this->get_total_records($sql, $num_records, $extra);

        $total_pages = $per_page ? ceil($total_records / $per_page) : 0;
        // Global number of pages limit (only for user section)
        if (MAIN_TYPE_USER && $this->PAGES_LIMIT && $total_pages > $this->PAGES_LIMIT) {
            $old_total_pages = $total_pages;
            $total_pages = $this->PAGES_LIMIT;
        }
        // Filter not existing pages numbers
        if ( ! $requested_page || $requested_page < 1) {
            $cur_page = 1;
        } elseif ($requested_page > $total_pages) {
            $cur_page = $total_pages;
        } else {
            $cur_page = $requested_page;
        }
        $render_func = 'render_type_' . $render_type;
        $rendered = $this->$render_func([
            'total_records' => $total_records,
            'per_page' => $per_page,
            'requested_page' => $requested_page,
            'cur_page' => $cur_page,
            'total_pages' => $total_pages,
            'url_path' => $url_path . ($add_get_vars ? _add_get(['page']) : ''),
            'tpls_path' => $tpls_path,
            'pages_per_block' => ($extra['pages_per_block'] ?? null) ?: $this->PAGES_PER_BLOCK,
            'size' => $extra['size'] ?? '',
            'align' => $extra['align'] ?? '',
        ]);
        $limited_pages = null;
        $result = [
            'limit_sql' => ' LIMIT ' . (int) ($rendered['first']) . ', ' . (int) $per_page,
            'pages_html' => trim($rendered['html']),
            'total_records' => (int) $total_records,
            'first_record' => (int) ($rendered['first']), // Counter start value for the current page
            'total_pages' => (int) $total_pages,
            'limited_pages' => (int) $limited_pages,
            'per_page' => (int) $per_page,
            'requested_page' => (int) $requested_page,
        ];
        return array_values($result); // Needed for compatibility with tons of legacy code, that using list(...) = divide_pages(...)
    }

go_with_array

public function go_with_array($items_array = [], $url_path = '', $render_type = '', $records_on_page = 0, $num_records = 0, $tpls_path = '', $add_get_vars = 1, $extra = [])

Divide pages using given array.

    public function go_with_array($items_array = [], $url_path = '', $render_type = '', $records_on_page = 0, $num_records = 0, $tpls_path = '', $add_get_vars = 1, $extra = [])
    {
        $result = $this->go(null, $url_path, $render_type, $records_on_page, $num_records ?: count((array) $items_array), $tpls_path, $add_get_vars, $extra);
        $per_page = $result[6];
        $requested_page = $result[7];
        if (count((array) $items_array) > $per_page) {
            $items_array = array_slice($items_array, (empty($requested_page) ? 0 : $requested_page - 1) * $per_page, $per_page, true);
        }
        $result[0] = $items_array;
        return $result;
    }
public function render_type_blocks($params = [])

Render pager type "blocks".

    public function render_type_blocks($params = [])
    {
        $limited_pages = null;
        $total_records = $params['total_records'];
        $per_page = $params['per_page'];
        $requested_page = $params['requested_page'];
        $url_path = $params['url_path'];
        $tpls_path = $params['tpls_path'];
        $total_pages = $params['total_pages'];
        $cur_page = $params['cur_page'];
        $pages_per_block = ($params['pages_per_block'] ?? null) ?: $this->PAGES_PER_BLOCK;

        $items = [];
        $limited_pages = null;
        if ($total_records < $per_page) {
            $first = 0;
        } else {
            $total_blocks = $pages_per_block ? ceil($total_pages / $pages_per_block) : 0;
            $cur_block = $pages_per_block ? ceil($cur_page / $pages_per_block) : 0;
            $start_page = ($cur_block - 1) * $pages_per_block + 1;
            $end_page = $start_page + $pages_per_block;
            if ($end_page > $total_pages) {
                $end_page = $total_pages + 1;
            }
            // Show link to first page
            if ($cur_page > 1) {
                $items['page_first'] = tpl()->parse($tpls_path . 'page_first', [
                    'link' => $url_path . '&page=1',
                ]);
            }
            // Show link to the previous block (if needed)
            if ($cur_block > 1) {
                $items['block_prev'] = tpl()->parse($tpls_path . 'block_prev', [
                    'link' => $url_path . '&page=' . (($cur_block - 1) * $pages_per_block),
                    'pages_per_block' => $pages_per_block,
                ]);
            }
            // Show link to previous page
            if ($cur_page > 1) {
                $items['page_prev'] = tpl()->parse($tpls_path . 'page_prev', [
                    'link' => $url_path . '&page=' . (int) ($cur_page - 1),
                ]);
            }
            // Process current block of pages
            for ($k = $start_page; $k < $end_page; $k++) {
                $items['pages'] = ($items['pages'] ?? '') . tpl()->parse($tpls_path . ($cur_page == $k ? 'page_current' : 'page_other'), [
                    'link' => $url_path . '&page=' . $k,
                    'page_num' => $k,
                ]);
            }
            // Show link to next page
            if ($cur_page < $total_pages) {
                $items['page_next'] = tpl()->parse($tpls_path . 'page_next', [
                    'link' => $url_path . '&page=' . ($cur_page + 1),
                ]);
            }
            // Show link to the next block (if needed)
            if ($cur_block < $total_blocks) {
                $items['block_next'] = tpl()->parse($tpls_path . 'block_next', [
                    'link' => $url_path . '&page=' . $k,
                    'pages_per_block' => $pages_per_block,
                ]);
            }
            // Show link to last page
            if ($total_pages > $pages_per_block && $cur_page < $total_pages) {
                $items['page_last'] = tpl()->parse($tpls_path . 'page_last', [
                    'link' => $url_path . '&page=' . $total_pages,
                ]);
            }
            // Set first value for the database query
            $first = ($cur_page - 1) * $per_page;
            // First record could be only positive
            if ($first < 0) {
                $first = 0;
            }
        }
        $html = tpl()->parse($tpls_path . 'main', [
            'total_pages' => (int) $total_pages,
            'total_records' => (int) $total_records,
            'record_first' => (int) ($first + 1),
            'record_last' => (int) ($cur_page * $per_page),
            'page_first' => ($items['page_first'] ?? null),
            'block_prev' => ($items['block_prev'] ?? null),
            'page_prev' => ($items['page_prev'] ?? null),
            'pages' => ($items['pages'] ?? null),
            'page_next' => ($items['page_next'] ?? null),
            'block_next' => ($items['block_next'] ?? null),
            'page_last' => ($items['page_last'] ?? null),
            'current_page' => $cur_page,
        ] + $this->_main_classes($params));
        return [
            'html' => $html,
            'total_pages' => $total_pages,
            'limited_pages' => $limited_pages,
            'first' => $first,
        ];
    }
public function render_type_slide($params = [])

Render pager type "slide".

    public function render_type_slide($params = [])
    {
        $limited_pages = null;
        $total_records = $params['total_records'];
        $per_page = $params['per_page'];
        $requested_page = $params['requested_page'];
        $url_path = $params['url_path'];
        $tpls_path = $params['tpls_path'];
        $total_pages = $params['total_pages'];
        $cur_page = $params['cur_page'];
        $pages_per_block = ($params['pages_per_block'] ?? null) ?: $this->PAGES_PER_BLOCK;

        $items = [];
        $limited_pages = null;
        if ($total_records < $per_page) {
            $first = 0;
        } else {
            $half = ceil($pages_per_block / 2);
            $start_page = $cur_page - $half + 1;
            if ($start_page <= 0) {
                $start_page = 1;
            }
            $end_page = $start_page + $pages_per_block;
            if ($end_page > $total_pages) {
                $end_page = $total_pages + 1;
            }
            if ($pages_per_block > ($end_page - $start_page)) {
                $start_page -= $pages_per_block - ($end_page - $start_page);
                if ($start_page <= 0) {
                    $start_page = 1;
                }
            }
            // Show link to first page
            if ($cur_page > 1) {
                $items['page_first'] = tpl()->parse($tpls_path . 'page_first', [
                    'link' => $url_path . '&page=1',
                ]);
            }
            // Show link to previous page
            if ($cur_page > 1) {
                $items['page_prev'] = tpl()->parse($tpls_path . 'page_prev', [
                    'link' => $url_path . '&page=' . (int) ($cur_page - 1),
                ]);
            }
            // Process current block of pages
            for ($k = $start_page; $k < $end_page; $k++) {
                $items['pages'] = ($items['pages'] ?? '') . tpl()->parse($tpls_path . ($cur_page == $k ? 'page_current' : 'page_other'), [
                    'link' => $url_path . '&page=' . $k,
                    'page_num' => $k,
                ]);
            }
            // Show link to next page
            if ($cur_page < $total_pages) {
                $items['page_next'] = tpl()->parse($tpls_path . 'page_next', [
                    'link' => $url_path . '&page=' . ($cur_page + 1),
                ]);
            }
            // Show link to last page
            if ($total_pages > $pages_per_block && $cur_page < $total_pages) {
                $items['page_last'] = tpl()->parse($tpls_path . 'page_last', [
                    'link' => $url_path . '&page=' . $total_pages,
                ]);
            }
            // Set first value for the database query
            $first = ($cur_page - 1) * $per_page;
            // First record could be only positive
            if ($first < 0) {
                $first = 0;
            }
        }
        $html = tpl()->parse($tpls_path . 'main', [
            'total_pages' => (int) $total_pages,
            'total_records' => (int) $total_records,
            'record_first' => (int) ($first + 1),
            'record_last' => (int) ($cur_page * $per_page),
            'page_first' => ($items['page_first'] ?? null),
            'block_prev' => '',
            'page_prev' => ($items['page_prev'] ?? null),
            'pages' => ($items['pages'] ?? null),
            'page_next' => ($items['page_next'] ?? null),
            'block_next' => '',
            'page_last' => ($items['page_last'] ?? null),
            'current_page' => $cur_page,
        ] + $this->_main_classes($params));
        return [
            'html' => $html,
            'total_pages' => $total_pages,
            'limited_pages' => $limited_pages,
            'first' => $first,
        ];
    }

Methods starting with _ hooks and helpers; not routable as page actions

_main_classes

public function _main_classes($params = [])

Template vars of the `size` (sm, lg) and `align` (center, end) options for main.stpl: pagination_class (with a leading space) and pagination_wrap_attr (the Bootstrap 3 wrapper's class attribute); both are empty without the options.

  • $params array
    public function _main_classes($params = [])
    {
        $fw = (string) conf('css_framework');
        // as in main.stpl / main.bs5.stpl: bs5, Bootstrap 2 for an empty css_framework, Bootstrap 3 markup otherwise
        $fw = $fw === 'bs5' ? 'bs5' : ($fw === '' ? 'bs2' : 'bs3');
        [$list, $wrap] = html()->_pagination_classes($params['size'] ?? '', $params['align'] ?? '', $fw);
        return [
            'pagination_class' => strlen($list) ? ' ' . $list : '',
            'pagination_wrap_attr' => strlen($wrap) ? ' class="' . $wrap . '"' : '',
        ];
    }