ncatenate_scripts * @global bool $compress_scripts * @global bool $compress_css */ function script_concat_settings() { global $concatenate_scripts, $compress_scripts, $compress_css; $compressed_output = ( ini_get( 'zlib.output_compression' ) || 'ob_gzhandler' === ini_get( 'output_handler' ) ); if ( ! isset( $concatenate_scripts ) ) { $concatenate_scripts = defined( 'CONCATENATE_SCRIPTS' ) ? CONCATENATE_SCRIPTS : true; if ( ( ! is_admin() && ! did_action( 'login_init' ) ) || ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ) { $concatenate_scripts = false; } } if ( ! isset( $compress_scripts ) ) { $compress_scripts = defined( 'COMPRESS_SCRIPTS' ) ? COMPRESS_SCRIPTS : true; if ( $compress_scripts && ( ! get_site_option( 'can_compress_scripts' ) || $compressed_output ) ) { $compress_scripts = false; } } if ( ! isset( $compress_css ) ) { $compress_css = defined( 'COMPRESS_CSS' ) ? COMPRESS_CSS : true; if ( $compress_css && ( ! get_site_option( 'can_compress_scripts' ) || $compressed_output ) ) { $compress_css = false; } } } /** * Handles the enqueueing of block scripts and styles that are common to both * the editor and the front-end. * * @since 5.0.0 * * @global WP_Screen $current_screen WordPress current screen object. */ function wp_common_block_scripts_and_styles() { if ( is_admin() && ! wp_should_load_block_editor_scripts_and_styles() ) { return; } wp_enqueue_style( 'wp-block-library' ); if ( current_theme_supports( 'wp-block-styles' ) ) { wp_enqueue_style( 'wp-block-library-theme' ); } /** * Fires after enqueuing block assets for both editor and front-end. * * Call `add_action` on any hook before 'wp_enqueue_scripts'. * * In the function call you supply, simply use `wp_enqueue_script` and * `wp_enqueue_style` to add your functionality to the Gutenberg editor. * * @since 5.0.0 */ do_action( 'enqueue_block_assets' ); } /** * Enqueues the global styles defined via theme.json. * * @since 5.8.0 */ function wp_enqueue_global_styles() { if ( ! WP_Theme_JSON_Resolver::theme_has_support() ) { return; } $separate_assets = wp_should_load_separate_core_block_assets(); /* * Global styles should be printed in the head when loading all styles combined. * The footer should only be used to print global styles for classic themes with separate core assets enabled. * * See https://core.trac.wordpress.org/ticket/53494. */ if ( ( ! $separate_assets && doing_action( 'wp_footer' ) ) || ( $separate_assets && doing_action( 'wp_enqueue_scripts' ) ) ) { return; } $can_use_cache = ( ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) && ( ! defined( 'SCRIPT_DEBUG' ) || ! SCRIPT_DEBUG ) && ( ! defined( 'REST_REQUEST' ) || ! REST_REQUEST ) && ! is_admin() ); $stylesheet = null; if ( $can_use_cache ) { $cache = get_transient( 'global_styles' ); if ( $cache ) { $stylesheet = $cache; } } if ( null === $stylesheet ) { $settings = get_default_block_editor_settings(); $theme_json = WP_Theme_JSON_Resolver::get_merged_data( $settings ); $stylesheet = $theme_json->get_stylesheet(); if ( $can_use_cache ) { set_transient( 'global_styles', $stylesheet, MINUTE_IN_SECONDS ); } } if ( empty( $stylesheet ) ) { return; } wp_register_style( 'global-styles', false, array(), true, true ); wp_add_inline_style( 'global-styles', $stylesheet ); wp_enqueue_style( 'global-styles' ); } /** * Checks if the editor scripts and styles for all registered block types * should be enqueued on the current screen. * * @since 5.6.0 * * @return bool Whether scripts and styles should be enqueued. */ function wp_should_load_block_editor_scripts_and_styles() { global $current_screen; $is_block_editor_screen = ( $current_screen instanceof WP_Screen ) && $current_screen->is_block_editor(); /** * Filters the flag that decides whether or not block editor scripts and styles * are going to be enqueued on the current screen. * * @since 5.6.0 * * @param bool $is_block_editor_screen Current value of the flag. */ return apply_filters( 'should_load_block_editor_scripts_and_styles', $is_block_editor_screen ); } /** * Checks whether separate styles should be loaded for core blocks on-render. * * When this function returns true, other functions ensure that core blocks * only load their assets on-render, and each block loads its own, individual * assets. Third-party blocks only load their assets when rendered. * * When this function returns false, all core block assets are loaded regardless * of whether they are rendered in a page or not, because they are all part of * the `block-library/style.css` file. Assets for third-party blocks are always * enqueued regardless of whether they are rendered or not. * * This only affects front end and not the block editor screens. * * @see wp_enqueue_registered_block_scripts_and_styles() * @see register_block_style_handle() * * @since 5.8.0 * * @return bool Whether separate assets will be loaded. */ function wp_should_load_separate_core_block_assets() { if ( is_admin() || is_feed() || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ) { return false; } /** * Filters whether block styles should be loaded separately. * * Returning false loads all core block assets, regardless of whether they are rendered * in a page or not. Returning true loads core block assets only when they are rendered. * * @since 5.8.0 * * @param bool $load_separate_assets Whether separate assets will be loaded. * Default false (all block assets are loaded, even when not used). */ return apply_filters( 'should_load_separate_core_block_assets', false ); } /** * Enqueues registered block scripts and styles, depending on current rendered * context (only enqueuing editor scripts while in context of the editor). * * @since 5.0.0 * * @global WP_Screen $current_screen WordPress current screen object. */ function wp_enqueue_registered_block_scripts_and_styles() { global $current_screen; if ( wp_should_load_separate_core_block_assets() ) { return; } $load_editor_scripts = is_admin() && wp_should_load_block_editor_scripts_and_styles(); $block_registry = WP_Block_Type_Registry::get_instance(); foreach ( $block_registry->get_all_registered() as $block_name => $block_type ) { // Front-end styles. if ( ! empty( $block_type->style ) ) { wp_enqueue_style( $block_type->style ); } // Front-end script. if ( ! empty( $block_type->script ) ) { wp_enqueue_script( $block_type->script ); } // Editor styles. if ( $load_editor_scripts && ! empty( $block_type->editor_style ) ) { wp_enqueue_style( $block_type->editor_style ); } // Editor script. if ( $load_editor_scripts && ! empty( $block_type->editor_script ) ) { wp_enqueue_script( $block_type->editor_script ); } } } /** * Function responsible for enqueuing the styles required for block styles functionality on the editor and on the frontend. * * @since 5.3.0 */ function enqueue_block_styles_assets() { $block_styles = WP_Block_Styles_Registry::get_instance()->get_all_registered(); foreach ( $block_styles as $block_name => $styles ) { foreach ( $styles as $style_properties ) { if ( isset( $style_properties['style_handle'] ) ) { // If the site loads separate styles per-block, enqueue the stylesheet on render. if ( wp_should_load_separate_core_block_assets() ) { add_filter( 'render_block', function( $html ) use ( $style_properties ) { wp_enqueue_style( $style_properties['style_handle'] ); return $html; } ); } else { wp_enqueue_style( $style_properties['style_handle'] ); } } if ( isset( $style_properties['inline_style'] ) ) { // Default to "wp-block-library". $handle = 'wp-block-library'; // If the site loads separate styles per-block, check if the block has a stylesheet registered. if ( wp_should_load_separate_core_block_assets() ) { $block_stylesheet_handle = generate_block_asset_handle( $block_name, 'style' ); global $wp_styles; if ( isset( $wp_styles->registered[ $block_stylesheet_handle ] ) ) { $handle = $block_stylesheet_handle; } } // Add inline styles to the calculated handle. wp_add_inline_style( $handle, $style_properties['inline_style'] ); } } } } /** * Function responsible for enqueuing the assets required for block styles functionality on the editor. * * @since 5.3.0 */ function enqueue_editor_block_styles_assets() { $block_styles = WP_Block_Styles_Registry::get_instance()->get_all_registered(); $register_script_lines = array( '( function() {' ); foreach ( $block_styles as $block_name => $styles ) { foreach ( $styles as $style_properties ) { $block_style = array( 'name' => $style_properties['name'], 'label' => $style_properties['label'], ); if ( isset( $style_properties['is_default'] ) ) { $block_style['isDefault'] = $style_properties['is_default']; } $register_script_lines[] = sprintf( ' wp.blocks.registerBlockStyle( \'%s\', %s );', $block_name, wp_json_encode( $block_style ) ); } } $register_script_lines[] = '} )();'; $inline_script = implode( "\n", $register_script_lines ); wp_register_script( 'wp-block-styles', false, array( 'wp-blocks' ), true, true ); wp_add_inline_script( 'wp-block-styles', $inline_script ); wp_enqueue_script( 'wp-block-styles' ); } /** * Enqueues the assets required for the block directory within the block editor. * * @since 5.5.0 */ function wp_enqueue_editor_block_directory_assets() { wp_enqueue_script( 'wp-block-directory' ); wp_enqueue_style( 'wp-block-directory' ); } /** * Enqueues the assets required for the format library within the block editor. * * @since 5.8.0 */ function wp_enqueue_editor_format_library_assets() { wp_enqueue_script( 'wp-format-library' ); wp_enqueue_style( 'wp-format-library' ); } /** * Sanitizes an attributes array into an attributes string to be placed inside a `\n", wp_sanitize_script_attributes( $attributes ) ); } /** * Prints formatted `\n", wp_sanitize_script_attributes( $attributes ), $javascript ); } /** * Prints inline JavaScript wrapped in `"; } reateDynamicStatisticsQueryBuilder(): QueryBuilder { $subscribersTable = $this->entityManager->getClassMetadata(SubscriberEntity::class)->getTableName(); return $this->entityManager ->getConnection() ->createQueryBuilder() ->from($subscribersTable) ->addSelect("IFNULL(SUM( CASE WHEN $subscribersTable.deleted_at IS NULL THEN 1 ELSE 0 END ), 0) as `all`") ->addSelect("IFNULL(SUM( CASE WHEN $subscribersTable.deleted_at IS NOT NULL THEN 1 ELSE 0 END ), 0) as trash") ->addSelect("IFNULL(SUM( CASE WHEN $subscribersTable.status = :status_subscribed AND $subscribersTable.deleted_at IS NULL THEN 1 ELSE 0 END ), 0) as :status_subscribed") ->addSelect("IFNULL(SUM( CASE WHEN $subscribersTable.status = :status_unsubscribed AND $subscribersTable.deleted_at IS NULL THEN 1 ELSE 0 END ), 0) as :status_unsubscribed") ->addSelect("IFNULL(SUM( CASE WHEN $subscribersTable.status = :status_inactive AND $subscribersTable.deleted_at IS NULL THEN 1 ELSE 0 END ), 0) as :status_inactive") ->addSelect("IFNULL(SUM( CASE WHEN $subscribersTable.status = :status_unconfirmed AND $subscribersTable.deleted_at IS NULL THEN 1 ELSE 0 END ), 0) as :status_unconfirmed") ->addSelect("IFNULL(SUM( CASE WHEN $subscribersTable.status = :status_bounced AND $subscribersTable.deleted_at IS NULL THEN 1 ELSE 0 END ), 0) as :status_bounced") ->setParameter('status_subscribed', SubscriberEntity::STATUS_SUBSCRIBED) ->setParameter('status_unsubscribed', SubscriberEntity::STATUS_UNSUBSCRIBED) ->setParameter('status_inactive', SubscriberEntity::STATUS_INACTIVE) ->setParameter('status_unconfirmed', SubscriberEntity::STATUS_UNCONFIRMED) ->setParameter('status_bounced', SubscriberEntity::STATUS_BOUNCED); } private function createStaticStatisticsQueryBuilder(SegmentEntity $segment): QueryBuilder { $subscriberSegmentTable = $this->entityManager->getClassMetadata(SubscriberSegmentEntity::class)->getTableName(); $subscribersTable = $this->entityManager->getClassMetadata(SubscriberEntity::class)->getTableName(); return $this->entityManager ->getConnection() ->createQueryBuilder() ->from($subscriberSegmentTable, 'subscriber_segment') ->where('subscriber_segment.segment_id = :segment_id') ->setParameter('segment_id', $segment->getId()) ->join('subscriber_segment', $subscribersTable, 'subscribers', 'subscribers.id = subscriber_segment.subscriber_id') ->addSelect('IFNULL(SUM( CASE WHEN subscribers.deleted_at IS NULL THEN 1 ELSE 0 END ), 0) as `all`') ->addSelect('IFNULL(SUM( CASE WHEN subscribers.deleted_at IS NOT NULL THEN 1 ELSE 0 END ), 0) as trash') ->addSelect('IFNULL(SUM( CASE WHEN subscribers.status = :status_subscribed AND subscriber_segment.status = :status_subscribed AND subscribers.deleted_at IS NULL THEN 1 ELSE 0 END ), 0) as :status_subscribed') ->addSelect('IFNULL(SUM( CASE WHEN (subscribers.status = :status_unsubscribed OR subscriber_segment.status = :status_unsubscribed) AND subscribers.deleted_at IS NULL THEN 1 ELSE 0 END ), 0) as :status_unsubscribed') ->addSelect('IFNULL(SUM( CASE WHEN subscribers.status = :status_inactive AND subscriber_segment.status != :status_unsubscribed AND subscribers.deleted_at IS NULL THEN 1 ELSE 0 END ), 0) as :status_inactive') ->addSelect('IFNULL(SUM( CASE WHEN subscribers.status = :status_unconfirmed AND subscriber_segment.status != :status_unsubscribed AND subscribers.deleted_at IS NULL THEN 1 ELSE 0 END ), 0) as :status_unconfirmed') ->addSelect('IFNULL(SUM( CASE WHEN subscribers.status = :status_bounced AND subscriber_segment.status != :status_unsubscribed AND subscribers.deleted_at IS NULL THEN 1 ELSE 0 END ), 0) as :status_bounced') ->setParameter('status_subscribed', SubscriberEntity::STATUS_SUBSCRIBED) ->setParameter('status_unsubscribed', SubscriberEntity::STATUS_UNSUBSCRIBED) ->setParameter('status_inactive', SubscriberEntity::STATUS_INACTIVE) ->setParameter('status_unconfirmed', SubscriberEntity::STATUS_UNCONFIRMED) ->setParameter('status_bounced', SubscriberEntity::STATUS_BOUNCED); } private function createStaticGlobalStatusStatisticsQueryBuilder(SegmentEntity $segment): QueryBuilder { $subscriberSegmentTable = $this->entityManager->getClassMetadata(SubscriberSegmentEntity::class)->getTableName(); $subscribersTable = $this->entityManager->getClassMetadata(SubscriberEntity::class)->getTableName(); return $this->entityManager ->getConnection() ->createQueryBuilder() ->from($subscriberSegmentTable, 'subscriber_segment') ->where('subscriber_segment.segment_id = :segment_id') ->setParameter('segment_id', $segment->getId()) ->join('subscriber_segment', $subscribersTable, 'subscribers', 'subscribers.id = subscriber_segment.subscriber_id') ->addSelect('IFNULL(SUM( CASE WHEN subscribers.deleted_at IS NULL THEN 1 ELSE 0 END ), 0) as `all`') ->addSelect('IFNULL(SUM( CASE WHEN subscribers.deleted_at IS NOT NULL THEN 1 ELSE 0 END ), 0) as trash') ->addSelect('IFNULL(SUM( CASE WHEN subscribers.status = :status_subscribed AND subscribers.deleted_at IS NULL THEN 1 ELSE 0 END ), 0) as :status_subscribed') ->addSelect('IFNULL(SUM( CASE WHEN subscribers.status = :status_unsubscribed AND subscribers.deleted_at IS NULL THEN 1 ELSE 0 END ), 0) as :status_unsubscribed') ->addSelect('IFNULL(SUM( CASE WHEN subscribers.status = :status_inactive AND subscribers.deleted_at IS NULL THEN 1 ELSE 0 END ), 0) as :status_inactive') ->addSelect('IFNULL(SUM( CASE WHEN subscribers.status = :status_unconfirmed AND subscribers.deleted_at IS NULL THEN 1 ELSE 0 END ), 0) as :status_unconfirmed') ->addSelect('IFNULL(SUM( CASE WHEN subscribers.status = :status_bounced AND subscribers.deleted_at IS NULL THEN 1 ELSE 0 END ), 0) as :status_bounced') ->setParameter('status_subscribed', SubscriberEntity::STATUS_SUBSCRIBED) ->setParameter('status_unsubscribed', SubscriberEntity::STATUS_UNSUBSCRIBED) ->setParameter('status_inactive', SubscriberEntity::STATUS_INACTIVE) ->setParameter('status_unconfirmed', SubscriberEntity::STATUS_UNCONFIRMED) ->setParameter('status_bounced', SubscriberEntity::STATUS_BOUNCED); } public function getSubscribersWithoutSegmentCount(): int { $queryBuilder = $this->entityManager->createQueryBuilder(); $queryBuilder ->select('COUNT(DISTINCT s) AS subscribersCount') ->from(SubscriberEntity::class, 's'); $this->addConstraintsForSubscribersWithoutSegment($queryBuilder); return (int)$queryBuilder->getQuery()->getSingleScalarResult(); } public function getSubscribersWithoutSegmentStatisticsCount(): array { $subscribersTable = $this->entityManager->getClassMetadata(SubscriberEntity::class)->getTableName(); $queryBuilder = $this->entityManager ->getConnection() ->createQueryBuilder(); $queryBuilder ->addSelect('IFNULL(SUM( CASE WHEN s.deleted_at IS NULL THEN 1 ELSE 0 END ), 0) as `all`') ->addSelect('IFNULL(SUM( CASE WHEN s.deleted_at IS NOT NULL THEN 1 ELSE 0 END ), 0) as trash') ->addSelect('IFNULL(SUM( CASE WHEN s.status = :status_subscribed AND s.deleted_at IS NULL THEN 1 ELSE 0 END ), 0) as :status_subscribed') ->addSelect('IFNULL(SUM( CASE WHEN s.status = :status_unsubscribed AND s.deleted_at IS NULL THEN 1 ELSE 0 END ), 0) as :status_unsubscribed') ->addSelect('IFNULL(SUM( CASE WHEN s.status = :status_inactive AND s.deleted_at IS NULL THEN 1 ELSE 0 END ), 0) as :status_inactive') ->addSelect('IFNULL(SUM( CASE WHEN s.status = :status_unconfirmed AND s.deleted_at IS NULL THEN 1 ELSE 0 END ), 0) as :status_unconfirmed') ->addSelect('IFNULL(SUM( CASE WHEN s.status = :status_bounced AND s.deleted_at IS NULL THEN 1 ELSE 0 END ), 0) as :status_bounced') ->from($subscribersTable, 's') ->setParameter('status_subscribed', SubscriberEntity::STATUS_SUBSCRIBED) ->setParameter('status_unsubscribed', SubscriberEntity::STATUS_UNSUBSCRIBED) ->setParameter('status_inactive', SubscriberEntity::STATUS_INACTIVE) ->setParameter('status_unconfirmed', SubscriberEntity::STATUS_UNCONFIRMED) ->setParameter('status_bounced', SubscriberEntity::STATUS_BOUNCED); $this->addConstraintsForSubscribersWithoutSegmentToDBAL($queryBuilder); $statement = $this->executeQuery($queryBuilder); $result = $statement->fetch(); return $result; } public function addConstraintsForSubscribersWithoutSegment(ORMQueryBuilder $queryBuilder): void { $deletedSegmentsQueryBuilder = $this->entityManager->createQueryBuilder(); $deletedSegmentsQueryBuilder->select('sg.id') ->from(SegmentEntity::class, 'sg') ->where($deletedSegmentsQueryBuilder->expr()->isNotNull('sg.deletedAt')); $queryBuilder ->leftJoin('s.subscriberSegments', 'ssg', Join::WITH, (string)$queryBuilder->expr()->andX( $queryBuilder->expr()->eq('ssg.subscriber', 's.id'), $queryBuilder->expr()->eq('ssg.status', ':statusSubscribed'), $queryBuilder->expr()->notIn('ssg.segment', $deletedSegmentsQueryBuilder->getDQL()) )) ->andWhere('s.deletedAt IS NULL') ->andWhere('ssg.id IS NULL') ->setParameter('statusSubscribed', SubscriberEntity::STATUS_SUBSCRIBED); } public function addConstraintsForSubscribersWithoutSegmentToDBAL(QueryBuilder $queryBuilder): void { $deletedSegmentsQueryBuilder = $this->entityManager->createQueryBuilder(); $subscribersSegmentTable = $this->entityManager->getClassMetadata(SubscriberSegmentEntity::class)->getTableName(); $deletedSegmentsQueryBuilder->select('sg.id') ->from(SegmentEntity::class, 'sg') ->where($deletedSegmentsQueryBuilder->expr()->isNotNull('sg.deletedAt')); $queryBuilder ->leftJoin('s', $subscribersSegmentTable, 'ssg', (string)$queryBuilder->expr()->and( $queryBuilder->expr()->eq('ssg.subscriber_id', 's.id'), $queryBuilder->expr()->eq('ssg.status', ':statusSubscribed'), $queryBuilder->expr()->notIn('ssg.segment_id', $deletedSegmentsQueryBuilder->getQuery()->getSQL()) )) ->andWhere('ssg.id IS NULL') ->setParameter('statusSubscribed', SubscriberEntity::STATUS_SUBSCRIBED); } private function loadSubscriberIdsInSegment(int $segmentId, array $candidateIds = null): array { $segment = $this->getSegment($segmentId); $subscribersTable = $this->entityManager->getClassMetadata(SubscriberEntity::class)->getTableName(); $queryBuilder = $this->entityManager ->getConnection() ->createQueryBuilder() ->select("DISTINCT $subscribersTable.id") ->from($subscribersTable); if ($segment->isStatic()) { $queryBuilder = $this->filterSubscribersInStaticSegment($queryBuilder, $segment, SubscriberEntity::STATUS_SUBSCRIBED); } else { $queryBuilder = $this->filterSubscribersInDynamicSegment($queryBuilder, $segment, SubscriberEntity::STATUS_SUBSCRIBED); } if ($candidateIds) { $queryBuilder->andWhere("$subscribersTable.id IN (:candidateIds)") ->setParameter('candidateIds', $candidateIds, Connection::PARAM_STR_ARRAY); } $statement = $this->executeQuery($queryBuilder); $result = $statement->fetchAll(); return array_column($result, 'id'); } private function filterSubscribersInStaticSegment( QueryBuilder $queryBuilder, SegmentEntity $segment, string $status = null ): QueryBuilder { $subscribersSegmentsTable = $this->entityManager->getClassMetadata(SubscriberSegmentEntity::class)->getTableName(); $subscribersTable = $this->entityManager->getClassMetadata(SubscriberEntity::class)->getTableName(); $parameterName = "segment_{$segment->getId()}"; // When we use this method more times the parameter name has to be unique $queryBuilder = $queryBuilder->join( $subscribersTable, $subscribersSegmentsTable, 'subsegment', "subsegment.subscriber_id = $subscribersTable.id AND subsegment.segment_id = :$parameterName" )->andWhere("$subscribersTable.deleted_at IS NULL") ->setParameter($parameterName, $segment->getId()); if ($status) { $queryBuilder = $queryBuilder->andWhere("$subscribersTable.status = :status") ->andWhere("subsegment.status = :status") ->setParameter('status', $status); } return $queryBuilder; } private function filterSubscribersInDynamicSegment( QueryBuilder $queryBuilder, SegmentEntity $segment, string $status = null ): QueryBuilder { $filters = []; $dynamicFilters = $segment->getDynamicFilters(); foreach ($dynamicFilters as $dynamicFilter) { $filters[] = $dynamicFilter->getFilterData(); } // We don't allow dynamic segment without filers since it would return all subscribers // For BC compatibility fetching an empty result if (count($filters) === 0) { return $queryBuilder->andWhere('0 = 1'); } elseif ($segment instanceof SegmentEntity) { $queryBuilder = $this->filterHandler->apply($queryBuilder, $segment); } $subscribersTable = $this->entityManager->getClassMetadata(SubscriberEntity::class)->getTableName(); $queryBuilder = $queryBuilder->andWhere("$subscribersTable.deleted_at IS NULL"); if ($status) { $queryBuilder = $queryBuilder->andWhere("$subscribersTable.status = :status") ->setParameter('status', $status); } return $queryBuilder; } private function getSegment(int $id): SegmentEntity { $segment = $this->entityManager->find(SegmentEntity::class, $id); if (!$segment instanceof SegmentEntity) { throw new NotFoundException('Segment not found'); } return $segment; } private function executeQuery(QueryBuilder $queryBuilder): Statement { $statement = $queryBuilder->execute(); // Execute for select always returns statement but PHP Stan doesn't know that :( if (!$statement instanceof Statement) { throw new InvalidStateException('Invalid query.'); } return $statement; } public function getSubscribersGlobalStatusStatisticsCount(SegmentEntity $segment): array { if ($segment->isStatic()) { $queryBuilder = $this->createStaticGlobalStatusStatisticsQueryBuilder($segment); } else { $queryBuilder = $this->createDynamicStatisticsQueryBuilder(); $this->filterSubscribersInDynamicSegment($queryBuilder, $segment); } $statement = $this->executeQuery($queryBuilder); return $statement->fetch(); } public function getSubscribersStatisticsCount(SegmentEntity $segment): array { if ($segment->isStatic()) { $queryBuilder = $this->createStaticStatisticsQueryBuilder($segment); } else { $queryBuilder = $this->createDynamicStatisticsQueryBuilder(); $this->filterSubscribersInDynamicSegment($queryBuilder, $segment); } $statement = $this->executeQuery($queryBuilder); return $statement->fetch(); } }