Example #1
0
/**
 * Enqueue the required styles
 */
function siteorigin_panels_enqueue_styles()
{
    // Register the style to support possible lazy loading
    wp_register_style('siteorigin-panels-front', plugin_dir_url(__FILE__) . 'css/front.css', array(), SITEORIGIN_PANELS_VERSION);
    if (is_singular() && get_post_meta(get_the_ID(), true) != '') {
        wp_enqueue_style('siteorigin-panels-front');
        // Enqueue the general layout CSS
        global $siteorigin_panels_inline_css;
        if (empty($siteorigin_panels_inline_css)) {
            $siteorigin_panels_inline_css = array();
        }
        $siteorigin_panels_inline_css[get_the_ID()] = siteorigin_panels_generate_css(get_the_ID());
    }
}
/**
 * Render the panels
 *
 * @param int|string|bool $post_id The Post ID or 'home'.
 * @param bool $enqueue_css Should we also enqueue the layout CSS.
 * @param array|bool $panels_data Existing panels data. By default load from settings or post meta.
 * @return string
 */
function siteorigin_panels_render($post_id = false, $enqueue_css = true, $panels_data = false)
{
    if (empty($post_id)) {
        $post_id = get_the_ID();
    }
    global $siteorigin_panels_current_post;
    $old_current_post = $siteorigin_panels_current_post;
    $siteorigin_panels_current_post = $post_id;
    // Try get the cached panel from in memory cache.
    global $siteorigin_panels_cache;
    if (!empty($siteorigin_panels_cache) && !empty($siteorigin_panels_cache[$post_id])) {
        return $siteorigin_panels_cache[$post_id];
    }
    if (empty($panels_data)) {
        if ($post_id == 'home') {
            $panels_data = get_option('siteorigin_panels_home_page', get_theme_mod('panels_home_page', null));
            if (is_null($panels_data)) {
                // Load the default layout
                $layouts = apply_filters('siteorigin_panels_prebuilt_layouts', array());
                $panels_data = !empty($layouts['home']) ? $layouts['home'] : current($layouts);
            }
        } else {
            if (post_password_required($post_id)) {
                return false;
            }
            $panels_data = get_post_meta($post_id, 'panels_data', true);
        }
    }
    $panels_data = apply_filters('siteorigin_panels_data', $panels_data, $post_id);
    if (empty($panels_data) || empty($panels_data['grids'])) {
        return '';
    }
    // Create the skeleton of the grids
    $grids = array();
    if (!empty($panels_data['grids']) && !empty($panels_data['grids'])) {
        foreach ($panels_data['grids'] as $gi => $grid) {
            $gi = intval($gi);
            $grids[$gi] = array();
            for ($i = 0; $i < $grid['cells']; $i++) {
                $grids[$gi][$i] = array();
            }
        }
    }
    if (!empty($panels_data['widgets']) && is_array($panels_data['widgets'])) {
        foreach ($panels_data['widgets'] as $widget) {
            $grids[intval($widget['info']['grid'])][intval($widget['info']['cell'])][] = $widget;
        }
    }
    ob_start();
    global $siteorigin_panels_inline_css;
    if (empty($siteorigin_panels_inline_css)) {
        $siteorigin_panels_inline_css = '';
    }
    if ($enqueue_css) {
        if (siteorigin_panels_setting('inline-css')) {
            wp_enqueue_style('siteorigin-panels-front');
            $siteorigin_panels_inline_css .= siteorigin_panels_generate_css($post_id, $panels_data);
        } else {
            // This is the CSS for the page layout.
            wp_enqueue_style('siteorigin-panels-post-css-' . $post_id, add_query_arg(array('action' => 'siteorigin_panels_post_css', 'post' => $post_id, 'layout' => substr(md5(serialize($panels_data)), 0, 8)), admin_url('admin-ajax.php')), array('siteorigin-panels-front'), SITEORIGIN_PANELS_VERSION);
        }
    }
    foreach ($grids as $gi => $cells) {
        // This allows other themes and plugins to add html before the row
        echo apply_filters('siteorigin_panels_before_row', '', $panels_data['grids'][$gi]);
        $grid_classes = apply_filters('siteorigin_panels_row_classes', array('panel-grid'), $panels_data['grids'][$gi]);
        $grid_attributes = apply_filters('siteorigin_panels_row_attributes', array('class' => implode(' ', $grid_classes), 'id' => 'pg-' . $post_id . '-' . $gi), $panels_data['grids'][$gi]);
        echo '<div ';
        foreach ($grid_attributes as $name => $value) {
            echo $name . '="' . esc_attr($value) . '" ';
        }
        echo '>';
        $style_attributes = array();
        if (!empty($panels_data['grids'][$gi]['style']['class'])) {
            $style_attributes['class'] = array('panel-row-style-' . $panels_data['grids'][$gi]['style']['class']);
        }
        // Themes can add their own attributes to the style wrapper
        $style_attributes = apply_filters('siteorigin_panels_row_style_attributes', $style_attributes, !empty($panels_data['grids'][$gi]['style']) ? $panels_data['grids'][$gi]['style'] : array());
        if (!empty($style_attributes)) {
            if (empty($style_attributes['class'])) {
                $style_attributes['class'] = array();
            }
            $style_attributes['class'][] = 'panel-row-style';
            $style_attributes['class'] = array_unique($style_attributes['class']);
            echo '<div ';
            foreach ($style_attributes as $name => $value) {
                if (is_array($value)) {
                    echo $name . '="' . esc_attr(implode(" ", array_unique($value))) . '" ';
                } else {
                    echo $name . '="' . esc_attr($value) . '" ';
                }
            }
            echo '>';
        }
        foreach ($cells as $ci => $widgets) {
            // Themes can add their own styles to cells
            $cell_classes = apply_filters('siteorigin_panels_row_cell_classes', array('panel-grid-cell'), $panels_data);
            $cell_attributes = apply_filters('siteorigin_panels_row_cell_attributes', array('class' => implode(' ', $cell_classes), 'id' => 'pgc-' . $post_id . '-' . $gi . '-' . $ci), $panels_data);
            echo '<div ';
            foreach ($cell_attributes as $name => $value) {
                echo $name . '="' . esc_attr($value) . '" ';
            }
            echo '>';
            foreach ($widgets as $pi => $widget_info) {
                $data = $widget_info;
                unset($data['info']);
                siteorigin_panels_the_widget($widget_info['info']['class'], $data, $gi, $ci, $pi, $pi == 0, $pi == count($widgets) - 1, $post_id);
            }
            if (empty($widgets)) {
                echo '&nbsp;';
            }
            echo '</div>';
        }
        echo '</div>';
        if (!empty($style_attributes)) {
            echo '</div>';
        }
        // This allows other themes and plugins to add html after the row
        echo apply_filters('siteorigin_panels_after_row', '', $panels_data['grids'][$gi]);
    }
    $html = ob_get_clean();
    // Reset the current post
    $siteorigin_panels_current_post = $old_current_post;
    return apply_filters('siteorigin_panels_render', $html, $post_id, !empty($post) ? $post : null);
}
/**
 * Render the panels
 *
 * @param int|string|bool $post_id The Post ID or 'home'.
 * @param bool $enqueue_css Should we also enqueue the layout CSS.
 * @param array|bool $panels_data Existing panels data. By default load from settings or post meta.
 * @return string
 */
