true, 'with_header_date_control' => true, ); /** * Whether the section's data only reaches WordPress.com through the analytics * full sync, so its numbers are incomplete until that sync has finished once. * * @since 0.4.0 * @var bool */ public $requires_sync = false; /** * Availability flag or callback. * * @var bool|callable */ private $is_available = true; /** * Default layout array or callback. * * @var array|callable */ private $default_layout = array(); /** * Constructor. * * @param string $dashboard_name Dashboard identifier. * @param string $id Section identifier. * @param array $args Optional. Section arguments. */ public function __construct( $dashboard_name, $id, $args = array() ) { $this->dashboard_name = $dashboard_name; $this->id = $id; $this->slug = self::derive_slug( $id ); $this->label = $id; $this->set_props( $args ); } /** * Derives the URL-facing slug from a namespaced section identifier. * * @param string $id Section identifier, e.g. `analytics/traffic`. * @return string The segment after the namespace, e.g. `traffic`. */ private static function derive_slug( $id ) { $separator = strpos( (string) $id, '/' ); return false === $separator ? (string) $id : substr( $id, $separator + 1 ); } /** * Returns whether this section should be exposed. * * @return bool */ public function is_available() { if ( is_callable( $this->is_available ) ) { return (bool) call_user_func( $this->is_available, $this ); } return (bool) $this->is_available; } /** * Returns the section's default widget layout, run through the default-layout filter. * * @return array Array of widget instances. */ public function get_default_layout() { $layout = is_callable( $this->default_layout ) ? call_user_func( $this->default_layout, $this ) : $this->default_layout; $layout = is_array( $layout ) ? array_values( $layout ) : array(); /** * Filters a dashboard section's default widget layout. * * Each entry matches the dashboard's widget instance shape: `uuid`, `type`, optional * `attributes`, optional `placement`. Runs for every section, so a callback adding an * instance to one switches on `$section_id`. * * @since 0.8.0 Runs from the section, with its declared layout and its * namespaced id; it received an empty array and any alias before. * * @param array $layout The section's declared default widget instances. * @param string $section_id Namespaced section identifier, e.g. `analytics/traffic`. * @param Dashboard_Section $section The section. */ $layout = apply_filters( DASHBOARD_DEFAULT_LAYOUT_FILTER, $layout, $this->id, $this ); return is_array( $layout ) ? array_values( $layout ) : array(); } /** * Returns the public REST representation. * * @return array */ public function to_array() { return array( 'id' => $this->id, 'slug' => $this->slug, 'label' => $this->label, 'title' => $this->title, 'order' => (int) $this->order, 'date_filter' => $this->date_filter, 'date_filter_options' => $this->date_filter_options, 'requires_sync' => $this->requires_sync, 'default_layout' => $this->get_default_layout(), ); } /** * Hydrates section properties from the args array. * * @param array $args Section arguments. * @return void */ private function set_props( $args ) { if ( ! is_array( $args ) ) { return; } if ( isset( $args['label'] ) ) { $this->label = (string) $args['label']; } // An empty string is a registrant saying "none", not a heading: kept as-is it // would defeat the label fallback and render an `

` with no accessible name. if ( isset( $args['title'] ) ) { $title = (string) $args['title']; $this->title = '' === $title ? null : $title; } if ( isset( $args['order'] ) ) { $this->order = (int) $args['order']; } // An unrecognized surface keeps the default rather than reaching the // dashboard, where the frontend has no filter to render for it. if ( isset( $args['date_filter'] ) && in_array( $args['date_filter'], self::DATE_FILTERS, true ) ) { $this->date_filter = (string) $args['date_filter']; } // Merged over the defaults so a partial array keeps the rest, and narrowed // to the known options, which is all the dashboard renders. if ( isset( $args['date_filter_options'] ) && is_array( $args['date_filter_options'] ) ) { $options = array_merge( $this->date_filter_options, $args['date_filter_options'] ); $this->date_filter_options = array( 'with_date_comparison' => (bool) $options['with_date_comparison'], 'with_header_date_control' => (bool) $options['with_header_date_control'], ); } if ( isset( $args['requires_sync'] ) ) { $this->requires_sync = (bool) $args['requires_sync']; } if ( array_key_exists( 'is_available', $args ) ) { $this->is_available = $args['is_available']; } if ( array_key_exists( 'default_layout', $args ) ) { $this->default_layout = $args['default_layout']; } } }