blocks = $blocks; $this->widgets = $widgets; $this->summary = $summary; } /** * Whether the current user can see the card. * * @return bool */ public function can_view(): bool { return current_user_can( DashboardPage::CAPABILITY ); } /** * Whether the current user can see the widget list. * * @return bool */ public function can_view_widgets(): bool { return current_user_can( self::WIDGETS_CAPABILITY ); } /** * The card's data: the first page of each list it shows, and where the * feature is set up. `widgets` is null for users who can't edit widgets. * * @return array{blocks: array, widgets: array|null, setupLinks: array} */ public function data(): array { return array( 'blocks' => $this->blocks_data(), 'widgets' => $this->can_view_widgets() ? $this->widgets_data() : null, 'setupLinks' => $this->setup_links(), ); } /** * One page of the content with block rules, with counts. * * @param int $page Page number, from 1. * @param int $per_page Items per page. * @return array{total: int, blocks: int, counts: string, page: int, pages: int, items: array} */ public function blocks_data( int $page = 1, int $per_page = self::CARD_ITEMS ): array { $all = $this->blocks->all(); $kinds = array( 'post' => 0, 'template' => 0, 'pattern' => 0, ); foreach ( $all as $item ) { ++$kinds[ $item['kind'] ]; } $paged = $this->paginate( $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'], 'blocks' => $item['blocks'], 'editUrl' => $item['edit_url'], ); } return array( 'total' => count( $all ), 'blocks' => (int) array_sum( array_column( $all, 'blocks' ) ), 'counts' => $this->kinds_text( $kinds ), 'page' => $paged['page'], 'pages' => $paged['pages'], 'items' => $items, ); } /** * One page of the classic widgets with rules, with counts. * * @param int $page Page number, from 1. * @param int $per_page Items per page. * @return array{total: int, areas: int, page: int, pages: int, items: array} */ public function widgets_data( int $page = 1, int $per_page = self::CARD_ITEMS ): array { $all = $this->widgets->all(); $paged = $this->paginate( $all, $page, $per_page ); $items = array(); foreach ( $paged['items'] as $item ) { $items[] = array( 'key' => 'widget-' . $item['id'], 'title' => '' !== $item['title'] ? $item['title'] : $item['type'], 'type' => $item['type'], 'areaName' => $item['area_name'], 'editUrl' => admin_url( 'widgets.php' ), 'summary' => $this->summary->summarize( $item['rule'] ), ); } return array( 'total' => count( $all ), 'areas' => count( array_unique( array_column( $all, 'area' ) ) ), 'page' => $paged['page'], 'pages' => $paged['pages'], 'items' => $items, ); } /** * One page of a list. * * @template T * @param array $all Every item. * @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 paginate( array $all, int $page, int $per_page ): array { $per_page = max( 1, $per_page ); $pages = (int) max( 1, ceil( count( $all ) / $per_page ) ); $page = min( max( 1, $page ), $pages ); return array( 'page' => $page, 'pages' => $pages, 'items' => array_slice( $all, ( $page - 1 ) * $per_page, $per_page ), ); } /** * Where the blocks are, e.g. "3 posts, 1 template and 2 patterns". * * @param array{post: int, template: int, pattern: int} $kinds How many of each. * @return string */ private function kinds_text( array $kinds ): string { $parts = array(); if ( $kinds['post'] > 0 ) { /* translators: %s: number of posts and pages. */ $parts[] = sprintf( _n( '%s post', '%s posts', $kinds['post'], 'yangra-conditional' ), number_format_i18n( $kinds['post'] ) ); } if ( $kinds['template'] > 0 ) { /* translators: %s: number of templates, template parts and Navigation menus. */ $parts[] = sprintf( _n( '%s template', '%s templates', $kinds['template'], 'yangra-conditional' ), number_format_i18n( $kinds['template'] ) ); } if ( $kinds['pattern'] > 0 ) { /* translators: %s: number of synced patterns. */ $parts[] = sprintf( _n( '%s pattern', '%s patterns', $kinds['pattern'], 'yangra-conditional' ), number_format_i18n( $kinds['pattern'] ) ); } return wp_sprintf_l( '%l', $parts ); } /** * Where rules on blocks and widgets are set, for the empty card's tip. * * @return array */ private function setup_links(): array { $links = array( array( 'label' => __( 'Posts', 'yangra-conditional' ), 'url' => admin_url( 'edit.php' ), ), array( 'label' => __( 'Pages', 'yangra-conditional' ), 'url' => admin_url( 'edit.php?post_type=page' ), ), ); if ( $this->can_view_widgets() && current_theme_supports( 'widgets' ) ) { $links[] = array( 'label' => __( 'Appearance → Widgets', 'yangra-conditional' ), 'url' => admin_url( 'widgets.php' ), ); } return $links; } }