: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
class ET_Builder_Module_Portfolio extends ET_Builder_Module_Type_PostBased {
$this->name = esc_html__( 'Portfolio', 'et_builder' );
$this->plural = esc_html__( 'Portfolios', 'et_builder' );
$this->slug = 'et_pb_portfolio';
$this->vb_support = 'on';
$this->main_css_element = '%%order_class%% .et_pb_portfolio_item';
$this->settings_modal_toggles = array(
'main_content' => et_builder_i18n( 'Content' ),
'elements' => et_builder_i18n( 'Elements' ),
'layout' => et_builder_i18n( 'Layout' ),
'overlay' => et_builder_i18n( 'Overlay' ),
'title' => et_builder_i18n( 'Image' ),
'title' => et_builder_i18n( 'Text' ),
$this->advanced_fields = array(
'label' => et_builder_i18n( 'Title' ),
'main' => "{$this->main_css_element} h2, {$this->main_css_element} h2 a, {$this->main_css_element} h1.et_pb_module_header, {$this->main_css_element} h1.et_pb_module_header a, {$this->main_css_element} h3.et_pb_module_header, {$this->main_css_element} h3.et_pb_module_header a, {$this->main_css_element} h4.et_pb_module_header, {$this->main_css_element} h4.et_pb_module_header a, {$this->main_css_element} h5.et_pb_module_header, {$this->main_css_element} h5.et_pb_module_header a, {$this->main_css_element} h6.et_pb_module_header, {$this->main_css_element} h6.et_pb_module_header a",
'hover' => "{$this->main_css_element} h2:hover, {$this->main_css_element} h2:hover a, {$this->main_css_element} h1.et_pb_module_header:hover, {$this->main_css_element} h1.et_pb_module_header:hover a, {$this->main_css_element} h3.et_pb_module_header:hover, {$this->main_css_element} h3.et_pb_module_header:hover a, {$this->main_css_element} h4.et_pb_module_header:hover, {$this->main_css_element} h4.et_pb_module_header:hover a, {$this->main_css_element} h5.et_pb_module_header:hover, {$this->main_css_element} h5.et_pb_module_header:hover a, {$this->main_css_element} h6.et_pb_module_header:hover, {$this->main_css_element} h6.et_pb_module_header:hover a",
'label' => esc_html__( 'Meta', 'et_builder' ),
'main' => "{$this->main_css_element} .post-meta, {$this->main_css_element} .post-meta a",
'hover' => "{$this->main_css_element} .post-meta a:hover",
'label' => esc_html__( 'Pagination', 'et_builder' ),
'main' => function_exists( 'wp_pagenavi' ) ? "%%order_class%% .wp-pagenavi a, %%order_class%% .wp-pagenavi span" : "%%order_class%% .pagination a",
'important' => function_exists( 'wp_pagenavi' ) ? 'all' : array(),
'text_align' => '%%order_class%% .wp-pagenavi',
'hover' => function_exists( 'wp_pagenavi' ) ? "%%order_class%% .wp-pagenavi a:hover, %%order_class%% .wp-pagenavi span:hover" : "%%order_class%% .pagination a:hover",
'hide_text_align' => ! function_exists( 'wp_pagenavi' ),
'options' => et_builder_get_text_orientation_options( array( 'justified' ), array() ),
'border_radii' => $this->main_css_element,
'border_styles' => $this->main_css_element,
'border_radii' => "{$this->main_css_element} .et_portfolio_image",
'border_styles' => "{$this->main_css_element} .et_portfolio_image",
'label_prefix' => et_builder_i18n( 'Image' ),
'tab_slug' => 'advanced',
'toggle_slug' => 'image',
'label' => esc_html__( 'Image Box Shadow', 'et_builder' ),
'option_category' => 'layout',
'tab_slug' => 'advanced',
'toggle_slug' => 'image',
'main' => '%%order_class%% .et_pb_portfolio_item .et_portfolio_image',
'default_on_fronts' => array(
'margin_padding' => array(
'main' => '%%order_class%%',
'important' => array( 'custom_margin' ), // needed to overwrite last module margin-bottom styling
'use_background_layout' => true,
'background_layout' => array(
'main' => '%%order_class%% .et_pb_module_header, %%order_class%% .post-meta'
'main' => '%%order_class%%',
'child_filters_target' => array(
'tab_slug' => 'advanced',
'toggle_slug' => 'image',
'main' => '%%order_class%% .et_portfolio_image',
'scroll_effects' => array(
$this->custom_css_fields = array(
'portfolio_image' => array(
'label' => esc_html__( 'Portfolio Image', 'et_builder' ),
'selector' => '.et_portfolio_image',
'label' => et_builder_i18n( 'Overlay' ),
'selector' => '.et_overlay',
'label' => esc_html__( 'Overlay Icon', 'et_builder' ),
'selector' => '.et_overlay:before',
'portfolio_title' => array(
'label' => esc_html__( 'Portfolio Title', 'et_builder' ),
'selector' => '.et_pb_portfolio_item h2',
'portfolio_post_meta' => array(
'label' => esc_html__( 'Portfolio Post Meta', 'et_builder' ),
'selector' => '.et_pb_portfolio_item .post-meta',
'label' => esc_html__( 'Portfolio Pagination', 'et_builder' ),
'selector' => function_exists( 'wp_pagenavi' ) ? '%%order_class%% .wp-pagenavi a, %%order_class%% .wp-pagenavi span' : '%%order_class%% .pagination a',
$this->help_videos = array(
'name' => esc_html__( 'An introduction to the Portfolio module', 'et_builder' ),
'label' => et_builder_i18n( 'Layout' ),
'option_category' => 'layout',
'on' => esc_html__( 'Fullwidth', 'et_builder' ),
'off' => esc_html__( 'Grid', 'et_builder' ),
'default_on_front' => 'on',
'description' => esc_html__( 'Choose your desired portfolio layout style.', 'et_builder' ),
'computed_affects' => array(
'tab_slug' => 'advanced',
'toggle_slug' => 'layout',
'label' => esc_html__( 'Post Count', 'et_builder' ),
'option_category' => 'configuration',
'description' => esc_html__( 'Define the number of projects that should be displayed per page.', 'et_builder' ),
'computed_affects' => array(
'toggle_slug' => 'main_content',
'include_categories' => array(
'label' => esc_html__( 'Included Categories', 'et_builder' ),
'meta_categories' => array(
'all' => esc_html__( 'All Categories', 'et_builder' ),
'current' => esc_html__( 'Current Category', 'et_builder' ),
'option_category' => 'basic_option',
'description' => esc_html__( 'Select the categories that you would like to include in the feed.', 'et_builder' ),
'toggle_slug' => 'main_content',
'computed_affects' => array(
'taxonomy_name' => 'project_category',
'label' => esc_html__( 'Show Title', 'et_builder' ),
'type' => 'yes_no_button',
'option_category' => 'configuration',
'on' => et_builder_i18n( 'Yes' ),
'off' => et_builder_i18n( 'No' ),
'default_on_front' => 'on',
'toggle_slug' => 'elements',
'description' => esc_html__( 'Turn project titles on or off.', 'et_builder' ),
'mobile_options' => true,
'show_categories' => array(
'label' => esc_html__( 'Show Categories', 'et_builder' ),
'type' => 'yes_no_button',
'option_category' => 'configuration',
'on' => et_builder_i18n( 'Yes' ),
'off' => et_builder_i18n( 'No' ),
'default_on_front' => 'on',
'toggle_slug' => 'elements',
'description' => esc_html__( 'Turn the category links on or off.', 'et_builder' ),
'mobile_options' => true,
'show_pagination' => array(
'label' => esc_html__( 'Show Pagination', 'et_builder' ),
'type' => 'yes_no_button',
'option_category' => 'configuration',
'on' => et_builder_i18n( 'Yes' ),
'off' => et_builder_i18n( 'No' ),
'default_on_front' => 'on',
'toggle_slug' => 'elements',
'description' => esc_html__( 'Enable or disable pagination for this feed.', 'et_builder' ),
'mobile_options' => true,
'zoom_icon_color' => array(
'label' => esc_html__( 'Zoom Icon Color', 'et_builder' ),
'description' => esc_html__( 'Here you can define a custom color for the zoom icon.', 'et_builder' ),
'depends_show_if' => 'off',
'tab_slug' => 'advanced',
'toggle_slug' => 'overlay',
'mobile_options' => true,
'hover_overlay_color' => array(
'label' => esc_html__( 'Hover Overlay Color', 'et_builder' ),
'description' => esc_html__( 'Here you can define a custom color for the overlay', 'et_builder' ),
'depends_show_if' => 'off',
'tab_slug' => 'advanced',
'toggle_slug' => 'overlay',
'mobile_options' => true,
'label' => esc_html__( 'Hover Icon Picker', 'et_builder' ),
'description' => esc_html__( 'Here you can define a custom icon for the overlay', 'et_builder' ),
'option_category' => 'configuration',
'class' => array( 'et-pb-font-icon' ),
'depends_show_if' => 'off',
'tab_slug' => 'advanced',
'toggle_slug' => 'overlay',
'computed_callback' => array( 'ET_Builder_Module_Portfolio', 'get_portfolio_item' ),
'computed_depends_on' => array(
'computed_callback' => array( 'ET_Builder_Module_Portfolio', 'get_portfolio_item' ),
'computed_affects' => array(
public function get_transition_fields_css_props() {
$fields = parent::get_transition_fields_css_props();
$fields['max_width'] = array( 'max-width' => '%%order_class%%, %%order_class%% .et_pb_portfolio_item' );
$fields['width'] = array( 'width' => '%%order_class%%, %%order_class%% .et_pb_portfolio_item' );
* Get portfolio objects for portfolio module
* @param array $args arguments that affect et_pb_portfolio query
* @param array $conditional_tags conditional tag for update process
* @param array $current_page current page params
* @return mixed portfolio item data
static function get_portfolio_item( $args = array(), $conditional_tags = array(), $current_page = array() ) {
global $et_fb_processing_shortcode_object, $post;
$global_processing_original_value = $et_fb_processing_shortcode_object;
'include_categories' => '',
$args = wp_parse_args( $args, $defaults );
// Native conditional tag only works on page load. Data update needs $conditional_tags data
$is_front_page = et_fb_conditional_tag( 'is_front_page', $conditional_tags );
$is_search = et_fb_conditional_tag( 'is_search', $conditional_tags );
// Prepare query arguments
'posts_per_page' => (int) $args['posts_number'],
'post_type' => 'project',
'post_status' => array( 'publish', 'private' ),
// Conditionally get paged data
if ( defined( 'DOING_AJAX' ) && isset( $current_page[ 'paged'] ) ) {
$et_paged = intval( $current_page[ 'paged' ] );
$et_paged = $is_front_page ? get_query_var( 'page' ) : get_query_var( 'paged' );
$paged = $et_paged; // phpcs:ignore WordPress.Variables.GlobalVariables.OverrideProhibited
// support pagination in VB
if ( isset( $args['__page'] ) ) {
$et_paged = $args['__page'];
$query_args['paged'] = $et_paged;
// Passed categories parameter
$include_categories = self::filter_include_categories( $args['include_categories'], 0, 'project_category' );
if ( ! empty( $include_categories ) ) {
$query_args['tax_query'] = array(
'taxonomy' => 'project_category',
'terms' => $include_categories,
$query = new WP_Query( $query_args );
// Format portfolio output, and add supplementary data
$width = 'on' === $args['fullwidth'] ? 1080 : 400;
$width = (int) apply_filters( 'et_pb_portfolio_image_width', $width );
$height = 'on' === $args['fullwidth'] ? 9999 : 284;
$height = (int) apply_filters( 'et_pb_portfolio_image_height', $height );
$classtext = 'on' === $args['fullwidth'] ? 'et_pb_post_main_image' : '';
$titletext = get_the_title();
// Loop portfolio item data and add supplementary data
if ( $query->have_posts() ) {
while( $query->have_posts() ) {
ET_Post_Stack::replace( $post );
$categories_object = get_the_terms( get_the_ID(), 'project_category' );
if ( ! empty( $categories_object ) ) {
foreach ( $categories_object as $category ) {
'id' => $category->term_id,
'label' => $category->name,
'permalink' => get_term_link( $category ),
// need to disable processnig to make sure get_thumbnail() doesn't generate errors
$et_fb_processing_shortcode_object = false;
// Capture the ALT text defined in WP Media Library
$alttext = get_post_meta( get_post_thumbnail_id(), '_wp_attachment_image_alt', true );
$thumbnail = get_thumbnail( $width, $height, $classtext, $alttext, $titletext, false, 'Blogimage' );
$et_fb_processing_shortcode_object = $global_processing_original_value;
// Append value to query post
$query->posts[ $post_index ]->post_permalink = get_permalink();
$query->posts[ $post_index ]->featured_image = isset( $thumbnail['fullpath'] ) ? $thumbnail['fullpath'] : null;
$query->posts[ $post_index ]->post_thumbnail = print_thumbnail( $thumbnail['thumb'], $thumbnail['use_timthumb'], $titletext, $width, $height, '', false, true );
$query->posts[ $post_index ]->post_categories = $categories;
$query->posts[ $post_index ]->post_class_name = get_post_class( '', get_the_ID() );
$query->posts_next = array(
'label' => esc_html__( '« Older Entries', 'et_builder' ),
'url' => self::get_next_link( $et_paged, $query->max_num_pages ),
$query->posts_prev = array(
'label' => esc_html__( 'Next Entries »', 'et_builder' ),
'url' => self::get_previous_link( $et_paged ),
// Added wp_pagenavi support
$query->wp_pagenavi = function_exists( 'wp_pagenavi' ) ? wp_pagenavi( array(
} else if ( self::is_processing_computed_prop() ) {
$query = array( 'posts' => self::get_no_results_template() );
* @param int $paged Current page.
* @param int $max Max number of pages.
private static function get_next_link( $paged, $max ) {