View source
<?php
class AlphaPagination {
protected $handler;
public function __construct(views_handler $handler) {
$this->handler = $handler;
}
public function __sleep() {
$this->_handler = implode(':', [
$this->handler->view->name,
$this->handler->view->current_display,
$this->handler->handler_type,
$this->handler->real_field ?: $this->handler->field,
]);
return [
'_handler',
];
}
public function __wakeup() {
list($name, $display_id, $type, $id) = explode(':', $this->_handler);
$view = views_get_view($name);
$view
->set_display($display_id);
$this->handler = $view->display_handler
->get_handler($type, $id);
unset($this->_handler);
}
public function addClasses($classes, array &$attributes) {
$processed = [];
foreach ((array) $classes as $v) {
foreach (array_filter(explode(' ', $v)) as $vv) {
$processed[] = views_clean_css_identifier($vv);
}
}
if ($processed) {
if (!isset($attributes['class'])) {
$attributes['class'] = [];
}
$attributes['class'] = array_unique(array_merge($attributes['class'], $processed));
}
return $classes;
}
public function buildTokenTree($fieldset = NULL) {
static $build;
if (!isset($build)) {
if (module_exists('token')) {
$build = [
'#type' => 'container',
'#title' => t('Browse available tokens'),
];
$build['help'] = [
'#theme' => 'token_tree_link',
'#token_types' => [
'alpha_pagination',
],
'#global_types' => TRUE,
'#dialog' => TRUE,
];
}
else {
$build = [
'#type' => 'fieldset',
'#title' => 'Available tokens',
'#collapsible' => TRUE,
'#collapsed' => TRUE,
];
$items = [];
$token_info = alpha_pagination_token_info();
foreach ($token_info['tokens'] as $_type => $_tokens) {
foreach ($_tokens as $_token => $_data) {
$items[] = "[{$_type}:{$_token}] - {$_data['description']}";
}
}
$build['help'] = [
'#theme' => 'item_list',
'#items' => $items,
];
}
}
return isset($fieldset) ? [
'#fieldset' => $fieldset,
] + $build : $build;
}
public function ensureQuery() {
if (!$this
->getOption('query') && !empty($this->handler->view->build_info['query'])) {
$query = $this->handler->view->build_info['query'];
$quoted = $query
->getArguments();
$connection = Database::getConnection();
foreach ($quoted as $key => $val) {
if (is_array($val)) {
$quoted[$key] = implode(', ', array_map([
$connection,
'quote',
], $val));
}
else {
$quoted[$key] = $connection
->quote($val);
}
}
$this->handler->options['query'] = check_plain(strtr($query, $quoted));
}
}
public function getAlphabet($langcode = NULL) {
global $language;
static $default = [
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
];
static $alphabets;
if (!isset($langcode)) {
$langcode = $language->language;
}
if (!isset($alphabets)) {
$cid = "alpha_pagination:alphabets";
if (($cache = cache_get($cid)) && !empty($cache->data)) {
$alphabets = $cache->data;
}
else {
$alphabets['ar'] = [
'ا',
'ب',
'ت',
'ث',
'ج',
'ح',
'خ',
'د',
'ذ',
'ر',
'ز',
'س',
'ش',
'ص',
'ض',
'ط',
'ظ',
'ع',
'غ',
'ف',
'ق',
'ك',
'ل',
'م',
'ن',
'و',
'ه',
'ي',
];
$alphabets['en'] = $default;
$alphabets['ru'] = [
'А',
'Б',
'В',
'Г',
'Д',
'Е',
'Ё',
'Ж',
'З',
'И',
'Й',
'К',
'Л',
'М',
'Н',
'О',
'П',
'Р',
'С',
'Т',
'У',
'Ф',
'Х',
'Ц',
'Ч',
'Ш',
'Щ',
'Ы',
'Э',
'Ю',
'Я',
];
drupal_alter('alpha_pagination_alphabet', $alphabets, $this);
cache_set($cid, $alphabets);
}
}
return isset($alphabets[$langcode]) ? $alphabets[$langcode] : $default;
}
public function getAreaHandlers(array $types = [
'header',
'footer',
]) {
$areas = [];
foreach ($types as $type) {
foreach ($this->handler->view->display_handler
->get_handlers($type) as $handler) {
if ($handler instanceof \views_handler_area_alpha_pagination) {
$areas[] = $handler;
}
}
}
return $areas;
}
public function getCharacters() {
static $characters;
if (!isset($characters)) {
$all = $this
->getOption('paginate_all_display') === '1' ? $this
->getOption('paginate_all_label', t('All')) : '';
$all_value = $this
->getOption('paginate_all_value', 'all');
$numeric_label = $this
->getOption('paginate_numeric_label');
$numeric_type = $this
->getOption('paginate_view_numbers', '0');
$numeric_value = $this
->getOption('paginate_numeric_value');
$numeric_divider = $numeric_type !== '2' && $this
->getOption('paginate_numeric_divider') ? [
'-' => '',
] : [];
$cid = $this
->getCid();
if (($cache = cache_get($cid)) && !empty($cache->data)) {
$characters = $cache->data;
}
else {
foreach ($this
->getAlphabet() as $value) {
$characters[$value] = $value;
}
$numeric = [];
if ($numeric_type !== '0') {
if ($numeric_type === '2') {
$numeric[$numeric_value] = check_plain($numeric_label);
}
else {
foreach ($this
->getNumbers() as $value) {
$numeric[$value] = $value;
}
}
if ($this
->getOption('paginate_numeric_position') === 'after') {
$characters = array_merge($characters, $numeric_divider, $numeric);
}
else {
$characters = array_merge($numeric, $numeric_divider, $characters);
}
}
if ($all) {
if ($this
->getOption('paginate_all_position') === 'before') {
$characters = [
$all_value => $all,
] + $characters;
}
else {
$characters[$all_value] = $all;
}
}
foreach ($characters as $value => $label) {
$characters[$value] = new AlphaPaginationCharacter($this, $label, $value);
}
$prefixes = $this
->getEntityPrefixes();
foreach ($prefixes as $value) {
if ($this
->isNumeric($value) && $numeric_type === '2') {
$value = $numeric_value;
}
if (isset($characters[$value])) {
$characters[$value]
->setEnabled(TRUE);
}
}
if (!$this
->getOption('paginate_toggle_empty')) {
if ($all) {
$prefixes[] = $all_value;
}
if ($numeric_divider) {
$prefixes[] = '-';
}
$characters = array_filter(array_intersect_key($characters, array_flip($prefixes)));
}
if ($this
->getOption('paginate_numeric_hide_empty')) {
$numeric_results = array_filter(array_intersect_key($characters, array_flip($numeric)));
if (!$numeric_results) {
$characters = array_diff_key($characters, array_flip($numeric));
}
}
cache_set($cid, $characters, 'cache');
}
$current = $all ? $all_value : '';
$arg_count = count($this->handler->view->args);
if ($arg_count) {
$arg = $this->handler->view->args[$arg_count - 1];
if ($arg && in_array($arg, array_keys($characters))) {
$current = $arg;
}
}
if ($current) {
foreach ($characters as $character) {
if ($character
->isNumeric() && $numeric_type === '2' ? $numeric_value === $current : $character
->getValue() === $current) {
$character
->setActive(TRUE);
break;
}
}
}
}
return $characters;
}
public function getCid() {
global $language;
$this
->ensureQuery();
$data = [
'langcode' => $language->language,
'view' => $this->handler->view->name,
'display' => $this->handler->view->current_display,
'query' => $this
->getOption('query') ? md5($this
->getOption('query')) : '',
'options' => $this->handler->options,
];
return 'alpha_pagination:' . drupal_hash_base64(serialize($data));
}
public function getEntityIds() {
$this
->ensureQuery();
$query_parts = explode("\n", $this
->getOption('query'));
$base_field = $this->handler->view->base_field;
foreach ($query_parts as $k => $part) {
if ($position = strpos($part, "SUBSTRING")) {
$part = substr($part, 0, $position) . " 1 OR " . substr($part, $position);
$query_parts[$k] = $part;
}
}
$last_line = array_pop($query_parts);
if (substr($last_line, 0, 5) != "LIMIT") {
$query_parts[] = $last_line;
}
$query = join("\n", $query_parts);
$query = str_replace("'", '\'', $query);
$query = str_replace("&", '&', $query);
$query = str_replace("<", '<', $query);
$query = str_replace(">", '>', $query);
$entity_ids = [];
$result = db_query($query);
while ($data = $result
->fetchObject()) {
$entity_ids[] = $data->{$base_field};
}
return $entity_ids;
}
public function getEntityPrefixes() {
$prefixes = [];
if ($entity_ids = $this
->getEntityIds()) {
switch ($this
->getOption('paginate_view_field')) {
case 'name':
$table = $this->handler->view->base_table;
$where = $this->handler->view->base_field;
$table_data = views_fetch_data($table);
$entity_info = entity_get_property_info($table_data['table']['entity type']);
$field = isset($entity_info['properties']['name']['schema field']) ? $entity_info['properties']['name']['schema field'] : 'name';
break;
case 'title':
$table = $this->handler->view->base_table;
$where = $this->handler->view->base_field;
$table_data = views_fetch_data($table);
$entity_info = entity_get_property_info($table_data['table']['entity type']);
$field = isset($entity_info['properties']['title']['schema field']) ? $entity_info['properties']['title']['schema field'] : 'title';
break;
default:
if (strpos($this
->getOption('paginate_view_field'), ':') === FALSE) {
$field = $this
->getOption('paginate_view_field') . '_value';
$table = 'field_data_' . $this
->getOption('paginate_view_field');
}
else {
$field = str_replace(':', '_', $this
->getOption('paginate_view_field'));
$field_name_components = explode(':', $this
->getOption('paginate_view_field'));
$table = 'field_data_' . $field_name_components[0];
}
$where = 'entity_id';
break;
}
$result = db_query('SELECT DISTINCT(SUBSTR(' . $field . ', 1, 1)) AS prefix
FROM {' . $table . '}
WHERE ' . $where . ' IN ( :nids )', [
':nids' => $entity_ids,
]);
while ($data = $result
->fetchObject()) {
$prefixes[] = is_numeric($data->prefix) ? $data->prefix : drupal_strtoupper($data->prefix);
}
}
return array_unique(array_filter($prefixes));
}
public function getLabel($value) {
$characters = $this
->getCharacters();
if ($this
->getOption('paginate_view_numbers') === '2' && $this
->isNumeric($value)) {
return $characters[$this
->getOption('paginate_numeric_value')]
->getLabel();
}
elseif (isset($characters[$value])) {
return $characters[$value]
->getLabel();
}
return $value;
}
public function getNumbers($langcode = NULL) {
global $language;
static $default = [
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
];
static $numbers;
if (!isset($langcode)) {
$langcode = $language->language;
}
if (!isset($numbers)) {
$cid = "alpha_pagination:numbers";
if (($cache = cache_get($cid)) && !empty($cache->data)) {
$numbers = $cache->data;
}
else {
$numbers['en'] = $default;
drupal_alter('alpha_pagination_numbers', $numbers, $this);
cache_set($cid, $numbers);
}
}
return isset($numbers[$langcode]) ? $numbers[$langcode] : $default;
}
public function getOption($name, $default = '') {
return (string) (isset($this->handler->options[$name]) ? $this->handler->options[$name] : $default);
}
public function getTokens($value = NULL) {
return [
'alpha_pagination' => [
'path' => $this
->getUrl(),
'value' => $value,
],
];
}
public function getUrl() {
static $url;
if (!isset($url)) {
if (!empty($this->handler->view->override_url)) {
return $this->handler->view->override_url;
}
$path = $this->handler->view
->get_path();
$args = $this->handler->view->args;
$position = 0;
if (!empty($this->handler->view->argument)) {
foreach ($this->handler->view->argument as $argument_id => $argument) {
if (!empty($argument->options['default_argument_skip_url'])) {
unset($args[$position]);
}
$position++;
}
}
if (empty($path) || empty($args) && strpos($path, '%') === FALSE) {
$path = current_path();
$pieces = explode('/', $path);
if (array_key_exists(end($pieces), $this
->getCharacters())) {
array_pop($pieces);
}
$url = implode('/', $pieces);
return $url;
}
$pieces = [];
$argument_keys = isset($this->handler->view->argument) ? array_keys($this->handler->view->argument) : [];
$id = current($argument_keys);
foreach (explode('/', $path) as $piece) {
if ($piece != '%') {
$pieces[] = $piece;
}
else {
if (empty($args)) {
if ($id && !empty($this->handler->view->argument[$id]->options['exception']['value'])) {
$pieces[] = $this->handler->view->argument[$id]->options['exception']['value'];
}
else {
$pieces[] = '*';
}
}
else {
$pieces[] = array_shift($args);
}
if ($id) {
$id = next($argument_keys);
}
}
}
$url = implode('/', $pieces);
}
return $url;
}
public function getValue($value) {
$characters = $this
->getCharacters();
if ($this
->getOption('paginate_view_numbers') === '2' && $this
->isNumeric($value)) {
return $characters[$this
->getOption('paginate_numeric_value')]
->getValue();
}
elseif (isset($characters[$value])) {
return $characters[$value]
->getLabel();
}
return $value;
}
public function isNumeric($value) {
return $this
->getOption('paginate_view_numbers') === '2' && $value === $this
->getOption('paginate_numeric_value') || in_array($value, $this
->getNumbers());
}
public function parseAttributes($string = NULL, array $tokens = []) {
$attributes = [];
if (!empty($string)) {
$parts = explode(',', $string);
foreach ($parts as $attribute) {
if (strpos($attribute, '|') !== FALSE) {
list($key, $value) = explode('|', token_replace($attribute, $tokens, [
'clear' => TRUE,
]));
$attributes[$key] = $value;
}
}
}
return $attributes;
}
public function ui_name() {
if ($ui_name = $this
->getOption('ui_name')) {
return check_plain($ui_name);
}
return t('Alpha Pagination');
}
public function validate() {
$name = $this->handler->view->name;
$display_id = $this->handler->view->current_display;
$items = $this->handler->view
->get_items($this->handler->handler_type, $display_id);
$field = $this->handler->real_field ?: $this->handler->field;
if (!isset($items[$field])) {
return [];
}
static $errors = [];
if (!isset($errors["{$name}:{$display_id}"])) {
$errors["{$name}:{$display_id}"] = [];
$areas = $this
->getAreaHandlers();
if (!$areas) {
$errors["{$name}:{$display_id}"][] = t('The view "@name:@display" must have at least one configured alpha pagination area in either the header or footer to use "@field".', [
'@field' => $this->handler->real_field,
'@name' => $this->handler->view->name,
'@display' => $this->handler->view->current_display,
]);
}
elseif (count($areas) > 1) {
$errors["{$name}:{$display_id}"][] = t('The view "@name:@display" can only have one configured alpha pagination area in either the header or footer.', [
'@name' => $this->handler->view->name,
'@display' => $this->handler->view->current_display,
]);
}
}
return $errors["{$name}:{$display_id}"];
}
}