function siteorigin_panels_render($post_id = false, $enqueue_css = true, $panels_data = false)
{
    if (empty($post_id)) {
        $post_id = get_the_ID();
    }
    global $siteorigin_panels_current_post;
    $old_current_post = $siteorigin_panels_current_post;
    $siteorigin_panels_current_post = $post_id;
    // Try get the cached panel from in memory cache.
    //global $siteorigin_panels_cache;
    //if ( !empty( $siteorigin_panels_cache ) && !empty( $siteorigin_panels_cache[$post_id] ) )
    //	return $siteorigin_panels_cache[$post_id];
    if (empty($panels_data)) {
        if ($post_id == 'home') {
            $panels_data = get_option('siteorigin_panels_home_page', get_theme_mod('panels_home_page', null));
            if (is_null($panels_data)) {
                // Load the default layout
                $layouts = apply_filters('siteorigin_panels_prebuilt_layouts', array());
                $panels_data = !empty($layouts['home']) ? $layouts['home'] : current($layouts);
            }
        } else {
            //Allowing rendering for password protected Tab( wc_product_tab ) post types
            if (post_password_required($post_id) && get_post_type($post_id) != 'wc_product_tab') {
                return false;
            }
            $panels_data = get_post_meta($post_id, 'panels_data', true);
        }
    }
    $panels_data = apply_filters('siteorigin_panels_data', $panels_data, $post_id);
    if (empty($panels_data) || empty($panels_data['grids'])) {
        return '';
    }
    //Removing filters for proper functionality
    remove_filter('the_content', 'wptexturize');
    //wptexturize : Replaces each & with &#038; unless it already looks like an entity
    remove_filter('the_content', 'convert_chars');
    //convert_chars : Converts lone & characters into &#38; ( a.k.a. &amp; )
    remove_filter('the_content', 'wpautop');
    //wpautop : Adds the Stupid Paragraphs for two line breaks
    // Create the skeleton of the grids
    $grids = array();
    if (!empty($panels_data['grids']) && !empty($panels_data['grids'])) {
        foreach ($panels_data['grids'] as $gi => $grid) {
            $gi = intval($gi);
            $grids[$gi] = array();
            for ($i = 0; $i < $grid['cells']; $i++) {
                $grids[$gi][$i] = array();
            }
        }
    }
    if (!empty($panels_data['widgets']) && is_array($panels_data['widgets'])) {
        foreach ($panels_data['widgets'] as $widget) {
            $grids[intval($widget['info']['grid'])][intval($widget['info']['cell'])][] = $widget;
        }
    }
    ob_start();
    global $siteorigin_panels_inline_css;
    if (empty($siteorigin_panels_inline_css)) {
        $siteorigin_panels_inline_css = '';
    }
    if ($enqueue_css) {
        if (siteorigin_panels_setting('inline-css')) {
            wp_enqueue_style('siteorigin-panels-front');
            $siteorigin_panels_inline_css .= siteorigin_panels_generate_css($post_id, $panels_data);
        } else {
            // This is the CSS for the page layout.
            wp_enqueue_style('siteorigin-panels-post-css-' . $post_id, add_query_arg(array('action' => 'siteorigin_panels_post_css', 'post' => $post_id, 'layout' => substr(md5(serialize($panels_data)), 0, 8)), admin_url('admin-ajax.php')), array('siteorigin-panels-front'), POOTLEPAGE_VERSION);
        }
    }
    foreach ($grids as $gi => $cells) {
        // This allows other themes and plugins to add html before the row
        echo apply_filters('siteorigin_panels_before_row', '', $panels_data['grids'][$gi]);
        $grid_classes = apply_filters('siteorigin_panels_row_classes', array('panel-grid'), $panels_data['grids'][$gi]);
        $grid_attributes = apply_filters('siteorigin_panels_row_attributes', array('class' => implode(' ', $grid_classes), 'id' => 'pg-' . $post_id . '-' . $gi), $panels_data['grids'][$gi]);
        echo '<div ';
        foreach ($grid_attributes as $name => $value) {
            echo $name . '="' . esc_attr($value) . '" ';
        }
        echo '>';
        $style_attributes = array();
        if (!empty($panels_data['grids'][$gi]['style']['class'])) {
            $style_attributes['class'] = array('panel-row-style-' . $panels_data['grids'][$gi]['style']['class']);
        }
        // Themes can add their own attributes to the style wrapper
        $styleArray = !empty($panels_data['grids'][$gi]['style']) ? $panels_data['grids'][$gi]['style'] : array();
        $style_attributes = apply_filters('siteorigin_panels_row_style_attributes', $style_attributes, $styleArray);
        if (!empty($style_attributes)) {
            if (empty($style_attributes['class'])) {
                $style_attributes['class'] = array();
            }
            $style_attributes['class'][] = 'panel-row-style';
            $style_attributes['class'] = array_unique($style_attributes['class']);
            echo '<div ';
            foreach ($style_attributes as $name => $value) {
                if (is_array($value)) {
                    echo $name . '="' . esc_attr(implode(" ", array_unique($value))) . '" ';
                } else {
                    echo $name . '="' . esc_attr($value) . '" ';
                }
            }
            echo '>';
        }
        if (isset($styleArray['background']) && isset($styleArray['background_color_over_image']) && $styleArray['background_color_over_image'] == true) {
            $rowID = '#pg-' . $post_id . '-' . $gi;
            ?>

			<style>
				/* make this sit under .panel-row-style:before, so background color will be on top on background image */
				<?php 
            echo esc_attr($rowID);
            ?>
 > .panel-row-style:before {
					background-color: <?php 
            echo $styleArray['background'];
            ?>
;
				}
				<?php 
            echo esc_attr($rowID);
            ?>
 > .panel-row-style {
					position: relative;
					z-index: 10;
				}
				<?php 
            echo esc_attr($rowID);
            ?>
 > .panel-row-style:before {
					position: absolute;
					width: 100%;
					height: 100%;
					content: "";
					top: 0;
					left: 0;
					z-index: 20;
				}
				.panel-grid-cell-container {
					position: relative;
					z-index: 30; /* row content needs to be on top of row background color */
				}
				</style>
				<?php 
        }
        echo "<div class='panel-grid-cell-container'>";
        foreach ($cells as $ci => $widgets) {
            // Themes can add their own styles to cells
            $cellId = 'pgc-' . $post_id . '-' . $gi . '-' . $ci;
            $cell_classes = apply_filters('siteorigin_panels_row_cell_classes', array('panel-grid-cell'), $panels_data);
            $cell_attributes = apply_filters('siteorigin_panels_row_cell_attributes', array('class' => implode(' ', $cell_classes), 'id' => $cellId), $panels_data);
            echo '<div ';
            foreach ($cell_attributes as $name => $value) {
                echo $name . '="' . esc_attr($value) . '" ';
            }
            echo '>';
            foreach ($widgets as $pi => $widget_info) {
                $data = $widget_info;
                $widgetStyle = isset($data['info']['style']) ? json_decode($data['info']['style'], true) : pp_get_default_widget_style();
                unset($data['info']);
                // don't do shortcode or it will mess up shortcodes when WP do shortcode at the end
                if ($widget_info['info']['class'] == 'Pootle_Text_Widget') {
                    remove_filter('widget_text', 'do_shortcode');
                    if (isset($widget_info['hide-title']) && $widget_info['hide-title'] == '1') {
                        $widgetStyle['hide-title'] = 'none';
                    }
                }
                siteorigin_panels_the_widget($widget_info['info']['class'], $data, $widgetStyle, $gi, $ci, $pi, $pi == 0, $pi == count($widgets) - 1, $post_id);
                if ($widget_info['info']['class'] == 'Pootle_Text_Widget') {
                    add_filter('widget_text', 'do_shortcode');
                }
                // post loop css for multiple columns
                if ($widget_info['info']['class'] == "SiteOrigin_Panels_Widgets_PostLoop") {
                    $css = '';
                    if (isset($widget_info['column_count'])) {
                        $count = (int) $widget_info['column_count'];
                        // fix division by zero
                        if ($count < 1) {
                            $count = 1;
                        }
                        $width = 100 / $count . "%";
                        $cssId = 'panel-' . $post_id . '-' . $gi . '-' . $ci . '-' . $pi;
                        $css .= "#{$cssId} {\n";
                        $css .= "\t" . "font-size: 0; \n";
                        $css .= "}\n";
                        $css .= "#{$cssId} > article {\n";
                        $css .= "\t" . "width: " . $width . ";\n";
                        $css .= "\t" . 'display: inline-block;' . "\n";
                        $css .= "\t" . 'box-sizing: border-box;' . "\n";
                        $css .= "\t" . 'padding-right: 10px;' . "\n";
                        $css .= "\t" . 'vertical-align: top;' . "\n";
                        $css .= "}\n";
                    }
                    if (isset($widget_info['post_meta_enable'])) {
                        if ($widget_info['post_meta_enable'] != '1') {
                            $cssId = 'panel-' . $post_id . '-' . $gi . '-' . $ci . '-' . $pi;
                            $css .= "#{$cssId} > article > .post-meta {\n";
                            $css .= "\t" . "display: none;\n";
                            $css .= "}\n";
                        }
                    }
                    echo "<style>\n" . $css . "</style>\n";
                }
                if ($widget_info['info']['class'] == "Woo_Widget_Component") {
                    wp_reset_query();
                }
            }
            if (empty($widgets)) {
                echo '&nbsp;';
            }
            echo '</div>';
        }
        echo "</div>";
        echo '</div>';
        if (!empty($style_attributes)) {
            echo '</div>';
        }
        // This allows other themes and plugins to add html after the row
        echo apply_filters('siteorigin_panels_after_row', '', $panels_data['grids'][$gi]);
    }
    $html = ob_get_clean();
    // Reset the current post
    $siteorigin_panels_current_post = $old_current_post;
    return apply_filters('siteorigin_panels_render', $html, $post_id, !empty($post) ? $post : null);
}
 /**
  * This is a rewrite of siteorigin_panels_render function in the SiteOrigin Page Builder plugin
  *
  * @return String - HTML of page builder field
  */
 function acf_siteorigin_panels_render($panel_id, $panels_data)
 {
     $GLOBALS['panel_id'] = $panel_id;
     if (is_string($panels_data)) {
         $panels_data = json_decode($panels_data, true);
     }
     if (empty($post_id)) {
         $post_id = get_the_ID();
     }
     $panels_data = apply_filters('siteorigin_panels_data', $panels_data, $post_id, $panel_id);
     if (empty($panels_data) || empty($panels_data['grids'])) {
         return '';
     }
     // Filter the widgets to add indexes
     if (!empty($panels_data['widgets'])) {
         $last_gi = 0;
         $last_ci = 0;
         $last_wi = 0;
         foreach ($panels_data['widgets'] as $wid => &$widget_info) {
             if ($widget_info['panels_info']['grid'] != $last_gi) {
                 $last_gi = $widget_info['panels_info']['grid'];
                 $last_ci = 0;
                 $last_wi = 0;
             } elseif ($widget_info['panels_info']['cell'] != $last_ci) {
                 $last_ci = $widget_info['panels_info']['cell'];
                 $last_wi = 0;
             }
             $widget_info['panels_info']['cell_index'] = $last_wi++;
         }
     }
     if (is_rtl()) {
         $panels_data = siteorigin_panels_make_rtl($panels_data);
     }
     // Create the skeleton of the grids
     $grids = array();
     if (!empty($panels_data['grids']) && !empty($panels_data['grids'])) {
         foreach ($panels_data['grids'] as $gi => $grid) {
             $gi = intval($gi);
             $grids[$gi] = array();
             for ($i = 0; $i < $grid['cells']; $i++) {
                 $grids[$gi][$i] = array();
             }
         }
     }
     // We need this to migrate from the old $panels_data that put widget meta into the "info" key instead of "panels_info"
     if (!empty($panels_data['widgets']) && is_array($panels_data['widgets'])) {
         foreach ($panels_data['widgets'] as $i => $widget) {
             if (empty($panels_data['widgets'][$i]['panels_info'])) {
                 $panels_data['widgets'][$i]['panels_info'] = $panels_data['widgets'][$i]['info'];
                 unset($panels_data['widgets'][$i]['info']);
             }
         }
     }
     if (!empty($panels_data['widgets']) && is_array($panels_data['widgets'])) {
         foreach ($panels_data['widgets'] as $widget) {
             // Put the widgets in the grids
             $grids[intval($widget['panels_info']['grid'])][intval($widget['panels_info']['cell'])][] = $widget;
         }
     }
     ob_start();
     // Add the panel layout wrapper
     $panel_layout_classes = apply_filters('siteorigin_panels_layout_classes', array(), $post_id, $panels_data, $panel_id);
     $panel_layout_attributes = apply_filters('siteorigin_panels_layout_attributes', array('class' => implode(' ', $panel_layout_classes), 'id' => 'pl-' . $post_id), $post_id, $panels_data);
     echo '<div';
     foreach ($panel_layout_attributes as $name => $value) {
         if ($value) {
             echo ' ' . $name . '="' . esc_attr($value) . '"';
         }
     }
     echo '>';
     global $acf_siteorigin_panels_inline_css;
     if (empty($acf_siteorigin_panels_inline_css)) {
         $acf_siteorigin_panels_inline_css = array();
     }
     if (!isset($acf_siteorigin_panels_inline_css[$post_id])) {
         wp_enqueue_style('siteorigin-panels-front');
         $acf_siteorigin_panels_inline_css[$panel_id] = siteorigin_panels_generate_css($post_id, $panels_data);
     }
     $this->page_styles = $acf_siteorigin_panels_inline_css;
     echo apply_filters('siteorigin_panels_before_content', '', $panels_data, $post_id);
     foreach ($grids as $gi => $cells) {
         $grid_classes = apply_filters('siteorigin_panels_row_classes', array('panel-grid'), $panels_data['grids'][$gi]);
         $grid_attributes = apply_filters('siteorigin_panels_row_attributes', array('class' => implode(' ', $grid_classes), 'id' => 'pg-' . $post_id . '-' . $gi), $panels_data['grids'][$gi]);
         // This allows other themes and plugins to add html before the row
         echo apply_filters('siteorigin_panels_before_row', '', $panels_data['grids'][$gi], $grid_attributes);
         echo '<div ';
         foreach ($grid_attributes as $name => $value) {
             echo $name . '="' . esc_attr($value) . '" ';
         }
         echo '>';
         $style_attributes = array();
         if (!empty($panels_data['grids'][$gi]['style']['class'])) {
             $style_attributes['class'] = array('panel-row-style-' . $panels_data['grids'][$gi]['style']['class']);
         }
         // Themes can add their own attributes to the style wrapper
         $row_style_wrapper = siteorigin_panels_start_style_wrapper('row', $style_attributes, !empty($panels_data['grids'][$gi]['style']) ? $panels_data['grids'][$gi]['style'] : array());
         if (!empty($row_style_wrapper)) {
             echo $row_style_wrapper;
         }
         foreach ($cells as $ci => $widgets) {
             // Themes can add their own styles to cells
             $cell_classes = apply_filters('siteorigin_panels_row_cell_classes', array('panel-grid-cell'), $panels_data);
             $cell_attributes = apply_filters('siteorigin_panels_row_cell_attributes', array('class' => implode(' ', $cell_classes), 'id' => 'pgc-' . $post_id . '-' . $gi . '-' . $ci), $panels_data);
             echo '<div ';
             foreach ($cell_attributes as $name => $value) {
                 echo $name . '="' . esc_attr($value) . '" ';
             }
             echo '>';
             $cell_style_wrapper = siteorigin_panels_start_style_wrapper('cell', array(), !empty($panels_data['grids'][$gi]['style']) ? $panels_data['grids'][$gi]['style'] : array());
             if (!empty($cell_style_wrapper)) {
                 echo $cell_style_wrapper;
             }
             $widget_index = 0;
             foreach ($widgets as $pi => $widget_info) {
                 $widget_info['panels_info']['widget_index'] = $widget_index;
                 $widget_index += 1;
                 // TODO this wrapper should go in the before/after widget arguments
                 $widget_style_wrapper = siteorigin_panels_start_style_wrapper('widget', array(), !empty($widget_info['panels_info']['style']) ? $widget_info['panels_info']['style'] : array());
                 siteorigin_panels_the_widget($widget_info['panels_info'], $widget_info, $gi, $ci, $pi, $pi == 0, $pi == count($widgets) - 1, $post_id, $widget_style_wrapper);
             }
             if (empty($widgets)) {
                 echo '&nbsp;';
             }
             if (!empty($cell_style_wrapper)) {
                 echo '</div>';
             }
             echo '</div>';
         }
         echo '</div>';
         // Close the
         if (!empty($row_style_wrapper)) {
             echo '</div>';
         }
         // This allows other themes and plugins to add html after the row
         echo apply_filters('siteorigin_panels_after_row', '', $panels_data['grids'][$gi], $grid_attributes);
     }
     echo apply_filters('siteorigin_panels_after_content', '', $panels_data, $post_id);
     echo '</div>';
     $html = ob_get_clean();
     return apply_filters('siteorigin_panels_render', $html, $post_id, !empty($post) ? $post : null);
 }
