index = $index; $this->saved_rules = $saved_rules; $this->summary = $summary; } /** * Whether the current user can see the card. * * @return bool */ public function can_view(): bool { return current_user_can( DashboardPage::CAPABILITY ); } /** * One page of the posts that use the shortcode, with counts, the card's * saved rules and a link to the builder. * * @param int $page Page number, from 1. Out-of-range pages are clamped. * @param int $per_page Items per page. * @return array{total: int, shortcodes: int, page: int, pages: int, items: array, savedRules: array{total: int, page: int, pages: int, items: array}, builderUrl: string} */ public function data( int $page = 1, int $per_page = self::CARD_ITEMS ): array { $all = $this->all(); $paged = $this->page( $all, $page, $per_page ); $items = array(); foreach ( $paged['items'] as $item ) { $items[] = array( 'key' => 'post-' . $item['id'], 'title' => '' !== $item['title'] ? $item['title'] : __( '(no title)', 'yangra-conditional' ), 'type' => $item['type'], 'shortcodes' => $item['shortcodes'], 'editUrl' => $item['edit_url'], ); } return array( 'total' => count( $all ), 'shortcodes' => (int) array_sum( array_column( $all, 'shortcodes' ) ), 'page' => $paged['page'], 'pages' => $paged['pages'], 'items' => $items, 'savedRules' => $this->saved_rules_data(), 'builderUrl' => ShortcodeBuilderPage::url(), ); } /** * One page of the saved rules that are on and have conditions, by name, * each with its rule summary and how many shortcodes use it. * * @param int $page Page number, from 1. Out-of-range pages are clamped. * @param int $per_page Items per page. * @return array{total: int, page: int, pages: int, items: array} */ public function saved_rules_data( int $page = 1, int $per_page = self::CARD_ITEMS ): array { $active = array(); foreach ( $this->saved_rules->all() as $saved ) { foreach ( $saved['rule']['groups'] as $group ) { if ( $saved['rule']['enabled'] && array() !== $group['conditions'] ) { $active[] = $saved; break; } } } $paged = $this->page( $active, $page, $per_page ); $uses = array() !== $paged['items'] ? $this->saved_rule_uses() : array(); $items = array(); foreach ( $paged['items'] as $saved ) { $items[] = array( 'key' => 'rule-' . $saved['id'], 'name' => '' !== $saved['name'] ? $saved['name'] : __( '(no name)', 'yangra-conditional' ), 'summary' => $this->summary->summarize( $saved['rule'] ), 'shortcodes' => $uses[ $saved['id'] ] ?? 0, ); } return array( 'total' => count( $active ), 'page' => $paged['page'], 'pages' => $paged['pages'], 'items' => $items, ); } /** * Every post the current user can edit that uses the shortcode, most * recently changed first. * * @return array */ public function all(): array { $items = array(); foreach ( $this->index->live_posts() as $post_id => $index ) { $count = (int) ( $index['shortcodes'] ?? 0 ); if ( $count < 1 || ! current_user_can( 'edit_post', $post_id ) ) { continue; } $post = get_post( $post_id ); if ( null === $post ) { continue; } $type = get_post_type_object( $post->post_type ); $items[] = array( 'id' => (int) $post_id, 'title' => trim( html_entity_decode( wp_strip_all_tags( $post->post_title ), ENT_QUOTES, 'UTF-8' ) ), 'type' => null !== $type ? (string) $type->labels->singular_name : $post->post_type, 'shortcodes' => $count, 'edit_url' => (string) get_edit_post_link( $post_id, 'raw' ), 'modified' => (int) strtotime( $post->post_modified_gmt . ' UTC' ), ); } usort( $items, static function ( array $a, array $b ): int { return array( $b['modified'], $a['id'] ) <=> array( $a['modified'], $b['id'] ); } ); return $items; } /** * How many shortcodes use each saved rule, in shown content the current * user can edit. * * @return array Saved rule ID => shortcodes. */ private function saved_rule_uses(): array { $uses = array(); foreach ( $this->index->live_posts() as $post_id => $index ) { $rules = isset( $index['rules'] ) && is_array( $index['rules'] ) ? $index['rules'] : array(); if ( array() === $rules || ! current_user_can( 'edit_post', $post_id ) ) { continue; } foreach ( $rules as $id => $count ) { $uses[ (string) $id ] = ( $uses[ (string) $id ] ?? 0 ) + (int) $count; } } return $uses; } /** * One page of a list. * * @template T * @param array $rows The whole list. * @param int $page Page number, from 1. Out-of-range pages are clamped. * @param int $per_page Items per page. * @return array{page: int, pages: int, items: array} */ private function page( array $rows, int $page, int $per_page ): array { $per_page = max( 1, $per_page ); $pages = (int) max( 1, ceil( count( $rows ) / $per_page ) ); $page = min( max( 1, $page ), $pages ); return array( 'page' => $page, 'pages' => $pages, 'items' => array_slice( $rows, ( $page - 1 ) * $per_page, $per_page ), ); } }