Page Builder by SiteOrigin - Version 2.6.3

Version Description

  • 6 March 2018 =
  • Use delete_post_meta_by_key instead of direct DB query to clear old cache renders.
  • Removed special handling for retrieving data from TinyMCE editor fields. Just use the field value directly.
  • Show correct preview for current editor when another editor has created an autosave.
  • Use minified CSS files.
Download this release

Release Info

Developer gpriday
Plugin Icon 128x128 Page Builder by SiteOrigin
Version 2.6.3
Comparing to
See all releases

Code changes from version 2.6.2 to 2.6.3

css/admin.css CHANGED
@@ -1461,6 +1461,8 @@
1461
  padding: 6px;
1462
  }
1463
  .so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-directory-item-wrapper {
 
 
1464
  height: 100%;
1465
  box-sizing: border-box;
1466
  padding: 15px 10px;
@@ -1475,10 +1477,8 @@
1475
  margin: 0 0 13px 0;
1476
  }
1477
  .so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-screenshot {
1478
- height: calc(100% - 50px);
1479
- background: #ffffff;
1480
  margin-bottom: 10px;
1481
- border: 1px solid #d0d0d0;
1482
  cursor: pointer;
1483
  }
1484
  .so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-screenshot.so-loading {
@@ -1500,14 +1500,21 @@
1500
  .so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-screenshot .so-screenshot-wrapper {
1501
  display: block;
1502
  min-height: 40px;
 
 
1503
  }
1504
  .so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-description {
 
1505
  font-size: 0.9em;
1506
  color: #666;
1507
  margin-bottom: 10px;
 
 
1508
  }
1509
  .so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-bottom {
 
1510
  position: relative;
 
1511
  margin: 10px -10px -15px -10px;
1512
  background: #fcfcfc;
1513
  border-top: 1px solid #d0d0d0;
@@ -1516,6 +1523,8 @@
1516
  margin: 0;
1517
  padding: 16px 10px;
1518
  cursor: pointer;
 
 
1519
  }
1520
  .so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-bottom .so-buttons {
1521
  position: absolute;
1461
  padding: 6px;
1462
  }
1463
  .so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-directory-item-wrapper {
1464
+ display: flex;
1465
+ flex-flow: column nowrap;
1466
  height: 100%;
1467
  box-sizing: border-box;
1468
  padding: 15px 10px;
1477
  margin: 0 0 13px 0;
1478
  }
1479
  .so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-screenshot {
1480
+ flex: 3 auto;
 
1481
  margin-bottom: 10px;
 
1482
  cursor: pointer;
1483
  }
1484
  .so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-screenshot.so-loading {
1500
  .so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-screenshot .so-screenshot-wrapper {
1501
  display: block;
1502
  min-height: 40px;
1503
+ background: #808080;
1504
+ border: 1px solid #d0d0d0;
1505
  }
1506
  .so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-description {
1507
+ flex: 1 auto;
1508
  font-size: 0.9em;
1509
  color: #666;
1510
  margin-bottom: 10px;
1511
+ max-height: 60px;
1512
+ overflow: hidden;
1513
  }
1514
  .so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-bottom {
1515
+ flex: 1 auto;
1516
  position: relative;
1517
+ max-height: 50px;
1518
  margin: 10px -10px -15px -10px;
1519
  background: #fcfcfc;
1520
  border-top: 1px solid #d0d0d0;
1523
  margin: 0;
1524
  padding: 16px 10px;
1525
  cursor: pointer;
1526
+ overflow: hidden;
1527
+ white-space: nowrap;
1528
  }
1529
  .so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-bottom .so-buttons {
1530
  position: absolute;
css/admin.min.css ADDED
@@ -0,0 +1 @@
 
1
+ @font-face{font-family:siteorigin-panels-icons;src:url(icons/panels-icons.eot);src:url(icons/panels-icons.eot) format("embedded-opentype"),url(icons/panels-icons.woff) format("woff"),url(icons/panels-icons.ttf) format("truetype"),url(icons/panels-icons.svg) format("svg");font-weight:400;font-style:normal}#so-panels-panels.attached-to-editor{margin-top:20px}#so-panels-panels.attached-to-editor .handlediv,#so-panels-panels.attached-to-editor .hndle{display:none!important}#so-panels-panels.attached-to-editor .inside{margin:0!important;padding:0!important}#so-panels-panels.attached-to-editor .so-toolbar .so-switch-to-standard{display:block}.siteorigin-panels-builder{position:relative}.siteorigin-panels-builder .so-tool-button{padding:6px 7px;text-decoration:none;line-height:1em;float:left;margin-right:2px;display:block;visibility:visible;position:relative;cursor:pointer;border:1px solid #bebebe;background:#eee;background:-o-linear-gradient(#f9f9f9,#eee);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#f9f9f9",endColorstr="#eeeeee",GradientType=0);box-shadow:0 1px 1px rgba(0,0,0,.04),inset 0 1px 0 hsla(0,0%,100%,.5);outline:none;border-radius:2px}.siteorigin-panels-builder .so-tool-button .so-panels-icon{font-size:12px}.siteorigin-panels-builder .so-tool-button span{display:inline-block;color:#666;text-shadow:0 1px 0 #fff;min-width:10px;text-align:center}.siteorigin-panels-builder .so-tool-button:hover{background:#fff}.siteorigin-panels-builder .so-tool-button:hover span{color:#444}.siteorigin-panels-builder .so-builder-toolbar{-ms-box-sizing:border-box;box-sizing:border-box;border-bottom:1px solid #d0d0d0;background:#f5f5f5;line-height:1em;z-index:101;white-space:nowrap;overflow-x:hidden;position:relative;box-shadow:0 1px 1px rgba(0,0,0,.04);top:0;left:0;width:100%;padding:6px 9px;margin-top:0!important;zoom:1}.siteorigin-panels-builder .so-builder-toolbar:before{content:"";display:block}.siteorigin-panels-builder .so-builder-toolbar:after{content:"";display:table;clear:both}.siteorigin-panels-builder .so-builder-toolbar .so-tool-button{display:inline-block;color:#666;padding:2px 10px 2px 8px}.siteorigin-panels-builder .so-builder-toolbar .so-tool-button .so-button-text{margin:3px 0 2px;font-size:11px}.siteorigin-panels-builder .so-builder-toolbar .so-tool-button .so-panels-icon{float:left;margin:3px 7px 2px 0;font-size:14px;color:#747474}.siteorigin-panels-builder .so-builder-toolbar .so-tool-button:hover,.siteorigin-panels-builder .so-builder-toolbar .so-tool-button:hover .so-panels-icon{color:#444}.siteorigin-panels-builder .so-builder-toolbar .so-tool-button.so-learn{background:#e5e5e5;background:-o-linear-gradient(#f6f6f6,#e5e5e5);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#f6f6f6",endColorstr="#e5e5e5",GradientType=0)}.siteorigin-panels-builder .so-builder-toolbar .so-tool-button.so-learn:hover{background:#fff}.siteorigin-panels-builder .so-builder-toolbar .so-switch-to-standard{cursor:pointer;float:right;display:none;text-decoration:none;color:#666;padding:5px 6px;border-radius:2px;border:1px solid transparent;font-size:11px}.siteorigin-panels-builder .so-builder-toolbar .so-switch-to-standard:hover{background:#fafafa;border:1px solid #999;color:#444}.siteorigin-panels-builder .so-rows-container{padding:20px 15px 0}.siteorigin-panels-builder .so-rows-container .so-row-color-1.so-row-color{background-color:#cde2ec;border:1px solid #a4cadd}.siteorigin-panels-builder .so-rows-container .so-row-color-1.so-row-color.so-row-color-selected:before{background:#a8cdde}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-1 .so-cells .cell .cell-wrapper{background-color:#cde2ec}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-1 .so-cells .cell.cell-selected .cell-wrapper{background-color:#99c4d8}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-1 .so-cells .cell .resize-handle{background-color:#e7f1f6}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-1 .so-cells .cell .resize-handle:hover{background-color:#dcebf2}.siteorigin-panels-builder .so-rows-container .so-row-color-2.so-row-color{background-color:#f2c2be;border:1px solid #e9968f}.siteorigin-panels-builder .so-rows-container .so-row-color-2.so-row-color.so-row-color-selected:before{background:#ea9a93}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-2 .so-cells .cell .cell-wrapper{background-color:#f2c2be}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-2 .so-cells .cell.cell-selected .cell-wrapper{background-color:#e68a83}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-2 .so-cells .cell .resize-handle{background-color:#f8dedc}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-2 .so-cells .cell .resize-handle:hover{background-color:#f5d2cf}.siteorigin-panels-builder .so-rows-container .so-row-color-3.so-row-color{background-color:#d5ccdf;border:1px solid #b9aac9}.siteorigin-panels-builder .so-rows-container .so-row-color-3.so-row-color.so-row-color-selected:before{background:#bbadcb}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-3 .so-cells .cell .cell-wrapper{background-color:#d5ccdf}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-3 .so-cells .cell.cell-selected .cell-wrapper{background-color:#b1a0c3}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-3 .so-cells .cell .resize-handle{background-color:#e7e2ed}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-3 .so-cells .cell .resize-handle:hover{background-color:#dfd9e7}.siteorigin-panels-builder .so-rows-container .so-row-color-4.so-row-color{background-color:#cae7cd;border:1px solid #a3d6a9}.siteorigin-panels-builder .so-rows-container .so-row-color-4.so-row-color.so-row-color-selected:before{background:#a7d7ac}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-4 .so-cells .cell .cell-wrapper{background-color:#cae7cd}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-4 .so-cells .cell.cell-selected .cell-wrapper{background-color:#99d19f}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-4 .so-cells .cell .resize-handle{background-color:#e3f2e4}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-4 .so-cells .cell .resize-handle:hover{background-color:#d8edda}.siteorigin-panels-builder .so-rows-container .so-row-color-5.so-row-color{background-color:#e2dcb1;border:1px solid #d3ca88}.siteorigin-panels-builder .so-rows-container .so-row-color-5.so-row-color.so-row-color-selected:before{background:#d4cb8c}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-5 .so-cells .cell .cell-wrapper{background-color:#e2dcb1}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-5 .so-cells .cell.cell-selected .cell-wrapper{background-color:#cfc57d}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-5 .so-cells .cell .resize-handle{background-color:#ece8cb}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-5 .so-cells .cell .resize-handle:hover{background-color:#e8e3c0}.siteorigin-panels-builder .so-rows-container h3.so-row-label{display:inline-block;font-size:1em;font-weight:500;color:#474747;margin:0 0 0 4px;line-height:22px;float:left}.siteorigin-panels-builder .so-rows-container .so-row-toolbar{zoom:1;margin-bottom:4px}.siteorigin-panels-builder .so-rows-container .so-row-toolbar:before{content:"";display:block}.siteorigin-panels-builder .so-rows-container .so-row-toolbar:after{content:"";display:table;clear:both}.siteorigin-panels-builder .so-rows-container .so-row-toolbar .so-tool-button{-ms-box-sizing:border-box;box-sizing:border-box;padding:4px;float:right}.siteorigin-panels-builder .so-rows-container .so-row-toolbar .so-tool-button .so-panels-icon{color:#777;font-size:11px;width:11px;height:11px;display:block}.siteorigin-panels-builder .so-rows-container .so-row-toolbar .so-tool-button:hover .so-panels-icon{color:#555}.siteorigin-panels-builder .so-rows-container .so-row-toolbar .so-tool-button.so-row-move{cursor:move}.siteorigin-panels-builder .so-rows-container .so-row-toolbar .so-dropdown-wrapper .so-dropdown-links-wrapper{visibility:hidden;opacity:0;transition:visibility 0s linear 75ms,opacity 75ms linear;z-index:101;right:-10px;top:100%;width:125px}.siteorigin-panels-builder .so-rows-container .so-row-toolbar .so-dropdown-wrapper .so-dropdown-links-wrapper ul li a.so-row-delete{color:#a00}.siteorigin-panels-builder .so-rows-container .so-row-toolbar .so-dropdown-wrapper .so-dropdown-links-wrapper ul li a.so-row-delete:hover{color:#fff;background:#a00}.siteorigin-panels-builder .so-rows-container .so-row-toolbar .so-dropdown-wrapper .so-dropdown-links-wrapper ul li.so-row-colors-container{display:flex;justify-content:space-around;padding:5px}.siteorigin-panels-builder .so-rows-container .so-row-toolbar .so-dropdown-wrapper .so-dropdown-links-wrapper ul li.so-row-colors-container .so-row-color{display:inline-block;cursor:pointer;position:relative;text-align:center;width:14px;height:14px}.siteorigin-panels-builder .so-rows-container .so-row-toolbar .so-dropdown-wrapper .so-dropdown-links-wrapper ul li.so-row-colors-container .so-row-color.so-row-color-selected:before{content:"";display:block;position:absolute;top:2px;bottom:2px;left:2px;right:2px}.siteorigin-panels-builder .so-rows-container .so-row-toolbar .so-dropdown-wrapper:hover .so-dropdown-links-wrapper{visibility:visible;opacity:1;transition-delay:0s}.siteorigin-panels-builder .so-rows-container .ui-sortable-placeholder{visibility:visible!important;background:#f7f7f7;-ms-box-sizing:border-box;box-sizing:border-box}.siteorigin-panels-builder .so-rows-container .so-row-container{margin-bottom:15px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.siteorigin-panels-builder .so-rows-container .so-row-container.ui-sortable-helper{opacity:.9}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells{zoom:1;margin:0 -5px;position:relative}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells:before{content:"";display:block}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells:after{content:"";display:table;clear:both}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .ui-resizable-handle.ui-resizable-w{width:10px;left:-11px;cursor:col-resize;background:rgba(0,150,211,.25);transition:background .25s ease-in-out}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .ui-resizable-handle.ui-resizable-w:hover{background:rgba(0,150,211,.1)}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell{-ms-box-sizing:border-box;box-sizing:border-box;float:left;position:relative;padding:0 5px}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell.so-first{margin-left:0}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell.so-last{margin-right:0}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .cell-wrapper{background:#e4eff4;padding:7px 7px 0;height:100%;min-height:63px;transition:background .25s ease-in-out 0s}@media (-webkit-min-device-pixel-ratio:2),(min-resolution:192dpi){.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell.cell-selected .cell-wrapper{background-size:3px 3px}}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell,.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .cell-wrapper{-ms-box-sizing:border-box;box-sizing:border-box}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget{cursor:move;margin-bottom:7px;background:#f9f9fb;border:1px solid hsla(0,0%,100%,.75);max-height:49px;box-shadow:0 1px 1px rgba(0,0,0,.075);-ms-box-sizing:border-box;box-sizing:border-box}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget.so-widget-no-move{cursor:auto}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget:hover{border:1px solid hsla(0,0%,100%,.55);background:#fff;box-shadow:0 0 2px rgba(0,0,0,.1)}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget .so-widget-wrapper{padding:7px 8px;overflow:hidden;position:relative}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget h4{display:block;cursor:pointer;margin:0 15px 3px 0;font-weight:600;line-height:1.25em;color:#474747;text-shadow:0 1px 0 #fff;white-space:nowrap}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget h4 span{font-weight:400;display:inline-block;color:#999;text-shadow:0 1px 0 #fff;margin-left:12px;margin-right:5px;font-style:italic}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget.so-widget-no-edit h4{cursor:auto}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget .title .actions{font-size:12px;position:absolute;top:5px;right:7px;cursor:pointer;padding:2px 2px 2px 15px;z-index:10}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget .title .actions:hover{background:#feffff}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget .title .actions:hover a{opacity:1}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget .title .actions a{display:none;margin-right:3px;text-decoration:none}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget .title .actions a.widget-delete{color:red}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget .title .actions a.widget-delete:hover{color:#fff;background:red}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget:hover .title a{display:inline-block;opacity:.5}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget.panel-being-dragged .title .actions{display:none}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget small{display:block;height:16px;overflow:hidden;color:#777}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget .form{display:none}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget.so-widget-read-only,.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget.so-widget-read-only:hover{background:#f5f5f5;border:1px solid #a6bac1;box-shadow:none}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget.so-widget-read-only:hover h4,.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget.so-widget-read-only:hover small,.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget.so-widget-read-only h4,.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget.so-widget-read-only small{opacity:.5}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget.so-hovered{background:#3a7096;border:1px solid #39618c;box-shadow:0 2px 2px rgba(0,0,0,.1)}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget.so-hovered h4,.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget.so-hovered small,.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget.so-hovered span{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.85)}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget.so-hovered small{color:#eee}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget-sortable-highlight{border:1px solid rgba(0,0,0,.075);background:rgba(0,0,0,.025);-ms-box-sizing:border-box;box-sizing:border-box;height:49px;margin-bottom:7px;position:relative;box-shadow:inset 2px 2px 2px rgba(0,0,0,.01)}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .resize-handle{z-index:100;position:absolute;top:0;width:10px;left:-5px;cursor:col-resize;background:#f6fafb;height:100%;transition:background .25s ease-in-out 0s}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell:first-child .resize-handle{display:none}.siteorigin-panels-builder .so-panels-welcome-message{text-align:center;padding:0 15px 20px;color:#555;line-height:1.8em}.siteorigin-panels-builder .so-panels-welcome-message .so-message-wrapper{padding:15px 10px;background:#f8f8f8;border:1px solid #e0e0e0}.siteorigin-panels-builder .so-panels-welcome-message .so-tool-button{font-size:inherit;display:inline-block;float:none;color:#666;padding:5px 10px;margin:0 3px}.siteorigin-panels-builder .so-panels-welcome-message .so-tool-button .so-panels-icon{color:#777;font-size:.8em}.siteorigin-panels-builder .so-panels-welcome-message .so-tip-wrapper{margin-top:15px;font-size:.95em}.siteorigin-panels-builder.so-display-narrow .so-builder-toolbar{padding:10px}.siteorigin-panels-builder.so-display-narrow .so-builder-toolbar>.so-tool-button{padding-right:2px}.siteorigin-panels-builder.so-display-narrow .so-builder-toolbar>.so-tool-button .so-panels-icon{font-size:14px}.siteorigin-panels-builder.so-display-narrow .so-builder-toolbar>.so-tool-button.so-learn,.siteorigin-panels-builder.so-display-narrow .so-builder-toolbar>.so-tool-button span.so-button-text{display:none}.siteorigin-panels-builder.so-display-narrow .so-builder-toolbar .so-switch-to-standard,.siteorigin-panels-builder.so-display-narrow .widgets-container .so-widget .actions{display:none!important}.so-widget.ui-sortable-helper.widget-being-dragged{z-index:500002!important;opacity:.9;pointer-events:none;border:1px solid rgba(0,0,0,.35)!important;cursor:move;margin-bottom:7px;background:#f9f9fb;border:1px solid hsla(0,0%,100%,.75);max-height:49px;box-shadow:0 1px 1px rgba(0,0,0,.075);-ms-box-sizing:border-box;box-sizing:border-box}.so-widget.ui-sortable-helper.widget-being-dragged.so-widget-no-move{cursor:auto}.so-widget.ui-sortable-helper.widget-being-dragged:hover{border:1px solid hsla(0,0%,100%,.55);background:#fff;box-shadow:0 0 2px rgba(0,0,0,.1)}.so-widget.ui-sortable-helper.widget-being-dragged .so-widget-wrapper{padding:7px 8px;overflow:hidden;position:relative}.so-widget.ui-sortable-helper.widget-being-dragged h4{display:block;cursor:pointer;margin:0 15px 3px 0;font-weight:600;line-height:1.25em;color:#474747;text-shadow:0 1px 0 #fff;white-space:nowrap}.so-widget.ui-sortable-helper.widget-being-dragged h4 span{font-weight:400;display:inline-block;color:#999;text-shadow:0 1px 0 #fff;margin-left:12px;margin-right:5px;font-style:italic}.so-widget.ui-sortable-helper.widget-being-dragged.so-widget-no-edit h4{cursor:auto}.so-widget.ui-sortable-helper.widget-being-dragged .title .actions{font-size:12px;position:absolute;top:5px;right:7px;cursor:pointer;padding:2px 2px 2px 15px;z-index:10}.so-widget.ui-sortable-helper.widget-being-dragged .title .actions:hover{background:#feffff}.so-widget.ui-sortable-helper.widget-being-dragged .title .actions:hover a{opacity:1}.so-widget.ui-sortable-helper.widget-being-dragged .title .actions a{display:none;margin-right:3px;text-decoration:none}.so-widget.ui-sortable-helper.widget-being-dragged .title .actions a.widget-delete{color:red}.so-widget.ui-sortable-helper.widget-being-dragged .title .actions a.widget-delete:hover{color:#fff;background:red}.so-widget.ui-sortable-helper.widget-being-dragged:hover .title a{display:inline-block;opacity:.5}.so-widget.ui-sortable-helper.widget-being-dragged.panel-being-dragged .title .actions{display:none}.so-widget.ui-sortable-helper.widget-being-dragged small{display:block;height:16px;overflow:hidden;color:#777}.so-widget.ui-sortable-helper.widget-being-dragged .form{display:none}.so-widget.ui-sortable-helper.widget-being-dragged.so-widget-read-only,.so-widget.ui-sortable-helper.widget-being-dragged.so-widget-read-only:hover{background:#f5f5f5;border:1px solid #a6bac1;box-shadow:none}.so-widget.ui-sortable-helper.widget-being-dragged.so-widget-read-only:hover h4,.so-widget.ui-sortable-helper.widget-being-dragged.so-widget-read-only:hover small,.so-widget.ui-sortable-helper.widget-being-dragged.so-widget-read-only h4,.so-widget.ui-sortable-helper.widget-being-dragged.so-widget-read-only small{opacity:.5}.so-widget.ui-sortable-helper.widget-being-dragged.so-hovered{background:#3a7096;border:1px solid #39618c;box-shadow:0 2px 2px rgba(0,0,0,.1)}.so-widget.ui-sortable-helper.widget-being-dragged.so-hovered h4,.so-widget.ui-sortable-helper.widget-being-dragged.so-hovered small,.so-widget.ui-sortable-helper.widget-being-dragged.so-hovered span{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.85)}.so-widget.ui-sortable-helper.widget-being-dragged.so-hovered small{color:#eee}.widgets-holder-wrap .widget-inside .siteorigin-panels-builder .so-builder-container{padding-top:0}.widgets-holder-wrap .widget-inside .siteorigin-panels-builder .so-rows-container{padding:10px 0 0}.widgets-holder-wrap .widget-inside .siteorigin-panels-builder .so-builder-toolbar{padding-left:15px;padding-right:15px;margin:0 -15px}.so-panels-dialog .so-content,.so-panels-dialog .so-left-sidebar,.so-panels-dialog .so-overlay,.so-panels-dialog .so-right-sidebar,.so-panels-dialog .so-title-bar,.so-panels-dialog .so-toolbar{z-index:100001;position:fixed;-ms-box-sizing:border-box;box-sizing:border-box;padding:15px}.so-panels-dialog .so-content,.so-panels-dialog .so-left-sidebar,.so-panels-dialog .so-right-sidebar{overflow-y:auto}.so-panels-dialog .so-overlay{top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.5)}.so-panels-dialog .so-content{top:80px;left:30px;right:30px;bottom:88px;background-color:#fdfdfd;overflow-x:hidden;box-shadow:inset 0 2px 2px rgba(0,0,0,.03)}.so-panels-dialog .so-content>:first-child{margin-top:0}.so-panels-dialog .so-content>:last-child{margin-bottom:0}.so-panels-dialog .so-content .so-content-tabs>*{display:none}.so-panels-dialog .so-title-bar{left:30px;right:30px;top:30px;height:50px;background-color:#fafafa;border-bottom:1px solid #d8d8d8}.so-panels-dialog .so-title-bar h3.so-title{-ms-box-sizing:border-box;box-sizing:border-box;margin:-3px 150px 0 -3px;padding:5px 6px;display:block}.so-panels-dialog .so-title-bar h3.so-title.so-title-editable:focus,.so-panels-dialog .so-title-bar h3.so-title.so-title-editable:hover{outline:none;background-color:#f0f0f0}.so-panels-dialog .so-title-bar h3.so-title.so-title-editable:focus{margin-top:-4px;margin-left:-4px;border:1px solid #e4e4e4}.so-panels-dialog .so-title-bar input[type=text].so-edit-title{margin-top:-3px;margin-left:-3px;display:none;color:#23282d;font-size:1.3em;font-weight:600;border:none;box-shadow:none;background-color:#f0f0f0;padding:4px 5px}.so-panels-dialog .so-title-bar h3.so-parent-link{cursor:pointer;position:relative;float:left;margin:0 15px 0 0!important;padding:0 27px 0 0!important}.so-panels-dialog .so-title-bar h3.so-parent-link .so-separator{position:absolute;top:-15px;right:0;width:12px;height:50px;display:block;background:url(images/dialog-separator.png) no-repeat}@media (-webkit-min-device-pixel-ratio:2),(min-resolution:192dpi){.so-panels-dialog .so-title-bar h3.so-parent-link .so-separator{background:url(images/dialog-separator@2x.png) no-repeat;background-size:cover}}.so-panels-dialog .so-title-bar a{cursor:pointer;position:absolute;box-sizing:border-box;width:50px;height:50px;display:block;top:0;right:0;transition:all .2s ease 0s;background:#fafafa;border-left:1px solid #d8d8d8;border-bottom:1px solid #d8d8d8}.so-panels-dialog .so-title-bar a:hover{background:#e9e9e9}.so-panels-dialog .so-title-bar a:hover .so-dialog-icon{color:#333}.so-panels-dialog .so-title-bar a .so-dialog-icon{position:absolute;top:50%;left:50%;text-decoration:none;width:20px;height:20px;margin-left:-10px;margin-top:-10px;color:#666;text-align:center}.so-panels-dialog .so-title-bar a .so-dialog-icon:before{font:400 20px/1em dashicons;top:7px;left:13px}.so-panels-dialog .so-title-bar a.so-close{right:0}.so-panels-dialog .so-title-bar a.so-close .so-dialog-icon:before{content:"\f335"}.so-panels-dialog .so-title-bar a.so-next{right:50px}.so-panels-dialog .so-title-bar a.so-next .so-dialog-icon:before{content:"\f345"}.so-panels-dialog .so-title-bar a.so-previous{right:100px}.so-panels-dialog .so-title-bar a.so-previous .so-dialog-icon:before{content:"\f341"}.so-panels-dialog .so-title-bar a.so-nav.so-disabled{cursor:default;pointer-events:none}.so-panels-dialog .so-title-bar a.so-nav.so-disabled .so-dialog-icon{color:#ddd}.so-panels-dialog .so-title-bar.so-has-icon{padding-left:45px}.so-panels-dialog .so-title-bar.so-has-icon .so-panels-icon{position:absolute;top:14.5px;left:14px;font-size:22px;line-height:22px;display:block;width:22px;height:22px;text-align:center;color:#666}.so-panels-dialog .so-toolbar{left:30px;right:30px;bottom:30px;height:58px;background-color:#fafafa;border-top:1px solid #d8d8d8;z-index:100002}.so-panels-dialog .so-toolbar .so-status{float:left;padding-top:6px;padding-bottom:6px;font-style:italic;color:#999;line-height:1em}.so-panels-dialog .so-toolbar .so-status.so-panels-loading{padding-left:26px;background-position:0}.so-panels-dialog .so-toolbar .so-status .dashicons-warning{color:#a00;vertical-align:middle;margin-right:7px;margin-top:-1px}.so-panels-dialog .so-toolbar .so-buttons{float:right}.so-panels-dialog .so-toolbar .so-buttons .action-buttons{position:absolute;left:15px;top:50%;margin-top:-.65em}.so-panels-dialog .so-toolbar .so-buttons .action-buttons a{cursor:pointer;display:inline;padding:.2em .5em;line-height:1em;margin-right:.5em;text-decoration:none}.so-panels-dialog .so-toolbar .so-buttons .action-buttons .so-delete{color:#a00}.so-panels-dialog .so-toolbar .so-buttons .action-buttons .so-delete:hover{background:#a00;color:#fff}.so-panels-dialog .so-toolbar .so-buttons .action-buttons .so-duplicate:hover{text-decoration:underline}.so-panels-dialog .so-left-sidebar,.so-panels-dialog .so-right-sidebar{background-color:#f3f3f3}.so-panels-dialog .so-left-sidebar{display:none;top:30px;left:30px;bottom:30px;width:290px;border-right:1px solid #d8d8d8}.so-panels-dialog .so-left-sidebar h4{margin:0 0 20px;font-size:18px}.so-panels-dialog .so-left-sidebar .so-sidebar-search{width:100%;padding:6px;margin-bottom:20px}.so-panels-dialog .so-left-sidebar .so-sidebar-tabs{list-style:none;margin:0 -15px}.so-panels-dialog .so-left-sidebar .so-sidebar-tabs li{margin-bottom:0}.so-panels-dialog .so-left-sidebar .so-sidebar-tabs li a{padding:7px 16px;display:block;font-size:14px;text-decoration:none;box-shadow:none!important}.so-panels-dialog .so-left-sidebar .so-sidebar-tabs li a:hover{background:#fff}.so-panels-dialog .so-left-sidebar .so-sidebar-tabs li.tab-active a{color:#555;font-weight:700;background:#fff}.so-panels-dialog .so-left-sidebar .so-sidebar-tabs li.tab-active a:hover{background:#fff}.so-panels-dialog .so-right-sidebar{display:none;top:80px;right:30px;bottom:88px;width:290px;border-left:1px solid #d8d8d8}.so-panels-dialog .so-right-sidebar h3{color:#333}.so-panels-dialog .so-right-sidebar h3:first-child{margin-top:0}.so-panels-dialog .so-sidebar .form-field{margin-bottom:20px}.so-panels-dialog .so-sidebar .form-field label{font-weight:500;font-size:15px;display:block;margin-bottom:10px}.so-panels-dialog.so-panels-dialog-has-left-sidebar .so-content,.so-panels-dialog.so-panels-dialog-has-left-sidebar .so-title-bar,.so-panels-dialog.so-panels-dialog-has-left-sidebar .so-toolbar{left:320px}.so-panels-dialog.so-panels-dialog-has-left-sidebar .so-content{box-shadow:inset 2px 2px 2px rgba(0,0,0,.03)}.so-panels-dialog.so-panels-dialog-has-left-sidebar .so-left-sidebar{display:block}.so-panels-dialog.so-panels-dialog-has-right-sidebar .so-content{right:320px}.so-panels-dialog.so-panels-dialog-has-right-sidebar .so-right-sidebar{display:block}.so-panels-dialog.so-panels-dialog-edit-widget .so-left-sidebar .so-widgets .so-widget{border-radius:2px;border:1px solid #ccc;cursor:pointer;padding:10px;background:#f9f9f9;box-shadow:0 1px 2px rgba(0,0,0,.075),inset 0 1px 0 #fff;margin-bottom:15px}.so-panels-dialog.so-panels-dialog-edit-widget .so-left-sidebar .so-widgets .so-widget:hover{border:1px solid #bbb;background:#fff}.so-panels-dialog.so-panels-dialog-edit-widget .so-left-sidebar .so-widgets .so-widget.so-current{border-color:#0074a2;background:#2ea2cc;cursor:auto;box-shadow:0 1px 2px rgba(0,0,0,.15),inset 0 1px 0 hsla(0,0%,100%,.2)}.so-panels-dialog.so-panels-dialog-edit-widget .so-left-sidebar .so-widgets .so-widget.so-current h3{color:#fff}.so-panels-dialog.so-panels-dialog-edit-widget .so-left-sidebar .so-widgets .so-widget.so-current small{color:#eee}.so-panels-dialog.so-panels-dialog-edit-widget .so-left-sidebar .so-widgets .so-widget.so-current:hover{border-color:#0074a2;background:#2ea2cc}.so-panels-dialog.so-panels-dialog-edit-widget .so-left-sidebar .so-widgets .so-widget:last-child{margin-bottom:0}.so-panels-dialog.so-panels-dialog-edit-widget .so-left-sidebar .so-widgets .so-widget h3{margin:0 0 7px;padding:0;height:1.2em;color:#222;font-size:14px}.so-panels-dialog.so-panels-dialog-edit-widget .so-left-sidebar .so-widgets .so-widget small{font-size:11px;line-height:1.25em;display:block;overflow:hidden;color:#888}.so-panels-dialog.so-panels-dialog-add-widget .widget-type-list{zoom:1;margin:0 -5px -10px;min-height:10px}.so-panels-dialog.so-panels-dialog-add-widget .widget-type-list:before{content:"";display:block}.so-panels-dialog.so-panels-dialog-add-widget .widget-type-list:after{content:"";display:table;clear:both}.so-panels-dialog.so-panels-dialog-add-widget .widget-type-list .widget-type{-ms-user-select:none;-moz-user-select:-moz-none;-webkit-user-select:none;user-select:none;-ms-box-sizing:border-box;box-sizing:border-box;width:25%;padding:0 5px;margin-bottom:10px;float:left}@media (max-width:1280px){.so-panels-dialog.so-panels-dialog-add-widget .widget-type-list .widget-type{width:33.333%}}@media (max-width:960px){.so-panels-dialog.so-panels-dialog-add-widget .widget-type-list .widget-type{width:50%}}.so-panels-dialog.so-panels-dialog-add-widget .widget-type-list .widget-type h3{margin:0 0 7px;padding:0;color:#222;font-size:14px}.so-panels-dialog.so-panels-dialog-add-widget .widget-type-list .widget-type small{font-size:11px;min-height:2.5em;line-height:1.25em;display:block;overflow:hidden;color:#888}.so-panels-dialog.so-panels-dialog-add-widget .widget-type-list .widget-type .widget-icon{font-size:20px;width:20px;height:20px;color:#666;float:left;margin:-1px .5em 0 0}.so-panels-dialog.so-panels-dialog-add-widget .widget-type-list .widget-type-wrapper{border:1px solid #ccc;cursor:pointer;padding:10px;background:#f8f8f8;box-shadow:0 1px 2px rgba(0,0,0,.075)}.so-panels-dialog.so-panels-dialog-add-widget .widget-type-list .widget-type-wrapper:hover{border:1px solid #bbb;background:#fff;box-shadow:0 2px 2px rgba(0,0,0,.075)}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-set-form{zoom:1;padding:8px;border:1px solid #ccc;margin-bottom:20px;background:#f3f3f3}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-set-form:before{content:"";display:block}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-set-form:after{content:"";display:table;clear:both}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-set-form button,.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-set-form input,.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-set-form select,.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-set-form span,.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-set-form strong{display:inline;margin:1px 5px;outline:none;box-shadow:none}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-set-form button{margin-top:2px}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-set-form label{display:inline}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview{margin:0 -6px;height:360px;position:relative;white-space:nowrap}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell,.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell-in,.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell-weight{-ms-box-sizing:border-box;box-sizing:border-box}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell{display:inline-block;position:relative;padding:0 6px;cursor:pointer}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell .preview-cell-in{border:1px solid #bcccd2;min-height:360px;background:#e4eff4;position:relative}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell .preview-cell-in.cell-selected{background:#cae7f4 url(images/cell-selected.png) repeat;border-color:#9abcc7;box-shadow:0 0 5px rgba(0,0,0,.2)}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell .preview-cell-in .preview-cell-weight,.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell .preview-cell-in .preview-cell-weight-input{position:absolute;font-size:17px;font-weight:700;top:50%;left:50%;width:80px;text-align:center;color:#5e6d72;margin:-.95em 0 0 -40px;padding:10px 0;border:1px solid transparent;line-height:1.4em!important;overflow:hidden;cursor:pointer}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell .preview-cell-in .preview-cell-weight-input:after,.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell .preview-cell-in .preview-cell-weight:after{content:"%"}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell .preview-cell-in .preview-cell-weight-input:hover,.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell .preview-cell-in .preview-cell-weight:hover{background:#f6f6f6;border:1px solid #d0d0d0}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell .preview-cell-in .preview-cell-weight-input{background:#f6f6f6;border:1px solid #d0d0d0;box-shadow:none}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell .resize-handle{z-index:100;position:absolute;top:0;width:12px;left:-6px;cursor:col-resize;background:#e5f4fb;height:360px;transition:background .15s ease-in-out 0s}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell .resize-handle.ui-draggable-dragging,.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell .resize-handle:hover{background:#b7e0f1}.so-panels-dialog.so-panels-dialog-history .so-left-sidebar{padding:0}.so-panels-dialog.so-panels-dialog-history .history-entries .history-entry{padding:10px;background:#f8f8f8;cursor:pointer;border-bottom:1px solid #ccc}.so-panels-dialog.so-panels-dialog-history .history-entries .history-entry h3{margin:0 0 .6em;font-size:12px;font-weight:700;color:#444;line-height:1em}.so-panels-dialog.so-panels-dialog-history .history-entries .history-entry .timesince{color:#999;font-size:11px;line-height:1em}.so-panels-dialog.so-panels-dialog-history .history-entries .history-entry:hover{background:#f0f0f0}.so-panels-dialog.so-panels-dialog-history .history-entries .history-entry.so-selected{background:#eee}.so-panels-dialog.so-panels-dialog-history .history-entries .history-entry .count{color:#999}.so-panels-dialog.so-panels-dialog-history .so-content{padding:0;overflow-y:hidden}.so-panels-dialog.so-panels-dialog-history .so-content form.history-form{display:none}.so-panels-dialog.so-panels-dialog-history .so-content iframe.siteorigin-panels-history-iframe{width:100%;height:100%}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content{padding-left:10px;padding-right:10px}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-error-message{font-size:14px;border:1px solid #ccc;background:#f8f8f8;padding:15px 20px}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .export-file-ui{padding:5px 15px;text-align:right}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .import-upload-ui{padding:15px}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .import-upload-ui .drag-drop-message{display:none}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .import-upload-ui.has-drag-drop .drag-drop-message{display:block}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .import-upload-ui p.drag-drop-message{font-size:1em;margin-bottom:0}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .import-upload-ui .drag-upload-area{display:block;-ms-box-sizing:border-box;box-sizing:border-box;padding:50px 30px;border:4px dashed #e0e0e0;text-align:center;transition:all .25s ease 0s}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .import-upload-ui .drag-upload-area.file-dragover{background-color:#f2f9fc;border-color:#0074a2}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .import-upload-ui .progress-bar{display:none;padding:2px;border:2px solid #2181b1;border-radius:2px;margin-top:20px}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .import-upload-ui .progress-bar .progress-percent{height:14px;background-color:#358ebe;border-radius:1px}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .import-upload-ui .file-browse-button{padding:12px 30px;height:auto}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-browse{background:#f3f3f3;border-bottom:1px solid #d0d0d0;margin:-15px -10px 15px;padding:15px;font-weight:700}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items-wrapper{display:flex;flex-flow:row wrap}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-no-results{margin:20px 0;padding:0 5px}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item{-ms-box-sizing:border-box;box-sizing:border-box;padding:6px}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-directory-item-wrapper{display:flex;flex-flow:column nowrap;height:100%;box-sizing:border-box;padding:15px 10px;background:#f7f7f7;border:1px solid #d0d0d0;box-shadow:0 1px 1px rgba(0,0,0,.1)}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-title{font-size:15px;margin:0 0 13px}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-screenshot{flex:3 auto;margin-bottom:10px;cursor:pointer}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-screenshot.so-loading{background-image:url(images/wpspin_light.gif);background-position:50%;background-repeat:no-repeat}@media (-webkit-min-device-pixel-ratio:2),(min-resolution:192dpi){.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-screenshot.so-loading{background-image:url(images/wpspin_light-2x.gif);background-size:16px 16px}}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-screenshot img{display:block;width:100%;height:auto}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-screenshot .so-screenshot-wrapper{display:block;min-height:40px;background:gray;border:1px solid #d0d0d0}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-description{flex:1 auto;font-size:.9em;color:#666;margin-bottom:10px;max-height:60px;overflow:hidden}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-bottom{flex:1 auto;position:relative;max-height:50px;margin:10px -10px -15px;background:#fcfcfc;border-top:1px solid #d0d0d0}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-bottom .so-title{margin:0;padding:16px 10px;cursor:pointer;overflow:hidden;white-space:nowrap}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-bottom .so-buttons{position:absolute;z-index:2;top:0;bottom:0;right:0;height:100%;visibility:hidden;-ms-box-sizing:border-box;box-sizing:border-box;padding:11px 10px 10px 15px;border-left:1px solid #d0d0d0;background:#f6f6f6;box-shadow:-1px 0 1px rgba(0,0,0,.05)}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item:hover .so-buttons{visibility:visible}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item.selected{background-color:#e5f4fa}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item.selected .so-directory-item-wrapper{background:#deeef4;border-color:#9abcc7}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item.selected .so-bottom{background:#f8fdff;border-color:#bcccd2}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item.selected .so-bottom .so-title{color:#3e484c}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item.selected .so-bottom .so-buttons{background:#eaf2f6;border-color:#bcccd2}@media only screen and (min-width:1680px){.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item{width:20%}}@media only screen and (max-width:1679px) and (min-width:1280px){.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item{width:25%}}@media only screen and (max-width:1279px) and (min-width:1140px){.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item{width:33.333%}}@media only screen and (max-width:1139px){.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item{width:50%}}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-pages{margin-top:15px;padding:0 5px}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-pages .button-disabled{pointer-events:none}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-toolbar .so-buttons select.so-layout-position{vertical-align:baseline}.so-panels-dialog .so-visual-styles{margin:-15px}.so-panels-dialog .so-visual-styles h3{line-height:1em;margin:0;padding:20px 15px;border-bottom:1px solid #ddd}.so-panels-dialog .so-visual-styles .style-section-head{background:#fff;padding:15px 10px;border-bottom:1px solid #ddd;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.so-panels-dialog .so-visual-styles .style-section-head h4{margin:0}.so-panels-dialog .so-visual-styles .style-section-fields{padding:15px;border-bottom:1px solid #ddd;background:#f7f7f7}.so-panels-dialog .so-visual-styles .style-section-fields .style-field-wrapper{margin-bottom:20px}.so-panels-dialog .so-visual-styles .style-section-fields .style-field-wrapper:last-child{margin-bottom:0}.so-panels-dialog .so-visual-styles .style-section-fields .style-field-wrapper>label{font-weight:700;display:block;margin-bottom:3px}.so-panels-dialog .so-visual-styles .style-section-fields .style-field-wrapper .style-field{zoom:1}.so-panels-dialog .so-visual-styles .style-section-fields .style-field-wrapper .style-field:before{content:"";display:block}.so-panels-dialog .so-visual-styles .style-section-fields .style-field-wrapper .style-field:after{content:"";display:table;clear:both}.so-panels-dialog .so-visual-styles .style-section-fields .style-field-wrapper .style-field input{font-size:12px}.so-panels-dialog .so-visual-styles .style-input-wrapper{zoom:1}.so-panels-dialog .so-visual-styles .style-input-wrapper:before{content:"";display:block}.so-panels-dialog .so-visual-styles .style-input-wrapper:after{content:"";display:table;clear:both}.so-panels-dialog .so-visual-styles .style-input-wrapper input{max-width:100%}.so-panels-dialog .so-visual-styles .style-field-measurement .measurement-inputs{overflow:auto;margin:0 -3px 4px}.so-panels-dialog .so-visual-styles .style-field-measurement .measurement-wrapper{box-sizing:border-box;float:left;width:25%;padding:0 3px}.so-panels-dialog .so-visual-styles .style-field-measurement .measurement-wrapper .measurement-value{border-width:1px;display:block;max-width:100%}.so-panels-dialog .so-visual-styles .style-field-measurement .measurement-wrapper .measurement-value.measurement-top{box-shadow:inset 0 2px 1px rgba(0,115,170,.35)}.so-panels-dialog .so-visual-styles .style-field-measurement .measurement-wrapper .measurement-value.measurement-right{box-shadow:inset -3px 0 2px rgba(0,115,170,.35)}.so-panels-dialog .so-visual-styles .style-field-measurement .measurement-wrapper .measurement-value.measurement-bottom{box-shadow:inset 0 -2px 1px rgba(0,115,170,.35)}.so-panels-dialog .so-visual-styles .style-field-measurement .measurement-wrapper .measurement-value.measurement-left{box-shadow:inset 3px 0 2px rgba(0,115,170,.35)}.so-panels-dialog .so-visual-styles .style-field-measurement .measurement-unit-multiple{width:100%;display:block}.so-panels-dialog .so-visual-styles .style-field-measurement .measurement-unit-single{float:right;width:25%}.so-panels-dialog .so-visual-styles .style-field-measurement .measurement-value-single{float:left;width:72%}.so-panels-dialog .so-visual-styles .style-field-image .so-image-selector{display:inline-block;background-color:#f7f7f7;border:1px solid #ccc;height:28px;float:left;border-radius:3px;cursor:pointer;box-shadow:inset 0 1px #fff}.so-panels-dialog .so-visual-styles .style-field-image .so-image-selector .current-image{height:28px;width:28px;float:left;background:#fff;border-right:1px solid #ccc;background-size:cover;-webkit-border-top-right-radius:0;-webkit-border-bottom-right-radius:0;-webkit-border-bottom-left-radius:3px;-webkit-border-top-left-radius:3px;-moz-border-radius-topright:0;-moz-border-radius-bottomright:0;-moz-border-radius-bottomleft:3px;-moz-border-radius-topleft:3px;border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:3px;border-top-left-radius:3px;background-clip:padding-box}.so-panels-dialog .so-visual-styles .style-field-image .so-image-selector .select-image{font-size:12px;line-height:28px;float:left;padding:0 8px;color:#555}.so-panels-dialog .so-visual-styles .style-field-image .remove-image{font-size:12px;margin-top:4px;margin-left:15px;display:inline-block;float:left;color:#666;text-decoration:none}.so-panels-dialog .so-visual-styles .style-field-image .remove-image .remove-image{color:#333}.so-panels-dialog .so-visual-styles .style-field-checkbox label{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.so-panels-dialog .so-visual-styles .so-field-code{font-size:12px;font-family:Courier\ 10 Pitch,Courier,monospace}.so-panels-dialog .so-visual-styles .so-description{color:#999;font-size:12px;margin-top:5px;margin-bottom:0;font-style:italic;clear:both}.so-panels-dialog .so-visual-styles.so-cell-styles{margin-top:15px}.so-panels-dialog .so-content .siteorigin-panels-builder .so-builder-toolbar{border:1px solid #dedede}.so-panels-dialog .so-content .siteorigin-panels-builder .so-rows-container{padding:20px 0 0}.so-panels-dialog .so-content .siteorigin-panels-builder .so-panels-welcome-message{padding-left:0;padding-right:0}.so-panels-dialog .so-dropdown-wrapper input[type=button].button-primary{width:125px;height:28px}.so-panels-dialog .so-dropdown-wrapper .so-dropdown-links-wrapper{display:block;z-index:11;bottom:28px;width:125px}.so-panels-dialog .so-dropdown-wrapper .so-dropdown-links-wrapper.hidden{display:none}.wp-customizer .so-panels-dialog .so-content,.wp-customizer .so-panels-dialog .so-left-sidebar,.wp-customizer .so-panels-dialog .so-overlay,.wp-customizer .so-panels-dialog .so-right-sidebar,.wp-customizer .so-panels-dialog .so-title-bar,.wp-customizer .so-panels-dialog .so-toolbar{z-index:500001}.wp-customizer .so-panels-dialog .so-toolbar{z-index:500002}.so-panels-live-editor>div{position:fixed;z-index:99999;-ms-box-sizing:border-box;box-sizing:border-box}.so-panels-live-editor .live-editor-form{display:none}.so-panels-live-editor .live-editor-collapse{position:fixed;top:18px;left:10px;line-height:1em;cursor:pointer;z-index:100000}.so-panels-live-editor .live-editor-collapse .collapse-icon{float:left;margin:-4px 6px 0 0;border-radius:50%;width:20px;height:20px;overflow:hidden;transition:all .25s ease 0s}.so-panels-live-editor .live-editor-collapse .collapse-icon:before{display:block;content:"\f148";background:#eee;font:normal 20px/1 dashicons;speak:none;padding:0;-webkit-font-smoothing:antialiased}.so-panels-live-editor .live-editor-collapse:hover{color:#0073aa}.so-panels-live-editor .live-editor-collapse:hover .collapse-icon{box-shadow:0 0 3px rgba(30,140,190,.8)}.so-panels-live-editor .so-sidebar-tools{background:#eee;border-bottom:1px solid #ddd;border-right:1px solid #d0d0d0;top:0;left:0;height:46px;width:360px}.so-panels-live-editor .so-sidebar-tools .live-editor-close{margin:9px 10px 0 15px;float:right}.so-panels-live-editor .so-sidebar-tools .live-editor-mode{float:right;margin:9px 4px 0 0}.so-panels-live-editor .so-sidebar-tools .live-editor-mode .dashicons{font-size:30px;width:30px;height:30px;cursor:pointer;color:#999}.so-panels-live-editor .so-sidebar-tools .live-editor-mode .dashicons:hover{color:#666}.so-panels-live-editor .so-sidebar-tools .live-editor-mode.so-active .dashicons,.so-panels-live-editor .so-sidebar-tools .live-editor-mode.so-active .dashicons:hover{color:#0073aa}.so-panels-live-editor .so-sidebar{top:46px;left:0;bottom:0;width:360px;overflow-y:auto;background:#f7f7f7;border-right:1px solid #d0d0d0}.so-panels-live-editor .so-sidebar .siteorigin-panels-builder .so-rows-container{padding:10px 10px 0!important}.so-panels-live-editor .so-preview{top:0;right:0;bottom:0;left:360px;background-color:#191e23}.so-panels-live-editor .so-preview form{display:none}.so-panels-live-editor .so-preview iframe{float:left;width:100%;height:100%;margin:0 auto}.so-panels-live-editor .so-preview-overlay{display:none;opacity:.975;top:0;right:0;bottom:0;left:360px;background-color:#f4f4f4;cursor:wait}.so-panels-live-editor .so-preview-overlay .so-loading-container{opacity:.6;position:absolute;top:50%;width:200px;padding:2px;border-radius:5px;left:50%;margin-left:-104px;margin-top:-9px;border:2px solid #aaa}.so-panels-live-editor .so-preview-overlay .so-loading-container .so-loading-bar{width:50%;border-radius:3px;height:10px;background:#aaa}.so-panels-live-editor.so-collapsed .live-editor-collapse .collapse-icon{transform:rotate(180deg)}.so-panels-live-editor.so-collapsed .so-sidebar,.so-panels-live-editor.so-collapsed .so-sidebar-tools{display:none}.so-panels-live-editor.so-collapsed .so-preview,.so-panels-live-editor.so-collapsed .so-preview-overlay{left:0}.so-panels-live-editor.live-editor-mobile-mode .so-preview iframe{max-width:480px;max-height:640px;position:absolute;top:50%;left:50%;margin-left:-240px;margin-top:-320px}@media (max-width:840px){.so-panels-live-editor.live-editor-mobile-mode .so-preview iframe{position:static;margin-left:0;margin-top:0}}@media (max-height:640px){.so-panels-live-editor.live-editor-mobile-mode .so-preview iframe{position:static;margin-left:0;margin-top:0}}.so-panels-live-editor.live-editor-tablet-mode .so-preview iframe{position:absolute;max-width:768px;top:0;left:50%;margin-left:-384px}@media (max-width:1128px){.so-panels-live-editor.live-editor-tablet-mode .so-preview iframe{position:static;margin-left:0;margin-top:0}}.so-panels-loading{background-image:url(images/wpspin_light.gif);background-position:50%;background-repeat:no-repeat}@media (-webkit-min-device-pixel-ratio:2),(min-resolution:192dpi){.so-panels-loading{background-image:url(images/wpspin_light-2x.gif);background-size:16px 16px}}#panels-home-page .switch{margin:0 10px 0 0;float:left;position:relative;display:inline-block;vertical-align:top;width:68px;height:24px;padding:3px;background-color:#fff;border-radius:24px;box-shadow:inset 0 -1px #fff,inset 0 1px 1px rgba(0,0,0,.05);cursor:pointer;background-image:linear-gradient(180deg,#eee,#fff 25px)}#panels-home-page .switch .switch-input{position:absolute;top:0;left:0;opacity:0}#panels-home-page .switch .switch-label{position:relative;display:block;height:inherit;font-size:12px;text-transform:uppercase;background:#eceeef;border-radius:inherit;box-shadow:inset 0 1px 2px rgba(0,0,0,.12),inset 0 0 2px rgba(0,0,0,.15);transition:.15s ease-out;transition-property:opacity background}#panels-home-page .switch .switch-label:after,#panels-home-page .switch .switch-label:before{position:absolute;top:50%;margin-top:-.5em;line-height:1;transition:inherit}#panels-home-page .switch .switch-label:before{content:attr(data-off);right:11px;color:#aaa;text-shadow:0 1px hsla(0,0%,100%,.5)}#panels-home-page .switch .switch-label:after{content:attr(data-on);left:13px;color:#fff;text-shadow:0 1px rgba(0,0,0,.2);opacity:0}#panels-home-page .switch .switch-input:checked~.switch-label{background:#47a8d8;box-shadow:inset 0 1px 2px rgba(0,0,0,.15),inset 0 0 3px rgba(0,0,0,.2)}#panels-home-page .switch .switch-input:checked~.switch-label:before{opacity:0}#panels-home-page .switch .switch-input:checked~.switch-label:after{opacity:1}#panels-home-page .switch .switch-handle{position:absolute;top:4px;left:4px;width:22px;height:22px;background:#fff;border-radius:12px;box-shadow:1px 1px 5px rgba(0,0,0,.2);background-image:linear-gradient(180deg,#fff 40%,#f0f0f0);transition:left .15s ease-out}#panels-home-page .switch .switch-handle:before{content:"";position:absolute;top:50%;left:50%;margin:-7px 0 0 -7px;width:14px;height:14px;background:#f9f9f9;border-radius:7px;box-shadow:inset 0 1px rgba(0,0,0,.02);background-image:linear-gradient(180deg,#eee,#fff)}#panels-home-page .switch .switch-input:checked~.switch-handle{left:48px;box-shadow:-1px 1px 5px rgba(0,0,0,.2)}#panels-home-page .switch .switch-green>.switch-input:checked~.switch-label{background:#4fb845}#panels-home-page #panels-view-as-page{display:inline-block;margin-left:50px}.siteorigin-panels-builder-form .siteorigin-panels-builder{border:1px solid #d0d0d0;background-color:#fff;margin:10px 0}.siteorigin-panels-builder-form .siteorigin-panels-builder.so-panels-loading{min-height:150px}.siteorigin-page-builder-widget .siteorigin-panels-display-builder{display:inline-block!important}.siteorigin-page-builder-widget .siteorigin-panels-no-builder{display:none!important}.so-panels-contextual-menu{border:1px solid silver;background:#f9f9f9;box-shadow:0 1px 1px rgba(0,0,0,.04);outline:none;border-radius:2px;position:absolute;width:180px;top:20px;left:20px;z-index:999999;display:none;overflow-y:auto}.so-panels-contextual-menu,.so-panels-contextual-menu *{font-size:12px}.so-panels-contextual-menu .so-section{border-bottom:1px solid silver}.so-panels-contextual-menu .so-section:last-child{border-bottom:none}.so-panels-contextual-menu .so-section h5{margin:0 0 5px;padding:8px 10px 5px;border-bottom:1px solid #d0d0d0;background:#f6f6f6}.so-panels-contextual-menu .so-section .so-search-wrapper{margin:-5px 0 5px;border-bottom:1px solid #d0d0d0;background:#f4f4f4}.so-panels-contextual-menu .so-section .so-search-wrapper input[type=text]{box-sizing:border-box;display:block;width:100%;margin:0;border:none;padding:5px 10px;background:#fbfbfb}.so-panels-contextual-menu .so-section .so-search-wrapper input[type=text]:active,.so-panels-contextual-menu .so-section .so-search-wrapper input[type=text]:focus{border:none;box-shadow:none;background:#fff}.so-panels-contextual-menu .so-section ul{margin:5px 0 0;padding:0 0 5px}.so-panels-contextual-menu .so-section ul li{cursor:pointer;margin:0;padding:4px 10px;line-height:1em}.so-panels-contextual-menu .so-section ul li.so-active,.so-panels-contextual-menu .so-section ul li:hover{background:#f0f0f0;color:#444}.so-panels-contextual-menu .so-section ul li.so-confirm{color:#a00}.so-panels-contextual-menu .so-section ul li.so-confirm.so-active,.so-panels-contextual-menu .so-section ul li.so-confirm:hover{background:#a00;color:#fff}.so-panels-contextual-menu .so-section ul li .dashicons{width:12px;height:12px;font-size:12px;margin:0;float:right;line-height:12px}.so-panels-contextual-menu .so-section .so-no-results{padding:0 10px 5px;display:none;font-style:italic}.so-dropdown-wrapper{position:relative;float:right}.so-dropdown-wrapper .so-dropdown-links-wrapper{position:absolute;padding:6px 0 0}.so-dropdown-wrapper .so-dropdown-links-wrapper ul{margin:0;border:1px solid silver;background:#f9f9f9;border-radius:2px;padding:4px 0;box-shadow:0 2px 2px rgba(0,0,0,.1)}.so-dropdown-wrapper .so-dropdown-links-wrapper ul li{margin:0}.so-dropdown-wrapper .so-dropdown-links-wrapper ul li:first-child{border-top-width:1px}.so-dropdown-wrapper .so-dropdown-links-wrapper ul li a{display:block;padding:2px 8px;text-decoration:none;color:#666;font-size:11px;cursor:pointer;outline:0!important;box-shadow:none}.so-dropdown-wrapper .so-dropdown-links-wrapper ul li a:hover{background:#f0f0f0;color:#444}.so-dropdown-wrapper .so-dropdown-links-wrapper ul li a .dashicons{font-size:16px;margin:0;float:right;line-height:16px}.so-dropdown-wrapper .so-dropdown-links-wrapper .so-pointer{width:12px;height:6px;position:absolute;z-index:12;background:url(images/dropdown-pointer.png);background-size:12px 6px;top:1px;right:18px}.so-panels-icon{font-family:siteorigin-panels-icons;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.so-panels-icon.so-panels-icon-add-row:before{content:"\e900"}.so-panels-icon.so-panels-icon-add-widget:before{content:"\e901"}.so-panels-icon.so-panels-icon-addons:before{content:"\e902"}.so-panels-icon.so-panels-icon-history:before{content:"\e903"}.so-panels-icon.so-panels-icon-layouts:before{content:"\e904"}.so-panels-icon.so-panels-icon-learn:before{content:"\e905"}.so-panels-icon.so-panels-icon-live-editor:before{content:"\e906"}.so-panels-icon.so-panels-icon-move:before{content:"\e907"}.so-panels-icon.so-panels-icon-settings:before{content:"\e908"}#post-status-info.for-siteorigin-panels{margin-top:-21px!important}
css/front-flex.min.css ADDED
@@ -0,0 +1 @@
 
1
+ .panel-grid.panel-has-style>.panel-row-style,.panel-grid.panel-no-style{display:flex;-ms-flex-wrap:wrap;flex-wrap:nowrap;-ms-justify-content:space-between;justify-content:space-between}.panel-layout.panel-is-rtl .panel-grid.panel-has-style>.panel-row-style,.panel-layout.panel-is-rtl .panel-grid.panel-no-style{-ms-flex-direction:row-reverse;flex-direction:row-reverse}.panel-grid-cell{-ms-box-sizing:border-box;box-sizing:border-box}.panel-grid-cell .panel-cell-style{height:100%}.panel-grid-cell .so-panel{zoom:1}.panel-grid-cell .so-panel:before{content:"";display:block}.panel-grid-cell .so-panel:after{content:"";display:table;clear:both}.panel-grid-cell .panel-last-child{margin-bottom:0}.panel-grid-cell .widget-title{margin-top:0}body.siteorigin-panels-before-js{overflow-x:hidden}body.siteorigin-panels-before-js .siteorigin-panels-stretch{margin-right:-1000px!important;margin-left:-1000px!important;padding-right:1000px!important;padding-left:1000px!important}
css/front-legacy.min.css ADDED
@@ -0,0 +1 @@
 
1
+ .panel-grid{zoom:1}.panel-grid:before{content:"";display:block}.panel-grid:after{content:"";display:table;clear:both}.panel-grid-cell{-ms-box-sizing:border-box;box-sizing:border-box;min-height:1em;float:left}.panel-grid-cell .so-panel{zoom:1}.panel-grid-cell .so-panel:before{content:"";display:block}.panel-grid-cell .so-panel:after{content:"";display:table;clear:both}.panel-grid-cell .panel-last-child{margin-bottom:0}.panel-grid-cell .widget-title{margin-top:0}.panel-row-style{zoom:1}.panel-row-style:before{content:"";display:block}.panel-row-style:after{content:"";display:table;clear:both}
css/front.min.css ADDED
@@ -0,0 +1 @@
 
1
+ .panel-grid.panel-has-style>.panel-row-style,.panel-grid.panel-no-style{display:flex;-ms-flex-wrap:wrap;flex-wrap:nowrap;-ms-justify-content:space-between;justify-content:space-between}.panel-grid-cell{-ms-box-sizing:border-box;box-sizing:border-box}.panel-grid-cell .panel-cell-style{height:100%}.panel-grid-cell .so-panel{zoom:1}.panel-grid-cell .so-panel:before{content:"";display:block}.panel-grid-cell .so-panel:after{content:"";display:table;clear:both}.panel-grid-cell .panel-last-child{margin-bottom:0}.panel-grid-cell .widget-title{margin-top:0}body.siteorigin-panels-before-js{overflow-x:hidden}body.siteorigin-panels-before-js .siteorigin-panels-stretch{margin-right:-1000px!important;margin-left:-1000px!important;padding-right:1000px!important;padding-left:1000px!important}
css/live-editor-front.min.css ADDED
@@ -0,0 +1 @@
 
1
+ .so-panel{transition-duration:.6s!important}.so-panel.so-panels-highlighted{opacity:1!important}.so-panel.so-panels-faded{opacity:.275!important}
css/live-editor-preview.min.css ADDED
@@ -0,0 +1 @@
 
1
+ html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}body,button,input,select,textarea{color:#404040;font-size:14px;line-height:1.5}h1,h2,h3,h4,h5,h6{clear:both}p{margin-bottom:1.5em}cite,dfn,em,i{font-style:italic}blockquote{margin:0 1.5em}address{margin:0 0 1.5em}pre{background:#eee;font-family:Courier\ 10 Pitch,Courier,monospace;line-height:1.6;margin-bottom:1.6em;max-width:100%;overflow:auto;padding:1.6em}code,kbd,pre,tt,var{font-size:15px;font-size:.9375rem}code,kbd,tt,var{font-family:Monaco,Consolas,Andale Mono,DejaVu Sans Mono,monospace}abbr,acronym{border-bottom:1px dotted #666;cursor:help}ins,mark{background:#fff9c0;text-decoration:none}big{font-size:125%}html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}body{background:#fff}blockquote:after,blockquote:before,q:after,q:before{content:""}blockquote,q{quotes:"" ""}hr{background-color:#ccc;border:0;height:1px;margin-bottom:1.5em}ol,ul{margin:0 0 1.5em 3em}ul{list-style:disc}ol{list-style:decimal}li>ol,li>ul{margin-bottom:0;margin-left:1.5em}dt{font-weight:700}dd{margin:0 1.5em 1.5em}img{height:auto;max-width:100%}table{margin:0 0 1.5em;width:100%}button,input[type=button],input[type=reset],input[type=submit]{border:1px solid;border-color:#ccc #ccc #bbb;border-radius:3px;background:#e6e6e6;box-shadow:inset 0 1px 0 hsla(0,0%,100%,.5),inset 0 15px 17px hsla(0,0%,100%,.5),inset 0 -5px 12px rgba(0,0,0,.05);color:rgba(0,0,0,.8);font-size:12px;font-size:.75rem;line-height:1;padding:.6em 1em .4em;text-shadow:0 1px 0 hsla(0,0%,100%,.8)}button:hover,input[type=button]:hover,input[type=reset]:hover,input[type=submit]:hover{border-color:#ccc #bbb #aaa;box-shadow:inset 0 1px 0 hsla(0,0%,100%,.8),inset 0 15px 17px hsla(0,0%,100%,.8),inset 0 -5px 12px rgba(0,0,0,.02)}button:active,button:focus,input[type=button]:active,input[type=button]:focus,input[type=reset]:active,input[type=reset]:focus,input[type=submit]:active,input[type=submit]:focus{border-color:#aaa #bbb #bbb;box-shadow:inset 0 -1px 0 hsla(0,0%,100%,.5),inset 0 2px 5px rgba(0,0,0,.15)}input[type=email],input[type=password],input[type=search],input[type=text],input[type=url],textarea{color:#666;border:1px solid #ccc;border-radius:3px}input[type=email]:focus,input[type=password]:focus,input[type=search]:focus,input[type=text]:focus,input[type=url]:focus,textarea:focus{color:#111}input[type=email],input[type=password],input[type=search],input[type=text],input[type=url]{padding:3px}textarea{padding-left:3px;width:100%}a{color:#4169e1}a:visited{color:purple}a:active,a:focus,a:hover{color:#191970}a:focus{outline:thin dotted}a:active,a:hover{outline:0}.main-navigation{clear:both;display:block;float:left;width:100%}.main-navigation ul{display:none;list-style:none;margin:0;padding-left:0}.main-navigation li{float:left;position:relative}.main-navigation a{display:block;text-decoration:none}.main-navigation ul ul{box-shadow:0 3px 3px rgba(0,0,0,.2);float:left;position:absolute;top:1.5em;left:-999em;z-index:99999}.main-navigation ul ul ul{left:-999em;top:0}.main-navigation ul ul a{width:200px}.main-navigation ul li.focus>ul,.main-navigation ul li:hover>ul{left:auto}.main-navigation ul ul li.focus>ul,.main-navigation ul ul li:hover>ul{left:100%}.main-navigation.toggled ul,.menu-toggle{display:block}@media screen and (min-width:37.5em){.menu-toggle{display:none}.main-navigation ul{display:block}}.site-main .comment-navigation,.site-main .post-navigation,.site-main .posts-navigation{margin:0 0 1.5em;overflow:hidden}.comment-navigation .nav-previous,.post-navigation .nav-previous,.posts-navigation .nav-previous{float:left;width:50%}.comment-navigation .nav-next,.post-navigation .nav-next,.posts-navigation .nav-next{float:right;text-align:right;width:50%}.screen-reader-text{clip:rect(1px,1px,1px,1px);position:absolute!important;height:1px;width:1px;overflow:hidden}.screen-reader-text:focus{background-color:#f1f1f1;border-radius:3px;box-shadow:0 0 2px 2px rgba(0,0,0,.6);clip:auto!important;color:#21759b;display:block;font-size:14px;font-size:.875rem;font-weight:700;height:auto;left:5px;line-height:normal;padding:15px 23px 14px;text-decoration:none;top:5px;width:auto;z-index:100000}.alignleft{display:inline;float:left;margin-right:1.5em}.alignright{display:inline;float:right;margin-left:1.5em}.aligncenter{clear:both;display:block;margin-left:auto;margin-right:auto}.clear:after,.clear:before,.comment-content:after,.comment-content:before,.entry-content:after,.entry-content:before,.site-content:after,.site-content:before,.site-footer:after,.site-footer:before,.site-header:after,.site-header:before{content:"";display:table}.clear:after,.comment-content:after,.entry-content:after,.site-content:after,.site-footer:after,.site-header:after{clear:both}.widget{margin:0 0 1.5em}.widget select{max-width:100%}.widget_search .search-submit{display:none}.sticky{display:block}.hentry{margin:0 0 1.5em}.byline,.updated:not(.published){display:none}.group-blog .byline,.single .byline{display:inline}.entry-content,.entry-summary,.page-content{margin:1.5em 0 0}.page-links{clear:both;margin:0 0 1.5em}.archive .format-aside .entry-title,.blog .format-aside .entry-title{display:none}.comment-content a{word-wrap:break-word}.bypostauthor{display:block}.infinite-scroll.neverending .site-footer,.infinite-scroll .posts-navigation{display:none}.infinity-end.neverending .site-footer{display:block}.comment-content .wp-smiley,.entry-content .wp-smiley,.page-content .wp-smiley{border:none;margin-bottom:0;margin-top:0;padding:0}.wp-caption,embed,iframe,object{max-width:100%}.wp-caption{margin-bottom:1.5em}.wp-caption img[class*=wp-image-]{display:block;margin:0 auto}.wp-caption-text{text-align:center}.wp-caption .wp-caption-text{margin:.8075em 0}.gallery{margin-bottom:1.5em}.gallery-item{display:inline-block;text-align:center;vertical-align:top;width:100%}.gallery-columns-2 .gallery-item{max-width:50%}.gallery-columns-3 .gallery-item{max-width:33.33%}.gallery-columns-4 .gallery-item{max-width:25%}.gallery-columns-5 .gallery-item{max-width:20%}.gallery-columns-6 .gallery-item{max-width:16.66%}.gallery-columns-7 .gallery-item{max-width:14.28%}.gallery-columns-8 .gallery-item{max-width:12.5%}.gallery-columns-9 .gallery-item{max-width:11.11%}.gallery-caption{display:block}#content{box-sizing:border-box;max-width:1280px;margin:0 auto;padding:20px 40px}
inc/admin-layouts.php CHANGED
@@ -1,463 +1,467 @@
1
- <?php
2
-
3
- /**
4
- * Class SiteOrigin_Panels_Admin
5
- *
6
- * Handles all the admin and database interactions.
7
- */
8
- class SiteOrigin_Panels_Admin_Layouts {
9
-
10
- const LAYOUT_URL = 'http://layouts.siteorigin.com/';
11
-
12
- function __construct() {
13
- // Filter all the available external layout directories.
14
- add_filter( 'siteorigin_panels_external_layout_directories', array( $this, 'filter_directories' ), 8 );
15
- // Filter all the available local layout folders.
16
- add_filter( 'siteorigin_panels_prebuilt_layouts', array( $this, 'get_local_layouts' ), 8 );
17
-
18
- add_action( 'wp_ajax_so_panels_layouts_query', array( $this, 'action_get_prebuilt_layouts' ) );
19
- add_action( 'wp_ajax_so_panels_get_layout', array( $this, 'action_get_prebuilt_layout' ) );
20
- add_action( 'wp_ajax_so_panels_import_layout', array( $this, 'action_import_layout' ) );
21
- add_action( 'wp_ajax_so_panels_export_layout', array( $this, 'action_export_layout' ) );
22
- add_action( 'wp_ajax_so_panels_directory_enable', array( $this, 'action_directory_enable' ) );
23
- }
24
-
25
- /**
26
- * @return SiteOrigin_Panels_Admin_Layouts
27
- */
28
- public static function single() {
29
- static $single;
30
- return empty( $single ) ? $single = new self() : $single;
31
- }
32
-
33
- /**
34
- * Add the main SiteOrigin layout directory
35
- */
36
- public function filter_directories( $directories ){
37
- if ( apply_filters( 'siteorigin_panels_layouts_directory_enabled', true ) ) {
38
- $directories['siteorigin'] = array(
39
- // The title of the layouts directory in the sidebar.
40
- 'title' => __( 'Layouts Directory', 'siteorigin-panels' ),
41
- // The URL of the directory.
42
- 'url' => self::LAYOUT_URL,
43
- // Any additional arguments to pass to the layouts server
44
- 'args' => array()
45
- );
46
- }
47
-
48
- return $directories;
49
- }
50
-
51
- /**
52
- * Get all the layout directories.
53
- *
54
- * @return array
55
- */
56
- public function get_directories(){
57
- $directories = apply_filters( 'siteorigin_panels_external_layout_directories', array() );
58
- if( empty( $directories ) || ! is_array( $directories ) ) {
59
- $directories = array();
60
- }
61
-
62
- return $directories;
63
- }
64
-
65
-
66
- /**
67
- * Looks through local folders in the active theme and any others filtered in by theme and plugins, to find JSON
68
- * prebuilt layouts.
69
- *
70
- */
71
- public function get_local_layouts() {
72
-
73
- // By default we'll look for layouts in a directory in the active theme
74
- $layout_folders = array( get_template_directory() . '/siteorigin-page-builder-layouts' );
75
-
76
- // And the child theme if there is one.
77
- if ( is_child_theme() ) {
78
- $layout_folders[] = get_stylesheet_directory() . '/siteorigin-page-builder-layouts';
79
- }
80
-
81
- // This allows themes and plugins to customize where we look for layouts.
82
- $layout_folders = apply_filters( 'siteorigin_panels_local_layouts_directories', $layout_folders );
83
-
84
- $layouts = array();
85
- foreach ( $layout_folders as $folder ) {
86
- $files = array();
87
- if ( file_exists( $folder ) && is_dir( $folder ) ) {
88
- $files = list_files( $folder, 1 );
89
- }
90
-
91
- foreach ( $files as $file ) {
92
- // get file mime type
93
- $mime_type = mime_content_type( $file );
94
-
95
- // skip non text files.
96
- if ( strpos( $mime_type, 'text/' ) !== 0 ) {
97
- continue;
98
- }
99
-
100
- // get file contents
101
- $file_contents = file_get_contents( $file );
102
- // json decode
103
- $panels_data = json_decode( $file_contents, true );
104
-
105
- // get file name by stripping out folder path and .json extension
106
- $file_name = str_replace( $folder . '/' , '', $file );
107
- $file_name = str_replace( '.json', '', $file_name );
108
-
109
- // get name: check for id or name else use filename
110
- $panels_data['id'] = sanitize_title_with_dashes( $this->get_layout_id( $panels_data, $file_name ) );
111
-
112
- if ( empty( $panels_data['name'] ) ) {
113
- $panels_data['name'] = $file_name;
114
- }
115
-
116
- $panels_data['name'] = sanitize_text_field( $panels_data['name'] );
117
-
118
- // get screenshot: check for screenshot prop else try use image file with same filename.
119
- $panels_data['screenshot'] = $this->get_layout_file_screenshot( $panels_data, $folder, $file_name );
120
-
121
- // set item on layouts array
122
- $layouts[ $panels_data['id'] ] = $panels_data;
123
- }
124
- }
125
-
126
- return $layouts;
127
- }
128
-
129
- private function get_layout_id( $layout_data, $fallback ) {
130
- if ( ! empty( $layout_data['id'] ) ) {
131
- return $layout_data['id'];
132
- } else if ( ! empty( $layout_data['name'] ) ) {
133
- return $layout_data['name'];
134
- } else {
135
- return $fallback;
136
- }
137
- }
138
-
139
- private function get_layout_file_screenshot( $panels_data, $folder_path, $file_name ) {
140
- if ( ! empty( $panels_data['screenshot'] ) ) {
141
- return $panels_data['screenshot'];
142
- } else {
143
- $paths = glob( $folder_path . "/$file_name.{jpg,jpeg,gif,png}", GLOB_BRACE );
144
- // Highlander Condition. There can be only one.
145
- $screenshot_path = empty( $paths ) ? '' : wp_normalize_path( $paths[0] );
146
- $wp_content_dir = wp_normalize_path( WP_CONTENT_DIR );
147
- $screenshot_url = '';
148
- if ( file_exists( $screenshot_path ) &&
149
- strrpos( $screenshot_path, $wp_content_dir ) === 0 ) {
150
-
151
- $screenshot_url = str_replace( $wp_content_dir, content_url(), $screenshot_path );
152
- }
153
-
154
- return $screenshot_url;
155
- }
156
- }
157
-
158
- /**
159
- * Gets all the prebuilt layouts.
160
- */
161
- function action_get_prebuilt_layouts() {
162
- if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
163
- wp_die( __( 'Invalid request.', 'siteorigin-panels' ), 403 );
164
- }
165
-
166
- // Get any layouts that the current user could edit.
167
- header( 'content-type: application/json' );
168
-
169
- $type = ! empty( $_REQUEST['type'] ) ? $_REQUEST['type'] : 'directory-siteorigin';
170
- $search = ! empty( $_REQUEST['search'] ) ? trim( strtolower( $_REQUEST['search'] ) ) : '';
171
- $page_num = ! empty( $_REQUEST['page'] ) ? intval( $_REQUEST['page'] ) : 1;
172
-
173
- $return = array(
174
- 'title' => '',
175
- 'items' => array()
176
- );
177
- if ( $type == 'prebuilt' ) {
178
- $return['title'] = __( 'Theme Defined Layouts', 'siteorigin-panels' );
179
-
180
- // This is for theme bundled prebuilt directories
181
- $layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
182
-
183
- foreach ( $layouts as $id => $vals ) {
184
- if ( ! empty( $search ) && strpos( strtolower( $vals['name'] ), $search ) === false ) {
185
- continue;
186
- }
187
-
188
- $return['items'][] = array(
189
- 'title' => $vals['name'],
190
- 'id' => $id,
191
- 'type' => 'prebuilt',
192
- 'description' => isset( $vals['description'] ) ? $vals['description'] : '',
193
- 'screenshot' => ! empty( $vals['screenshot'] ) ? $vals['screenshot'] : ''
194
- );
195
- }
196
-
197
- $return['max_num_pages'] = 1;
198
- } elseif ( substr( $type, 0, 10 ) == 'directory-' ) {
199
- $return['title'] = __( 'Layouts Directory', 'siteorigin-panels' );
200
-
201
- // This is a query of the prebuilt layout directory
202
- $query = array();
203
- if ( ! empty( $search ) ) {
204
- $query['search'] = $search;
205
- }
206
- $query['page'] = $page_num;
207
-
208
- $directory_id = str_replace( 'directory-', '', $type );
209
- $directories = $this->get_directories();
210
- $directory = ! empty( $directories[ $directory_id ] ) ? $directories[ $directory_id ] : false;
211
-
212
- if( empty( $directory ) ) {
213
- return false;
214
- }
215
-
216
- $url = add_query_arg( $query, $directory[ 'url' ] . 'wp-admin/admin-ajax.php?action=query_layouts' );
217
- if( ! empty( $directory[ 'args' ] ) && is_array( $directory[ 'args' ] ) ) {
218
- $url = add_query_arg( $directory[ 'args' ], $url );
219
- }
220
-
221
- $url = apply_filters( 'siteorigin_panels_layouts_directory_url', $url );
222
- $response = wp_remote_get( $url );
223
-
224
- if ( is_array( $response ) && $response['response']['code'] == 200 ) {
225
- $results = json_decode( $response['body'], true );
226
- if ( ! empty( $results ) && ! empty( $results['items'] ) ) {
227
- foreach ( $results['items'] as $item ) {
228
- $item['id'] = $item['slug'];
229
- $item['type'] = $type;
230
-
231
- if( empty( $item['screenshot'] ) && ! empty( $item['preview'] ) ) {
232
- $preview_url = add_query_arg( 'screenshot', 'true', $item[ 'preview' ] );
233
- $item['screenshot'] = 'https://s.wordpress.com/mshots/v1/' . urlencode( $preview_url ) . '?w=700';
234
- }
235
-
236
- $return['items'][] = $item;
237
- }
238
- }
239
-
240
- $return['max_num_pages'] = $results['max_num_pages'];
241
- }
242
- } elseif ( strpos( $type, 'clone_' ) !== false ) {
243
- // Check that the user can view the given page types
244
- $post_type = get_post_type_object( str_replace( 'clone_', '', $type ) );
245
- if( empty( $post_type ) ) {
246
- return;
247
- }
248
-
249
- $return['title'] = sprintf( __( 'Clone %s', 'siteorigin-panels' ), esc_html( $post_type->labels->singular_name ) );
250
-
251
- global $wpdb;
252
- $user_can_read_private = ( $post_type == 'post' && current_user_can( 'read_private_posts' ) || ( $post_type == 'page' && current_user_can( 'read_private_pages' ) ) );
253
- $include_private = $user_can_read_private ? "OR posts.post_status = 'private' " : "";
254
-
255
- // Select only the posts with the given post type that also have panels_data
256
- $results = $wpdb->get_results( "
257
- SELECT SQL_CALC_FOUND_ROWS DISTINCT ID, post_title, meta.meta_value
258
- FROM {$wpdb->posts} AS posts
259
- JOIN {$wpdb->postmeta} AS meta ON posts.ID = meta.post_id
260
- WHERE
261
- posts.post_type = '" . esc_sql( $post_type->name ) . "'
262
- AND meta.meta_key = 'panels_data'
263
- " . ( ! empty( $search ) ? 'AND posts.post_title LIKE "%' . esc_sql( $search ) . '%"' : '' ) . "
264
- AND ( posts.post_status = 'publish' OR posts.post_status = 'draft' " . $include_private . ")
265
- ORDER BY post_date DESC
266
- LIMIT 16 OFFSET " . intval( ( $page_num - 1 ) * 16 ) );
267
- $total_posts = $wpdb->get_var( "SELECT FOUND_ROWS();" );
268
-
269
- foreach ( $results as $result ) {
270
- $thumbnail = get_the_post_thumbnail_url( $result->ID, array( 400, 300 ) );
271
- $return['items'][] = array(
272
- 'id' => $result->ID,
273
- 'title' => $result->post_title,
274
- 'type' => $type,
275
- 'screenshot' => ! empty( $thumbnail ) ? $thumbnail : ''
276
- );
277
- }
278
-
279
- $return['max_num_pages'] = ceil( $total_posts / 16 );
280
-
281
- } else {
282
- // An invalid type. Display an error message.
283
- }
284
-
285
- // Add the search part to the title
286
- if ( ! empty( $search ) ) {
287
- $return['title'] .= __( ' - Results For:', 'siteorigin-panels' ) . ' <em>' . esc_html( $search ) . '</em>';
288
- }
289
-
290
- echo json_encode( $return );
291
-
292
- wp_die();
293
- }
294
-
295
- /**
296
- * Ajax handler to get an individual prebuilt layout
297
- */
298
- function action_get_prebuilt_layout() {
299
- if ( empty( $_REQUEST['type'] ) ) {
300
- wp_die();
301
- }
302
- if ( empty( $_REQUEST['lid'] ) ) {
303
- wp_die();
304
- }
305
- if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
306
- wp_die();
307
- }
308
-
309
- header( 'content-type: application/json' );
310
- $panels_data = array();
311
- $raw_panels_data = false;
312
-
313
- if ( $_REQUEST['type'] == 'prebuilt' ) {
314
- $layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
315
- $lid = ! empty( $_REQUEST['lid'] ) ? $_REQUEST['lid'] : false;
316
-
317
- if ( empty( $lid ) || empty( $layouts[ $lid ] ) ) {
318
- wp_send_json_error( array(
319
- 'error' => true,
320
- 'message' => __( 'Missing layout ID or no such layout exists', 'siteorigin-panels' ),
321
- ) );
322
- }
323
-
324
- $layout = $layouts[ $_REQUEST['lid'] ];
325
-
326
- // Fix the format of this layout
327
- if( !empty( $layout[ 'filename' ] ) ) {
328
- $filename = $layout[ 'filename' ];
329
- // Only accept filenames that end with .json
330
- if( substr( $filename, -5, 5 ) === '.json' && file_exists( $filename ) ) {
331
- $panels_data = json_decode( file_get_contents( $filename ), true );
332
- $layout[ 'widgets' ] = ! empty( $panels_data[ 'widgets' ] ) ? $panels_data[ 'widgets' ] : array();
333
- $layout[ 'grids' ] = ! empty( $panels_data[ 'grids' ] ) ? $panels_data[ 'grids' ] : array();
334
- $layout[ 'grid_cells' ] = ! empty( $panels_data[ 'grid_cells' ] ) ? $panels_data[ 'grid_cells' ] : array();
335
- }
336
- }
337
-
338
- // A theme or plugin could use this to change the data in the layout
339
- $panels_data = apply_filters( 'siteorigin_panels_prebuilt_layout', $layout, $lid );
340
-
341
- // Remove all the layout specific attributes
342
- if ( isset( $panels_data['name'] ) ) unset( $panels_data['name'] );
343
- if ( isset( $panels_data['screenshot'] ) ) unset( $panels_data['screenshot'] );
344
- if ( isset( $panels_data['filename'] ) ) unset( $panels_data['filename'] );
345
-
346
- $raw_panels_data = true;
347
-
348
- } elseif ( substr( $_REQUEST['type'], 0, 10 ) == 'directory-' ) {
349
- $directory_id = str_replace( 'directory-', '', $_REQUEST['type'] );
350
- $directories = $this->get_directories();
351
- $directory = ! empty( $directories[ $directory_id ] ) ? $directories[ $directory_id ] : false;
352
-
353
- if( ! empty( $directory ) ) {
354
- $url = $directory[ 'url' ] . 'layout/' . urlencode( $_REQUEST[ 'lid' ] ) . '/?action=download';
355
- if( ! empty( $directory[ 'args' ] ) && is_array( $directory[ 'args' ] ) ) {
356
- $url = add_query_arg( $directory[ 'args' ], $url );
357
- }
358
-
359
- $response = wp_remote_get( $url );
360
- if ( $response['response']['code'] == 200 ) {
361
- // For now, we'll just pretend to load this
362
- $panels_data = json_decode( $response['body'], true );
363
- } else {
364
- wp_send_json_error( array(
365
- 'error' => true,
366
- 'message' => __( 'There was a problem fetching the layout. Please try again later.', 'siteorigin-panels' ),
367
- ) );
368
- }
369
- }
370
- $raw_panels_data = true;
371
-
372
- } elseif ( current_user_can( 'edit_post', $_REQUEST['lid'] ) ) {
373
- $panels_data = get_post_meta( $_REQUEST['lid'], 'panels_data', true );
374
- }
375
-
376
- if( $raw_panels_data ) {
377
- // This panels_data is flagged as raw, so it needs to be processed.
378
- $panels_data = apply_filters( 'siteorigin_panels_data', $panels_data, false );
379
- $panels_data['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets( $panels_data['widgets'], array(), true, true );
380
- }
381
-
382
- wp_send_json_success( $panels_data );
383
- }
384
-
385
- /**
386
- * Ajax handler to import a layout
387
- */
388
- function action_import_layout() {
389
- if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
390
- wp_die();
391
- }
392
-
393
- if ( ! empty( $_FILES['panels_import_data']['tmp_name'] ) ) {
394
- header( 'content-type:application/json' );
395
- $json = file_get_contents( $_FILES['panels_import_data']['tmp_name'] );
396
- @unlink( $_FILES['panels_import_data']['tmp_name'] );
397
- echo $json;
398
- }
399
- wp_die();
400
- }
401
-
402
- /**
403
- * Export a given layout as a JSON file.
404
- */
405
- function action_export_layout() {
406
- if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
407
- wp_die();
408
- }
409
-
410
- $export_data = wp_unslash( $_POST['panels_export_data'] );
411
-
412
- $decoded_export_data = json_decode( $export_data, true );
413
-
414
- if ( ! empty( $decoded_export_data['name'] ) ) {
415
- $decoded_export_data['id'] = sanitize_title_with_dashes( $decoded_export_data['name'] );
416
- $filename = $decoded_export_data['id'];
417
- } else {
418
- $filename = 'layout-' . date( 'dmY' );
419
- }
420
-
421
-
422
- header( 'content-type: application/json' );
423
- header( "Content-Disposition: attachment; filename=$filename.json" );
424
-
425
- echo $export_data;
426
-
427
- wp_die();
428
- }
429
-
430
- /**
431
- * Enable the directory.
432
- */
433
- function action_directory_enable() {
434
- if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
435
- wp_die();
436
- }
437
- $user = get_current_user_id();
438
- update_user_meta( $user, 'so_panels_directory_enabled', true );
439
- wp_die();
440
- }
441
-
442
- /**
443
- * Load a layout from a json file
444
- *
445
- * @param $id
446
- * @param $name
447
- * @param $json_file
448
- * @param bool $screenshot
449
- *
450
- * @return array The data for the layout
451
- */
452
- public static function load_layout($id, $name, $json_file, $screenshot = false) {
453
- $layout_data = json_decode(file_get_contents($json_file), true);
454
- $layout_data = apply_filters('siteorigin_panels_load_layout_' . $id, $layout_data);
455
-
456
- $layout_data = array_merge(array(
457
- 'name' => $name,
458
- 'screenshot' => $screenshot,
459
- ), $layout_data);
460
-
461
- return $layout_data;
462
- }
463
- }
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class SiteOrigin_Panels_Admin
5
+ *
6
+ * Handles all the admin and database interactions.
7
+ */
8
+ class SiteOrigin_Panels_Admin_Layouts {
9
+
10
+ const LAYOUT_URL = 'http://layouts.siteorigin.com/';
11
+
12
+ function __construct() {
13
+ // Filter all the available external layout directories.
14
+ add_filter( 'siteorigin_panels_external_layout_directories', array( $this, 'filter_directories' ), 8 );
15
+ // Filter all the available local layout folders.
16
+ add_filter( 'siteorigin_panels_prebuilt_layouts', array( $this, 'get_local_layouts' ), 8 );
17
+
18
+ add_action( 'wp_ajax_so_panels_layouts_query', array( $this, 'action_get_prebuilt_layouts' ) );
19
+ add_action( 'wp_ajax_so_panels_get_layout', array( $this, 'action_get_prebuilt_layout' ) );
20
+ add_action( 'wp_ajax_so_panels_import_layout', array( $this, 'action_import_layout' ) );
21
+ add_action( 'wp_ajax_so_panels_export_layout', array( $this, 'action_export_layout' ) );
22
+ add_action( 'wp_ajax_so_panels_directory_enable', array( $this, 'action_directory_enable' ) );
23
+ }
24
+
25
+ /**
26
+ * @return SiteOrigin_Panels_Admin_Layouts
27
+ */
28
+ public static function single() {
29
+ static $single;
30
+ return empty( $single ) ? $single = new self() : $single;
31
+ }
32
+
33
+ /**
34
+ * Add the main SiteOrigin layout directory
35
+ */
36
+ public function filter_directories( $directories ){
37
+ if ( apply_filters( 'siteorigin_panels_layouts_directory_enabled', true ) ) {
38
+ $directories['siteorigin'] = array(
39
+ // The title of the layouts directory in the sidebar.
40
+ 'title' => __( 'Layouts Directory', 'siteorigin-panels' ),
41
+ // The URL of the directory.
42
+ 'url' => self::LAYOUT_URL,
43
+ // Any additional arguments to pass to the layouts server
44
+ 'args' => array()
45
+ );
46
+ }
47
+
48
+ return $directories;
49
+ }
50
+
51
+ /**
52
+ * Get all the layout directories.
53
+ *
54
+ * @return array
55
+ */
56
+ public function get_directories(){
57
+ $directories = apply_filters( 'siteorigin_panels_external_layout_directories', array() );
58
+ if( empty( $directories ) || ! is_array( $directories ) ) {
59
+ $directories = array();
60
+ }
61
+
62
+ return $directories;
63
+ }
64
+
65
+
66
+ /**
67
+ * Looks through local folders in the active theme and any others filtered in by theme and plugins, to find JSON
68
+ * prebuilt layouts.
69
+ *
70
+ */
71
+ public function get_local_layouts() {
72
+
73
+ // By default we'll look for layouts in a directory in the active theme
74
+ $layout_folders = array( get_template_directory() . '/siteorigin-page-builder-layouts' );
75
+
76
+ // And the child theme if there is one.
77
+ if ( is_child_theme() ) {
78
+ $layout_folders[] = get_stylesheet_directory() . '/siteorigin-page-builder-layouts';
79
+ }
80
+
81
+ // This allows themes and plugins to customize where we look for layouts.
82
+ $layout_folders = apply_filters( 'siteorigin_panels_local_layouts_directories', $layout_folders );
83
+
84
+ $layouts = array();
85
+ foreach ( $layout_folders as $folder ) {
86
+ if ( file_exists( $folder ) && is_dir( $folder ) ) {
87
+ $files = list_files( $folder, 1 );
88
+ if ( empty( $files ) ) {
89
+ continue;
90
+ }
91
+
92
+ foreach ( $files as $file ) {
93
+ // get file mime type
94
+ $mime_type = mime_content_type( $file );
95
+
96
+ // skip non text files.
97
+ if ( strpos( $mime_type, 'text/' ) !== 0 ) {
98
+ continue;
99
+ }
100
+
101
+ // get file contents
102
+ $file_contents = file_get_contents( $file );
103
+
104
+ // json decode
105
+ $panels_data = json_decode( $file_contents, true );
106
+
107
+ if ( ! empty( $panels_data ) ) {
108
+ // get file name by stripping out folder path and .json extension
109
+ $file_name = str_replace( array( $folder . '/', '.json' ), '', $file );
110
+
111
+ // get name: check for id or name else use filename
112
+ $panels_data['id'] = sanitize_title_with_dashes( $this->get_layout_id( $panels_data, $file_name ) );
113
+
114
+ if ( empty( $panels_data['name'] ) ) {
115
+ $panels_data['name'] = $file_name;
116
+ }
117
+
118
+ $panels_data['name'] = sanitize_text_field( $panels_data['name'] );
119
+
120
+ // get screenshot: check for screenshot prop else try use image file with same filename.
121
+ $panels_data['screenshot'] = $this->get_layout_file_screenshot( $panels_data, $folder, $file_name );
122
+
123
+ // set item on layouts array
124
+ $layouts[ $panels_data['id'] ] = $panels_data;
125
+ }
126
+ }
127
+ }
128
+ }
129
+
130
+ return $layouts;
131
+ }
132
+
133
+ private function get_layout_id( $layout_data, $fallback ) {
134
+ if ( ! empty( $layout_data['id'] ) ) {
135
+ return $layout_data['id'];
136
+ } else if ( ! empty( $layout_data['name'] ) ) {
137
+ return $layout_data['name'];
138
+ } else {
139
+ return $fallback;
140
+ }
141
+ }
142
+
143
+ private function get_layout_file_screenshot( $panels_data, $folder_path, $file_name ) {
144
+ if ( ! empty( $panels_data['screenshot'] ) ) {
145
+ return $panels_data['screenshot'];
146
+ } else {
147
+ $paths = glob( $folder_path . "/$file_name.{jpg,jpeg,gif,png}", GLOB_BRACE );
148
+ // Highlander Condition. There can be only one.
149
+ $screenshot_path = empty( $paths ) ? '' : wp_normalize_path( $paths[0] );
150
+ $wp_content_dir = wp_normalize_path( WP_CONTENT_DIR );
151
+ $screenshot_url = '';
152
+ if ( file_exists( $screenshot_path ) &&
153
+ strrpos( $screenshot_path, $wp_content_dir ) === 0 ) {
154
+
155
+ $screenshot_url = str_replace( $wp_content_dir, content_url(), $screenshot_path );
156
+ }
157
+
158
+ return $screenshot_url;
159
+ }
160
+ }
161
+
162
+ /**
163
+ * Gets all the prebuilt layouts.
164
+ */
165
+ function action_get_prebuilt_layouts() {
166
+ if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
167
+ wp_die( __( 'Invalid request.', 'siteorigin-panels' ), 403 );
168
+ }
169
+
170
+ // Get any layouts that the current user could edit.
171
+ header( 'content-type: application/json' );
172
+
173
+ $type = ! empty( $_REQUEST['type'] ) ? $_REQUEST['type'] : 'directory-siteorigin';
174
+ $search = ! empty( $_REQUEST['search'] ) ? trim( strtolower( $_REQUEST['search'] ) ) : '';
175
+ $page_num = ! empty( $_REQUEST['page'] ) ? intval( $_REQUEST['page'] ) : 1;
176
+
177
+ $return = array(
178
+ 'title' => '',
179
+ 'items' => array()
180
+ );
181
+ if ( $type == 'prebuilt' ) {
182
+ $return['title'] = __( 'Theme Defined Layouts', 'siteorigin-panels' );
183
+
184
+ // This is for theme bundled prebuilt directories
185
+ $layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
186
+
187
+ foreach ( $layouts as $id => $vals ) {
188
+ if ( ! empty( $search ) && strpos( strtolower( $vals['name'] ), $search ) === false ) {
189
+ continue;
190
+ }
191
+
192
+ $return['items'][] = array(
193
+ 'title' => $vals['name'],
194
+ 'id' => $id,
195
+ 'type' => 'prebuilt',
196
+ 'description' => isset( $vals['description'] ) ? $vals['description'] : '',
197
+ 'screenshot' => ! empty( $vals['screenshot'] ) ? $vals['screenshot'] : ''
198
+ );
199
+ }
200
+
201
+ $return['max_num_pages'] = 1;
202
+ } elseif ( substr( $type, 0, 10 ) == 'directory-' ) {
203
+ $return['title'] = __( 'Layouts Directory', 'siteorigin-panels' );
204
+
205
+ // This is a query of the prebuilt layout directory
206
+ $query = array();
207
+ if ( ! empty( $search ) ) {
208
+ $query['search'] = $search;
209
+ }
210
+ $query['page'] = $page_num;
211
+
212
+ $directory_id = str_replace( 'directory-', '', $type );
213
+ $directories = $this->get_directories();
214
+ $directory = ! empty( $directories[ $directory_id ] ) ? $directories[ $directory_id ] : false;
215
+
216
+ if( empty( $directory ) ) {
217
+ return false;
218
+ }
219
+
220
+ $url = add_query_arg( $query, $directory[ 'url' ] . 'wp-admin/admin-ajax.php?action=query_layouts' );
221
+ if( ! empty( $directory[ 'args' ] ) && is_array( $directory[ 'args' ] ) ) {
222
+ $url = add_query_arg( $directory[ 'args' ], $url );
223
+ }
224
+
225
+ $url = apply_filters( 'siteorigin_panels_layouts_directory_url', $url );
226
+ $response = wp_remote_get( $url );
227
+
228
+ if ( is_array( $response ) && $response['response']['code'] == 200 ) {
229
+ $results = json_decode( $response['body'], true );
230
+ if ( ! empty( $results ) && ! empty( $results['items'] ) ) {
231
+ foreach ( $results['items'] as $item ) {
232
+ $item['id'] = $item['slug'];
233
+ $item['type'] = $type;
234
+
235
+ if( empty( $item['screenshot'] ) && ! empty( $item['preview'] ) ) {
236
+ $preview_url = add_query_arg( 'screenshot', 'true', $item[ 'preview' ] );
237
+ $item['screenshot'] = 'https://s.wordpress.com/mshots/v1/' . urlencode( $preview_url ) . '?w=700';
238
+ }
239
+
240
+ $return['items'][] = $item;
241
+ }
242
+ }
243
+
244
+ $return['max_num_pages'] = $results['max_num_pages'];
245
+ }
246
+ } elseif ( strpos( $type, 'clone_' ) !== false ) {
247
+ // Check that the user can view the given page types
248
+ $post_type = get_post_type_object( str_replace( 'clone_', '', $type ) );
249
+ if( empty( $post_type ) ) {
250
+ return;
251
+ }
252
+
253
+ $return['title'] = sprintf( __( 'Clone %s', 'siteorigin-panels' ), esc_html( $post_type->labels->singular_name ) );
254
+
255
+ global $wpdb;
256
+ $user_can_read_private = ( $post_type == 'post' && current_user_can( 'read_private_posts' ) || ( $post_type == 'page' && current_user_can( 'read_private_pages' ) ) );
257
+ $include_private = $user_can_read_private ? "OR posts.post_status = 'private' " : "";
258
+
259
+ // Select only the posts with the given post type that also have panels_data
260
+ $results = $wpdb->get_results( "
261
+ SELECT SQL_CALC_FOUND_ROWS DISTINCT ID, post_title, meta.meta_value
262
+ FROM {$wpdb->posts} AS posts
263
+ JOIN {$wpdb->postmeta} AS meta ON posts.ID = meta.post_id
264
+ WHERE
265
+ posts.post_type = '" . esc_sql( $post_type->name ) . "'
266
+ AND meta.meta_key = 'panels_data'
267
+ " . ( ! empty( $search ) ? 'AND posts.post_title LIKE "%' . esc_sql( $search ) . '%"' : '' ) . "
268
+ AND ( posts.post_status = 'publish' OR posts.post_status = 'draft' " . $include_private . ")
269
+ ORDER BY post_date DESC
270
+ LIMIT 16 OFFSET " . intval( ( $page_num - 1 ) * 16 ) );
271
+ $total_posts = $wpdb->get_var( "SELECT FOUND_ROWS();" );
272
+
273
+ foreach ( $results as $result ) {
274
+ $thumbnail = get_the_post_thumbnail_url( $result->ID, array( 400, 300 ) );
275
+ $return['items'][] = array(
276
+ 'id' => $result->ID,
277
+ 'title' => $result->post_title,
278
+ 'type' => $type,
279
+ 'screenshot' => ! empty( $thumbnail ) ? $thumbnail : ''
280
+ );
281
+ }
282
+
283
+ $return['max_num_pages'] = ceil( $total_posts / 16 );
284
+
285
+ } else {
286
+ // An invalid type. Display an error message.
287
+ }
288
+
289
+ // Add the search part to the title
290
+ if ( ! empty( $search ) ) {
291
+ $return['title'] .= __( ' - Results For:', 'siteorigin-panels' ) . ' <em>' . esc_html( $search ) . '</em>';
292
+ }
293
+
294
+ echo json_encode( $return );
295
+
296
+ wp_die();
297
+ }
298
+
299
+ /**
300
+ * Ajax handler to get an individual prebuilt layout
301
+ */
302
+ function action_get_prebuilt_layout() {
303
+ if ( empty( $_REQUEST['type'] ) ) {
304
+ wp_die();
305
+ }
306
+ if ( empty( $_REQUEST['lid'] ) ) {
307
+ wp_die();
308
+ }
309
+ if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
310
+ wp_die();
311
+ }
312
+
313
+ header( 'content-type: application/json' );
314
+ $panels_data = array();
315
+ $raw_panels_data = false;
316
+
317
+ if ( $_REQUEST['type'] == 'prebuilt' ) {
318
+ $layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
319
+ $lid = ! empty( $_REQUEST['lid'] ) ? $_REQUEST['lid'] : false;
320
+
321
+ if ( empty( $lid ) || empty( $layouts[ $lid ] ) ) {
322
+ wp_send_json_error( array(
323
+ 'error' => true,
324
+ 'message' => __( 'Missing layout ID or no such layout exists', 'siteorigin-panels' ),
325
+ ) );
326
+ }
327
+
328
+ $layout = $layouts[ $_REQUEST['lid'] ];
329
+
330
+ // Fix the format of this layout
331
+ if( !empty( $layout[ 'filename' ] ) ) {
332
+ $filename = $layout[ 'filename' ];
333
+ // Only accept filenames that end with .json
334
+ if( substr( $filename, -5, 5 ) === '.json' && file_exists( $filename ) ) {
335
+ $panels_data = json_decode( file_get_contents( $filename ), true );
336
+ $layout[ 'widgets' ] = ! empty( $panels_data[ 'widgets' ] ) ? $panels_data[ 'widgets' ] : array();
337
+ $layout[ 'grids' ] = ! empty( $panels_data[ 'grids' ] ) ? $panels_data[ 'grids' ] : array();
338
+ $layout[ 'grid_cells' ] = ! empty( $panels_data[ 'grid_cells' ] ) ? $panels_data[ 'grid_cells' ] : array();
339
+ }
340
+ }
341
+
342
+ // A theme or plugin could use this to change the data in the layout
343
+ $panels_data = apply_filters( 'siteorigin_panels_prebuilt_layout', $layout, $lid );
344
+
345
+ // Remove all the layout specific attributes
346
+ if ( isset( $panels_data['name'] ) ) unset( $panels_data['name'] );
347
+ if ( isset( $panels_data['screenshot'] ) ) unset( $panels_data['screenshot'] );
348
+ if ( isset( $panels_data['filename'] ) ) unset( $panels_data['filename'] );
349
+
350
+ $raw_panels_data = true;
351
+
352
+ } elseif ( substr( $_REQUEST['type'], 0, 10 ) == 'directory-' ) {
353
+ $directory_id = str_replace( 'directory-', '', $_REQUEST['type'] );
354
+ $directories = $this->get_directories();
355
+ $directory = ! empty( $directories[ $directory_id ] ) ? $directories[ $directory_id ] : false;
356
+
357
+ if( ! empty( $directory ) ) {
358
+ $url = $directory[ 'url' ] . 'layout/' . urlencode( $_REQUEST[ 'lid' ] ) . '/?action=download';
359
+ if( ! empty( $directory[ 'args' ] ) && is_array( $directory[ 'args' ] ) ) {
360
+ $url = add_query_arg( $directory[ 'args' ], $url );
361
+ }
362
+
363
+ $response = wp_remote_get( $url );
364
+ if ( $response['response']['code'] == 200 ) {
365
+ // For now, we'll just pretend to load this
366
+ $panels_data = json_decode( $response['body'], true );
367
+ } else {
368
+ wp_send_json_error( array(
369
+ 'error' => true,
370
+ 'message' => __( 'There was a problem fetching the layout. Please try again later.', 'siteorigin-panels' ),
371
+ ) );
372
+ }
373
+ }
374
+ $raw_panels_data = true;
375
+
376
+ } elseif ( current_user_can( 'edit_post', $_REQUEST['lid'] ) ) {
377
+ $panels_data = get_post_meta( $_REQUEST['lid'], 'panels_data', true );
378
+ }
379
+
380
+ if( $raw_panels_data ) {
381
+ // This panels_data is flagged as raw, so it needs to be processed.
382
+ $panels_data = apply_filters( 'siteorigin_panels_data', $panels_data, false );
383
+ $panels_data['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets( $panels_data['widgets'], array(), true, true );
384
+ }
385
+
386
+ wp_send_json_success( $panels_data );
387
+ }
388
+
389
+ /**
390
+ * Ajax handler to import a layout
391
+ */
392
+ function action_import_layout() {
393
+ if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
394
+ wp_die();
395
+ }
396
+
397
+ if ( ! empty( $_FILES['panels_import_data']['tmp_name'] ) ) {
398
+ header( 'content-type:application/json' );
399
+ $json = file_get_contents( $_FILES['panels_import_data']['tmp_name'] );
400
+ @unlink( $_FILES['panels_import_data']['tmp_name'] );
401
+ echo $json;
402
+ }
403
+ wp_die();
404
+ }
405
+
406
+ /**
407
+ * Export a given layout as a JSON file.
408
+ */
409
+ function action_export_layout() {
410
+ if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
411
+ wp_die();
412
+ }
413
+
414
+ $export_data = wp_unslash( $_POST['panels_export_data'] );
415
+
416
+ $decoded_export_data = json_decode( $export_data, true );
417
+
418
+ if ( ! empty( $decoded_export_data['name'] ) ) {
419
+ $decoded_export_data['id'] = sanitize_title_with_dashes( $decoded_export_data['name'] );
420
+ $filename = $decoded_export_data['id'];
421
+ } else {
422
+ $filename = 'layout-' . date( 'dmY' );
423
+ }
424
+
425
+
426
+ header( 'content-type: application/json' );
427
+ header( "Content-Disposition: attachment; filename=$filename.json" );
428
+
429
+ echo $export_data;
430
+
431
+ wp_die();
432
+ }
433
+
434
+ /**
435
+ * Enable the directory.
436
+ */
437
+ function action_directory_enable() {
438
+ if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
439
+ wp_die();
440
+ }
441
+ $user = get_current_user_id();
442
+ update_user_meta( $user, 'so_panels_directory_enabled', true );
443
+ wp_die();
444
+ }
445
+
446
+ /**
447
+ * Load a layout from a json file
448
+ *
449
+ * @param $id
450
+ * @param $name
451
+ * @param $json_file
452
+ * @param bool $screenshot
453
+ *
454
+ * @return array The data for the layout
455
+ */
456
+ public static function load_layout($id, $name, $json_file, $screenshot = false) {
457
+ $layout_data = json_decode(file_get_contents($json_file), true);
458
+ $layout_data = apply_filters('siteorigin_panels_load_layout_' . $id, $layout_data);
459
+
460
+ $layout_data = array_merge(array(
461
+ 'name' => $name,
462
+ 'screenshot' => $screenshot,
463
+ ), $layout_data);
464
+
465
+ return $layout_data;
466
+ }
467
+ }
inc/admin-widget-dialog.php CHANGED
@@ -1,193 +1,193 @@
1
- <?php
2
-
3
- class SiteOrigin_Panels_Admin_Widget_Dialog {
4
-
5
- function __construct() {
6
- add_filter( 'siteorigin_panels_widgets', array( $this, 'add_recommended_widgets' ) );
7
- add_filter( 'siteorigin_panels_widget_dialog_tabs', array( $this, 'add_widgets_dialog_tabs' ), 20 );
8
- }
9
-
10
- /**
11
- * @return SiteOrigin_Panels_Admin
12
- */
13
- public static function single() {
14
- static $single;
15
- return empty( $single ) ? $single = new self() : $single;
16
- }
17
-
18
- /**
19
- * Add some default recommended widgets.
20
- *
21
- * @param $widgets
22
- *
23
- * @return array
24
- */
25
- function add_recommended_widgets( $widgets ) {
26
-
27
- if ( ! empty( $widgets['WP_Widget_Black_Studio_TinyMCE'] ) ) {
28
- $widgets['WP_Widget_Black_Studio_TinyMCE']['groups'] = array( 'recommended' );
29
- $widgets['WP_Widget_Black_Studio_TinyMCE']['icon'] = 'dashicons dashicons-edit';
30
- }
31
-
32
- if ( siteorigin_panels_setting( 'recommended-widgets' ) ) {
33
- // Add in all the widgets bundle widgets
34
- $widgets = wp_parse_args(
35
- $widgets,
36
- include plugin_dir_path( __FILE__ ) . 'data/widgets-bundle.php'
37
- );
38
- }
39
-
40
- foreach ( $widgets as $class => $data ) {
41
- if ( strpos( $class, 'SiteOrigin_Panels_Widgets_' ) === 0 || strpos( $class, 'SiteOrigin_Panels_Widget_' ) === 0 ) {
42
- $widgets[ $class ]['groups'] = array( 'panels' );
43
- }
44
- }
45
-
46
- if ( ! empty( $widgets['SiteOrigin_Panels_Widgets_Layout'] ) ) {
47
- $widgets['SiteOrigin_Panels_Widgets_Layout']['icon'] = 'dashicons dashicons-analytics';
48
- }
49
-
50
- $wordpress_widgets = array(
51
- 'WP_Widget_Pages',
52
- 'WP_Widget_Links',
53
- 'WP_Widget_Search',
54
- 'WP_Widget_Archives',
55
- 'WP_Widget_Meta',
56
- 'WP_Widget_Calendar',
57
- 'WP_Widget_Text',
58
- 'WP_Widget_Categories',
59
- 'WP_Widget_Recent_Posts',
60
- 'WP_Widget_Recent_Comments',
61
- 'WP_Widget_RSS',
62
- 'WP_Widget_Tag_Cloud',
63
- 'WP_Nav_Menu_Widget',
64
- );
65
-
66
- foreach ( $wordpress_widgets as $wordpress_widget ) {
67
- if ( isset( $widgets[ $wordpress_widget ] ) ) {
68
- $widgets[ $wordpress_widget ]['groups'] = array( 'wordpress' );
69
- $widgets[ $wordpress_widget ]['icon'] = 'dashicons dashicons-wordpress';
70
- }
71
- }
72
-
73
- // Third-party plugins dettection.
74
- foreach ( $widgets as $widget_id => &$widget ) {
75
- if ( strpos( $widget_id, 'WC_' ) === 0 || strpos( $widget_id, 'WooCommerce' ) !== false ) {
76
- $widget['groups'][] = 'woocommerce';
77
- }
78
- if ( strpos( $widget_id, 'BBP_' ) === 0 || strpos( $widget_id, 'BBPress' ) !== false ) {
79
- $widget['groups'][] = 'bbpress';
80
- }
81
- if ( strpos( $widget_id, 'Jetpack' ) !== false || strpos( $widget['title'], 'Jetpack' ) !== false ) {
82
- $widget['groups'][] = 'jetpack';
83
- }
84
- }
85
-
86
- return $widgets;
87
- }
88
-
89
- /**
90
- * Add tabs to the widget dialog
91
- *
92
- * @param $tabs
93
- *
94
- * @return array
95
- */
96
- function add_widgets_dialog_tabs( $tabs ) {
97
-
98
- $tabs['widgets_bundle'] = array(
99
- 'title' => __( 'Widgets Bundle', 'siteorigin-panels' ),
100
- 'filter' => array(
101
- 'groups' => array( 'so-widgets-bundle' )
102
- )
103
- );
104
-
105
- if ( class_exists( 'SiteOrigin_Widgets_Bundle' ) ) {
106
- // Add a message about enabling more widgets
107
- $tabs['widgets_bundle']['message'] = preg_replace(
108
- array(
109
- '/1\{ *(.*?) *\}/'
110
- ),
111
- array(
112
- '<a href="' . admin_url( 'plugins.php?page=so-widgets-plugins' ) . '">$1</a>'
113
- ),
114
- __( 'Enable more widgets in the 1{Widgets Bundle settings}.', 'siteorigin-panels' )
115
- );
116
- } else {
117
- // Add a message about installing the widgets bundle
118
- $tabs['widgets_bundle']['message'] = preg_replace(
119
- '/1\{ *(.*?) *\}/',
120
- '<a href="' . siteorigin_panels_plugin_activation_install_url( 'so-widgets-bundle', __( 'SiteOrigin Widgets Bundle', 'siteorigin-panels' ) ) . '">$1</a>',
121
- __( 'Install the 1{Widgets Bundle} to get extra widgets.', 'siteorigin-panels' )
122
- );
123
- }
124
-
125
- // Add the Widgets Bundle message to the main widgets tab
126
- $tabs[0]['message'] = $tabs['widgets_bundle']['message'];
127
-
128
- $tabs['page_builder'] = array(
129
- 'title' => __( 'Page Builder Widgets', 'siteorigin-panels' ),
130
- 'message' => preg_replace(
131
- array(
132
- '/1\{ *(.*?) *\}/'
133
- ),
134
- array(
135
- '<a href="' . admin_url( 'options-general.php?page=siteorigin_panels' ) . '">$1</a>'
136
- ),
137
- __( 'You can enable the legacy (PB) widgets in the 1{Page Builder settings}.', 'siteorigin-panels' )
138
- ),
139
- 'filter' => array(
140
- 'groups' => array( 'panels' )
141
- )
142
- );
143
-
144
- $tabs['wordpress'] = array(
145
- 'title' => __( 'WordPress Widgets', 'siteorigin-panels' ),
146
- 'filter' => array(
147
- 'groups' => array( 'wordpress' )
148
- )
149
- );
150
-
151
- // Check for woocommerce plugin.
152
- if ( defined( 'WOOCOMMERCE_VERSION' ) ) {
153
- $tabs['woocommerce'] = array(
154
- // TRANSLATORS: The name of WordPress plugin
155
- 'title' => __( 'WooCommerce', 'woocommerce' ),
156
- 'filter' => array(
157
- 'groups' => array( 'woocommerce' )
158
- )
159
- );
160
- }
161
-
162
- // Check for jetpack plugin.
163
- if ( defined( 'JETPACK__VERSION' ) ) {
164
- $tabs['jetpack'] = array(
165
- // TRANSLATORS: The name of WordPress plugin
166
- 'title' => __( 'Jetpack', 'jetpack' ),
167
- 'filter' => array(
168
- 'groups' => array( 'jetpack' )
169
- ),
170
- );
171
- }
172
-
173
- // Check for bbpress plugin.
174
- if ( function_exists( 'bbpress' ) ) {
175
- $tabs['bbpress'] = array(
176
- // TRANSLATORS: The name of WordPress plugin
177
- 'title' => __( 'BBPress', 'bbpress' ),
178
- 'filter' => array(
179
- 'groups' => array( 'bbpress' )
180
- ),
181
- );
182
- }
183
-
184
- $tabs['recommended'] = array(
185
- 'title' => __( 'Recommended Widgets', 'siteorigin-panels' ),
186
- 'filter' => array(
187
- 'groups' => array( 'recommended' )
188
- )
189
- );
190
-
191
- return $tabs;
192
- }
193
- }
1
+ <?php
2
+
3
+ class SiteOrigin_Panels_Admin_Widget_Dialog {
4
+
5
+ function __construct() {
6
+ add_filter( 'siteorigin_panels_widgets', array( $this, 'add_recommended_widgets' ) );
7
+ add_filter( 'siteorigin_panels_widget_dialog_tabs', array( $this, 'add_widgets_dialog_tabs' ), 20 );
8
+ }
9
+
10
+ /**
11
+ * @return SiteOrigin_Panels_Admin
12
+ */
13
+ public static function single() {
14
+ static $single;
15
+ return empty( $single ) ? $single = new self() : $single;
16
+ }
17
+
18
+ /**
19
+ * Add some default recommended widgets.
20
+ *
21
+ * @param $widgets
22
+ *
23
+ * @return array
24
+ */
25
+ function add_recommended_widgets( $widgets ) {
26
+
27
+ if ( ! empty( $widgets['WP_Widget_Black_Studio_TinyMCE'] ) ) {
28
+ $widgets['WP_Widget_Black_Studio_TinyMCE']['groups'] = array( 'recommended' );
29
+ $widgets['WP_Widget_Black_Studio_TinyMCE']['icon'] = 'dashicons dashicons-edit';
30
+ }
31
+
32
+ if ( siteorigin_panels_setting( 'recommended-widgets' ) ) {
33
+ // Add in all the widgets bundle widgets
34
+ $widgets = wp_parse_args(
35
+ $widgets,
36
+ include plugin_dir_path( __FILE__ ) . 'data/widgets-bundle.php'
37
+ );
38
+ }
39
+
40
+ foreach ( $widgets as $class => $data ) {
41
+ if ( strpos( $class, 'SiteOrigin_Panels_Widgets_' ) === 0 || strpos( $class, 'SiteOrigin_Panels_Widget_' ) === 0 ) {
42
+ $widgets[ $class ]['groups'] = array( 'panels' );
43
+ }
44
+ }
45
+
46
+ if ( ! empty( $widgets['SiteOrigin_Panels_Widgets_Layout'] ) ) {
47
+ $widgets['SiteOrigin_Panels_Widgets_Layout']['icon'] = 'dashicons dashicons-analytics';
48
+ }
49
+
50
+ $wordpress_widgets = array(
51
+ 'WP_Widget_Pages',
52
+ 'WP_Widget_Links',
53
+ 'WP_Widget_Search',
54
+ 'WP_Widget_Archives',
55
+ 'WP_Widget_Meta',
56
+ 'WP_Widget_Calendar',
57
+ 'WP_Widget_Text',
58
+ 'WP_Widget_Categories',
59
+ 'WP_Widget_Recent_Posts',
60
+ 'WP_Widget_Recent_Comments',
61
+ 'WP_Widget_RSS',
62
+ 'WP_Widget_Tag_Cloud',
63
+ 'WP_Nav_Menu_Widget',
64
+ );
65
+
66
+ foreach ( $wordpress_widgets as $wordpress_widget ) {
67
+ if ( isset( $widgets[ $wordpress_widget ] ) ) {
68
+ $widgets[ $wordpress_widget ]['groups'] = array( 'wordpress' );
69
+ $widgets[ $wordpress_widget ]['icon'] = 'dashicons dashicons-wordpress';
70
+ }
71
+ }
72
+
73
+ // Third-party plugins dettection.
74
+ foreach ( $widgets as $widget_id => &$widget ) {
75
+ if ( strpos( $widget_id, 'WC_' ) === 0 || strpos( $widget_id, 'WooCommerce' ) !== false ) {
76
+ $widget['groups'][] = 'woocommerce';
77
+ }
78
+ if ( strpos( $widget_id, 'BBP_' ) === 0 || strpos( $widget_id, 'BBPress' ) !== false ) {
79
+ $widget['groups'][] = 'bbpress';
80
+ }
81
+ if ( strpos( $widget_id, 'Jetpack' ) !== false || strpos( $widget['title'], 'Jetpack' ) !== false ) {
82
+ $widget['groups'][] = 'jetpack';
83
+ }
84
+ }
85
+
86
+ return $widgets;
87
+ }
88
+
89
+ /**
90
+ * Add tabs to the widget dialog
91
+ *
92
+ * @param $tabs
93
+ *
94
+ * @return array
95
+ */
96
+ function add_widgets_dialog_tabs( $tabs ) {
97
+
98
+ $tabs['widgets_bundle'] = array(
99
+ 'title' => __( 'Widgets Bundle', 'siteorigin-panels' ),
100
+ 'filter' => array(
101
+ 'groups' => array( 'so-widgets-bundle' )
102
+ )
103
+ );
104
+
105
+ if ( class_exists( 'SiteOrigin_Widgets_Bundle' ) ) {
106
+ // Add a message about enabling more widgets
107
+ $tabs['widgets_bundle']['message'] = preg_replace(
108
+ array(
109
+ '/1\{ *(.*?) *\}/'
110
+ ),
111
+ array(
112
+ '<a href="' . admin_url( 'plugins.php?page=so-widgets-plugins' ) . '">$1</a>'
113
+ ),
114
+ __( 'Enable more widgets in the 1{Widgets Bundle settings}.', 'siteorigin-panels' )
115
+ );
116
+ } else {
117
+ // Add a message about installing the widgets bundle
118
+ $tabs['widgets_bundle']['message'] = preg_replace(
119
+ '/1\{ *(.*?) *\}/',
120
+ '<a href="' . siteorigin_panels_plugin_activation_install_url( 'so-widgets-bundle', __( 'SiteOrigin Widgets Bundle', 'siteorigin-panels' ) ) . '">$1</a>',
121
+ __( 'Install the 1{Widgets Bundle} to get extra widgets.', 'siteorigin-panels' )
122
+ );
123
+ }
124
+
125
+ // Add the Widgets Bundle message to the main widgets tab
126
+ $tabs[0]['message'] = $tabs['widgets_bundle']['message'];
127
+
128
+ $tabs['page_builder'] = array(
129
+ 'title' => __( 'Page Builder Widgets', 'siteorigin-panels' ),
130
+ 'message' => preg_replace(
131
+ array(
132
+ '/1\{ *(.*?) *\}/'
133
+ ),
134
+ array(
135
+ '<a href="' . admin_url( 'options-general.php?page=siteorigin_panels' ) . '">$1</a>'
136
+ ),
137
+ __( 'You can enable the legacy (PB) widgets in the 1{Page Builder settings}.', 'siteorigin-panels' )
138
+ ),
139
+ 'filter' => array(
140
+ 'groups' => array( 'panels' )
141
+ )
142
+ );
143
+
144
+ $tabs['wordpress'] = array(
145
+ 'title' => __( 'WordPress Widgets', 'siteorigin-panels' ),
146
+ 'filter' => array(
147
+ 'groups' => array( 'wordpress' )
148
+ )
149
+ );
150
+
151
+ // Check for woocommerce plugin.
152
+ if ( defined( 'WOOCOMMERCE_VERSION' ) ) {
153
+ $tabs['woocommerce'] = array(
154
+ // TRANSLATORS: The name of WordPress plugin
155
+ 'title' => __( 'WooCommerce', 'woocommerce' ),
156
+ 'filter' => array(
157
+ 'groups' => array( 'woocommerce' )
158
+ )
159
+ );
160
+ }
161
+
162
+ // Check for jetpack plugin.
163
+ if ( defined( 'JETPACK__VERSION' ) ) {
164
+ $tabs['jetpack'] = array(
165
+ // TRANSLATORS: The name of WordPress plugin
166
+ 'title' => __( 'Jetpack', 'jetpack' ),
167
+ 'filter' => array(
168
+ 'groups' => array( 'jetpack' )
169
+ ),
170
+ );
171
+ }
172
+
173
+ // Check for bbpress plugin.
174
+ if ( function_exists( 'bbpress' ) ) {
175
+ $tabs['bbpress'] = array(
176
+ // TRANSLATORS: The name of WordPress plugin
177
+ 'title' => __( 'BBPress', 'bbpress' ),
178
+ 'filter' => array(
179
+ 'groups' => array( 'bbpress' )
180
+ ),
181
+ );
182
+ }
183
+
184
+ $tabs['recommended'] = array(
185
+ 'title' => __( 'Recommended Widgets', 'siteorigin-panels' ),
186
+ 'filter' => array(
187
+ 'groups' => array( 'recommended' )
188
+ )
189
+ );
190
+
191
+ return $tabs;
192
+ }
193
+ }
inc/admin.php CHANGED
@@ -1,1188 +1,1188 @@
1
- <?php
2
-
3
- /**
4
- * Class SiteOrigin_Panels_Admin
5
- *
6
- * Handles all the admin and database interactions.
7
- */
8
- class SiteOrigin_Panels_Admin {
9
-
10
- /**
11
- * @var bool Store that we're in the save post action, to prevent infinite loops
12
- */
13
- private $in_save_post;
14
-
15
- function __construct() {
16
-
17
- add_action( 'plugin_action_links_siteorigin-panels/siteorigin-panels.php', array(
18
- $this,
19
- 'plugin_action_links'
20
- ) );
21
-
22
- add_action( 'current_screen', array( $this, 'admin_init' ) );
23
-
24
- add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ) );
25
- add_action( 'admin_init', array( $this, 'save_home_page' ) );
26
- add_action( 'save_post', array( $this, 'save_post' ) );
27
-
28
- add_action( 'after_switch_theme', array( $this, 'update_home_on_theme_change' ) );
29
-
30
- // Enqueuing admin scripts
31
- add_action( 'admin_print_scripts-post-new.php', array( $this, 'enqueue_admin_scripts' ) );
32
- add_action( 'admin_print_scripts-post.php', array( $this, 'enqueue_admin_scripts' ) );
33
- add_action( 'admin_print_scripts-appearance_page_so_panels_home_page', array(
34
- $this,
35
- 'enqueue_admin_scripts'
36
- ) );
37
- add_action( 'admin_print_scripts-widgets.php', array( $this, 'enqueue_admin_scripts' ) );
38
- add_action( 'admin_print_scripts-edit.php', array( $this, 'footer_column_css' ) );
39
-
40
- // Enqueue the admin styles
41
- add_action( 'admin_print_styles-post-new.php', array( $this, 'enqueue_admin_styles' ) );
42
- add_action( 'admin_print_styles-post.php', array( $this, 'enqueue_admin_styles' ) );
43
- add_action( 'admin_print_styles-appearance_page_so_panels_home_page', array( $this, 'enqueue_admin_styles' ) );
44
- add_action( 'admin_print_styles-widgets.php', array( $this, 'enqueue_admin_styles' ) );
45
-
46
- // The help tab
47
- add_action( 'load-page.php', array( $this, 'add_help_tab' ), 12 );
48
- add_action( 'load-post-new.php', array( $this, 'add_help_tab' ), 12 );
49
- add_action( 'load-appearance_page_so_panels_home_page', array( $this, 'add_help_tab' ), 12 );
50
-
51
- add_action( 'customize_controls_print_footer_scripts', array( $this, 'js_templates' ) );
52
-
53
- // Register all the admin actions
54
- add_action( 'wp_ajax_so_panels_builder_content', array( $this, 'action_builder_content' ) );
55
- add_action( 'wp_ajax_so_panels_widget_form', array( $this, 'action_widget_form' ) );
56
- add_action( 'wp_ajax_so_panels_live_editor_preview', array( $this, 'action_live_editor_preview' ) );
57
-
58
- // Initialize the additional admin classes.
59
- SiteOrigin_Panels_Admin_Widget_Dialog::single();
60
- SiteOrigin_Panels_Admin_Widgets_Bundle::single();
61
- SiteOrigin_Panels_Admin_Layouts::single();
62
-
63
- $this->in_save_post = false;
64
-
65
- add_filter( 'gutenberg_can_edit_post_type', array( $this, 'disable_gutenberg_for_panels_posts' ), 10, 2 );
66
- add_filter( 'filter_gutenberg_meta_boxes', array( $this, 'disable_panels_for_gutenberg_posts' ) );
67
- }
68
-
69
- /**
70
- * @return SiteOrigin_Panels_Admin
71
- */
72
- public static function single() {
73
- static $single;
74
- return empty( $single ) ? $single = new self() : $single;
75
- }
76
-
77
- /**
78
- * Do some general admin initialization
79
- */
80
- public function admin_init(){
81
- if( siteorigin_panels_setting( 'admin-widget-count' ) ) {
82
-
83
- // Add the custom columns
84
- $post_types = siteorigin_panels_setting( 'post-types' );
85
- if( ! empty( $post_types ) ) {
86
- foreach( $post_types as $post_type ) {
87
- add_filter( 'manage_' . $post_type . 's_columns' , array( $this, 'add_custom_column' ) );
88
- add_action( 'manage_' . $post_type . 's_custom_column' , array( $this, 'display_custom_column' ), 10, 2 );
89
- }
90
- }
91
- }
92
-
93
- if( self::is_admin() ) {
94
- // Setup everything for Page Builder learning as long as we're viewing a Page Builder page
95
- SiteOrigin_Learn_Dialog::single();
96
- add_filter( 'siteorigin_learn_lessons', array( $this, 'filter_learn_lessons' ) );
97
- add_filter( 'siteorigin_learn_strings', array( $this, 'filter_learn_strings' ), 99 );
98
- }
99
- }
100
-
101
- /**
102
- * Check if this is an admin page.
103
- *
104
- * @return mixed|void
105
- */
106
- static function is_admin() {
107
- $screen = get_current_screen();
108
- $is_panels_page = ( $screen->base == 'post' && in_array( $screen->id, siteorigin_panels_setting( 'post-types' ) ) ) || $screen->base == 'appearance_page_so_panels_home_page' || $screen->base == 'widgets' || $screen->base == 'customize';
109
-
110
- return apply_filters( 'siteorigin_panels_is_admin_page', $is_panels_page );
111
- }
112
-
113
- /**
114
- * Add action links to the plugin list for Page Builder.
115
- *
116
- * @param $links
117
- *
118
- * @return array
119
- */
120
- function plugin_action_links( $links ) {
121
- if( ! is_array( $links ) ) {
122
- return $links;
123
- }
124
-
125
- unset( $links['edit'] );
126
- $links[] = '<a href="http://siteorigin.com/threads/plugin-page-builder/">' . __( 'Support Forum', 'siteorigin-panels' ) . '</a>';
127
- $links[] = '<a href="http://siteorigin.com/page-builder/#newsletter">' . __( 'Newsletter', 'siteorigin-panels' ) . '</a>';
128
-
129
- if( SiteOrigin_Panels::display_premium_teaser() ) {
130
- $links[] = '<a href="' . esc_url( SiteOrigin_Panels::premium_url() ) . '" style="color: #3db634" target="_blank" rel="noopener noreferrer">' . __('Addons', 'siteorigin-panels') . '</a>';
131
- }
132
-
133
- return $links;
134
- }
135
-
136
- /**
137
- * Callback to register the Page Builder Metaboxes
138
- */
139
- function add_meta_boxes() {
140
- foreach ( siteorigin_panels_setting( 'post-types' ) as $type ) {
141
- add_meta_box(
142
- 'so-panels-panels',
143
- __( 'Page Builder', 'siteorigin-panels' ),
144
- array( $this, 'render_meta_boxes' ),
145
- ( string ) $type,
146
- 'advanced',
147
- 'high'
148
- );
149
- }
150
- }
151
-
152
- /**
153
- * Render a panel metabox.
154
- *
155
- * @param $post
156
- */
157
- function render_meta_boxes( $post ) {
158
- $panels_data = $this->get_current_admin_panels_data();
159
- include plugin_dir_path( __FILE__ ) . '../tpl/metabox-panels.php';
160
- }
161
-
162
- /**
163
- * Save the panels data
164
- *
165
- * @param $post_id
166
- * @param $post
167
- *
168
- * @action save_post
169
- */
170
- function save_post( $post_id ) {
171
- // Check that everything is valid with this save.
172
- if(
173
- $this->in_save_post ||
174
- ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) ||
175
- empty( $_POST['_sopanels_nonce'] ) ||
176
- ! wp_verify_nonce( $_POST['_sopanels_nonce'], 'save' ) ||
177
- ! current_user_can( 'edit_post', $post_id ) ||
178
- ! isset( $_POST['panels_data'] )
179
- ) {
180
- return;
181
- }
182
- $this->in_save_post = true;
183
- // Get post from db as it might have been changed and saved by other plugins.
184
- $post = get_post( $post_id );
185
- $old_panels_data = get_post_meta( $post_id, 'panels_data', true );
186
- $panels_data = json_decode( wp_unslash( $_POST['panels_data'] ), true );
187
-
188
- $panels_data['widgets'] = $this->process_raw_widgets(
189
- $panels_data['widgets'],
190
- ! empty( $old_panels_data['widgets'] ) ? $old_panels_data['widgets'] : false,
191
- false
192
- );
193
- $panels_data = SiteOrigin_Panels_Styles_Admin::single()->sanitize_all( $panels_data );
194
- $panels_data = apply_filters( 'siteorigin_panels_data_pre_save', $panels_data, $post, $post_id );
195
-
196
- if ( ! empty( $panels_data['widgets'] ) || ! empty( $panels_data['grids'] ) ) {
197
- // Use `update_metadata` instead of `update_post_meta` to prevent saving to parent post when it's a revision, e.g. preview.
198
- update_metadata( 'post', $post_id, 'panels_data', map_deep( $panels_data, array( 'SiteOrigin_Panels_Admin', 'double_slash_string' ) ) );
199
-
200
- if( siteorigin_panels_setting( 'copy-content' ) ) {
201
- // Store a version of the HTML in post_content
202
- SiteOrigin_Panels_Post_Content_Filters::add_filters();
203
- $GLOBALS[ 'SITEORIGIN_PANELS_POST_CONTENT_RENDER' ] = true;
204
- $post_content = SiteOrigin_Panels::renderer()->render( $post_id, false, $panels_data );
205
- $post_css = SiteOrigin_Panels::renderer()->generate_css( $post_id, $panels_data );
206
- SiteOrigin_Panels_Post_Content_Filters::remove_filters();
207
- unset( $GLOBALS[ 'SITEORIGIN_PANELS_POST_CONTENT_RENDER' ] );
208
-
209
- // Update the post_content
210
- $post->post_content = $post_content;
211
- if( siteorigin_panels_setting( 'copy-styles' ) ) {
212
- $post->post_content .= "\n\n";
213
- $post->post_content .= '<style type="text/css" class="panels-style" data-panels-style-for-post="' . intval( $post_id ) . '">';
214
- $post->post_content .= '@import url(' . SiteOrigin_Panels::front_css_url() . '); ';
215
- $post->post_content .= $post_css;
216
- $post->post_content .= '</style>';
217
- }
218
- wp_update_post( $post );
219
- }
220
-
221
- } else {
222
- // There are no widgets or rows, so delete the panels data
223
- delete_post_meta( $post_id, 'panels_data' );
224
- }
225
-
226
- $this->in_save_post = false;
227
- }
228
-
229
- /**
230
- * Enqueue the panels admin scripts
231
- *
232
- * @param string $prefix
233
- * @param bool $force Should we force the enqueues
234
- *
235
- * @action admin_print_scripts-post-new.php
236
- * @action admin_print_scripts-post.php
237
- * @action admin_print_scripts-appearance_page_so_panels_home_page
238
- */
239
- function enqueue_admin_scripts( $prefix = '', $force = false ) {
240
- $screen = get_current_screen();
241
- if ( $force || self::is_admin() ) {
242
- // Media is required for row styles
243
- wp_enqueue_media();
244
- wp_enqueue_script(
245
- 'so-panels-admin',
246
- siteorigin_panels_url( 'js/siteorigin-panels' . SITEORIGIN_PANELS_VERSION_SUFFIX . SITEORIGIN_PANELS_JS_SUFFIX . '.js' ),
247
- array(
248
- 'jquery',
249
- 'jquery-ui-resizable',
250
- 'jquery-ui-sortable',
251
- 'jquery-ui-draggable',
252
- 'underscore',
253
- 'backbone',
254
- 'plupload',
255
- 'plupload-all'
256
- ),
257
- SITEORIGIN_PANELS_VERSION,
258
- true
259
- );
260
- add_action( 'admin_footer', array( $this, 'js_templates' ) );
261
-
262
- $widgets = $this->get_widgets();
263
- $directory_enabled = get_user_meta( get_current_user_id(), 'so_panels_directory_enabled', true );
264
-
265
- // This is the widget we'll use for default text
266
- if( ! empty( $widgets[ 'SiteOrigin_Widget_Editor_Widget' ] ) ) $text_widget = 'SiteOrigin_Widget_Editor_Widget';
267
- else if( ! empty( $widgets[ 'WP_Widget_Text' ] ) ) $text_widget = 'WP_Widget_Text';
268
- else $text_widget = false;
269
- $text_widget = apply_filters( 'siteorigin_panels_text_widget_class', $text_widget );
270
-
271
- $user = wp_get_current_user();
272
- wp_localize_script( 'so-panels-admin', 'panelsOptions', array(
273
- 'user' => ! empty( $user ) ? $user->ID : 0,
274
- 'ajaxurl' => wp_nonce_url( admin_url( 'admin-ajax.php' ), 'panels_action', '_panelsnonce' ),
275
- 'widgets' => $widgets,
276
- 'text_widget' => $text_widget,
277
- 'widget_dialog_tabs' => apply_filters( 'siteorigin_panels_widget_dialog_tabs', array(
278
- 0 => array(
279
- 'title' => __( 'All Widgets', 'siteorigin-panels' ),
280
- 'filter' => array(
281
- 'installed' => true,
282
- 'groups' => ''
283
- )
284
- )
285
- ) ),
286
- 'row_layouts' => apply_filters( 'siteorigin_panels_row_layouts', array() ),
287
- 'directory_enabled' => ! empty( $directory_enabled ),
288
- 'copy_content' => siteorigin_panels_setting( 'copy-content' ),
289
- 'cache' => array(),
290
-
291
- // Settings for the contextual menu
292
- 'contextual' => array(
293
- // Developers can change which widgets are displayed by default using this filter
294
- 'default_widgets' => apply_filters( 'siteorigin_panels_contextual_default_widgets', array(
295
- 'SiteOrigin_Widget_Editor_Widget',
296
- 'SiteOrigin_Widget_Button_Widget',
297
- 'SiteOrigin_Widget_Image_Widget',
298
- 'SiteOrigin_Panels_Widgets_Layout',
299
- ) )
300
- ),
301
-
302
- // General localization messages
303
- 'loc' => array(
304
- 'missing_widget' => array(
305
- 'title' => __( 'Missing Widget', 'siteorigin-panels' ),
306
- 'description' => __( "Page Builder doesn't know about this widget.", 'siteorigin-panels' ),
307
- ),
308
- 'time' => array(
309
- // TRANSLATORS: Number of seconds since
310
- 'seconds' => __( '%d seconds', 'siteorigin-panels' ),
311
- // TRANSLATORS: Number of minutes since
312
- 'minutes' => __( '%d minutes', 'siteorigin-panels' ),
313
- // TRANSLATORS: Number of hours since
314
- 'hours' => __( '%d hours', 'siteorigin-panels' ),
315
-
316
- // TRANSLATORS: A single second since
317
- 'second' => __( '%d second', 'siteorigin-panels' ),
318
- // TRANSLATORS: A single minute since
319
- 'minute' => __( '%d minute', 'siteorigin-panels' ),
320
- // TRANSLATORS: A single hour since
321
- 'hour' => __( '%d hour', 'siteorigin-panels' ),
322
-
323
- // TRANSLATORS: Time ago - eg. "1 minute before".
324
- 'ago' => __( '%s before', 'siteorigin-panels' ),
325
- 'now' => __( 'Now', 'siteorigin-panels' ),
326
- ),
327
- 'history' => array(
328
- // History messages
329
- 'current' => __( 'Current', 'siteorigin-panels' ),
330
- 'revert' => __( 'Original', 'siteorigin-panels' ),
331
- 'restore' => __( 'Version restored', 'siteorigin-panels' ),
332
- 'back_to_editor' => __( 'Converted to editor', 'siteorigin-panels' ),
333
-
334
- // Widgets
335
- // TRANSLATORS: Message displayed in the history when a widget is deleted
336
- 'widget_deleted' => __( 'Widget deleted', 'siteorigin-panels' ),
337
- // TRANSLATORS: Message displayed in the history when a widget is added
338
- 'widget_added' => __( 'Widget added', 'siteorigin-panels' ),
339
- // TRANSLATORS: Message displayed in the history when a widget is edited
340
- 'widget_edited' => __( 'Widget edited', 'siteorigin-panels' ),
341
- // TRANSLATORS: Message displayed in the history when a widget is duplicated
342
- 'widget_duplicated' => __( 'Widget duplicated', 'siteorigin-panels' ),
343
- // TRANSLATORS: Message displayed in the history when a widget position is changed
344
- 'widget_moved' => __( 'Widget moved', 'siteorigin-panels' ),
345
-
346
- // Rows
347
- // TRANSLATORS: Message displayed in the history when a row is deleted
348
- 'row_deleted' => __( 'Row deleted', 'siteorigin-panels' ),
349
- // TRANSLATORS: Message displayed in the history when a row is added
350
- 'row_added' => __( 'Row added', 'siteorigin-panels' ),
351
- // TRANSLATORS: Message displayed in the history when a row is edited
352
- 'row_edited' => __( 'Row edited', 'siteorigin-panels' ),
353
- // TRANSLATORS: Message displayed in the history when a row position is changed
354
- 'row_moved' => __( 'Row moved', 'siteorigin-panels' ),
355
- // TRANSLATORS: Message displayed in the history when a row is duplicated
356
- 'row_duplicated' => __( 'Row duplicated', 'siteorigin-panels' ),
357
- // TRANSLATORS: Message displayed in the history when a row is pasted
358
- 'row_pasted' => __( 'Row pasted', 'siteorigin-panels' ),
359
-
360
- // Cells
361
- 'cell_resized' => __( 'Cell resized', 'siteorigin-panels' ),
362
-
363
- // Prebuilt
364
- 'prebuilt_loaded' => __( 'Prebuilt layout loaded', 'siteorigin-panels' ),
365
- ),
366
-
367
- // general localization
368
- 'prebuilt_loading' => __( 'Loading prebuilt layout', 'siteorigin-panels' ),
369
- 'confirm_use_builder' => __( "Would you like to copy this editor's existing content to Page Builder?", 'siteorigin-panels' ),
370
- 'confirm_stop_builder' => __( "Would you like to clear your Page Builder content and revert to using the standard visual editor?", 'siteorigin-panels' ),
371
- // TRANSLATORS: This is the title for a widget called "Layout Builder"
372
- 'layout_widget' => __( 'Layout Builder Widget', 'siteorigin-panels' ),
373
- // TRANSLATORS: A standard confirmation message
374
- 'dropdown_confirm' => __( 'Are you sure?', 'siteorigin-panels' ),
375
- // TRANSLATORS: When a layout file is ready to be inserted. %s is the filename.
376
- 'ready_to_insert' => __( '%s is ready to insert.', 'siteorigin-panels' ),
377
-
378
- // Everything for the contextual menu
379
- 'contextual' => array(
380
- 'add_widget_below' => __( 'Add Widget Below', 'siteorigin-panels' ),
381
- 'add_widget_cell' => __( 'Add Widget to Cell', 'siteorigin-panels' ),
382
- 'search_widgets' => __( 'Search Widgets', 'siteorigin-panels' ),
383
-
384
- 'add_row' => __( 'Add Row', 'siteorigin-panels' ),
385
- 'column' => __( 'Column', 'siteorigin-panels' ),
386
-
387
- 'cell_actions' => __( 'Cell Actions', 'siteorigin-panels' ),
388
- 'cell_paste_widget' => __( 'Paste Widget', 'siteorigin-panels' ),
389
-
390
- 'widget_actions' => __( 'Widget Actions', 'siteorigin-panels' ),
391
- 'widget_edit' => __( 'Edit Widget', 'siteorigin-panels' ),
392
- 'widget_duplicate' => __( 'Duplicate Widget', 'siteorigin-panels' ),
393
- 'widget_delete' => __( 'Delete Widget', 'siteorigin-panels' ),
394
- 'widget_copy' => __( 'Copy Widget', 'siteorigin-panels' ),
395
- 'widget_paste' => __( 'Paste Widget Below', 'siteorigin-panels' ),
396
-
397
- 'row_actions' => __( 'Row Actions', 'siteorigin-panels' ),
398
- 'row_edit' => __( 'Edit Row', 'siteorigin-panels' ),
399
- 'row_duplicate' => __( 'Duplicate Row', 'siteorigin-panels' ),
400
- 'row_delete' => __( 'Delete Row', 'siteorigin-panels' ),
401
- 'row_copy' => __( 'Copy Row', 'siteorigin-panels' ),
402
- 'row_paste' => __( 'Paste Row', 'siteorigin-panels' ),
403
- ),
404
- 'draft' => __( 'Draft', 'siteorigin-panels' ),
405
- 'untitled' => __( 'Untitled', 'siteorigin-panels' ),
406
- 'row' => array(
407
- 'add' => __( 'New Row', 'siteorigin-panels' ),
408
- 'edit' => __( 'Row', 'siteorigin-panels' ),
409
- ),
410
- 'welcomeMessage' => array(
411
- 'addingDisabled' => __( 'Hmmm... Adding layout elements is not enabled. Please check if Page Builder has been configured to allow adding elements.', 'siteorigin-panels' ),
412
- 'oneEnabled' => __( 'Add a {{%= items[0] %}} to get started.', 'siteorigin-panels' ),
413
- 'twoEnabled' => __( 'Add a {{%= items[0] %}} or {{%= items[1] %}} to get started.', 'siteorigin-panels' ),
414
- 'threeEnabled' => __( 'Add a {{%= items[0] %}}, {{%= items[1] %}} or {{%= items[2] %}} to get started.', 'siteorigin-panels' ),
415
- 'addWidgetButton' => "<a href='#' class='so-tool-button so-widget-add'>" . __( 'Widget', 'siteorigin-panels' ) . "</a>",
416
- 'addRowButton' => "<a href='#' class='so-tool-button so-row-add'>" . __( 'Row', 'siteorigin-panels' ) . "</a>",
417
- 'addPrebuiltButton' => "<a href='#' class='so-tool-button so-prebuilt-add'>" . __( 'Prebuilt Layout', 'siteorigin-panels' ) . "</a>",
418
- 'docsMessage' => sprintf(
419
- __( 'Read our %s if you need help.', 'siteorigin-panels' ),
420
- "<a href='https://siteorigin.com/page-builder/documentation/' target='_blank' rel='noopener noreferrer'>" . __( 'documentation', 'siteorigin-panels' ) . "</a>"
421
- ),
422
- ),
423
- ),
424
- 'plupload' => array(
425
- 'max_file_size' => wp_max_upload_size() . 'b',
426
- 'url' => wp_nonce_url( admin_url( 'admin-ajax.php' ), 'panels_action', '_panelsnonce' ),
427
- 'flash_swf_url' => includes_url( 'js/plupload/plupload.flash.swf' ),
428
- 'silverlight_xap_url' => includes_url( 'js/plupload/plupload.silverlight.xap' ),
429
- 'filter_title' => __( 'Page Builder layouts', 'siteorigin-panels' ),
430
- 'error_message' => __( 'Error uploading or importing file.', 'siteorigin-panels' ),
431
- ),
432
- 'wpColorPickerOptions' => apply_filters( 'siteorigin_panels_wpcolorpicker_options', array() ),
433
- 'prebuiltDefaultScreenshot' => siteorigin_panels_url( 'css/images/prebuilt-default.png' ),
434
- 'loadOnAttach' => siteorigin_panels_setting( 'load-on-attach' ),
435
- 'siteoriginWidgetRegex' => str_replace( '*+', '*', get_shortcode_regex( array( 'siteorigin_widget' ) ) ),
436
- ) );
437
-
438
- $js_widgets = array();
439
- if ( $screen->base != 'widgets' ) {
440
- // Render all the widget forms. A lot of widgets use this as a chance to enqueue their scripts
441
- $original_post = isset( $GLOBALS['post'] ) ? $GLOBALS['post'] : null; // Make sure widgets don't change the global post.
442
- global $wp_widget_factory;
443
- foreach ( $wp_widget_factory->widgets as $class => $widget_obj ) {
444
- ob_start();
445
- $return = $widget_obj->form( array() );
446
- // These are the new widgets in WP 4.8 which are largely JS based. They only enqueue their own
447
- // scripts on the 'widgets' screen.
448
- if ( method_exists( $widget_obj, 'enqueue_admin_scripts' ) ) {
449
- $widget_obj->enqueue_admin_scripts();
450
- }
451
- do_action_ref_array( 'in_widget_form', array( &$widget_obj, &$return, array() ) );
452
- ob_end_clean();
453
-
454
- // Need to render templates for new WP 4.8 widgets when not on the 'widgets' screen or in the customizer.
455
- if ( $this->is_js_widget( $widget_obj ) ) {
456
- $js_widgets[] = $widget_obj;
457
- }
458
- }
459
- $GLOBALS['post'] = $original_post;
460
- }
461
-
462
- // This gives panels a chance to enqueue scripts too, without having to check the screen ID.
463
- if ( $screen->base != 'widgets' && $screen->base != 'customize' ) {
464
- foreach ( $js_widgets as $js_widget ) {
465
- $js_widget->render_control_template_scripts();
466
- }
467
- do_action( 'siteorigin_panel_enqueue_admin_scripts' );
468
- do_action( 'sidebar_admin_setup' );
469
- }
470
- }
471
- }
472
-
473
- /**
474
- * Enqueue the admin panel styles
475
- *
476
- * @param string $prefix
477
- * @param bool $force Should we force the enqueue
478
- *
479
- * @action admin_print_styles-post-new.php
480
- * @action admin_print_styles-post.php
481
- */
482
- function enqueue_admin_styles( $prefix = '', $force = false ) {
483
- if ( $force || self::is_admin() ) {
484
- wp_enqueue_style(
485
- 'so-panels-admin',
486
- siteorigin_panels_url( 'css/admin.css' ),
487
- array( 'wp-color-picker' ),
488
- SITEORIGIN_PANELS_VERSION
489
- );
490
- do_action( 'siteorigin_panel_enqueue_admin_styles' );
491
- }
492
- }
493
-
494
- /**
495
- * Add a help tab to pages that include a Page Builder interface.
496
- *
497
- * @param $prefix
498
- */
499
- function add_help_tab( $prefix ) {
500
- $screen = get_current_screen();
501
- if (
502
- ( $screen->base == 'post' && ( in_array( $screen->id, siteorigin_panels_setting( 'post-types' ) ) || $screen->id == '' ) )
503
- || ( $screen->id == 'appearance_page_so_panels_home_page' )
504
- ) {
505
- $screen->add_help_tab( array(
506
- 'id' => 'panels-help-tab', //unique id for the tab
507
- 'title' => __( 'Page Builder', 'siteorigin-panels' ), //unique visible title for the tab
508
- 'callback' => array( $this, 'help_tab_content' )
509
- ) );
510
- }
511
- }
512
-
513
- /**
514
- * Display the content for the help tab.
515
- */
516
- function help_tab_content() {
517
- include plugin_dir_path( __FILE__ ) . '../tpl/help.php';
518
- }
519
-
520
- /**
521
- * Get the Page Builder data for the current admin page.
522
- *
523
- * @return array
524
- */
525
- function get_current_admin_panels_data() {
526
- $screen = get_current_screen();
527
-
528
- // Localize the panels with the panels data
529
- if ( $screen->base == 'appearance_page_so_panels_home_page' ) {
530
- $home_page_id = get_option( 'page_on_front' );
531
- if ( empty( $home_page_id ) ) {
532
- $home_page_id = get_option( 'siteorigin_panels_home_page_id' );
533
- }
534
-
535
- $panels_data = ! empty( $home_page_id ) ? get_post_meta( $home_page_id, 'panels_data', true ) : null;
536
-
537
- if ( is_null( $panels_data ) ) {
538
- // Load the default layout
539
- $layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
540
-
541
- $home_name = siteorigin_panels_setting( 'home-page-default' ) ? siteorigin_panels_setting( 'home-page-default' ) : 'home';
542
- $panels_data = ! empty( $layouts[ $home_name ] ) ? $layouts[ $home_name ] : current( $layouts );
543
- } elseif ( empty( $panels_data ) ) {
544
- // The current page_on_front isn't using page builder
545
- return false;
546
- }
547
-
548
- $panels_data = apply_filters( 'siteorigin_panels_data', $panels_data, 'home' );
549
- } else {
550
- global $post;
551
- $panels_data = get_post_meta( $post->ID, 'panels_data', true );
552
- $panels_data = apply_filters( 'siteorigin_panels_data', $panels_data, $post->ID );
553
- }
554
-
555
- if ( empty( $panels_data ) ) {
556
- $panels_data = array();
557
- }
558
-
559
- return $panels_data;
560
- }
561
-
562
- /**
563
- * Save home page
564
- */
565
- function save_home_page() {
566
- if ( ! isset( $_POST['_sopanels_home_nonce'] ) || ! wp_verify_nonce( $_POST['_sopanels_home_nonce'], 'save' ) ) {
567
- return;
568
- }
569
- if ( ! current_user_can( 'edit_theme_options' ) ) {
570
- return;
571
- }
572
- if ( ! isset( $_POST['panels_data'] ) ) {
573
- return;
574
- }
575
-
576
- // Check that the home page ID is set and the home page exists
577
- $page_id = get_option( 'page_on_front' );
578
- if ( empty( $page_id ) ) {
579
- $page_id = get_option( 'siteorigin_panels_home_page_id' );
580
- }
581
-
582
- $post_content = wp_unslash( $_POST['post_content'] );
583
-
584
- if ( ! $page_id || get_post_meta( $page_id, 'panels_data', true ) == '' ) {
585
- // Lets create a new page
586
- $page_id = wp_insert_post( array(
587
- // TRANSLATORS: This is the default name given to a user's home page
588
- 'post_title' => __( 'Home Page', 'siteorigin-panels' ),
589
- 'post_status' => ! empty( $_POST['siteorigin_panels_home_enabled'] ) ? 'publish' : 'draft',
590
- 'post_type' => 'page',
591
- 'post_content' => $post_content,
592
- 'comment_status' => 'closed',
593
- ) );
594
- update_option( 'page_on_front', $page_id );
595
- update_option( 'siteorigin_panels_home_page_id', $page_id );
596
-
597
- // Action triggered when creating a new home page through the custom home page interface
598
- do_action( 'siteorigin_panels_create_home_page', $page_id );
599
- } else {
600
- // `wp_insert_post` does it's own sanitization, but it seems `wp_update_post` doesn't.
601
- $post_content = sanitize_post_field( 'post_content', $post_content, $page_id, 'db' );
602
-
603
- // Update the post with changed content to save revision if necessary.
604
- wp_update_post( array( 'ID' => $page_id, 'post_content' => $post_content ) );
605
- }
606
-
607
- $page = get_post( $page_id );
608
-
609
- // Save the updated page data
610
- $old_panels_data = get_post_meta( $page_id, 'panels_data', true );
611
- $panels_data = json_decode( wp_unslash( $_POST['panels_data'] ), true );
612
- $panels_data['widgets'] = $this->process_raw_widgets(
613
- $panels_data['widgets'],
614
- ! empty( $old_panels_data['widgets'] ) ? $old_panels_data['widgets'] : false,
615
- false
616
- );
617
- $panels_data = SiteOrigin_Panels_Styles_Admin::single()->sanitize_all( $panels_data );
618
- $panels_data = apply_filters( 'siteorigin_panels_data_pre_save', $panels_data, $page, $page_id );
619
-
620
- update_post_meta( $page_id, 'panels_data', map_deep( $panels_data, array( 'SiteOrigin_Panels_Admin', 'double_slash_string' ) ) );
621
-
622
- $template = get_post_meta( $page_id, '_wp_page_template', true );
623
- $home_template = siteorigin_panels_setting( 'home-template' );
624
- if ( ( $template == '' || $template == 'default' ) && ! empty( $home_template ) ) {
625
- // Set the home page template
626
- update_post_meta( $page_id, '_wp_page_template', $home_template );
627
- }
628
-
629
- if ( ! empty( $_POST['siteorigin_panels_home_enabled'] ) ) {
630
- update_option( 'show_on_front', 'page' );
631
- update_option( 'page_on_front', $page_id );
632
- update_option( 'siteorigin_panels_home_page_id', $page_id );
633
- wp_publish_post( $page_id );
634
- } else {
635
- // We're disabling this home page
636
- update_option( 'show_on_front', 'posts' );
637
-
638
- // Change the post status to draft
639
- $post = get_post( $page_id );
640
- if ( $post->post_status != 'draft' ) {
641
- global $wpdb;
642
-
643
- $wpdb->update( $wpdb->posts, array( 'post_status' => 'draft' ), array( 'ID' => $post->ID ) );
644
- clean_post_cache( $post->ID );
645
-
646
- $old_status = $post->post_status;
647
- $post->post_status = 'draft';
648
- wp_transition_post_status( 'draft', $old_status, $post );
649
-
650
- do_action( 'edit_post', $post->ID, $post );
651
- do_action( "save_post_{$post->post_type}", $post->ID, $post, true );
652
- do_action( 'save_post', $post->ID, $post, true );
653
- do_action( 'wp_insert_post', $post->ID, $post, true );
654
- }
655
- }
656
- }
657
-
658
- /**
659
- * After the theme is switched, change the template on the home page if the theme supports home page functionality.
660
- */
661
- function update_home_on_theme_change() {
662
- $page_id = get_option( 'page_on_front' );
663
- if ( empty( $page_id ) ) {
664
- $page_id = get_option( 'siteorigin_panels_home_page_id' );
665
- }
666
-
667
- if ( siteorigin_panels_setting( 'home-page' ) && siteorigin_panels_setting( 'home-template' ) && $page_id && get_post_meta( $page_id, 'panels_data', true ) !== '' ) {
668
- // Lets update the home page to use the home template that this theme supports
669
- update_post_meta( $page_id, '_wp_page_template', siteorigin_panels_setting( 'home-template' ) );
670
- }
671
- }
672
-
673
- /**
674
- * @return array|mixed|void
675
- */
676
- function get_widgets() {
677
- global $wp_widget_factory;
678
- $widgets = array();
679
- foreach ( $wp_widget_factory->widgets as $class => $widget_obj ) {
680
- $widgets[ $class ] = array(
681
- 'class' => $class,
682
- 'title' => ! empty( $widget_obj->name ) ? $widget_obj->name : __( 'Untitled Widget', 'siteorigin-panels' ),
683
- 'description' => ! empty( $widget_obj->widget_options['description'] ) ? $widget_obj->widget_options['description'] : '',
684
- 'installed' => true,
685
- 'groups' => array(),
686
- );
687
-
688
- // Get Page Builder specific widget options
689
- if ( isset( $widget_obj->widget_options['panels_title'] ) ) {
690
- $widgets[ $class ]['panels_title'] = $widget_obj->widget_options['panels_title'];
691
- }
692
- if ( isset( $widget_obj->widget_options['panels_groups'] ) ) {
693
- $widgets[ $class ]['groups'] = $widget_obj->widget_options['panels_groups'];
694
- }
695
- if ( isset( $widget_obj->widget_options['panels_icon'] ) ) {
696
- $widgets[ $class ]['icon'] = $widget_obj->widget_options['panels_icon'];
697
- }
698
-
699
- }
700
-
701
- // Other plugins can manipulate the list of widgets. Possibly to add recommended widgets
702
- $widgets = apply_filters( 'siteorigin_panels_widgets', $widgets );
703
-
704
- // Sort the widgets alphabetically
705
- uasort( $widgets, array( $this, 'widgets_sorter' ) );
706
-
707
- return $widgets;
708
- }
709
-
710
- /**
711
- * Sorts widgets for get_widgets function by title
712
- *
713
- * @param $a
714
- * @param $b
715
- *
716
- * @return int
717
- */
718
- function widgets_sorter( $a, $b ) {
719
- if ( empty( $a['title'] ) ) {
720
- return - 1;
721
- }
722
- if ( empty( $b['title'] ) ) {
723
- return 1;
724
- }
725
-
726
- return $a['title'] > $b['title'] ? 1 : - 1;
727
- }
728
-
729
- /**
730
- * Process raw widgets that have come from the Page Builder front end.
731
- *
732
- * @param array $widgets An array of widgets from panels_data.
733
- * @param array $old_widgets
734
- * @param bool $escape_classes Should the class names be escaped.
735
- * @param bool $force
736
- *
737
- * @return array
738
- */
739
- function process_raw_widgets( $widgets, $old_widgets = array(), $escape_classes = false, $force = false ) {
740
- if ( empty( $widgets ) || ! is_array( $widgets ) ) {
741
- return array();
742
- }
743
-
744
- global $wp_widget_factory;
745
-
746
- $old_widgets_by_id = array();
747
- if( ! empty( $old_widgets ) ) {
748
- foreach( $old_widgets as $widget ) {
749
- if( ! empty( $widget[ 'panels_info' ][ 'widget_id' ] ) ) {
750
- $old_widgets_by_id[ $widget[ 'panels_info' ][ 'widget_id' ] ] = $widget;
751
- unset( $old_widgets_by_id[ $widget[ 'panels_info' ][ 'widget_id' ] ][ 'panels_info' ] );
752
- }
753
- }
754
- }
755
-
756
- foreach( $widgets as $i => & $widget ) {
757
- if ( ! is_array( $widget ) ) {
758
- continue;
759
- }
760
-
761
- if ( is_array( $widget ) ) {
762
- $info = (array) ( is_array( $widget['panels_info'] ) ? $widget['panels_info'] : $widget['info'] );
763
- } else {
764
- $info = array();
765
- }
766
- unset( $widget['info'] );
767
-
768
- $info[ 'class' ] = apply_filters( 'siteorigin_panels_widget_class', $info[ 'class' ] );
769
-
770
- if ( ! empty( $info['raw'] ) || $force ) {
771
- if ( isset( $wp_widget_factory->widgets[ $info['class'] ] ) && method_exists( $info['class'], 'update' ) ) {
772
-
773
- if(
774
- ! empty( $old_widgets_by_id ) &&
775
- ! empty( $widget[ 'panels_info' ][ 'widget_id' ] ) &&
776
- ! empty( $old_widgets_by_id[ $widget[ 'panels_info' ][ 'widget_id' ] ] )
777
- ){
778
- $old_widget = $old_widgets_by_id[ $widget[ 'panels_info' ][ 'widget_id' ] ];
779
- }
780
- else {
781
- $old_widget = $widget;
782
- }
783
-
784
- /** @var WP_Widget $the_widget */
785
- $the_widget = $wp_widget_factory->widgets[ $info['class'] ];
786
- $instance = $the_widget->update( $widget, $old_widget );
787
- $instance = apply_filters( 'widget_update_callback', $instance, $widget, $old_widget, $the_widget );
788
-
789
- $widget = $instance;
790
- unset( $info['raw'] );
791
- }
792
- }
793
-
794
- if( $escape_classes ) {
795
- // Escaping for namespaced widgets
796
- $info[ 'class' ] = preg_replace( '/\\\\+/', '\\\\\\\\', $info['class'] );
797
- }
798
- $widget['panels_info'] = $info;
799
- }
800
-
801
- return $widgets;
802
- }
803
-
804
- /**
805
- * Add all the footer JS templates.
806
- */
807
- function js_templates() {
808
- include plugin_dir_path( __FILE__ ) . '../tpl/js-templates.php';
809
- }
810
-
811
- /**
812
- * Render a widget form with all the Page Builder specific fields
813
- *
814
- * @param string $widget The class of the widget
815
- * @param array $instance Widget values
816
- * @param bool $raw
817
- * @param string $widget_number
818
- *
819
- * @return mixed|string The form
820
- */
821
- function render_form( $widget, $instance = array(), $raw = false, $widget_number = '{$id}' ) {
822
- global $wp_widget_factory;
823
-
824
- // This is a chance for plugins to replace missing widgets
825
- $the_widget = ! empty( $wp_widget_factory->widgets[ $widget ] ) ? $wp_widget_factory->widgets[ $widget ] : false;
826
- $the_widget = apply_filters( 'siteorigin_panels_widget_object', $the_widget, $widget );
827
-
828
- if ( empty( $the_widget ) || ! is_a( $the_widget, 'WP_Widget' ) ) {
829
- $widgets = $this->get_widgets();
830
-
831
- if ( ! empty( $widgets[ $widget ] ) && ! empty( $widgets[ $widget ]['plugin'] ) ) {
832
- // We know about this widget, show a form about installing it.
833
- $install_url = siteorigin_panels_plugin_activation_install_url( $widgets[ $widget ]['plugin']['slug'], $widgets[ $widget ]['plugin']['name'] );
834
- $form =
835
- '<div class="panels-missing-widget-form">' .
836
- '<p>' .
837
- preg_replace(
838
- array(
839
- '/1\{ *(.*?) *\}/',
840
- '/2\{ *(.*?) *\}/',
841
- ),
842
- array(
843
- '<a href="' . $install_url . '" target="_blank" rel="noopener noreferrer">$1</a>',
844
- '<strong>$1</strong>'
845
- ),
846
- sprintf(
847
- __( 'You need to install 1{%1$s} to use the widget 2{%2$s}.', 'siteorigin-panels' ),
848
- $widgets[ $widget ]['plugin']['name'],
849
- $widget
850
- )
851
- ) .
852
- '</p>' .
853
- '<p>' . __( "Save and reload this page to start using the widget after you've installed it.", 'siteorigin-panels' ) . '</p>' .
854
- '</div>';
855
- } else {
856
- // This widget is missing, so show a missing widgets form.
857
- $form =
858
- '<div class="panels-missing-widget-form"><p>' .
859
- preg_replace(
860
- array(
861
- '/1\{ *(.*?) *\}/',
862
- '/2\{ *(.*?) *\}/',
863
- ),
864
- array(
865
- '<strong>$1</strong>',
866
- '<a href="https://siteorigin.com/thread/" target="_blank" rel="noopener noreferrer">$1</a>'
867
- ),
868
- sprintf(
869
- __( 'The widget 1{%1$s} is not available. Please try locate and install the missing plugin. Post on the 2{support forums} if you need help.', 'siteorigin-panels' ),
870
- esc_html( $widget )
871
- )
872
- ) .
873
- '</p></div>';
874
- }
875
-
876
- // Allow other themes and plugins to change the missing widget form
877
- return apply_filters( 'siteorigin_panels_missing_widget_form', $form, $widget, $instance );
878
- }
879
-
880
- if ( $raw ) {
881
- $instance = $the_widget->update( $instance, $instance );
882
- }
883
-
884
- $the_widget->id = 'temp';
885
- $the_widget->number = $widget_number;
886
-
887
- ob_start();
888
- if ( $this->is_js_widget( $the_widget ) ) {
889
- ?><div class="widget-content"><?php
890
- }
891
- $return = $the_widget->form( $instance );
892
- do_action_ref_array( 'in_widget_form', array( &$the_widget, &$return, $instance ) );
893
- if ( $this->is_js_widget( $the_widget ) ) {
894
- ?>
895
- </div>
896
- <input type="hidden" name="id_base" class="id_base" value="<?php echo esc_attr( $the_widget->id_base ); ?>" />
897
- <?php
898
- }
899
- $form = ob_get_clean();
900
-
901
- // Convert the widget field naming into ones that Page Builder uses
902
- $exp = preg_quote( $the_widget->get_field_name( '____' ) );
903
- $exp = str_replace( '____', '(.*?)', $exp );
904
- $form = preg_replace( '/' . $exp . '/', 'widgets[' . preg_replace( '/\$(\d)/', '\\\$$1', $widget_number ) . '][$1]', $form );
905
-
906
- $form = apply_filters( 'siteorigin_panels_widget_form', $form, $widget, $instance );
907
-
908
- // Add all the information fields
909
- return $form;
910
- }
911
-
912
- function is_js_widget( $widget ) {
913
- $js_widgets = array(
914
- 'WP_Widget_Custom_HTML',
915
- 'WP_Widget_Media_Audio',
916
- 'WP_Widget_Media_Gallery',
917
- 'WP_Widget_Media_Image',
918
- 'WP_Widget_Media_Video',
919
- 'WP_Widget_Text',
920
- );
921
-
922
- $is_js_widget = in_array( get_class( $widget ), $js_widgets ) &&
923
- // Need to check this for `WP_Widget_Text` which was not a JS widget before 4.8
924
- method_exists( $widget, 'render_control_template_scripts' );
925
-
926
- return $is_js_widget;
927
- }
928
-
929
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
930
- // ADMIN AJAX ACTIONS
931
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
932
-
933
- /**
934
- * Get builder content based on the submitted panels_data.
935
- */
936
- function action_builder_content() {
937
- header( 'content-type: text/html' );
938
-
939
- if ( ! current_user_can( 'edit_post', $_POST['post_id'] ) ) {
940
- wp_die();
941
- }
942
-
943
- if ( empty( $_POST['post_id'] ) || empty( $_POST['panels_data'] ) ) {
944
- echo '';
945
- wp_die();
946
- }
947
-
948
- // echo the content
949
- $old_panels_data = get_post_meta( $_POST['post_id'], 'panels_data', true );
950
- $panels_data = json_decode( wp_unslash( $_POST['panels_data'] ), true );
951
- $panels_data['widgets'] = $this->process_raw_widgets(
952
- $panels_data['widgets'],
953
- ! empty( $old_panels_data['widgets'] ) ? $old_panels_data['widgets'] : false,
954
- false
955
- );
956
- $panels_data = SiteOrigin_Panels_Styles_Admin::single()->sanitize_all( $panels_data );
957
-
958
- // Create a version of the builder data for post content
959
- SiteOrigin_Panels_Post_Content_Filters::add_filters();
960
- $GLOBALS[ 'SITEORIGIN_PANELS_POST_CONTENT_RENDER' ] = true;
961
- echo SiteOrigin_Panels::renderer()->render( intval( $_POST['post_id'] ), false, $panels_data );
962
- SiteOrigin_Panels_Post_Content_Filters::remove_filters();
963
- unset( $GLOBALS[ 'SITEORIGIN_PANELS_POST_CONTENT_RENDER' ] );
964
-
965
- wp_die();
966
- }
967
-
968
- /**
969
- * Display a widget form with the provided data
970
- */
971
- function action_widget_form() {
972
- if ( empty( $_REQUEST['widget'] ) ) {
973
- wp_die();
974
- }
975
- if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
976
- wp_die();
977
- }
978
-
979
- $request = array_map( 'stripslashes_deep', $_REQUEST );
980
-
981
- $widget_class = $request['widget'];
982
- $widget_class = apply_filters( 'siteorigin_panels_widget_class', $widget_class );
983
- $instance = ! empty( $request['instance'] ) ? json_decode( $request['instance'], true ) : array();
984
-
985
- $form = $this->render_form( $widget_class, $instance, $_REQUEST['raw'] == 'true' );
986
- $form = apply_filters( 'siteorigin_panels_ajax_widget_form', $form, $widget_class, $instance );
987
-
988
- echo $form;
989
- wp_die();
990
- }
991
-
992
- /**
993
- * Preview in the live editor when there is no public view of the item
994
- */
995
- function action_live_editor_preview() {
996
- if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'live-editor-preview' ) ) {
997
- wp_die();
998
- }
999
-
1000
- include plugin_dir_path( __FILE__ ) . '../tpl/live-editor-preview.php';
1001
-
1002
- exit();
1003
- }
1004
-
1005
- /**
1006
- * Add a column that indicates if a column is powered by Page Builder
1007
- *
1008
- * @param $columns
1009
- *
1010
- * @return array
1011
- */
1012
- function add_custom_column( $columns ){
1013
- $index = array_search( 'comments', array_keys( $columns ) );
1014
-
1015
- if( empty( $index ) ) {
1016
- $columns = array_merge(
1017
- $columns,
1018
- array( 'panels' => __( 'Page Builder', 'siteorigin-panels' ) )
1019
- );
1020
- }
1021
- else {
1022
- $columns = array_slice( $columns, 0, $index, true ) +
1023
- array( 'panels' => __( 'Page Builder', 'siteorigin-panels' ) ) +
1024
- array_slice( $columns, $index, count( $columns ) - 1, true );
1025
- }
1026
-
1027
- return $columns;
1028
- }
1029
-
1030
- function display_custom_column( $column, $post_id ){
1031
- if( $column != 'panels' ) return;
1032
-
1033
- $panels_data = get_post_meta( $post_id, 'panels_data', true );
1034
- if( ! empty( $panels_data['widgets'] ) ) {
1035
- printf( __( '%s Widgets', 'siteorigin-panels' ), count( $panels_data['widgets'] ) );
1036
- }
1037
- else {
1038
- echo '—';
1039
- }
1040
- }
1041
-
1042
- public function footer_column_css(){
1043
- if( siteorigin_panels_setting( 'admin-widget-count' ) ) {
1044
- $screen = get_current_screen();
1045
- $post_types = siteorigin_panels_setting( 'post-types' );
1046
-
1047
- if(
1048
- $screen->base == 'edit' &&
1049
- is_array( $post_types ) &&
1050
- in_array( $screen->post_type, $post_types )
1051
- ){
1052
- ?><style type="text/css">.column-panels{ width: 10% }</style><?php
1053
- }
1054
- }
1055
- }
1056
-
1057
- /**
1058
- * Add double slashes to strings
1059
- *
1060
- * @param $value
1061
- *
1062
- * @return string
1063
- */
1064
- public static function double_slash_string( $value ){
1065
- return is_string( $value ) ? addcslashes( $value, '\\' ) : $value;
1066
- }
1067
-
1068
- public function get_layout_directories(){
1069
-
1070
- }
1071
-
1072
- /**
1073
- * Add all the courses to the learning dialog
1074
- *
1075
- * @param $lessons
1076
- *
1077
- * @return mixed
1078
- */
1079
- public function filter_learn_lessons( $lessons ) {
1080
- $lessons['page-builder-tips'] = array(
1081
- 'title' => __( '12 Page Builder Tips', 'siteorigin-panels' ),
1082
- 'video' => '212380146',
1083
- 'poster' => siteorigin_panels_url( 'posters/page-builder-tips.svg' ),
1084
- 'description' => __( "Sign up to our newsletter and we'll send you this free Page Builder video course.", 'siteorigin-panels' ) . ' ' .
1085
- __( "12 tips that'll help you get the most out of Page Builder.", 'siteorigin-panels' ) . ' ' .
1086
- __( "Watch the video to find out more, then sign up below to get started.", 'siteorigin-panels' ),
1087
- 'form_description' => __( "We'll email you a confirmation. You can unsubscribe at any time.", 'siteorigin-panels' ),
1088
- );
1089
-
1090
- $lessons['page-builder-animations'] = array(
1091
- 'title' => __( 'Free Page Builder Addons', 'siteorigin-panels' ),
1092
- 'video' => '212380210',
1093
- 'poster' => siteorigin_panels_url( 'posters/addons.svg' ),
1094
- 'description' => __( "The free animations addon allows you to add beautiful animations to Page Builder elements.", 'siteorigin-panels' ) . ' ' .
1095
- __( "Sign up to our newsletter and we'll send you the addon as a free gift.", 'siteorigin-panels' ) . ' ' .
1096
- __( "Plus, we'll send you even more powerful addons, for as long as you're subscribed.", 'siteorigin-panels' ),
1097
- 'form_description' => __( "We'll email you a confirmation. You can unsubscribe at any time.", 'siteorigin-panels' ),
1098
- );
1099
-