/**
 * Render the panels
 *
 * @param int|string|bool $post_id The Post ID or 'home'.
 * @param bool $enqueue_css Should we also enqueue the layout CSS.
 * @param array|bool $panels_data Existing panels data. By default load from settings or post meta.
 * @return string
 */
function siteorigin_panels_render($post_id = false, $enqueue_css = true, $panels_data = false)
{
    if (empty($post_id)) {
        $post_id = get_the_ID();
    }
    global $siteorigin_panels_current_post;
    $old_current_post = $siteorigin_panels_current_post;
    $siteorigin_panels_current_post = $post_id;
    // Try get the cached panel from in memory cache.
    global $siteorigin_panels_cache;
    if (!empty($siteorigin_panels_cache) && !empty($siteorigin_panels_cache[$post_id])) {
        return $siteorigin_panels_cache[$post_id];
    }
    if (empty($panels_data)) {
        if (strpos($post_id, 'prebuilt:') === 0) {
            list($null, $prebuilt_id) = explode(':', $post_id, 2);
            $layouts = apply_filters('siteorigin_panels_prebuilt_layouts', array());
            $panels_data = !empty($layouts[$prebuilt_id]) ? $layouts[$prebuilt_id] : array();
        } else {
            if ($post_id == 'home') {
                $panels_data = get_post_meta(get_option('siteorigin_panels_home_page_id'), 'panels_data', true);
                if (is_null($panels_data)) {
                    // Load the default layout
                    $layouts = apply_filters('siteorigin_panels_prebuilt_layouts', array());
                    $prebuilt_id = siteorigin_panels_setting('home-page-default') ? siteorigin_panels_setting('home-page-default') : 'home';
                    $panels_data = !empty($layouts[$prebuilt_id]) ? $layouts[$prebuilt_id] : current($layouts);
                }
            } else {
                if (post_password_required($post_id)) {
                    return false;
                }
                $panels_data = get_post_meta($post_id, 'panels_data', true);
            }
        }
    }
    $panels_data = apply_filters('siteorigin_panels_data', $panels_data, $post_id);
    if (empty($panels_data) || empty($panels_data['grids'])) {
        return '';
    }
    if (is_rtl()) {
        $panels_data = siteorigin_panels_make_rtl($panels_data);
    }
    // Create the skeleton of the grids
    $grids = array();
    if (!empty($panels_data['grids']) && !empty($panels_data['grids'])) {
        foreach ($panels_data['grids'] as $gi => $grid) {
            $gi = intval($gi);
            $grids[$gi] = array();
            for ($i = 0; $i < $grid['cells']; $i++) {
                $grids[$gi][$i] = array();
            }
        }
    }
    // We need this to migrate from the old $panels_data that put widget meta into the "info" key instead of "panels_info"
    if (!empty($panels_data['widgets']) && is_array($panels_data['widgets'])) {
        foreach ($panels_data['widgets'] as $i => $widget) {
            if (empty($panels_data['widgets'][$i]['panels_info'])) {
                $panels_data['widgets'][$i]['panels_info'] = $panels_data['widgets'][$i]['info'];
                unset($panels_data['widgets'][$i]['info']);
            }
        }
    }
    if (!empty($panels_data['widgets']) && is_array($panels_data['widgets'])) {
        foreach ($panels_data['widgets'] as $widget) {
            // Put the widgets in the grids
            $grids[intval($widget['panels_info']['grid'])][intval($widget['panels_info']['cell'])][] = $widget;
        }
    }
    ob_start();
    // Add the panel layout wrapper
    echo '<div id="pl-' . $post_id . '">';
    global $siteorigin_panels_inline_css;
    if (empty($siteorigin_panels_inline_css)) {
        $siteorigin_panels_inline_css = '';
    }
    if ($enqueue_css) {
        wp_enqueue_style('siteorigin-panels-front');
        $siteorigin_panels_inline_css .= siteorigin_panels_generate_css($post_id, $panels_data);
    }
    echo apply_filters('siteorigin_panels_before_content', '', $panels_data, $post_id);
    foreach ($grids as $gi => $cells) {
        $grid_classes = apply_filters('siteorigin_panels_row_classes', array('panel-grid'), $panels_data['grids'][$gi]);
        $grid_attributes = apply_filters('siteorigin_panels_row_attributes', array('class' => implode(' ', $grid_classes), 'id' => 'pg-' . $post_id . '-' . $gi), $panels_data['grids'][$gi]);
        // This allows other themes and plugins to add html before the row
        echo apply_filters('siteorigin_panels_before_row', '', $panels_data['grids'][$gi], $grid_attributes);
        echo '<div ';
        foreach ($grid_attributes as $name => $value) {
            echo $name . '="' . esc_attr($value) . '" ';
        }
        echo '>';
        $style_attributes = array();
        if (!empty($panels_data['grids'][$gi]['style']['class'])) {
            $style_attributes['class'] = array('panel-row-style-' . $panels_data['grids'][$gi]['style']['class']);
        }
        // Themes can add their own attributes to the style wrapper
        $row_style_wrapper = siteorigin_panels_start_style_wrapper('row', $style_attributes, !empty($panels_data['grids'][$gi]['style']) ? $panels_data['grids'][$gi]['style'] : array());
        if (!empty($row_style_wrapper)) {
            echo $row_style_wrapper;
        }
        foreach ($cells as $ci => $widgets) {
            // Themes can add their own styles to cells
            $cell_classes = apply_filters('siteorigin_panels_row_cell_classes', array('panel-grid-cell'), $panels_data);
            $cell_attributes = apply_filters('siteorigin_panels_row_cell_attributes', array('class' => implode(' ', $cell_classes), 'id' => 'pgc-' . $post_id . '-' . $gi . '-' . $ci), $panels_data);
            echo '<div ';
            foreach ($cell_attributes as $name => $value) {
                echo $name . '="' . esc_attr($value) . '" ';
            }
            echo '>';
            $cell_style_wrapper = siteorigin_panels_start_style_wrapper('cell', array(), !empty($panels_data['grids'][$gi]['style']) ? $panels_data['grids'][$gi]['style'] : array());
            if (!empty($cell_style_wrapper)) {
                echo $cell_style_wrapper;
            }
            foreach ($widgets as $pi => $widget_info) {
                $instance = $widget_info;
                unset($instance['panels_info']);
                // TODO this wrapper should go in the before/after widget arguments
                $widget_style_wrapper = siteorigin_panels_start_style_wrapper('widget', array(), !empty($widget_info['panels_info']['style']) ? $widget_info['panels_info']['style'] : array());
                siteorigin_panels_the_widget($widget_info['panels_info']['class'], $instance, $gi, $ci, $pi, $pi == 0, $pi == count($widgets) - 1, $post_id, $widget_style_wrapper);
            }
            if (empty($widgets)) {
                echo '&nbsp;';
            }
            if (!empty($cell_style_wrapper)) {
                echo '</div>';
            }
            echo '</div>';
        }
        echo '</div>';
        // Close the
        if (!empty($row_style_wrapper)) {
            echo '</div>';
        }
        // This allows other themes and plugins to add html after the row
        echo apply_filters('siteorigin_panels_after_row', '', $panels_data['grids'][$gi], $grid_attributes);
    }
    echo apply_filters('siteorigin_panels_after_content', '', $panels_data, $post_id);
    echo '</div>';
    $html = ob_get_clean();
    // Reset the current post
    $siteorigin_panels_current_post = $old_current_post;
    return apply_filters('siteorigin_panels_render', $html, $post_id, !empty($post) ? $post : null);
}