: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* @copyright Copyright (c) 2023, Code Atlantic LLC
if ( ! defined( 'ABSPATH' ) ) {
class PUM_Model_Popup extends PUM_Abstract_Model_Post {
protected $required_post_type = 'popup';
* Filtered array of conditions.
public $conditions_filtered = [];
* Old content caching, don't use.
* @deprecated 1.8.0 Was used in PUM ALM extension, needs time to get those changes published.
* Currently being passively migrated.
public $doing_passive_migration = false;
* The current model version.
public $model_version = 3;
* The version of the data currently stored for the current item.
// TODO Remove these once no longer needed.
* Used to hackishly insert settings for generated popups not stored in DB. (Shortcodes).
* Used to hackishly insert title for generated popups not stored in DB. (Shortcodes).
* Used to hackishly change the model to prevent queries. (Shortcodes).
* @param string $key Meta key.
* @param bool $single Get single only or multiple values.
public function get_meta( $key, $single = true ) {
return parent::get_meta( $key, $single );
* Returns the title of a popup.
* @uses filter `pum_popup_get_title`
public function get_title() {
$title = isset( $this->title ) ? $this->title : $this->get_meta( 'popup_title' );
return (string) apply_filters( 'pum_popup_get_title', (string) $title, $this->ID );
* Returns the content of a popup.
* @uses filter `pum_popup_content`
public function get_content() {
$this->content = $this->post_content;
return apply_filters( 'pum_popup_content', $this->post_content, $this->ID );
* Returns array of all popup settings.
public function get_settings() {
if ( ! isset( $this->settings ) ) {
// This hack is here to allow creating popups on the fly without saved meta.
$settings = isset( $this->settings ) ? $this->settings : $this->get_meta( 'popup_settings' );
if ( ! is_array( $settings ) ) {
// Review: the above should be removed and replaced with a hooked filter here to supply defaults when $settings === false.
$this->settings = apply_filters( 'pum_popup_settings', $settings, $this->ID );
* Returns a specific popup setting with optional default value when not found.
* @param string $key Setting key.
* @param mixed $default Default value if not set.
public function get_setting( $key, $default = false ) {
$settings = $this->get_settings();
return isset( $settings[ $key ] ) ? $settings[ $key ] : $default;
* @param string $key Setting key.
* @param mixed $value New value.
public function update_setting( $key, $value ) {
// TODO Once fields have been merged into the model itself, add automatic validation here.
$new_settings = [ $key => $value ];
return $this->update_settings( $new_settings, true );
* Update multiple settings at once.
* @param array $new_settings Array of new setting key=>value pairs.
* @param bool $merge Wheher to merge values or replace them.
public function update_settings( $new_settings = [], $merge = true ) {
$settings = $this->get_settings();
// TODO Once fields have been merged into the model itself, add automatic validation here.
foreach ( $new_settings as $key => $value ) {
$settings[ $key ] = $value;
$settings = $new_settings;
if ( empty( $settings['theme_id'] ) ) {
$settings['theme_id'] = pum_get_default_theme_id();
if ( empty( $settings['theme_slug'] ) ) {
$settings['theme_slug'] = get_post_field( 'post_name', $settings['theme_id'] );
return $this->update_meta( 'popup_settings', $settings );
* Returns cleansed public settings for a popup.
public function get_public_settings() {
$settings = wp_parse_args( $this->get_settings(), PUM_Admin_Popups::defaults() );
foreach ( $settings as $key => $value ) {
$field = PUM_Admin_Popups::get_field( $key );
if ( false === $field ) {
// This is a value set programatically, not by a defined field. ex theme_slug.
$settings[ $key ] = $value;
if ( $field['private'] ) {
unset( $settings[ $key ] );
} elseif ( 'checkbox' === $field['type'] ) {
$settings[ $key ] = (bool) $value;
$settings['id'] = $this->ID;
$settings['slug'] = $this->post_name;
// Pass conditions only if there are JS conditions.
if ( $this->has_conditions( [ 'js_only' => true ] ) ) {
$settings['conditions'] = $this->get_parsed_js_conditions();
return apply_filters( 'pum_popup_get_public_settings', $settings, $this );
* Preprocess PHP conditions in order for more accurate JS handling.
* @return array Array of conditions, whith PHP conditions replaced with boolean values.
public function get_parsed_js_conditions() {
$parsed_conditions = $this->get_conditions();
foreach ( $parsed_conditions as $group_index => $conditions ) {
foreach ( $conditions as $index => $condition ) {
// Check each non js condition, replace it with true/false depending on its result.
if ( ! $this->is_js_condition( $condition ) ) {
if ( ! $condition['not_operand'] && $this->check_condition( $condition ) ) {
} elseif ( $condition['not_operand'] && ! $this->check_condition( $condition ) ) {
$parsed_conditions[ $group_index ][ $index ] = $return;
return $parsed_conditions;
* Check if a given condition is JS based.
* @param array $condition Condition to check.
public function is_js_condition( $condition = [] ) {
$condition_args = PUM_Conditions::instance()->get_condition( $condition['target'] );
if ( ! $condition_args ) {
// Bail early with true for conditions that will be processed in JavaScript later.
return true === $condition_args['advanced'] || empty( $condition_args['callback'] );
public function get_cookies() {
return apply_filters( 'pum_popup_get_cookies', $this->get_setting( 'cookies', [] ), $this->ID );
* Check if popup has cookie by event.
* @param string $event Event to check for cookie on.
public function has_cookie( $event ) {
foreach ( (array) $this->get_cookies() as $cookie ) {
if ( $cookie['event'] === $event ) {
public function get_triggers() {
$triggers = $this->get_setting( 'triggers', [] );
// Automatically add click trigger when on the front end.
if ( ! is_admin() && ! ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
$has_click_trigger = false;
foreach ( $triggers as $trigger ) {
if ( 'click_open' === $trigger['type'] ) {
$has_click_trigger = true;
if ( ! $has_click_trigger && apply_filters( 'pum_add_default_click_trigger', true, $this->ID ) ) {
return apply_filters( 'pum_popup_get_triggers', $triggers, $this->ID );
* Check if popup has trigger of type.
* @param string $type Popup trigger type to check for.
public function has_trigger( $type ) {
$triggers = $this->get_triggers();
foreach ( $triggers as $trigger ) {
if ( $trigger['type'] === $type ) {
* Returns this popups theme id or the default id.
* @uses filter `pum_popup_get_theme_id`
public function get_theme_id() {
// TODO replace usage of popmake_get_default_popup_theme.
$theme_id = $this->get_setting( 'theme_id', pum_get_default_theme_id() );
return (int) apply_filters( 'pum_popup_get_theme_id', $theme_id, $this->ID );
* Array of deprecated settings groups.
* Retrieve settings in the form of deprecated grouped arrays.
* @param string $group Old group to fetch settings for.
* @param string $key Setting key to retrieve.
protected function dep_get_settings_group( $group, $key = null ) {
if ( ! isset( $this->dep_groups[ $group ] ) ) {
* Remap old meta settings to new settings location for v1.7. This acts as a passive migration when needed.
$remapped_keys = $this->remapped_meta_settings_keys( $group );
// This will only return data from extensions as core data has been migrated already.
$group_values = $this->get_meta( "popup_$group" );
if ( ! $group_values || ! is_array( $group_values ) ) {
// Data manipulation begins here. We don't want any of this saved, only returned for backward compatibility.
foreach ( $remapped_keys as $old_key => $new_key ) {
$group_values[ $old_key ] = $this->get_setting( $new_key );
$deprecated_values = popmake_get_popup_meta_group( $group, $this->ID );
if ( ! empty( $deprecated_values ) ) {
foreach ( $deprecated_values as $old_key => $value ) {
if ( ! isset( $group_values[ $old_key ] ) ) {
$group_values[ $old_key ] = $value;
$this->dep_groups[ $group ] = $group_values;
$values = apply_filters( "pum_popup_get_$group", $this->dep_groups[ $group ], $this->ID );
$value = isset( $values[ $key ] ) ? $values[ $key ] : null;
if ( ! isset( $value ) ) {
$value = $this->get_meta( "popup_{$group}_{$key}" );
return apply_filters( "pum_popup_get_{$group}_" . $key, $value, $this->ID );
* Get list of remappings for old data.
* @param string $group Group to get values for.
public function remapped_meta_settings_keys( $group ) {
$remapped_meta_settings_keys = [
'stackable' => 'stackable',
'overlay_disabled' => 'overlay_disabled',
'scrollable_content' => 'scrollable_content',
'disable_reposition' => 'disable_reposition',