: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* Whether a location type is standalone.
* @param string $location_type Location type.
private function is_standalone( string $location_type ): bool {
return in_array( $location_type, self::STANDALONE_LOCATION_TYPES, true );
* @param array $form_location Form location.
private function get_location_title( $form_location ) {
if ( $form_location['type'] !== self::WIDGET ) {
return $this->get_post_location_title( $form_location );
$sidebar_name = $this->get_widget_sidebar_name( $form_location['id'] );
// The widget is not found.
$title = $form_location['title'];
if ( strpos( $form_location['id'], self::WPFORMS_WIDGET_PREFIX ) === 0 ) {
$title = $this->wpforms_widget_title;
if ( strpos( $form_location['id'], 'text-' ) === 0 ) {
$title = $this->text_widget_title;
return $sidebar_name . ': ' . $title;
* @param array $form_location Form location.
private function get_location_url( $form_location ) {
// Get widget or wp_template url.
if ( $form_location['type'] === self::WIDGET || $this->is_wp_template( $form_location['type'] ) ) {
if ( $this->is_standalone( $form_location['type'] ) ) {
return $form_location['url'];
if ( ! $this->is_post_visible( $form_location ) ) {
return $form_location['url'];
* @param array $form_location Form location.
private function get_location_edit_url( array $form_location ): string {
if ( $form_location['type'] === self::WIDGET ) {
return current_user_can( 'edit_theme_options' ) ? admin_url( 'widgets.php' ) : '';
if ( $this->is_standalone( $form_location['type'] ) ) {
'page' => 'wpforms-builder',
'form_id' => $form_location['form_id'],
if ( ! $this->is_post_visible( $form_location ) ) {
if ( $this->is_wp_template( $form_location['type'] ) ) {
'postType' => $form_location['type'],
'postId' => get_stylesheet() . '//' . str_replace( '/', '', $form_location['url'] ),
admin_url( 'site-editor.php' )
return (string) get_edit_post_link( $form_location['id'], '' );
* Get location information to output as a row in the location pane.
* @param array $form_location Form location.
* @noinspection PhpTernaryExpressionCanBeReducedToShortVersionInspection
* @noinspection ElvisOperatorCanBeUsedInspection
private function get_location_row( $form_location ) {
$title = $this->get_location_title( $form_location );
$title = $title ? $title : __( '(no title)', 'wpforms-lite' );
$location_url = $this->get_location_url( $form_location );
$location_full_url = $this->home_url . $location_url;
// phpcs:ignore Generic.Commenting.DocComment.MissingShort
/** @noinspection HtmlUnknownTarget */
$location_link = sprintf(
' <a href="%1$s" target="_blank" class="wpforms-locations-link">%2$s <i class="fa fa-external-link" aria-hidden="true"></i></a>',
esc_url( $location_full_url ),
$location_edit_url = $this->get_location_edit_url( $form_location );
$location_edit_url = $location_edit_url ? $location_edit_url : '#';
// phpcs:ignore Generic.Commenting.DocComment.MissingShort
/** @noinspection HtmlUnknownTarget */
$location_edit_link = sprintf(
'<a href="%1$s">%2$s</a>',
esc_url( $location_edit_url ),
'<span class="wpforms-locations-list-item">%s</span>',
$location_edit_link . $location_link
* Get location information to output as rows in the location pane.
* @param array $form_locations Form locations.
private function get_location_rows( $form_locations ) {
foreach ( $form_locations as $form_location ) {
$rows[] = $this->get_location_row( $form_location );
$rows = array_unique( array_filter( $rows ) );
static function ( $a, $b ) {
$pattern = '/href=".+widgets.php">(.+?)</i';
$widget_title_a = preg_match( $pattern, $a, $ma ) ? $ma[1] : '';
$widget_title_b = preg_match( $pattern, $b, $mb ) ? $mb[1] : '';
return strcmp( $widget_title_a, $widget_title_b );
* Update form location on save_post action.
* @param int $post_ID Post ID.
* @param WP_Post $post Post object.
* @param bool $update Whether this is an existing post being updated.
* @noinspection PhpUnusedParameterInspection
public function save_post( $post_ID, $post, $update ) {
! in_array( $post->post_type, $this->get_post_types(), true ) ||
! in_array( $post->post_status, $this->get_post_statuses(), true )
$form_ids = $this->get_form_ids( $post->post_content );
$this->update_form_locations_metas( null, $post, [], $form_ids );
* Update form location on post_updated action.
* @param int $post_id Post id.
* @param WP_Post $post_after Post after the update.
* @param WP_Post $post_before Post before the update.
* @noinspection PhpUnusedParameterInspection
public function post_updated( $post_id, $post_after, $post_before ) {
! in_array( $post_after->post_type, $this->get_post_types(), true ) ||
! in_array( $post_after->post_status, $this->get_post_statuses(), true )
$form_ids_before = $this->get_form_ids( $post_before->post_content );
$form_ids_after = $this->get_form_ids( $post_after->post_content );
$this->update_form_locations_metas( $post_before, $post_after, $form_ids_before, $form_ids_after );
* Update form locations on trash_post action.
* @param int $post_id Post id.
public function trash_post( $post_id ) {
$post = get_post( $post_id );
$form_ids_before = $this->get_form_ids( $post->post_content );
$this->update_form_locations_metas( null, $post, $form_ids_before, $form_ids_after );
* Update form locations on untrash_post action.
* @param int $post_id Post id.
public function untrash_post( $post_id ) {
$post = get_post( $post_id );
$form_ids_after = $this->get_form_ids( $post->post_content );
$this->update_form_locations_metas( null, $post, $form_ids_before, $form_ids_after );
* Prepare widgets for further search.
* @param array|null $widgets Widgets.
* @param string $type Widget type.
private function prepare_widgets( $widgets, $type ) {
'option' => self::WPFORMS_WIDGET_OPTION,
'option' => self::TEXT_WIDGET_OPTION,
'option' => self::BLOCK_WIDGET_OPTION,
if ( ! array_key_exists( $type, $params ) ) {
$option = $params[ $type ]['option'];
$content = $params[ $type ]['content'];
$widgets = $widgets ?? (array) get_option( $option, [] );
static function ( $widget ) use ( $content ) {
return isset( $widget[ $content ] );
* Search forms in WPForms widgets.
* @param array $widgets Widgets.
private function search_in_wpforms_widgets( $widgets = null ) {
$widgets = $this->prepare_widgets( $widgets, 'wpforms' );
foreach ( $widgets as $id => $widget ) {
'title' => $widget['title'],
'form_id' => $widget['form_id'],
'id' => self::WPFORMS_WIDGET_PREFIX . $id,
* Search forms in text widgets.
* @param array $widgets Widgets.
private function search_in_text_widgets( $widgets = null ) {
$widgets = $this->prepare_widgets( $widgets, 'text' );
foreach ( $widgets as $id => $widget ) {
$form_ids = $this->get_form_ids( $widget['text'] );
foreach ( $form_ids as $form_id ) {
'title' => $widget['title'],
'id' => self::TEXT_WIDGET_PREFIX . $id,
* Search forms in block widgets.
* @param array $widgets Widgets.
private function search_in_block_widgets( $widgets = null ) {
$widgets = $this->prepare_widgets( $widgets, 'block' );
foreach ( $widgets as $id => $widget ) {
$form_ids = $this->get_form_ids( $widget['content'] );
foreach ( $form_ids as $form_id ) {
'title' => $this->block_widget_title,
'id' => self::BLOCK_WIDGET_PREFIX . $id,
* Search forms in widgets.
public function search_in_widgets() {
$this->search_in_wpforms_widgets(),
$this->search_in_text_widgets(),
$this->search_in_block_widgets()
* Get the difference of two arrays containing locations.
* @param array $locations1 Locations to subtract from.
* @param array $locations2 Locations to subtract.
private function array_udiff( $locations1, $locations2 ) {
static function ( $a, $b ) {
return ( $a === $b ) ? 0 : - 1;
* Remove locations from metas.
* @param array $locations_to_remove Locations to remove.
private function remove_locations( $locations_to_remove ) {
foreach ( $locations_to_remove as $location_to_remove ) {
$locations = get_post_meta( $location_to_remove['form_id'], self::LOCATIONS_META, true );
foreach ( $locations as $key => $location ) {
if ( $location['id'] === $location_to_remove['id'] ) {
unset( $locations[ $key ] );
update_post_meta( $location_to_remove['form_id'], self::LOCATIONS_META, $locations );
* Add locations to metas.
* @param array $locations_to_add Locations to add.