diff --git a/wp-content/plugins/nextgen-gallery/changelog.txt b/wp-content/plugins/nextgen-gallery/changelog.txt index 81af0c13dcf50d49c09a887e60174d0cab690298..52e63b540bbc3defb5650930fb4a3c03ec866458 100644 --- a/wp-content/plugins/nextgen-gallery/changelog.txt +++ b/wp-content/plugins/nextgen-gallery/changelog.txt @@ -1,6 +1,43 @@ NextGEN Gallery by Imagely += V2.1.49 - 07.26.2016 = +* NEW: Add a "Default" template option to override ATP settings when a global setting is used +* NEW: Added "generic" error reporting back during image upload. +* NEW: Added notice for deprecating PHP 5.2 +* NEW: Option to display child gallery and album descriptions when viewing albums +* Changed: ATP preview images are smaller with tighter margins to show more images +* Changed: Content of Upgrade to Pro page +* Changed: New NextGEN Overview page +* Changed: Replicate gallery name sanitation of NG legacy for gallery paths +* Fixed: Resolved all found PHP warnings/notices/deprecations and strict errors +* Fixed: Compatibility on Windows servers with network mounted document roots +* Fixed: Ensure EXIF meta data is loaded from the appropriate exif_data array instead of exif_array +* Fixed: Gallery Settings toggle not functioning +* Fixed: Uploading breaking when thumbnail or image resizing fails due to lack of specific format support for image libraries +* Fixed: Warning generated in nggallery.php checking useMediaRSS option + += V2.1.46 - 06.23.2016 = +* Fixed: Remove inner nextgen-gallery folder due to build issue + += V2.1.45 - 06.22.2016 = +* Fixed: Freemius assets should not be minified + += V2.1.44 - 06.22.2016 = +* NEW: "Add Gallery" button added next to "Add Media" button on Create/Edit Post screen +* NEW: IGW placeholder images are watermarked +* NEW: Added API for communicating with Lightroom plugin +* NEW: Gulp build system +* NEW: Added "ngg_igw_placeholder_line_2_settings" and "ngg_igw_placeholder_line_1_settings" filters +* NEW: Added "ngg_settings_during_image_generation" filter to adjust image generation +* NEW: Added "ngg_before_save_thumbnail" filter for image manipulation abilities +* NEW: Added the ability to apply GD filters during image generation +* NEW: Integrated with WordPress SEO sitemaps to show include NGG images in image counts +* Changed: Links to manage a gallery after it's been created don't appear in the IGW +* Fixed: Freemius code shouldn't be minified +* Fixed: When a datamapper entity is saved, it's corresponding cache should be cleared +* Fixed: IGW placeholder images aren't used by WordPress SEO's OpenGraph analysis + = V2.1.43 - 05.25.2016 = * NEW: Added Freemius integration * NEW: Added actions actions ngg_updated_image_meta, ngg_recovered_image, ngg_generated_image, ngg_moved_images, and ngg_copied_images @@ -24,7 +61,7 @@ by Imagely * NEW: Added constant NGG_SCRIPT_VERSION that is either the plugin version or rand() should SCRIPT_DEBUG be on * NEW: Added warning when saving galleries and refuse to automatically delete galleries with one or more "../" in their path. * Changed: ATP slug field disallow several characters (spaces, ?, |, &, [, ]) by replacing them with dashes as they are typed -* Changed: Made get_static_url() look in the WP_CONTENT/ngg/(module_name)/static directory for CSS/JS overrides +* Changed: Made get_static_url() look in the WP_CONTENT/ngg/(module_name)/static directory for CSS/JS overrides * Fixed: Bug introduced in 2.1.24 allowing gallery paths & slugs to contain spaces; galleries must be "saved" once to correct them * Fixed: Compatibility with WPML String Translation when uploading images without title or description * Fixed: Made get_image_url() encode gallery directory names 'because%this%is' a valid directory diff --git a/wp-content/plugins/nextgen-gallery/freemius/assets/css/admin/account.css b/wp-content/plugins/nextgen-gallery/freemius/assets/css/admin/account.css index 8044ac690ea0c2a9585f1044a899a0bc65595304..d4d179f146bcd5dc5b3f35e397666107130ae2e8 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/assets/css/admin/account.css +++ b/wp-content/plugins/nextgen-gallery/freemius/assets/css/admin/account.css @@ -1 +1 @@ -#fs_account .postbox,#fs_account .widefat{max-width:700px}#fs_account h3{font-size:1.3em;padding:12px 15px;margin:0 0 12px 0;line-height:1.4;border-bottom:1px solid #F1F1F1}#fs_account i.dashicons{font-size:1.2em;height:1.2em;width:1.2em}#fs_account .button i.dashicons{vertical-align:middle}#fs_account .fs-header-actions{position:absolute;top:17px;right:15px;font-size:0.9em}#fs_account .fs-header-actions ul{margin:0}#fs_account .fs-header-actions li{float:left}#fs_account .fs-header-actions li form{display:inline-block}#fs_account .fs-header-actions li a{text-decoration:none}.rtl #fs_account .fs-header-actions{left:15px;right:auto}.fs-key-value-table{width:100%}.fs-key-value-table form{display:inline-block}.fs-key-value-table tr td:first-child{text-align:right}.fs-key-value-table tr td:first-child nobr{font-weight:bold}.fs-key-value-table tr td:first-child form{display:block}.fs-key-value-table tr td.fs-right{text-align:right}.fs-key-value-table tr.fs-odd{background:#ebebeb}.fs-key-value-table td,.fs-key-value-table th{padding:10px}.fs-key-value-table var,.fs-key-value-table code{color:#0073AA;font-size:16px;background:none}label.fs-tag{background:#ffba00;color:#fff;display:inline-block;border-radius:3px;padding:5px;font-size:11px;line-height:11px;vertical-align:baseline}label.fs-tag.fs-warn{background:#ffba00}label.fs-tag.fs-success{background:#46b450}label.fs-tag.fs-error{background:#dc3232}#fs_addons h3{border:none;margin-bottom:0;padding:4px 5px}#fs_addons td{vertical-align:middle}#fs_addons td:first-child,#fs_addons th:first-child{text-align:left;font-weight:bold}#fs_addons td:last-child,#fs_addons th:last-child{text-align:right}#fs_addons th{font-weight:bold} +#fs_account .postbox,#fs_account .widefat{max-width:700px}#fs_account h3{font-size:1.3em;padding:12px 15px;margin:0 0 12px 0;line-height:1.4;border-bottom:1px solid #F1F1F1}#fs_account i.dashicons{font-size:1.2em;height:1.2em;width:1.2em}#fs_account .button i.dashicons{vertical-align:middle}#fs_account .fs-header-actions{position:absolute;top:17px;right:15px;font-size:0.9em}#fs_account .fs-header-actions ul{margin:0}#fs_account .fs-header-actions li{float:left}#fs_account .fs-header-actions li form{display:inline-block}#fs_account .fs-header-actions li a{text-decoration:none}.rtl #fs_account .fs-header-actions{left:15px;right:auto}.fs-key-value-table{width:100%}.fs-key-value-table form{display:inline-block}.fs-key-value-table tr td:first-child{text-align:right}.fs-key-value-table tr td:first-child nobr{font-weight:bold}.fs-key-value-table tr td:first-child form{display:block}.fs-key-value-table tr td.fs-right{text-align:right}.fs-key-value-table tr.fs-odd{background:#ebebeb}.fs-key-value-table td,.fs-key-value-table th{padding:10px}.fs-key-value-table var,.fs-key-value-table code{color:#0073AA;font-size:16px;background:none}label.fs-tag{background:#ffba00;color:#fff;display:inline-block;border-radius:3px;padding:5px;font-size:11px;line-height:11px;vertical-align:baseline}label.fs-tag.fs-warn{background:#ffba00}label.fs-tag.fs-success{background:#46b450}label.fs-tag.fs-error{background:#dc3232}#fs_addons h3{border:none;margin-bottom:0;padding:4px 5px}#fs_addons td{vertical-align:middle}#fs_addons td:first-child,#fs_addons th:first-child{text-align:left;font-weight:bold}#fs_addons td:last-child,#fs_addons th:last-child{text-align:right}#fs_addons th{font-weight:bold} diff --git a/wp-content/plugins/nextgen-gallery/freemius/assets/css/admin/add-ons.css b/wp-content/plugins/nextgen-gallery/freemius/assets/css/admin/add-ons.css index 0c2df5ab4c87dbc304f0b82068dff136edf072c3..60af6a14c44e59ee3ea3c78acbc8e2a36ff9fae8 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/assets/css/admin/add-ons.css +++ b/wp-content/plugins/nextgen-gallery/freemius/assets/css/admin/add-ons.css @@ -1,2 +1,2 @@ -#fs_addons .fs-cards-list{list-style:none}#fs_addons .fs-cards-list .fs-card{float:left;height:152px;width:310px;padding:0;margin:0 0 30px 30px;font-size:14px;list-style:none;border:1px solid #ddd;cursor:pointer;position:relative}#fs_addons .fs-cards-list .fs-card .fs-overlay{position:absolute;left:0;right:0;bottom:0;top:0;z-index:9}#fs_addons .fs-cards-list .fs-card .fs-inner{background-color:#fff;overflow:hidden;height:100%;position:relative}#fs_addons .fs-cards-list .fs-card .fs-inner ul{-moz-transition:all,0.15s;-o-transition:all,0.15s;-ms-transition:all,0.15s;-webkit-transition:all,0.15s;transition:all,0.15s;left:0;right:0;top:0;position:absolute}#fs_addons .fs-cards-list .fs-card .fs-inner li{list-style:none;line-height:18px;padding:0 15px;width:100%;display:block;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-card-banner{padding:0;margin:0;line-height:0;display:block;height:100px;background-repeat:repeat-x;background-size:100% 100%;-moz-transition:all,0.15s;-o-transition:all,0.15s;-ms-transition:all,0.15s;-webkit-transition:all,0.15s;transition:all,0.15s}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-title{margin:10px 0 0 0;height:18px;overflow:hidden;color:#000;white-space:nowrap;text-overflow:ellipsis;font-weight:bold}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-offer{font-size:0.9em}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-description{background-color:#f9f9f9;padding:10px 15px 100px 15px;border-top:1px solid #eee;margin:0 0 10px 0;color:#777}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-tag{position:absolute;top:10px;right:0px;background:greenyellow;display:block;padding:2px 10px;-moz-box-shadow:1px 1px 1px rgba(0,0,0,0.3);-webkit-box-shadow:1px 1px 1px rgba(0,0,0,0.3);box-shadow:1px 1px 1px rgba(0,0,0,0.3);text-transform:uppercase;font-size:0.9em;font-weight:bold}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-cta .button{position:absolute;top:112px;right:10px}@media screen and (min-width: 960px){#fs_addons .fs-cards-list .fs-card:hover .fs-overlay{border:2px solid #29abe1;margin-left:-1px;margin-top:-1px}#fs_addons .fs-cards-list .fs-card:hover .fs-inner ul{top:-100px}#fs_addons .fs-cards-list .fs-card:hover .fs-inner .fs-title,#fs_addons .fs-cards-list .fs-card:hover .fs-inner .fs-offer{color:#29abe1}} -#TB_window,#TB_window iframe{width:772px !important}#plugin-information #section-description h2,#plugin-information #section-description h3,#plugin-information #section-description p,#plugin-information #section-description b,#plugin-information #section-description i,#plugin-information #section-description blockquote,#plugin-information #section-description li,#plugin-information #section-description ul,#plugin-information #section-description ol{clear:none}#plugin-information #section-description .fs-selling-points{padding-bottom:10px;border-bottom:1px solid #ddd}#plugin-information #section-description .fs-selling-points ul{margin:0}#plugin-information #section-description .fs-selling-points ul li{padding:0;list-style:none outside none}#plugin-information #section-description .fs-selling-points ul li i.dashicons{color:#71ae00;font-size:3em;vertical-align:middle;line-height:30px;float:left;margin:0 0 0 -15px}#plugin-information #section-description .fs-selling-points ul li h3{margin:1em 30px !important}#plugin-information #section-description .fs-screenshots:after{content:"";display:table;clear:both}#plugin-information #section-description .fs-screenshots ul{list-style:none;margin:0}#plugin-information #section-description .fs-screenshots ul li{width:225px;height:225px;float:left;margin-bottom:20px;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}#plugin-information #section-description .fs-screenshots ul li a{display:block;width:100%;height:100%;border:1px solid;-moz-box-shadow:1px 1px 1px rgba(0,0,0,0.2);-webkit-box-shadow:1px 1px 1px rgba(0,0,0,0.2);box-shadow:1px 1px 1px rgba(0,0,0,0.2);background-size:cover}#plugin-information #section-description .fs-screenshots ul li.odd{margin-right:20px}#plugin-information .plugin-information-pricing{margin:-16px;border-bottom:1px solid #ddd}#plugin-information .plugin-information-pricing .fs-plan h3{margin-top:0;padding:20px;font-size:16px}#plugin-information .plugin-information-pricing .fs-plan .nav-tab-wrapper{border-bottom:1px solid #ddd}#plugin-information .plugin-information-pricing .fs-plan .nav-tab-wrapper .nav-tab{cursor:pointer;position:relative;padding:0 10px;font-size:0.9em}#plugin-information .plugin-information-pricing .fs-plan .nav-tab-wrapper .nav-tab label{text-transform:uppercase;color:green;background:greenyellow;position:absolute;left:-1px;right:-1px;bottom:100%;border:1px solid darkgreen;padding:2px;text-align:center;font-size:0.9em;line-height:1em}#plugin-information .plugin-information-pricing .fs-plan .nav-tab-wrapper .nav-tab.nav-tab-active{cursor:default;background:#fffeec;border-bottom-color:#fffeec}#plugin-information .plugin-information-pricing .fs-plan.fs-single-cycle h3{background:#fffeec;margin:0;padding-bottom:0;color:#0073aa}#plugin-information .plugin-information-pricing .fs-plan.fs-single-cycle .nav-tab-wrapper,#plugin-information .plugin-information-pricing .fs-plan.fs-single-cycle .fs-billing-frequency{display:none}#plugin-information .plugin-information-pricing .fs-plan .fs-pricing-body{background:#fffeec;padding:20px}#plugin-information .plugin-information-pricing .fs-plan .button{width:100%;text-align:center;font-weight:bold;text-transform:uppercase;font-size:1.1em}#plugin-information .plugin-information-pricing .fs-plan label{white-space:nowrap}#plugin-information .plugin-information-pricing .fs-plan var{font-style:normal}#plugin-information .plugin-information-pricing .fs-plan .fs-billing-frequency,#plugin-information .plugin-information-pricing .fs-plan .fs-annual-discount{text-align:center;display:block;font-weight:bold;margin-bottom:10px;text-transform:uppercase;background:#F3F3F3;padding:2px;border:1px solid #ccc}#plugin-information .plugin-information-pricing .fs-plan .fs-annual-discount{text-transform:none;color:green;background:greenyellow}#plugin-information .plugin-information-pricing .fs-plan ul.fs-trial-terms{font-size:0.9em}#plugin-information .plugin-information-pricing .fs-plan ul.fs-trial-terms i{float:left;margin:0 0 0 -15px}#plugin-information .plugin-information-pricing .fs-plan ul.fs-trial-terms li{margin:10px 0 0 0}#plugin-information #section-features .fs-features{margin:-20px -26px}#plugin-information #section-features table{width:100%;border-spacing:0;border-collapse:separate}#plugin-information #section-features table thead th{padding:10px 0}#plugin-information #section-features table thead .fs-price{color:#71ae00;font-weight:normal;display:block;text-align:center}#plugin-information #section-features table tbody td{border-top:1px solid #ccc;padding:10px 0;text-align:center;width:100px;color:#71ae00}#plugin-information #section-features table tbody td:first-child{text-align:left;width:auto;color:inherit;padding-left:26px}#plugin-information #section-features table tbody tr.fs-odd td{background:#fefefe}#plugin-information #section-features .dashicons-yes{width:30px;height:30px;font-size:30px}@media screen and (max-width: 961px){#fs_addons .fs-cards-list .fs-card{height:265px}} +#fs_addons .fs-cards-list{list-style:none}#fs_addons .fs-cards-list .fs-card{float:left;height:152px;width:310px;padding:0;margin:0 0 30px 30px;font-size:14px;list-style:none;border:1px solid #ddd;cursor:pointer;position:relative}#fs_addons .fs-cards-list .fs-card .fs-overlay{position:absolute;left:0;right:0;bottom:0;top:0;z-index:9}#fs_addons .fs-cards-list .fs-card .fs-inner{background-color:#fff;overflow:hidden;height:100%;position:relative}#fs_addons .fs-cards-list .fs-card .fs-inner ul{-moz-transition:all,0.15s;-o-transition:all,0.15s;-ms-transition:all,0.15s;-webkit-transition:all,0.15s;transition:all,0.15s;left:0;right:0;top:0;position:absolute}#fs_addons .fs-cards-list .fs-card .fs-inner li{list-style:none;line-height:18px;padding:0 15px;width:100%;display:block;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-card-banner{padding:0;margin:0;line-height:0;display:block;height:100px;background-repeat:repeat-x;background-size:100% 100%;-moz-transition:all,0.15s;-o-transition:all,0.15s;-ms-transition:all,0.15s;-webkit-transition:all,0.15s;transition:all,0.15s}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-title{margin:10px 0 0 0;height:18px;overflow:hidden;color:#000;white-space:nowrap;text-overflow:ellipsis;font-weight:bold}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-offer{font-size:0.9em}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-description{background-color:#f9f9f9;padding:10px 15px 100px 15px;border-top:1px solid #eee;margin:0 0 10px 0;color:#777}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-tag{position:absolute;top:10px;right:0px;background:greenyellow;display:block;padding:2px 10px;-moz-box-shadow:1px 1px 1px rgba(0,0,0,0.3);-webkit-box-shadow:1px 1px 1px rgba(0,0,0,0.3);box-shadow:1px 1px 1px rgba(0,0,0,0.3);text-transform:uppercase;font-size:0.9em;font-weight:bold}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-cta .button{position:absolute;top:112px;right:10px}@media screen and (min-width: 960px){#fs_addons .fs-cards-list .fs-card:hover .fs-overlay{border:2px solid #29abe1;margin-left:-1px;margin-top:-1px}#fs_addons .fs-cards-list .fs-card:hover .fs-inner ul{top:-100px}#fs_addons .fs-cards-list .fs-card:hover .fs-inner .fs-title,#fs_addons .fs-cards-list .fs-card:hover .fs-inner .fs-offer{color:#29abe1}} +#TB_window,#TB_window iframe{width:772px !important}#plugin-information #section-description h2,#plugin-information #section-description h3,#plugin-information #section-description p,#plugin-information #section-description b,#plugin-information #section-description i,#plugin-information #section-description blockquote,#plugin-information #section-description li,#plugin-information #section-description ul,#plugin-information #section-description ol{clear:none}#plugin-information #section-description .fs-selling-points{padding-bottom:10px;border-bottom:1px solid #ddd}#plugin-information #section-description .fs-selling-points ul{margin:0}#plugin-information #section-description .fs-selling-points ul li{padding:0;list-style:none outside none}#plugin-information #section-description .fs-selling-points ul li i.dashicons{color:#71ae00;font-size:3em;vertical-align:middle;line-height:30px;float:left;margin:0 0 0 -15px}#plugin-information #section-description .fs-selling-points ul li h3{margin:1em 30px !important}#plugin-information #section-description .fs-screenshots:after{content:"";display:table;clear:both}#plugin-information #section-description .fs-screenshots ul{list-style:none;margin:0}#plugin-information #section-description .fs-screenshots ul li{width:225px;height:225px;float:left;margin-bottom:20px;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}#plugin-information #section-description .fs-screenshots ul li a{display:block;width:100%;height:100%;border:1px solid;-moz-box-shadow:1px 1px 1px rgba(0,0,0,0.2);-webkit-box-shadow:1px 1px 1px rgba(0,0,0,0.2);box-shadow:1px 1px 1px rgba(0,0,0,0.2);background-size:cover}#plugin-information #section-description .fs-screenshots ul li.odd{margin-right:20px}#plugin-information .plugin-information-pricing{margin:-16px;border-bottom:1px solid #ddd}#plugin-information .plugin-information-pricing .fs-plan h3{margin-top:0;padding:20px;font-size:16px}#plugin-information .plugin-information-pricing .fs-plan .nav-tab-wrapper{border-bottom:1px solid #ddd}#plugin-information .plugin-information-pricing .fs-plan .nav-tab-wrapper .nav-tab{cursor:pointer;position:relative;padding:0 10px;font-size:0.9em}#plugin-information .plugin-information-pricing .fs-plan .nav-tab-wrapper .nav-tab label{text-transform:uppercase;color:green;background:greenyellow;position:absolute;left:-1px;right:-1px;bottom:100%;border:1px solid darkgreen;padding:2px;text-align:center;font-size:0.9em;line-height:1em}#plugin-information .plugin-information-pricing .fs-plan .nav-tab-wrapper .nav-tab.nav-tab-active{cursor:default;background:#fffeec;border-bottom-color:#fffeec}#plugin-information .plugin-information-pricing .fs-plan.fs-single-cycle h3{background:#fffeec;margin:0;padding-bottom:0;color:#0073aa}#plugin-information .plugin-information-pricing .fs-plan.fs-single-cycle .nav-tab-wrapper,#plugin-information .plugin-information-pricing .fs-plan.fs-single-cycle .fs-billing-frequency{display:none}#plugin-information .plugin-information-pricing .fs-plan .fs-pricing-body{background:#fffeec;padding:20px}#plugin-information .plugin-information-pricing .fs-plan .button{width:100%;text-align:center;font-weight:bold;text-transform:uppercase;font-size:1.1em}#plugin-information .plugin-information-pricing .fs-plan label{white-space:nowrap}#plugin-information .plugin-information-pricing .fs-plan var{font-style:normal}#plugin-information .plugin-information-pricing .fs-plan .fs-billing-frequency,#plugin-information .plugin-information-pricing .fs-plan .fs-annual-discount{text-align:center;display:block;font-weight:bold;margin-bottom:10px;text-transform:uppercase;background:#F3F3F3;padding:2px;border:1px solid #ccc}#plugin-information .plugin-information-pricing .fs-plan .fs-annual-discount{text-transform:none;color:green;background:greenyellow}#plugin-information .plugin-information-pricing .fs-plan ul.fs-trial-terms{font-size:0.9em}#plugin-information .plugin-information-pricing .fs-plan ul.fs-trial-terms i{float:left;margin:0 0 0 -15px}#plugin-information .plugin-information-pricing .fs-plan ul.fs-trial-terms li{margin:10px 0 0 0}#plugin-information #section-features .fs-features{margin:-20px -26px}#plugin-information #section-features table{width:100%;border-spacing:0;border-collapse:separate}#plugin-information #section-features table thead th{padding:10px 0}#plugin-information #section-features table thead .fs-price{color:#71ae00;font-weight:normal;display:block;text-align:center}#plugin-information #section-features table tbody td{border-top:1px solid #ccc;padding:10px 0;text-align:center;width:100px;color:#71ae00}#plugin-information #section-features table tbody td:first-child{text-align:left;width:auto;color:inherit;padding-left:26px}#plugin-information #section-features table tbody tr.fs-odd td{background:#fefefe}#plugin-information #section-features .dashicons-yes{width:30px;height:30px;font-size:30px}@media screen and (max-width: 961px){#fs_addons .fs-cards-list .fs-card{height:265px}} diff --git a/wp-content/plugins/nextgen-gallery/freemius/assets/css/admin/common.css b/wp-content/plugins/nextgen-gallery/freemius/assets/css/admin/common.css index e5715b82a2807bb28ef530147c808824a8d1bdfe..f58930c897b23d5000b06473cee01d3186c15f9a 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/assets/css/admin/common.css +++ b/wp-content/plugins/nextgen-gallery/freemius/assets/css/admin/common.css @@ -1 +1 @@ -.fs-notice{position:relative}.fs-notice.fs-has-title{margin-bottom:30px !important}.fs-notice.success{color:green}.fs-notice.promotion{border-color:#00a0d2 !important;background-color:#f2fcff !important}.fs-notice .fs-notice-body{margin:.5em 0;padding:2px}.fs-notice .fs-close{cursor:pointer;color:#aaa;float:right}.fs-notice .fs-close:hover{color:#666}.fs-notice .fs-close>*{margin-top:7px;display:inline-block}.fs-notice label.fs-plugin-title{background:rgba(0,0,0,0.3);color:#fff;padding:2px 10px;position:absolute;top:100%;bottom:auto;right:auto;-moz-border-radius:0 0 3px 3px;-webkit-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px;left:10px;font-size:12px;font-weight:bold;cursor:auto}.rtl .fs-notice .fs-close{float:left}.fs-secure-notice{position:fixed;top:32px;left:160px;right:0;background:#ebfdeb;padding:10px 20px;color:green;z-index:9999;box-shadow:0px 2px 2px rgba(6,113,6,0.3);opacity:0.95;filter:alpha(opacity=95)}.fs-secure-notice:hover{opacity:1;filter:alpha(opacity=100)}@media screen and (max-width: 960px){.fs-secure-notice{left:36px}}@media screen and (max-width: 782px){.fs-secure-notice{left:0;top:46px;text-align:center}}span.fs-submenu-item.fs-sub:before{content:'\21B3';padding:0 5px}.rtl span.fs-submenu-item.fs-sub:before{content:'\21B2'} +.fs-notice{position:relative}.fs-notice.fs-has-title{margin-bottom:30px !important}.fs-notice.success{color:green}.fs-notice.promotion{border-color:#00a0d2 !important;background-color:#f2fcff !important}.fs-notice .fs-notice-body{margin:.5em 0;padding:2px}.fs-notice .fs-close{cursor:pointer;color:#aaa;float:right}.fs-notice .fs-close:hover{color:#666}.fs-notice .fs-close>*{margin-top:7px;display:inline-block}.fs-notice label.fs-plugin-title{background:rgba(0,0,0,0.3);color:#fff;padding:2px 10px;position:absolute;top:100%;bottom:auto;right:auto;-moz-border-radius:0 0 3px 3px;-webkit-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px;left:10px;font-size:12px;font-weight:bold;cursor:auto}.rtl .fs-notice .fs-close{float:left}.fs-secure-notice{position:fixed;top:32px;left:160px;right:0;background:#ebfdeb;padding:10px 20px;color:green;z-index:9999;box-shadow:0px 2px 2px rgba(6,113,6,0.3);opacity:0.95;filter:alpha(opacity=95)}.fs-secure-notice:hover{opacity:1;filter:alpha(opacity=100)}@media screen and (max-width: 960px){.fs-secure-notice{left:36px}}@media screen and (max-width: 782px){.fs-secure-notice{left:0;top:46px;text-align:center}}span.fs-submenu-item.fs-sub:before{content:'\21B3';padding:0 5px}.rtl span.fs-submenu-item.fs-sub:before{content:'\21B2'} diff --git a/wp-content/plugins/nextgen-gallery/freemius/assets/css/admin/connect.css b/wp-content/plugins/nextgen-gallery/freemius/assets/css/admin/connect.css index b81b3df45d0f3f7b5f26329e6076558463f07a75..86ef2146ff8f198179a7eeb9ab7c821027e82aaa 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/assets/css/admin/connect.css +++ b/wp-content/plugins/nextgen-gallery/freemius/assets/css/admin/connect.css @@ -1 +1 @@ -#fs_connect{width:480px;-moz-box-shadow:0px 1px 2px rgba(0,0,0,0.3);-webkit-box-shadow:0px 1px 2px rgba(0,0,0,0.3);box-shadow:0px 1px 2px rgba(0,0,0,0.3);margin:20px 0}@media screen and (max-width: 479px){#fs_connect{-moz-box-shadow:none;-webkit-box-shadow:none;box-shadow:none;width:auto;margin:0 0 0 -10px}}#fs_connect .fs-content{background:#fff;padding:15px 20px}#fs_connect .fs-content p{margin:0;padding:0;font-size:1.2em}#fs_connect .fs-actions{padding:10px 20px;background:#C0C7CA}#fs_connect .fs-actions .button{padding:0 10px 1px;line-height:35px;height:37px;font-size:16px;margin-bottom:0}#fs_connect .fs-actions .button .dashicons{font-size:37px;margin-left:-8px;margin-right:12px}#fs_connect .fs-actions .button.button-primary{padding-right:15px;padding-left:15px}#fs_connect .fs-actions .button.button-primary:after{content:' \279C'}#fs_connect .fs-actions .button.button-primary.fs-loading:after{content:''}#fs_connect .fs-actions .button.button-secondary{float:right}#fs_connect.fs-anonymous-disabled .fs-actions .button.button-primary{width:100%}#fs_connect .fs-permissions{padding:10px 20px;background:#FEFEFE;-moz-transition:background 0.5s ease;-o-transition:background 0.5s ease;-ms-transition:background 0.5s ease;-webkit-transition:background 0.5s ease;transition:background 0.5s ease}#fs_connect .fs-permissions .fs-trigger{font-size:0.9em;text-decoration:none;text-align:center;display:block}#fs_connect .fs-permissions ul{height:0;overflow:hidden;margin:0}#fs_connect .fs-permissions ul li{margin-bottom:12px}#fs_connect .fs-permissions ul li:last-child{margin-bottom:0}#fs_connect .fs-permissions ul li i.dashicons{float:left;font-size:40px;width:40px;height:40px}#fs_connect .fs-permissions ul li div{margin-left:55px}#fs_connect .fs-permissions ul li div span{font-weight:bold;text-transform:uppercase;color:#23282d}#fs_connect .fs-permissions ul li div p{margin:2px 0 0 0}#fs_connect .fs-permissions.fs-open{background:#fff}#fs_connect .fs-permissions.fs-open ul{height:auto;margin:20px 20px 10px 20px}@media screen and (max-width: 479px){#fs_connect .fs-permissions{background:#fff}#fs_connect .fs-permissions .fs-trigger{display:none}#fs_connect .fs-permissions ul{height:auto;margin:20px}}#fs_connect .fs-visual{padding:12px;line-height:0;background:#fafafa;height:80px;position:relative}#fs_connect .fs-visual .fs-site-icon{position:absolute;left:20px;top:10px}#fs_connect .fs-visual .fs-connect-logo{position:absolute;right:20px;top:10px}#fs_connect .fs-visual .fs-plugin-icon{position:absolute;top:10px;left:50%;margin-left:-40px}#fs_connect .fs-visual .fs-plugin-icon,#fs_connect .fs-visual .fs-site-icon,#fs_connect .fs-visual img,#fs_connect .fs-visual object{width:80px;height:80px}#fs_connect .fs-visual .dashicons-wordpress{font-size:64px;background:#01749a;color:#fff;width:64px;height:64px;padding:8px}#fs_connect .fs-visual .dashicons-plus{position:absolute;top:50%;font-size:30px;margin-top:-10px;color:#bbb}#fs_connect .fs-visual .dashicons-plus.fs-first{left:28%}#fs_connect .fs-visual .dashicons-plus.fs-second{left:65%}#fs_connect .fs-visual .fs-plugin-icon,#fs_connect .fs-visual .fs-connect-logo,#fs_connect .fs-visual .fs-site-icon{border:1px solid #ccc;padding:1px;background:#fff}#fs_connect .fs-terms{text-align:center;font-size:0.85em;padding:5px;background:rgba(0,0,0,0.05)}#fs_connect .fs-terms,#fs_connect .fs-terms a{color:#999}#fs_connect .fs-terms a{text-decoration:none}.rtl #fs_connect .fs-actions{padding:10px 20px;background:#C0C7CA}.rtl #fs_connect .fs-actions .button .dashicons{font-size:37px;margin-left:-8px;margin-right:12px}.rtl #fs_connect .fs-actions .button.button-primary:after{content:' \000bb'}.rtl #fs_connect .fs-actions .button.button-primary.fs-loading:after{content:''}.rtl #fs_connect .fs-actions .button.button-secondary{float:left}.rtl #fs_connect .fs-permissions ul li div{margin-right:55px;margin-left:0}.rtl #fs_connect .fs-permissions ul li i.dashicons{float:right}.rtl #fs_connect .fs-visual .fs-site-icon{right:20px;left:auto}.rtl #fs_connect .fs-visual .fs-connect-logo{right:auto;left:20px}.wp-pointer-content #fs_connect{margin:0;-moz-box-shadow:none;-webkit-box-shadow:none;box-shadow:none}.fs-opt-in-pointer .wp-pointer-content{padding:0}.fs-opt-in-pointer.wp-pointer-top .wp-pointer-arrow{border-bottom-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-top .wp-pointer-arrow-inner{border-bottom-color:#fafafa}.fs-opt-in-pointer.wp-pointer-bottom .wp-pointer-arrow{border-top-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-bottom .wp-pointer-arrow-inner{border-top-color:#fafafa}.fs-opt-in-pointer.wp-pointer-left .wp-pointer-arrow{border-right-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-left .wp-pointer-arrow-inner{border-right-color:#fafafa}.fs-opt-in-pointer.wp-pointer-right .wp-pointer-arrow{border-left-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-right .wp-pointer-arrow-inner{border-left-color:#fafafa} +#fs_connect{width:480px;-moz-box-shadow:0px 1px 2px rgba(0,0,0,0.3);-webkit-box-shadow:0px 1px 2px rgba(0,0,0,0.3);box-shadow:0px 1px 2px rgba(0,0,0,0.3);margin:20px 0}@media screen and (max-width: 479px){#fs_connect{-moz-box-shadow:none;-webkit-box-shadow:none;box-shadow:none;width:auto;margin:0 0 0 -10px}}#fs_connect .fs-content{background:#fff;padding:15px 20px}#fs_connect .fs-content p{margin:0;padding:0;font-size:1.2em}#fs_connect .fs-actions{padding:10px 20px;background:#C0C7CA}#fs_connect .fs-actions .button{padding:0 10px 1px;line-height:35px;height:37px;font-size:16px;margin-bottom:0}#fs_connect .fs-actions .button .dashicons{font-size:37px;margin-left:-8px;margin-right:12px}#fs_connect .fs-actions .button.button-primary{padding-right:15px;padding-left:15px}#fs_connect .fs-actions .button.button-primary:after{content:' \279C'}#fs_connect .fs-actions .button.button-primary.fs-loading:after{content:''}#fs_connect .fs-actions .button.button-secondary{float:right}#fs_connect.fs-anonymous-disabled .fs-actions .button.button-primary{width:100%}#fs_connect .fs-permissions{padding:10px 20px;background:#FEFEFE;-moz-transition:background 0.5s ease;-o-transition:background 0.5s ease;-ms-transition:background 0.5s ease;-webkit-transition:background 0.5s ease;transition:background 0.5s ease}#fs_connect .fs-permissions .fs-trigger{font-size:0.9em;text-decoration:none;text-align:center;display:block}#fs_connect .fs-permissions ul{height:0;overflow:hidden;margin:0}#fs_connect .fs-permissions ul li{margin-bottom:12px}#fs_connect .fs-permissions ul li:last-child{margin-bottom:0}#fs_connect .fs-permissions ul li i.dashicons{float:left;font-size:40px;width:40px;height:40px}#fs_connect .fs-permissions ul li div{margin-left:55px}#fs_connect .fs-permissions ul li div span{font-weight:bold;text-transform:uppercase;color:#23282d}#fs_connect .fs-permissions ul li div p{margin:2px 0 0 0}#fs_connect .fs-permissions.fs-open{background:#fff}#fs_connect .fs-permissions.fs-open ul{height:auto;margin:20px 20px 10px 20px}@media screen and (max-width: 479px){#fs_connect .fs-permissions{background:#fff}#fs_connect .fs-permissions .fs-trigger{display:none}#fs_connect .fs-permissions ul{height:auto;margin:20px}}#fs_connect .fs-visual{padding:12px;line-height:0;background:#fafafa;height:80px;position:relative}#fs_connect .fs-visual .fs-site-icon{position:absolute;left:20px;top:10px}#fs_connect .fs-visual .fs-connect-logo{position:absolute;right:20px;top:10px}#fs_connect .fs-visual .fs-plugin-icon{position:absolute;top:10px;left:50%;margin-left:-40px}#fs_connect .fs-visual .fs-plugin-icon,#fs_connect .fs-visual .fs-site-icon,#fs_connect .fs-visual img,#fs_connect .fs-visual object{width:80px;height:80px}#fs_connect .fs-visual .dashicons-wordpress{font-size:64px;background:#01749a;color:#fff;width:64px;height:64px;padding:8px}#fs_connect .fs-visual .dashicons-plus{position:absolute;top:50%;font-size:30px;margin-top:-10px;color:#bbb}#fs_connect .fs-visual .dashicons-plus.fs-first{left:28%}#fs_connect .fs-visual .dashicons-plus.fs-second{left:65%}#fs_connect .fs-visual .fs-plugin-icon,#fs_connect .fs-visual .fs-connect-logo,#fs_connect .fs-visual .fs-site-icon{border:1px solid #ccc;padding:1px;background:#fff}#fs_connect .fs-terms{text-align:center;font-size:0.85em;padding:5px;background:rgba(0,0,0,0.05)}#fs_connect .fs-terms,#fs_connect .fs-terms a{color:#999}#fs_connect .fs-terms a{text-decoration:none}.rtl #fs_connect .fs-actions{padding:10px 20px;background:#C0C7CA}.rtl #fs_connect .fs-actions .button .dashicons{font-size:37px;margin-left:-8px;margin-right:12px}.rtl #fs_connect .fs-actions .button.button-primary:after{content:' \000bb'}.rtl #fs_connect .fs-actions .button.button-primary.fs-loading:after{content:''}.rtl #fs_connect .fs-actions .button.button-secondary{float:left}.rtl #fs_connect .fs-permissions ul li div{margin-right:55px;margin-left:0}.rtl #fs_connect .fs-permissions ul li i.dashicons{float:right}.rtl #fs_connect .fs-visual .fs-site-icon{right:20px;left:auto}.rtl #fs_connect .fs-visual .fs-connect-logo{right:auto;left:20px}.wp-pointer-content #fs_connect{margin:0;-moz-box-shadow:none;-webkit-box-shadow:none;box-shadow:none}.fs-opt-in-pointer .wp-pointer-content{padding:0}.fs-opt-in-pointer.wp-pointer-top .wp-pointer-arrow{border-bottom-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-top .wp-pointer-arrow-inner{border-bottom-color:#fafafa}.fs-opt-in-pointer.wp-pointer-bottom .wp-pointer-arrow{border-top-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-bottom .wp-pointer-arrow-inner{border-top-color:#fafafa}.fs-opt-in-pointer.wp-pointer-left .wp-pointer-arrow{border-right-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-left .wp-pointer-arrow-inner{border-right-color:#fafafa}.fs-opt-in-pointer.wp-pointer-right .wp-pointer-arrow{border-left-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-right .wp-pointer-arrow-inner{border-left-color:#fafafa} diff --git a/wp-content/plugins/nextgen-gallery/freemius/assets/css/admin/debug.css b/wp-content/plugins/nextgen-gallery/freemius/assets/css/admin/debug.css index 48fe92f9b96260c20dcc8842fb87b6c8ad4f6050..63779fb3db062df477688a34c336922ac0033c23 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/assets/css/admin/debug.css +++ b/wp-content/plugins/nextgen-gallery/freemius/assets/css/admin/debug.css @@ -1 +1 @@ -.switch{position:relative;display:inline-block;font-size:1.6em;font-weight:bold;color:#ccc;text-shadow:0px 1px 1px rgba(255,255,255,0.8);height:18px;padding:6px 6px 5px 6px;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);border-radius:4px;background:#ececec;box-shadow:0px 0px 4px rgba(0,0,0,0.1),inset 0px 1px 3px 0px rgba(0,0,0,0.1);cursor:pointer}.switch span{display:inline-block;width:35px;text-transform:uppercase}.switch span.on{color:#6bc406}.switch .toggle{position:absolute;top:1px;width:37px;height:25px;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.3);border-radius:4px;background:#fff;background:-moz-linear-gradient(top, #ececec 0%, #fff 100%);background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #ececec), color-stop(100%, #fff));background:-webkit-linear-gradient(top, #ececec 0%, #fff 100%);background:-o-linear-gradient(top, #ececec 0%, #fff 100%);background:-ms-linear-gradient(top, #ececec 0%, #fff 100%);background:linear-gradient(top, #ececec 0%, #fff 100%);box-shadow:inset 0px 1px 0px 0px rgba(255,255,255,0.5);z-index:999;-moz-transition:all 0.15s ease-in-out;-o-transition:all 0.15s ease-in-out;-ms-transition:all 0.15s ease-in-out;-webkit-transition:all 0.15s ease-in-out;transition:all 0.15s ease-in-out}.switch.on .toggle{left:2%}.switch.off .toggle{left:54%}.switch.round{padding:0px 20px;border-radius:40px}.switch.round .toggle{border-radius:40px;width:14px;height:14px}.switch.round.on .toggle{left:3%;background:#6bc406}.switch.round.off .toggle{left:58%}.switch-label{font-size:20px;line-height:31px;margin:0 5px} +.switch{position:relative;display:inline-block;font-size:1.6em;font-weight:bold;color:#ccc;text-shadow:0px 1px 1px rgba(255,255,255,0.8);height:18px;padding:6px 6px 5px 6px;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);border-radius:4px;background:#ececec;box-shadow:0px 0px 4px rgba(0,0,0,0.1),inset 0px 1px 3px 0px rgba(0,0,0,0.1);cursor:pointer}.switch span{display:inline-block;width:35px;text-transform:uppercase}.switch span.on{color:#6bc406}.switch .toggle{position:absolute;top:1px;width:37px;height:25px;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.3);border-radius:4px;background:#fff;background:-moz-linear-gradient(top, #ececec 0%, #fff 100%);background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #ececec), color-stop(100%, #fff));background:-webkit-linear-gradient(top, #ececec 0%, #fff 100%);background:-o-linear-gradient(top, #ececec 0%, #fff 100%);background:-ms-linear-gradient(top, #ececec 0%, #fff 100%);background:linear-gradient(top, #ececec 0%, #fff 100%);box-shadow:inset 0px 1px 0px 0px rgba(255,255,255,0.5);z-index:999;-moz-transition:all 0.15s ease-in-out;-o-transition:all 0.15s ease-in-out;-ms-transition:all 0.15s ease-in-out;-webkit-transition:all 0.15s ease-in-out;transition:all 0.15s ease-in-out}.switch.on .toggle{left:2%}.switch.off .toggle{left:54%}.switch.round{padding:0px 20px;border-radius:40px}.switch.round .toggle{border-radius:40px;width:14px;height:14px}.switch.round.on .toggle{left:3%;background:#6bc406}.switch.round.off .toggle{left:58%}.switch-label{font-size:20px;line-height:31px;margin:0 5px} diff --git a/wp-content/plugins/nextgen-gallery/freemius/assets/js/jquery.ba-postmessage.js b/wp-content/plugins/nextgen-gallery/freemius/assets/js/jquery.ba-postmessage.js index 5c0fbfef7cffb239d84c526a42ea2d349571a551..9f76e0539d46e64f4526b539a264ad956bf66752 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/assets/js/jquery.ba-postmessage.js +++ b/wp-content/plugins/nextgen-gallery/freemius/assets/js/jquery.ba-postmessage.js @@ -1,222 +1,222 @@ -/*! - * jQuery postMessage - v0.5 - 9/11/2009 - * http://benalman.com/projects/jquery-postmessage-plugin/ - * - * Copyright (c) 2009 "Cowboy" Ben Alman - * Dual licensed under the MIT and GPL licenses. - * http://benalman.com/about/license/ - */ - -// Script: jQuery postMessage: Cross-domain scripting goodness -// -// *Version: 0.5, Last updated: 9/11/2009* -// -// Project Home - http://benalman.com/projects/jquery-postmessage-plugin/ -// GitHub - http://github.com/cowboy/jquery-postmessage/ -// Source - http://github.com/cowboy/jquery-postmessage/raw/master/jquery.ba-postmessage.js -// (Minified) - http://github.com/cowboy/jquery-postmessage/raw/master/jquery.ba-postmessage.min.js (0.9kb) -// -// About: License -// -// Copyright (c) 2009 "Cowboy" Ben Alman, -// Dual licensed under the MIT and GPL licenses. -// http://benalman.com/about/license/ -// -// About: Examples -// -// This working example, complete with fully commented code, illustrates one -// way in which this plugin can be used. -// -// Iframe resizing - http://benalman.com/code/projects/jquery-postmessage/examples/iframe/ -// -// About: Support and Testing -// -// Information about what version or versions of jQuery this plugin has been -// tested with and what browsers it has been tested in. -// -// jQuery Versions - 1.3.2 -// Browsers Tested - Internet Explorer 6-8, Firefox 3, Safari 3-4, Chrome, Opera 9. -// -// About: Release History -// -// 0.5 - (9/11/2009) Improved cache-busting -// 0.4 - (8/25/2009) Initial release - -(function($){ - '$:nomunge'; // Used by YUI compressor. - - // A few vars used in non-awesome browsers. - var interval_id, - last_hash, - cache_bust = 1, - - // A var used in awesome browsers. - rm_callback, - - // A few convenient shortcuts. - window = this, - FALSE = !1, - - // Reused internal strings. - postMessage = 'postMessage', - addEventListener = 'addEventListener', - - p_receiveMessage, - - // I couldn't get window.postMessage to actually work in Opera 9.64! - has_postMessage = window[postMessage] && !$.browser.opera; - - // Method: jQuery.postMessage - // - // This method will call window.postMessage if available, setting the - // targetOrigin parameter to the base of the target_url parameter for maximum - // security in browsers that support it. If window.postMessage is not available, - // the target window's location.hash will be used to pass the message. If an - // object is passed as the message param, it will be serialized into a string - // using the jQuery.param method. - // - // Usage: - // - // > jQuery.postMessage( message, target_url [, target ] ); - // - // Arguments: - // - // message - (String) A message to be passed to the other frame. - // message - (Object) An object to be serialized into a params string, using - // the jQuery.param method. - // target_url - (String) The URL of the other frame this window is - // attempting to communicate with. This must be the exact URL (including - // any query string) of the other window for this script to work in - // browsers that don't support window.postMessage. - // target - (Object) A reference to the other frame this window is - // attempting to communicate with. If omitted, defaults to `parent`. - // - // Returns: - // - // Nothing. - - $[postMessage] = function( message, target_url, target ) { - if ( !target_url ) { return; } - - // Serialize the message if not a string. Note that this is the only real - // jQuery dependency for this script. If removed, this script could be - // written as very basic JavaScript. - message = typeof message === 'string' ? message : $.param( message ); - - // Default to parent if unspecified. - target = target || parent; - - if ( has_postMessage ) { - // The browser supports window.postMessage, so call it with a targetOrigin - // set appropriately, based on the target_url parameter. - target[postMessage]( message, target_url.replace( /([^:]+:\/\/[^\/]+).*/, '$1' ) ); - - } else if ( target_url ) { - // The browser does not support window.postMessage, so set the location - // of the target to target_url#message. A bit ugly, but it works! A cache - // bust parameter is added to ensure that repeat messages trigger the - // callback. - target.location = target_url.replace( /#.*$/, '' ) + '#' + (+new Date) + (cache_bust++) + '&' + message; - } - }; - - // Method: jQuery.receiveMessage - // - // Register a single callback for either a window.postMessage call, if - // supported, or if unsupported, for any change in the current window - // location.hash. If window.postMessage is supported and source_origin is - // specified, the source window will be checked against this for maximum - // security. If window.postMessage is unsupported, a polling loop will be - // started to watch for changes to the location.hash. - // - // Note that for simplicity's sake, only a single callback can be registered - // at one time. Passing no params will unbind this event (or stop the polling - // loop), and calling this method a second time with another callback will - // unbind the event (or stop the polling loop) first, before binding the new - // callback. - // - // Also note that if window.postMessage is available, the optional - // source_origin param will be used to test the event.origin property. From - // the MDC window.postMessage docs: This string is the concatenation of the - // protocol and "://", the host name if one exists, and ":" followed by a port - // number if a port is present and differs from the default port for the given - // protocol. Examples of typical origins are https://example.org (implying - // port 443), http://example.net (implying port 80), and http://example.com:8080. - // - // Usage: - // - // > jQuery.receiveMessage( callback [, source_origin ] [, delay ] ); - // - // Arguments: - // - // callback - (Function) This callback will execute whenever a <jQuery.postMessage> - // message is received, provided the source_origin matches. If callback is - // omitted, any existing receiveMessage event bind or polling loop will be - // canceled. - // source_origin - (String) If window.postMessage is available and this value - // is not equal to the event.origin property, the callback will not be - // called. - // source_origin - (Function) If window.postMessage is available and this - // function returns false when passed the event.origin property, the - // callback will not be called. - // delay - (Number) An optional zero-or-greater delay in milliseconds at - // which the polling loop will execute (for browser that don't support - // window.postMessage). If omitted, defaults to 100. - // - // Returns: - // - // Nothing! - - $.receiveMessage = p_receiveMessage = function( callback, source_origin, delay ) { - if ( has_postMessage ) { - // Since the browser supports window.postMessage, the callback will be - // bound to the actual event associated with window.postMessage. - - if ( callback ) { - // Unbind an existing callback if it exists. - rm_callback && p_receiveMessage(); - - // Bind the callback. A reference to the callback is stored for ease of - // unbinding. - rm_callback = function(e) { - if ( ( typeof source_origin === 'string' && e.origin !== source_origin ) - || ( $.isFunction( source_origin ) && source_origin( e.origin ) === FALSE ) ) { - return FALSE; - } - callback( e ); - }; - } - - if ( window[addEventListener] ) { - window[ callback ? addEventListener : 'removeEventListener' ]( 'message', rm_callback, FALSE ); - } else { - window[ callback ? 'attachEvent' : 'detachEvent' ]( 'onmessage', rm_callback ); - } - - } else { - // Since the browser sucks, a polling loop will be started, and the - // callback will be called whenever the location.hash changes. - - interval_id && clearInterval( interval_id ); - interval_id = null; - - if ( callback ) { - delay = typeof source_origin === 'number' - ? source_origin - : typeof delay === 'number' - ? delay - : 100; - - interval_id = setInterval(function(){ - var hash = document.location.hash, - re = /^#?\d+&/; - if ( hash !== last_hash && re.test( hash ) ) { - last_hash = hash; - callback({ data: hash.replace( re, '' ) }); - } - }, delay ); - } - } - }; - -})(jQuery); +/*! + * jQuery postMessage - v0.5 - 9/11/2009 + * http://benalman.com/projects/jquery-postmessage-plugin/ + * + * Copyright (c) 2009 "Cowboy" Ben Alman + * Dual licensed under the MIT and GPL licenses. + * http://benalman.com/about/license/ + */ + +// Script: jQuery postMessage: Cross-domain scripting goodness +// +// *Version: 0.5, Last updated: 9/11/2009* +// +// Project Home - http://benalman.com/projects/jquery-postmessage-plugin/ +// GitHub - http://github.com/cowboy/jquery-postmessage/ +// Source - http://github.com/cowboy/jquery-postmessage/raw/master/jquery.ba-postmessage.js +// (Minified) - http://github.com/cowboy/jquery-postmessage/raw/master/jquery.ba-postmessage.min.js (0.9kb) +// +// About: License +// +// Copyright (c) 2009 "Cowboy" Ben Alman, +// Dual licensed under the MIT and GPL licenses. +// http://benalman.com/about/license/ +// +// About: Examples +// +// This working example, complete with fully commented code, illustrates one +// way in which this plugin can be used. +// +// Iframe resizing - http://benalman.com/code/projects/jquery-postmessage/examples/iframe/ +// +// About: Support and Testing +// +// Information about what version or versions of jQuery this plugin has been +// tested with and what browsers it has been tested in. +// +// jQuery Versions - 1.3.2 +// Browsers Tested - Internet Explorer 6-8, Firefox 3, Safari 3-4, Chrome, Opera 9. +// +// About: Release History +// +// 0.5 - (9/11/2009) Improved cache-busting +// 0.4 - (8/25/2009) Initial release + +(function($){ + '$:nomunge'; // Used by YUI compressor. + + // A few vars used in non-awesome browsers. + var interval_id, + last_hash, + cache_bust = 1, + + // A var used in awesome browsers. + rm_callback, + + // A few convenient shortcuts. + window = this, + FALSE = !1, + + // Reused internal strings. + postMessage = 'postMessage', + addEventListener = 'addEventListener', + + p_receiveMessage, + + // I couldn't get window.postMessage to actually work in Opera 9.64! + has_postMessage = window[postMessage] && !$.browser.opera; + + // Method: jQuery.postMessage + // + // This method will call window.postMessage if available, setting the + // targetOrigin parameter to the base of the target_url parameter for maximum + // security in browsers that support it. If window.postMessage is not available, + // the target window's location.hash will be used to pass the message. If an + // object is passed as the message param, it will be serialized into a string + // using the jQuery.param method. + // + // Usage: + // + // > jQuery.postMessage( message, target_url [, target ] ); + // + // Arguments: + // + // message - (String) A message to be passed to the other frame. + // message - (Object) An object to be serialized into a params string, using + // the jQuery.param method. + // target_url - (String) The URL of the other frame this window is + // attempting to communicate with. This must be the exact URL (including + // any query string) of the other window for this script to work in + // browsers that don't support window.postMessage. + // target - (Object) A reference to the other frame this window is + // attempting to communicate with. If omitted, defaults to `parent`. + // + // Returns: + // + // Nothing. + + $[postMessage] = function( message, target_url, target ) { + if ( !target_url ) { return; } + + // Serialize the message if not a string. Note that this is the only real + // jQuery dependency for this script. If removed, this script could be + // written as very basic JavaScript. + message = typeof message === 'string' ? message : $.param( message ); + + // Default to parent if unspecified. + target = target || parent; + + if ( has_postMessage ) { + // The browser supports window.postMessage, so call it with a targetOrigin + // set appropriately, based on the target_url parameter. + target[postMessage]( message, target_url.replace( /([^:]+:\/\/[^\/]+).*/, '$1' ) ); + + } else if ( target_url ) { + // The browser does not support window.postMessage, so set the location + // of the target to target_url#message. A bit ugly, but it works! A cache + // bust parameter is added to ensure that repeat messages trigger the + // callback. + target.location = target_url.replace( /#.*$/, '' ) + '#' + (+new Date) + (cache_bust++) + '&' + message; + } + }; + + // Method: jQuery.receiveMessage + // + // Register a single callback for either a window.postMessage call, if + // supported, or if unsupported, for any change in the current window + // location.hash. If window.postMessage is supported and source_origin is + // specified, the source window will be checked against this for maximum + // security. If window.postMessage is unsupported, a polling loop will be + // started to watch for changes to the location.hash. + // + // Note that for simplicity's sake, only a single callback can be registered + // at one time. Passing no params will unbind this event (or stop the polling + // loop), and calling this method a second time with another callback will + // unbind the event (or stop the polling loop) first, before binding the new + // callback. + // + // Also note that if window.postMessage is available, the optional + // source_origin param will be used to test the event.origin property. From + // the MDC window.postMessage docs: This string is the concatenation of the + // protocol and "://", the host name if one exists, and ":" followed by a port + // number if a port is present and differs from the default port for the given + // protocol. Examples of typical origins are https://example.org (implying + // port 443), http://example.net (implying port 80), and http://example.com:8080. + // + // Usage: + // + // > jQuery.receiveMessage( callback [, source_origin ] [, delay ] ); + // + // Arguments: + // + // callback - (Function) This callback will execute whenever a <jQuery.postMessage> + // message is received, provided the source_origin matches. If callback is + // omitted, any existing receiveMessage event bind or polling loop will be + // canceled. + // source_origin - (String) If window.postMessage is available and this value + // is not equal to the event.origin property, the callback will not be + // called. + // source_origin - (Function) If window.postMessage is available and this + // function returns false when passed the event.origin property, the + // callback will not be called. + // delay - (Number) An optional zero-or-greater delay in milliseconds at + // which the polling loop will execute (for browser that don't support + // window.postMessage). If omitted, defaults to 100. + // + // Returns: + // + // Nothing! + + $.receiveMessage = p_receiveMessage = function( callback, source_origin, delay ) { + if ( has_postMessage ) { + // Since the browser supports window.postMessage, the callback will be + // bound to the actual event associated with window.postMessage. + + if ( callback ) { + // Unbind an existing callback if it exists. + rm_callback && p_receiveMessage(); + + // Bind the callback. A reference to the callback is stored for ease of + // unbinding. + rm_callback = function(e) { + if ( ( typeof source_origin === 'string' && e.origin !== source_origin ) + || ( $.isFunction( source_origin ) && source_origin( e.origin ) === FALSE ) ) { + return FALSE; + } + callback( e ); + }; + } + + if ( window[addEventListener] ) { + window[ callback ? addEventListener : 'removeEventListener' ]( 'message', rm_callback, FALSE ); + } else { + window[ callback ? 'attachEvent' : 'detachEvent' ]( 'onmessage', rm_callback ); + } + + } else { + // Since the browser sucks, a polling loop will be started, and the + // callback will be called whenever the location.hash changes. + + interval_id && clearInterval( interval_id ); + interval_id = null; + + if ( callback ) { + delay = typeof source_origin === 'number' + ? source_origin + : typeof delay === 'number' + ? delay + : 100; + + interval_id = setInterval(function(){ + var hash = document.location.hash, + re = /^#?\d+&/; + if ( hash !== last_hash && re.test( hash ) ) { + last_hash = hash; + callback({ data: hash.replace( re, '' ) }); + } + }, delay ); + } + } + }; + +})(jQuery); diff --git a/wp-content/plugins/nextgen-gallery/freemius/assets/js/jquery.ba-postmessage.min.js b/wp-content/plugins/nextgen-gallery/freemius/assets/js/jquery.ba-postmessage.min.js index 4a16443ca155319be63398b5ebd780707fc39b69..3b14638655b704c0bfec9e2901c429bf5c4659c9 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/assets/js/jquery.ba-postmessage.min.js +++ b/wp-content/plugins/nextgen-gallery/freemius/assets/js/jquery.ba-postmessage.min.js @@ -1 +1,9 @@ -eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('(7($){\'$:y\';u 8,m,s=1,a,6=x,g=!1,9=\'9\',i=\'i\',o,n=6[9]&&!$.w.A;$[9]=7(2,f,b){0(!f){p}2=h 2===\'r\'?2:$.D(2);b=b||C;0(n){b[9](2,f.k(/([^:]+:\\/\\/[^\\/]+).*/,\'$1\'))}j 0(f){b.v=f.k(/#.*$/,\'\')+\'#\'+(+B E)+(s++)+\'&\'+2}};$.z=o=7(4,3,c){0(n){0(4){a&&o();a=7(e){0((h 3===\'r\'&&e.q!==3)||($.H(3)&&3(e.q)===g)){p g}4(e)}}0(6[i]){6[4?i:\'O\'](\'2\',a,g)}j{6[4?\'P\':\'F\'](\'M\',a)}}j{8&&L(8);8=G;0(4){c=h 3===\'t\'?3:h c===\'t\'?c:I;8=J(7(){u 5=K.v.5,l=/^#?\\d+&/;0(5!==m&&l.R(5)){m=5;4({N:5.k(l,\'\')})}},c)}}}})(Q);',54,54,'if||message|source_origin|callback|hash|window|function|interval_id|postMessage|rm_callback|target|delay|||target_url|FALSE|typeof|addEventListener|else|replace|re|last_hash|has_postMessage|p_receiveMessage|return|origin|string|cache_bust|number|var|location|browser|this|nomunge|receiveMessage|opera|new|parent|param|Date|detachEvent|null|isFunction|100|setInterval|document|clearInterval|onmessage|data|removeEventListener|attachEvent|jQuery|test'.split('|'),0,{})) +/* + * jQuery postMessage - v0.5 - 9/11/2009 + * http://benalman.com/projects/jquery-postmessage-plugin/ + * + * Copyright (c) 2009 "Cowboy" Ben Alman + * Dual licensed under the MIT and GPL licenses. + * http://benalman.com/about/license/ + */ +(function($){var g,d,j=1,a,b=this,f=!1,h="postMessage",e="addEventListener",c,i=b[h]&&!$.browser.opera;$[h]=function(k,l,m){if(!l){return}k=typeof k==="string"?k:$.param(k);m=m||parent;if(i){m[h](k,l.replace(/([^:]+:\/\/[^\/]+).*/,"$1"))}else{if(l){m.location=l.replace(/#.*$/,"")+"#"+(+new Date)+(j++)+"&"+k}}};$.receiveMessage=c=function(l,m,k){if(i){if(l){a&&c();a=function(n){if((typeof m==="string"&&n.origin!==m)||($.isFunction(m)&&m(n.origin)===f)){return f}l(n)}}if(b[e]){b[l?e:"removeEventListener"]("message",a,f)}else{b[l?"attachEvent":"detachEvent"]("onmessage",a)}}else{g&&clearInterval(g);g=null;if(l){k=typeof m==="number"?m:typeof k==="number"?k:100;g=setInterval(function(){var o=document.location.hash,n=/^#?\d+&/;if(o!==d&&n.test(o)){d=o;l({data:o.replace(n,"")})}},k)}}}})(jQuery); \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/assets/js/nojquery.ba-postmessage.min.js b/wp-content/plugins/nextgen-gallery/freemius/assets/js/nojquery.ba-postmessage.min.js index 17aef76018f4960df21e6e32729a6c89dcb6f2d2..ae542d4e81fd6735c369904fca039ab83fa09f48 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/assets/js/nojquery.ba-postmessage.min.js +++ b/wp-content/plugins/nextgen-gallery/freemius/assets/js/nojquery.ba-postmessage.min.js @@ -1 +1,12 @@ -eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('3 F(o,l){z h,j,g,f,m,A=1;2(5.v){2(5.x){h=3(0){5.x(\'6\',0,c)}j=3(0){5.I(\'6\',0,c)}}s{h=3(0){5.J(\'u\',0)}j=3(0){5.G(\'u\',0)}}b[o]=3(6,7,i){2(!7){9}i.v(6,7.k(/([^:]+:\\/\\/[^\\/]+).*/,\'$1\'))}b[l]=3(0,4,8){2(g){j(g);g=C}2(!0){9 c}g=h(3(e){D(E.H.U.T(4)){t\'[q S]\':2(4!==e.r){9 c}p;t\'[q V]\':2(4(e.r)){9 c}p}0(e)})}}s{b[o]=3(6,7,i){2(!7){9}i.w=7.k(/#.*$/,\'\')+\'#\'+(+K R)+(A++)+\'&\'+6}b[l]=3(0,4,8){2(f){Q(f);f=C}2(0){8=B 4===\'y\'?4:B 8===\'y\'?8:M;f=L(3(){z a=N.w.a,n=/^#?\\d+&/;2(a!==m&&n.O(a)){m=a;0({P:a.k(n,\'\')})}},8)}}}9 b}',58,58,'callback||if|function|sourceOrigin|window|message|targetUrl|delay|return|hash|this|false|||intervalId|currentMsgCallback|setMessageCallback|target|unsetMessageCallback|replace|receiveBinding|lastHash|re|postBinding|break|object|origin|else|case|onmessage|postMessage|location|addEventListener|number|var|cacheBust|typeof|null|switch|Object|NoJQueryPostMessageMixin|detachEvent|prototype|removeEventListener|attachEvent|new|setInterval|100|document|test|data|clearInterval|Date|String|call|toString|Function'.split('|'),0,{})) +/* + * nojquery-postmessage by Jeff Lee + * a non-jQuery fork of: + * + * jQuery postMessage - v0.5 - 9/11/2009 + * http://benalman.com/projects/jquery-postmessage-plugin/ + * + * Copyright (c) 2009 "Cowboy" Ben Alman + * Dual licensed under the MIT and GPL licenses. + * http://benalman.com/about/license/ + */ +function NoJQueryPostMessageMixin(g,a){var b,h,e,d,f,c=1;if(window.postMessage){if(window.addEventListener){b=function(i){window.addEventListener("message",i,false)};h=function(i){window.removeEventListener("message",i,false)}}else{b=function(i){window.attachEvent("onmessage",i)};h=function(i){window.detachEvent("onmessage",i)}}this[g]=function(i,k,j){if(!k){return}j.postMessage(i,k.replace(/([^:]+:\/\/[^\/]+).*/,"$1"))};this[a]=function(k,j,i){if(e){h(e);e=null}if(!k){return false}e=b(function(l){switch(Object.prototype.toString.call(j)){case"[object String]":if(j!==l.origin){return false}break;case"[object Function]":if(j(l.origin)){return false}break}k(l)})}}else{this[g]=function(i,k,j){if(!k){return}j.location=k.replace(/#.*$/,"")+"#"+(+new Date)+(c++)+"&"+i};this[a]=function(k,j,i){if(d){clearInterval(d);d=null}if(k){i=typeof j==="number"?j:typeof i==="number"?i:100;d=setInterval(function(){var m=document.location.hash,l=/^#?\d+&/;if(m!==f&&l.test(m)){f=m;k({data:m.replace(l,"")})}},i)}}}return this}; \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/assets/scss/_load.scss b/wp-content/plugins/nextgen-gallery/freemius/assets/scss/_load.scss index ee175eea147fbbdba42c25f661bc49223be477f8..cd58776531f5a05109bd3e79354a24d4734b287f 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/assets/scss/_load.scss +++ b/wp-content/plugins/nextgen-gallery/freemius/assets/scss/_load.scss @@ -1,4 +1,4 @@ -@import 'mixins'; -@import "vars"; -@import "functions"; -@import "colors"; +@import 'mixins'; +@import "vars"; +@import "functions"; +@import "colors"; diff --git a/wp-content/plugins/nextgen-gallery/freemius/assets/scss/_start.scss b/wp-content/plugins/nextgen-gallery/freemius/assets/scss/_start.scss index 653f53ac8772154a24046483e5155bcf42d58c4a..6c15ef919b50c73e22fc65ae8d06ad6f63c30fc7 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/assets/scss/_start.scss +++ b/wp-content/plugins/nextgen-gallery/freemius/assets/scss/_start.scss @@ -1,4 +1,4 @@ -@import "vars"; -@import "colors"; -@import "mixins"; +@import "vars"; +@import "colors"; +@import "mixins"; @import "functions"; \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/assets/scss/_vars.scss b/wp-content/plugins/nextgen-gallery/freemius/assets/scss/_vars.scss index 053b22cf4179a24cd65e72e9acc1d4aa0c3c1286..d75ec6d999169fafb8a059bc666afede792298a3 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/assets/scss/_vars.scss +++ b/wp-content/plugins/nextgen-gallery/freemius/assets/scss/_vars.scss @@ -1,5 +1,5 @@ -$is_production: true; - -$img_common: if($is_production == true, '//img.freemius.com', 'http://img.freemius:8080'); - +$is_production: true; + +$img_common: if($is_production == true, '//img.freemius.com', 'http://img.freemius:8080'); + $layout_width: 960px; \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/assets/scss/admin/account.scss b/wp-content/plugins/nextgen-gallery/freemius/assets/scss/admin/account.scss index 0b5e38559bc58f824c27c0aa19317a0a07a91a1d..ecd24963b9b4b141167eca31315a1881e3da2468 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/assets/scss/admin/account.scss +++ b/wp-content/plugins/nextgen-gallery/freemius/assets/scss/admin/account.scss @@ -1,171 +1,171 @@ -#fs_account -{ - .postbox, - .widefat - { - max-width: 700px; - } - - h3 - { - font-size: 1.3em; - padding: 12px 15px; - margin: 0 0 12px 0; - line-height: 1.4; - border-bottom: 1px solid #F1F1F1; - } - - i.dashicons - { - font-size: 1.2em; - height: 1.2em; - width: 1.2em; - } - - .button - { - i.dashicons - { - vertical-align: middle; - } - } - - .fs-header-actions - { - position: absolute; - top: 17px; - right: 15px; - font-size: 0.9em; - - ul - { - margin: 0; - } - - li - { - form - { - display: inline-block; - } - - float: left; - a - { - text-decoration: none; - } - } - } -} - -.rtl #fs_account .fs-header-actions -{ - left: 15px; - right: auto; -} - -.fs-key-value-table -{ - width: 100%; - - form - { - display: inline-block; - } - - tr - { - td:first-child - { - nobr - { - font-weight: bold; - } - - text-align: right; - - form - { - display: block; - } - } - - td.fs-right - { - text-align: right; - } - - &.fs-odd - { - background: #ebebeb; - } - } - - td, th - { - padding: 10px; - } - - var, code - { - color: #0073AA; - font-size: 16px; - background: none; - } -} - -label.fs-tag -{ - background: #ffba00; - color: #fff; - display: inline-block; - border-radius: 3px; - padding: 5px; - font-size: 11px; - line-height: 11px; - vertical-align: baseline; - - &.fs-warn - { - background: #ffba00; - } - &.fs-success - { - background: #46b450; - } - &.fs-error - { - background: #dc3232; - } -} - -#fs_addons -{ - h3 - { - border: none; - margin-bottom: 0; - padding: 4px 5px; - } - - td - { - vertical-align: middle; - } - - td:first-child, - th:first-child - { - text-align: left; - font-weight: bold; - } - td:last-child, - th:last-child - { - text-align: right; - } - th - { - font-weight: bold; - } +#fs_account +{ + .postbox, + .widefat + { + max-width: 700px; + } + + h3 + { + font-size: 1.3em; + padding: 12px 15px; + margin: 0 0 12px 0; + line-height: 1.4; + border-bottom: 1px solid #F1F1F1; + } + + i.dashicons + { + font-size: 1.2em; + height: 1.2em; + width: 1.2em; + } + + .button + { + i.dashicons + { + vertical-align: middle; + } + } + + .fs-header-actions + { + position: absolute; + top: 17px; + right: 15px; + font-size: 0.9em; + + ul + { + margin: 0; + } + + li + { + form + { + display: inline-block; + } + + float: left; + a + { + text-decoration: none; + } + } + } +} + +.rtl #fs_account .fs-header-actions +{ + left: 15px; + right: auto; +} + +.fs-key-value-table +{ + width: 100%; + + form + { + display: inline-block; + } + + tr + { + td:first-child + { + nobr + { + font-weight: bold; + } + + text-align: right; + + form + { + display: block; + } + } + + td.fs-right + { + text-align: right; + } + + &.fs-odd + { + background: #ebebeb; + } + } + + td, th + { + padding: 10px; + } + + var, code + { + color: #0073AA; + font-size: 16px; + background: none; + } +} + +label.fs-tag +{ + background: #ffba00; + color: #fff; + display: inline-block; + border-radius: 3px; + padding: 5px; + font-size: 11px; + line-height: 11px; + vertical-align: baseline; + + &.fs-warn + { + background: #ffba00; + } + &.fs-success + { + background: #46b450; + } + &.fs-error + { + background: #dc3232; + } +} + +#fs_addons +{ + h3 + { + border: none; + margin-bottom: 0; + padding: 4px 5px; + } + + td + { + vertical-align: middle; + } + + td:first-child, + th:first-child + { + text-align: left; + font-weight: bold; + } + td:last-child, + th:last-child + { + text-align: right; + } + th + { + font-weight: bold; + } } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/assets/scss/admin/add-ons.scss b/wp-content/plugins/nextgen-gallery/freemius/assets/scss/admin/add-ons.scss index f1636cdef00aad685eba7481c269bc630fde0b9d..e744ff6da27e49fec1805bbfc90219ed9192b64a 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/assets/scss/admin/add-ons.scss +++ b/wp-content/plugins/nextgen-gallery/freemius/assets/scss/admin/add-ons.scss @@ -1,449 +1,449 @@ -@import "../start"; - -#fs_addons -{ - .fs-cards-list - { - list-style: none; - - .fs-card - { - float: left; - // height: 185px; // With reviews/ratings - height: 152px; - width: 310px; - padding: 0; - margin: 0 0 30px 30px; - font-size: 14px; - list-style: none; - border: 1px solid #ddd; - cursor: pointer; - position: relative; - - .fs-overlay - { - position: absolute; - left: 0; - right: 0; - bottom: 0; - top: 0; - z-index: 9; - } - - .fs-inner - { - background-color: #fff; - overflow: hidden; - height: 100%; - position: relative; - - ul - { - @include transition(all, 0.15s); - left: 0; - right: 0; - top: 0; - position: absolute; - } - - li - { - list-style: none; - line-height: 18px; - padding: 0 15px; - width: 100%; - display: block; - @include box-sizing(border-box); - } - - .fs-card-banner - { - padding: 0; - margin: 0; - line-height: 0; - display: block; - height: 100px; - background-repeat: repeat-x; - background-size: 100% 100%; - @include transition(all, 0.15s); - } - - .fs-title - { - margin: 10px 0 0 0; - height: 18px; - overflow: hidden; - color: #000; - white-space: nowrap; - text-overflow: ellipsis; - font-weight: bold; - } - - .fs-offer - { - font-size: 0.9em; - } - - .fs-description - { - background-color: #f9f9f9; - padding: 10px 15px 100px 15px; - border-top: 1px solid #eee; - margin: 0 0 10px 0; - color: #777; - } - - .fs-tag - { - position: absolute; - top: 10px; - right: 0px; - background: greenyellow; - display: block; - padding: 2px 10px; - @include box-shadow(1px 1px 1px rgba(0,0,0,0.3)); - text-transform: uppercase; - font-size: 0.9em; - font-weight: bold; - } - - .fs-cta - { - .button - { - position: absolute; - top: 112px; - right: 10px; - } - } - } - - @media screen and (min-width: 960px) { - &:hover - { - .fs-overlay - { - border: 2px solid $fms-link-color; - margin-left: -1px; - margin-top: -1px; - } - - .fs-inner - { - ul - { - top: -100px; - } - - .fs-card-banner - { - // background-position: 50% -100px; - } - - .fs-title, - .fs-offer - { - color: $fms-link-color; - } - } - } - } - } - } -} - -#TB_window -{ - &, iframe - { - width: 772px !important; - } -} - -#plugin-information -{ - #section-description - { - h2, h3, p, b, i, blockquote, li, ul, ol - { - clear: none; - } - - .fs-selling-points - { - padding-bottom: 10px; - border-bottom: 1px solid #ddd; - - ul - { - margin: 0; - - li - { - padding: 0; - list-style: none outside none; - - i.dashicons - { - color: $fs-logo-green-color; - font-size: 3em; - vertical-align: middle; - line-height: 30px; - float: left; - margin: 0 0 0 -15px; - } - - h3 - { - margin: 1em 30px !important; - } - } - } - } - - .fs-screenshots - { - @include clearfix(); - ul - { - list-style: none; - margin: 0; - - li - { - width: 225px; - height: 225px; - float: left; - margin-bottom: 20px; - @include box-sizing(content-box); - - a - { - display: block; - width: 100%; - height: 100%; - border: 1px solid; - @include box-shadow(1px 1px 1px rgba(0, 0, 0, 0.2)); - background-size: cover; - } - - &.odd - { - margin-right: 20px; - } - } - } - } - } - - .plugin-information-pricing - { - $pricing_color: #FFFEEC; - $borders_color: #DDD; - margin: -16px; - // padding: 20px; - border-bottom: 1px solid $borders_color; - - .fs-plan - { - - h3 - { - margin-top: 0; - padding: 20px; - font-size: 16px; - } - - .nav-tab-wrapper - { - border-bottom: 1px solid $borders_color; - - .nav-tab - { - cursor: pointer; - position: relative; - padding: 0 10px; - font-size: 0.9em; - - label - { - text-transform: uppercase; - color: green; - background: greenyellow; - position: absolute; - left: -1px; - right: -1px; - bottom: 100%; - border: 1px solid darkgreen; - padding: 2px; - text-align: center; - font-size: 0.9em; - line-height: 1em; - } - - &.nav-tab-active - { - cursor: default; - background: $pricing_color; - border-bottom-color: $pricing_color; - } - } - } - - &.fs-single-cycle - { - h3 - { - background: $pricing_color; - margin: 0; - padding-bottom: 0; - color: #0073aa; - } - - .nav-tab-wrapper, - .fs-billing-frequency - { - display: none; - } - } - - .fs-pricing-body - { - background: $pricing_color; - padding: 20px; - } - - .button - { - width: 100%; - text-align: center; - font-weight: bold; - text-transform: uppercase; - font-size: 1.1em; - } - - label - { - white-space: nowrap; - } - - var { - font-style: normal; - } - - .fs-billing-frequency, - .fs-annual-discount - { - text-align: center; - display: block; - font-weight: bold; - margin-bottom: 10px; - text-transform: uppercase; - background: #F3F3F3; - padding: 2px; - border: 1px solid #ccc; - } - - .fs-annual-discount - { - text-transform: none; - color: green; - background: greenyellow; - } - - ul.fs-trial-terms - { - font-size: 0.9em; - - i - { - float: left; - margin: 0 0 0 -15px; - } - - li - { - margin: 10px 0 0 0; - } - } - } - } - - #section-features - { - .fs-features - { - margin: -20px -26px; - } - - table - { - width: 100%; - border-spacing: 0; - border-collapse: separate; - - thead - { - th - { - padding: 10px 0; - } - - .fs-price - { - color: $fs-logo-green-color; - font-weight: normal; - display: block; - text-align: center; - } - } - - tbody - { - td - { - border-top: 1px solid #ccc; - padding: 10px 0; - text-align: center; - width: 100px; - color: $fs-logo-green-color; - - &:first-child - { - text-align: left; - width: auto; - color: inherit; - padding-left: 26px; - } - } - tr.fs-odd - { - td - { - background: #fefefe; - } - } - } - } - - .dashicons-yes - { - width: 30px; - height: 30px; - font-size: 30px; - } - } -} - -@media screen and (max-width: 961px) { - #fs_addons - { - .fs-cards-list - { - .fs-card - { - height: 265px; - } - } - } +@import "../start"; + +#fs_addons +{ + .fs-cards-list + { + list-style: none; + + .fs-card + { + float: left; + // height: 185px; // With reviews/ratings + height: 152px; + width: 310px; + padding: 0; + margin: 0 0 30px 30px; + font-size: 14px; + list-style: none; + border: 1px solid #ddd; + cursor: pointer; + position: relative; + + .fs-overlay + { + position: absolute; + left: 0; + right: 0; + bottom: 0; + top: 0; + z-index: 9; + } + + .fs-inner + { + background-color: #fff; + overflow: hidden; + height: 100%; + position: relative; + + ul + { + @include transition(all, 0.15s); + left: 0; + right: 0; + top: 0; + position: absolute; + } + + li + { + list-style: none; + line-height: 18px; + padding: 0 15px; + width: 100%; + display: block; + @include box-sizing(border-box); + } + + .fs-card-banner + { + padding: 0; + margin: 0; + line-height: 0; + display: block; + height: 100px; + background-repeat: repeat-x; + background-size: 100% 100%; + @include transition(all, 0.15s); + } + + .fs-title + { + margin: 10px 0 0 0; + height: 18px; + overflow: hidden; + color: #000; + white-space: nowrap; + text-overflow: ellipsis; + font-weight: bold; + } + + .fs-offer + { + font-size: 0.9em; + } + + .fs-description + { + background-color: #f9f9f9; + padding: 10px 15px 100px 15px; + border-top: 1px solid #eee; + margin: 0 0 10px 0; + color: #777; + } + + .fs-tag + { + position: absolute; + top: 10px; + right: 0px; + background: greenyellow; + display: block; + padding: 2px 10px; + @include box-shadow(1px 1px 1px rgba(0,0,0,0.3)); + text-transform: uppercase; + font-size: 0.9em; + font-weight: bold; + } + + .fs-cta + { + .button + { + position: absolute; + top: 112px; + right: 10px; + } + } + } + + @media screen and (min-width: 960px) { + &:hover + { + .fs-overlay + { + border: 2px solid $fms-link-color; + margin-left: -1px; + margin-top: -1px; + } + + .fs-inner + { + ul + { + top: -100px; + } + + .fs-card-banner + { + // background-position: 50% -100px; + } + + .fs-title, + .fs-offer + { + color: $fms-link-color; + } + } + } + } + } + } +} + +#TB_window +{ + &, iframe + { + width: 772px !important; + } +} + +#plugin-information +{ + #section-description + { + h2, h3, p, b, i, blockquote, li, ul, ol + { + clear: none; + } + + .fs-selling-points + { + padding-bottom: 10px; + border-bottom: 1px solid #ddd; + + ul + { + margin: 0; + + li + { + padding: 0; + list-style: none outside none; + + i.dashicons + { + color: $fs-logo-green-color; + font-size: 3em; + vertical-align: middle; + line-height: 30px; + float: left; + margin: 0 0 0 -15px; + } + + h3 + { + margin: 1em 30px !important; + } + } + } + } + + .fs-screenshots + { + @include clearfix(); + ul + { + list-style: none; + margin: 0; + + li + { + width: 225px; + height: 225px; + float: left; + margin-bottom: 20px; + @include box-sizing(content-box); + + a + { + display: block; + width: 100%; + height: 100%; + border: 1px solid; + @include box-shadow(1px 1px 1px rgba(0, 0, 0, 0.2)); + background-size: cover; + } + + &.odd + { + margin-right: 20px; + } + } + } + } + } + + .plugin-information-pricing + { + $pricing_color: #FFFEEC; + $borders_color: #DDD; + margin: -16px; + // padding: 20px; + border-bottom: 1px solid $borders_color; + + .fs-plan + { + + h3 + { + margin-top: 0; + padding: 20px; + font-size: 16px; + } + + .nav-tab-wrapper + { + border-bottom: 1px solid $borders_color; + + .nav-tab + { + cursor: pointer; + position: relative; + padding: 0 10px; + font-size: 0.9em; + + label + { + text-transform: uppercase; + color: green; + background: greenyellow; + position: absolute; + left: -1px; + right: -1px; + bottom: 100%; + border: 1px solid darkgreen; + padding: 2px; + text-align: center; + font-size: 0.9em; + line-height: 1em; + } + + &.nav-tab-active + { + cursor: default; + background: $pricing_color; + border-bottom-color: $pricing_color; + } + } + } + + &.fs-single-cycle + { + h3 + { + background: $pricing_color; + margin: 0; + padding-bottom: 0; + color: #0073aa; + } + + .nav-tab-wrapper, + .fs-billing-frequency + { + display: none; + } + } + + .fs-pricing-body + { + background: $pricing_color; + padding: 20px; + } + + .button + { + width: 100%; + text-align: center; + font-weight: bold; + text-transform: uppercase; + font-size: 1.1em; + } + + label + { + white-space: nowrap; + } + + var { + font-style: normal; + } + + .fs-billing-frequency, + .fs-annual-discount + { + text-align: center; + display: block; + font-weight: bold; + margin-bottom: 10px; + text-transform: uppercase; + background: #F3F3F3; + padding: 2px; + border: 1px solid #ccc; + } + + .fs-annual-discount + { + text-transform: none; + color: green; + background: greenyellow; + } + + ul.fs-trial-terms + { + font-size: 0.9em; + + i + { + float: left; + margin: 0 0 0 -15px; + } + + li + { + margin: 10px 0 0 0; + } + } + } + } + + #section-features + { + .fs-features + { + margin: -20px -26px; + } + + table + { + width: 100%; + border-spacing: 0; + border-collapse: separate; + + thead + { + th + { + padding: 10px 0; + } + + .fs-price + { + color: $fs-logo-green-color; + font-weight: normal; + display: block; + text-align: center; + } + } + + tbody + { + td + { + border-top: 1px solid #ccc; + padding: 10px 0; + text-align: center; + width: 100px; + color: $fs-logo-green-color; + + &:first-child + { + text-align: left; + width: auto; + color: inherit; + padding-left: 26px; + } + } + tr.fs-odd + { + td + { + background: #fefefe; + } + } + } + } + + .dashicons-yes + { + width: 30px; + height: 30px; + font-size: 30px; + } + } +} + +@media screen and (max-width: 961px) { + #fs_addons + { + .fs-cards-list + { + .fs-card + { + height: 265px; + } + } + } } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/assets/scss/admin/common.scss b/wp-content/plugins/nextgen-gallery/freemius/assets/scss/admin/common.scss index 4a2f75eb002c4229affc28f2fbe913c65c72cb40..a8edf586f14a9ae4e8a97999b71ad17eea623157 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/assets/scss/admin/common.scss +++ b/wp-content/plugins/nextgen-gallery/freemius/assets/scss/admin/common.scss @@ -1,134 +1,134 @@ -@import "../start"; - -.fs-notice -{ - position: relative; - - &.fs-has-title - { - margin-bottom: 30px !important; - } - - &.success - { - color: green; - // font-weight: normal; - } - - &.promotion - { - border-color: $fs-notice-promotion-border-color !important; - background-color: $fs-notice-promotion-bkg !important; - } - - .fs-notice-body - { - margin: .5em 0; - padding: 2px; - } - - .fs-close - { - // position: absolute; - // top: 2px; - // bottom: 2px; - // right: 2px; - // min-width: 100px; - // text-align: center; - // padding-right: 2px; - cursor: pointer; - color: #aaa; - float: right; - - &:hover - { - color: #666; - // background: #A9A9A9; - } - - > * - { - margin-top: 7px; - display: inline-block; - } - } - - label.fs-plugin-title - { - background: rgba(0, 0, 0, 0.3); - color: #fff; - padding: 2px 10px; - position: absolute; - top: 100%; - bottom: auto; - right: auto; - @include border-radius(0 0 3px 3px); - left: 10px; - font-size: 12px; - font-weight: bold; - cursor: auto; - } -} - -.rtl .fs-notice -{ - .fs-close - { - // left: 2px; - // right: auto; - // padding-right: 0; - // padding-left: 2px; - float: left; - } -} - -.fs-secure-notice -{ - position: fixed; - top: 32px; - left: 160px; - right: 0; - background: rgb(235, 253, 235); - padding: 10px 20px; - color: green; - z-index: 9999; - box-shadow: 0px 2px 2px rgba(6, 113, 6, 0.3); - @include opacity(0.95); - - &:hover - { - @include opacity(1); - } -} - -@media screen and (max-width: 960px) { - .fs-secure-notice - { - left: 36px; - } -} - -@media screen and (max-width: 782px) { - .fs-secure-notice - { - left: 0; - top: 46px; - text-align: center; - } -} - -span.fs-submenu-item.fs-sub:before -{ - // Add small arrow. - content: '\21B3'; - padding: 0 5px; -} - -.rtl -{ - span.fs-submenu-item.fs-sub:before - { - // Add small RTL arrow. - content: '\21B2'; - } +@import "../start"; + +.fs-notice +{ + position: relative; + + &.fs-has-title + { + margin-bottom: 30px !important; + } + + &.success + { + color: green; + // font-weight: normal; + } + + &.promotion + { + border-color: $fs-notice-promotion-border-color !important; + background-color: $fs-notice-promotion-bkg !important; + } + + .fs-notice-body + { + margin: .5em 0; + padding: 2px; + } + + .fs-close + { + // position: absolute; + // top: 2px; + // bottom: 2px; + // right: 2px; + // min-width: 100px; + // text-align: center; + // padding-right: 2px; + cursor: pointer; + color: #aaa; + float: right; + + &:hover + { + color: #666; + // background: #A9A9A9; + } + + > * + { + margin-top: 7px; + display: inline-block; + } + } + + label.fs-plugin-title + { + background: rgba(0, 0, 0, 0.3); + color: #fff; + padding: 2px 10px; + position: absolute; + top: 100%; + bottom: auto; + right: auto; + @include border-radius(0 0 3px 3px); + left: 10px; + font-size: 12px; + font-weight: bold; + cursor: auto; + } +} + +.rtl .fs-notice +{ + .fs-close + { + // left: 2px; + // right: auto; + // padding-right: 0; + // padding-left: 2px; + float: left; + } +} + +.fs-secure-notice +{ + position: fixed; + top: 32px; + left: 160px; + right: 0; + background: rgb(235, 253, 235); + padding: 10px 20px; + color: green; + z-index: 9999; + box-shadow: 0px 2px 2px rgba(6, 113, 6, 0.3); + @include opacity(0.95); + + &:hover + { + @include opacity(1); + } +} + +@media screen and (max-width: 960px) { + .fs-secure-notice + { + left: 36px; + } +} + +@media screen and (max-width: 782px) { + .fs-secure-notice + { + left: 0; + top: 46px; + text-align: center; + } +} + +span.fs-submenu-item.fs-sub:before +{ + // Add small arrow. + content: '\21B3'; + padding: 0 5px; +} + +.rtl +{ + span.fs-submenu-item.fs-sub:before + { + // Add small RTL arrow. + content: '\21B2'; + } } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/assets/scss/admin/connect.scss b/wp-content/plugins/nextgen-gallery/freemius/assets/scss/admin/connect.scss index 12d69678489a4f4230a35114be743c86ccf4ad89..39f2d6920ce85d550876872dae2aacfb8ea25fd9 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/assets/scss/admin/connect.scss +++ b/wp-content/plugins/nextgen-gallery/freemius/assets/scss/admin/connect.scss @@ -1,421 +1,421 @@ -@import "../start"; - -$form_width: 480px; - -#fs_connect -{ - width: $form_width; - @include box-shadow(0px 1px 2px rgba(0, 0, 0, 0.3)); - margin: 20px 0; - - @media screen and (max-width: ($form_width - 1)) { - @include box-shadow(none); - width: auto; - margin: 0 0 0 -10px; - } - - .fs-content - { - background: #fff; - padding: 15px 20px; - - p - { - margin: 0; - padding: 0; - font-size: 1.2em; - } - } - - .fs-actions - { - padding: 10px 20px; - background: #C0C7CA; - - .button - { - padding: 0 10px 1px; - line-height: 35px; - height: 37px; - font-size: 16px; - margin-bottom: 0; - - .dashicons - { - font-size: 37px; - margin-left: -8px; - margin-right: 12px; - } - - &.button-primary - { - padding-right: 15px; - padding-left: 15px; - - &:after - { - content: ' \279C'; - } - - &.fs-loading - { - &:after - { - content: ''; - } - } - } - - &.button-secondary - { - float: right; - } - } - - // .fs-skip - // { - // line-height: 38px; - // vertical-align: middle; - // text-decoration: none; - // margin-left: 10px; - // } - } - - &.fs-anonymous-disabled - { - .fs-actions - { - .button.button-primary - { - width: 100%; - } - } - } - - .fs-permissions - { - padding: 10px 20px; - background: #FEFEFE; - // background: #F1F1F1; - @include transition(background 0.5s ease); - - .fs-trigger - { - font-size: 0.9em; - text-decoration: none; - text-align: center; - display: block; - } - - ul - { - height: 0; - overflow: hidden; - margin: 0; - - li - { - margin-bottom: 12px; - - &:last-child - { - margin-bottom: 0; - } - - i.dashicons - { - float: left; - font-size: 40px; - width: 40px; - height: 40px; - } - - div - { - margin-left: 55px; - - span - { - font-weight: bold; - text-transform: uppercase; - color: #23282d; - } - - p - { - margin: 2px 0 0 0; - } - } - } - } - - &.fs-open - { - background: #fff; - - ul - { - height: auto; - margin: 20px 20px 10px 20px; - } - } - - @media screen and (max-width: ($form_width - 1)) { - background: #fff; - - .fs-trigger - { - display: none; - } - - ul - { - height: auto; - margin: 20px; - } - } - } - - $icon_size: 80px; - $wp_logo_padding: $icon_size / 10; - $icons_top: 10px; - - .fs-visual - { - padding: 12px; - line-height: 0; - background: #fafafa; - height: $icon_size; - position: relative; - - .fs-site-icon - { - position: absolute; - left: 20px; - top: $icons_top; - } - - .fs-connect-logo - { - position: absolute; - right: 20px; - top: $icons_top; - } - - .fs-plugin-icon - { - position: absolute; - top: $icons_top; - left: 50%; - margin-left: - ($icon_size / 2); - } - - .fs-plugin-icon, - .fs-site-icon, - img, - object - { - width: $icon_size; - height: $icon_size; - } - - .dashicons-wordpress - { - font-size: $icon_size - ($wp_logo_padding * 2); - background: $wordpress_color; - color: #fff; - width: $icon_size - ($wp_logo_padding * 2); - height: $icon_size - ($wp_logo_padding * 2); - padding: $wp_logo_padding; - } - - .dashicons-plus - { - position: absolute; - top: 50%; - font-size: 30px; - margin-top: -10px; - color: #bbb; - - &.fs-first - { - left: 28%; - } - &.fs-second - { - left: 65%; - } - } - - .fs-plugin-icon, - .fs-connect-logo, - .fs-site-icon - { - border: 1px solid #ccc; - padding: 1px; - background: #fff; - } - } - - .fs-terms - { - text-align: center; - font-size: 0.85em; - padding: 5px; - background: rgba(0, 0, 0, 0.05); - - &, a - { - color: #999; - } - - a - { - text-decoration: none; - } - } -} - -.rtl -{ - #fs_connect - { - .fs-actions - { - padding: 10px 20px; - background: #C0C7CA; - - .button - { - .dashicons - { - font-size: 37px; - margin-left: -8px; - margin-right: 12px; - } - - &.button-primary - { - &:after - { - content: ' \000bb'; - } - - &.fs-loading - { - &:after - { - content: ''; - } - } - } - - &.button-secondary - { - float: left; - } - } - } - - .fs-permissions - { - ul - { - li - { - div - { - margin-right: 55px; - margin-left: 0; - } - - i.dashicons - { - float: right; - } - - } - } - } - - .fs-visual - { - .fs-site-icon - { - right: 20px; - left: auto; - } - - .fs-connect-logo - { - right: auto; - left: 20px; - } - } - } -} - -.wp-pointer-content -{ - #fs_connect - { - margin: 0; - @include box-shadow(none); - } -} - -.fs-opt-in-pointer -{ - .wp-pointer-content - { - padding: 0; - } - - &.wp-pointer-top - { - .wp-pointer-arrow - { - border-bottom-color: #dfdfdf; - } - .wp-pointer-arrow-inner - { - border-bottom-color: #fafafa; - } - } - - &.wp-pointer-bottom - { - .wp-pointer-arrow - { - border-top-color: #dfdfdf; - } - .wp-pointer-arrow-inner - { - border-top-color: #fafafa; - } - } - - &.wp-pointer-left - { - .wp-pointer-arrow - { - border-right-color: #dfdfdf; - } - .wp-pointer-arrow-inner - { - border-right-color: #fafafa; - } - } - - &.wp-pointer-right - { - .wp-pointer-arrow - { - border-left-color: #dfdfdf; - } - .wp-pointer-arrow-inner - { - border-left-color: #fafafa; - } - } -} +@import "../start"; + +$form_width: 480px; + +#fs_connect +{ + width: $form_width; + @include box-shadow(0px 1px 2px rgba(0, 0, 0, 0.3)); + margin: 20px 0; + + @media screen and (max-width: ($form_width - 1)) { + @include box-shadow(none); + width: auto; + margin: 0 0 0 -10px; + } + + .fs-content + { + background: #fff; + padding: 15px 20px; + + p + { + margin: 0; + padding: 0; + font-size: 1.2em; + } + } + + .fs-actions + { + padding: 10px 20px; + background: #C0C7CA; + + .button + { + padding: 0 10px 1px; + line-height: 35px; + height: 37px; + font-size: 16px; + margin-bottom: 0; + + .dashicons + { + font-size: 37px; + margin-left: -8px; + margin-right: 12px; + } + + &.button-primary + { + padding-right: 15px; + padding-left: 15px; + + &:after + { + content: ' \279C'; + } + + &.fs-loading + { + &:after + { + content: ''; + } + } + } + + &.button-secondary + { + float: right; + } + } + + // .fs-skip + // { + // line-height: 38px; + // vertical-align: middle; + // text-decoration: none; + // margin-left: 10px; + // } + } + + &.fs-anonymous-disabled + { + .fs-actions + { + .button.button-primary + { + width: 100%; + } + } + } + + .fs-permissions + { + padding: 10px 20px; + background: #FEFEFE; + // background: #F1F1F1; + @include transition(background 0.5s ease); + + .fs-trigger + { + font-size: 0.9em; + text-decoration: none; + text-align: center; + display: block; + } + + ul + { + height: 0; + overflow: hidden; + margin: 0; + + li + { + margin-bottom: 12px; + + &:last-child + { + margin-bottom: 0; + } + + i.dashicons + { + float: left; + font-size: 40px; + width: 40px; + height: 40px; + } + + div + { + margin-left: 55px; + + span + { + font-weight: bold; + text-transform: uppercase; + color: #23282d; + } + + p + { + margin: 2px 0 0 0; + } + } + } + } + + &.fs-open + { + background: #fff; + + ul + { + height: auto; + margin: 20px 20px 10px 20px; + } + } + + @media screen and (max-width: ($form_width - 1)) { + background: #fff; + + .fs-trigger + { + display: none; + } + + ul + { + height: auto; + margin: 20px; + } + } + } + + $icon_size: 80px; + $wp_logo_padding: $icon_size / 10; + $icons_top: 10px; + + .fs-visual + { + padding: 12px; + line-height: 0; + background: #fafafa; + height: $icon_size; + position: relative; + + .fs-site-icon + { + position: absolute; + left: 20px; + top: $icons_top; + } + + .fs-connect-logo + { + position: absolute; + right: 20px; + top: $icons_top; + } + + .fs-plugin-icon + { + position: absolute; + top: $icons_top; + left: 50%; + margin-left: - ($icon_size / 2); + } + + .fs-plugin-icon, + .fs-site-icon, + img, + object + { + width: $icon_size; + height: $icon_size; + } + + .dashicons-wordpress + { + font-size: $icon_size - ($wp_logo_padding * 2); + background: $wordpress_color; + color: #fff; + width: $icon_size - ($wp_logo_padding * 2); + height: $icon_size - ($wp_logo_padding * 2); + padding: $wp_logo_padding; + } + + .dashicons-plus + { + position: absolute; + top: 50%; + font-size: 30px; + margin-top: -10px; + color: #bbb; + + &.fs-first + { + left: 28%; + } + &.fs-second + { + left: 65%; + } + } + + .fs-plugin-icon, + .fs-connect-logo, + .fs-site-icon + { + border: 1px solid #ccc; + padding: 1px; + background: #fff; + } + } + + .fs-terms + { + text-align: center; + font-size: 0.85em; + padding: 5px; + background: rgba(0, 0, 0, 0.05); + + &, a + { + color: #999; + } + + a + { + text-decoration: none; + } + } +} + +.rtl +{ + #fs_connect + { + .fs-actions + { + padding: 10px 20px; + background: #C0C7CA; + + .button + { + .dashicons + { + font-size: 37px; + margin-left: -8px; + margin-right: 12px; + } + + &.button-primary + { + &:after + { + content: ' \000bb'; + } + + &.fs-loading + { + &:after + { + content: ''; + } + } + } + + &.button-secondary + { + float: left; + } + } + } + + .fs-permissions + { + ul + { + li + { + div + { + margin-right: 55px; + margin-left: 0; + } + + i.dashicons + { + float: right; + } + + } + } + } + + .fs-visual + { + .fs-site-icon + { + right: 20px; + left: auto; + } + + .fs-connect-logo + { + right: auto; + left: 20px; + } + } + } +} + +.wp-pointer-content +{ + #fs_connect + { + margin: 0; + @include box-shadow(none); + } +} + +.fs-opt-in-pointer +{ + .wp-pointer-content + { + padding: 0; + } + + &.wp-pointer-top + { + .wp-pointer-arrow + { + border-bottom-color: #dfdfdf; + } + .wp-pointer-arrow-inner + { + border-bottom-color: #fafafa; + } + } + + &.wp-pointer-bottom + { + .wp-pointer-arrow + { + border-top-color: #dfdfdf; + } + .wp-pointer-arrow-inner + { + border-top-color: #fafafa; + } + } + + &.wp-pointer-left + { + .wp-pointer-arrow + { + border-right-color: #dfdfdf; + } + .wp-pointer-arrow-inner + { + border-right-color: #fafafa; + } + } + + &.wp-pointer-right + { + .wp-pointer-arrow + { + border-left-color: #dfdfdf; + } + .wp-pointer-arrow-inner + { + border-left-color: #fafafa; + } + } +} diff --git a/wp-content/plugins/nextgen-gallery/freemius/assets/scss/admin/debug.scss b/wp-content/plugins/nextgen-gallery/freemius/assets/scss/admin/debug.scss index f1ff001011e53a2ae3dd09134c837c1341a53b69..1c3836d44754934dc994be69981e9e07a4c9eb36 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/assets/scss/admin/debug.scss +++ b/wp-content/plugins/nextgen-gallery/freemius/assets/scss/admin/debug.scss @@ -1,91 +1,91 @@ -@import "../start"; - -.switch -{ - position: relative; - display: inline-block; - font-size: 1.6em; - font-weight: bold; - color: #ccc; - text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.8); - height: 18px; - padding: 6px 6px 5px 6px; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.2); - border-radius: 4px; - background: #ececec; - box-shadow: 0px 0px 4px rgba(0, 0, 0, 0.1), inset 0px 1px 3px 0px rgba(0, 0, 0, 0.1); - cursor: pointer; - - span - { - display: inline-block; width: 35px; - text-transform: uppercase; - - &.on - { - color: $button-primary-bkg; - } - } - - .toggle - { - position: absolute; - top: 1px; - width: 37px; - height: 25px; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.3); - border-radius: 4px; - background: #fff; - background: -moz-linear-gradient(top, #ececec 0%, #fff 100%); - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ececec), color-stop(100%, #fff)); - background: -webkit-linear-gradient(top, #ececec 0%, #fff 100%); - background: -o-linear-gradient(top, #ececec 0%, #fff 100%); - background: -ms-linear-gradient(top, #ececec 0%, #fff 100%); - background: linear-gradient(top, #ececec 0%, #fff 100%); - box-shadow: inset 0px 1px 0px 0px rgba(255, 255, 255, 0.5); - z-index: 999; - @include transition(all 0.15s ease-in-out); - } - - &.on .toggle - { - left: 2%; - } - &.off .toggle - { - left: 54%; - } - - /* Round switch */ - &.round - { - padding: 0px 20px; - border-radius: 40px; - - .toggle - { - border-radius: 40px; - width: 14px; - height: 14px; - } - - &.on .toggle - { - left: 3%; - background: $button-primary-bkg; - } - &.off .toggle - { - left: 58%; - } - } -} - -.switch-label -{ - font-size: 20px; - line-height: 31px; - margin: 0 5px; +@import "../start"; + +.switch +{ + position: relative; + display: inline-block; + font-size: 1.6em; + font-weight: bold; + color: #ccc; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.8); + height: 18px; + padding: 6px 6px 5px 6px; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 4px; + background: #ececec; + box-shadow: 0px 0px 4px rgba(0, 0, 0, 0.1), inset 0px 1px 3px 0px rgba(0, 0, 0, 0.1); + cursor: pointer; + + span + { + display: inline-block; width: 35px; + text-transform: uppercase; + + &.on + { + color: $button-primary-bkg; + } + } + + .toggle + { + position: absolute; + top: 1px; + width: 37px; + height: 25px; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.3); + border-radius: 4px; + background: #fff; + background: -moz-linear-gradient(top, #ececec 0%, #fff 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ececec), color-stop(100%, #fff)); + background: -webkit-linear-gradient(top, #ececec 0%, #fff 100%); + background: -o-linear-gradient(top, #ececec 0%, #fff 100%); + background: -ms-linear-gradient(top, #ececec 0%, #fff 100%); + background: linear-gradient(top, #ececec 0%, #fff 100%); + box-shadow: inset 0px 1px 0px 0px rgba(255, 255, 255, 0.5); + z-index: 999; + @include transition(all 0.15s ease-in-out); + } + + &.on .toggle + { + left: 2%; + } + &.off .toggle + { + left: 54%; + } + + /* Round switch */ + &.round + { + padding: 0px 20px; + border-radius: 40px; + + .toggle + { + border-radius: 40px; + width: 14px; + height: 14px; + } + + &.on .toggle + { + left: 3%; + background: $button-primary-bkg; + } + &.off .toggle + { + left: 58%; + } + } +} + +.switch-label +{ + font-size: 20px; + line-height: 31px; + margin: 0 5px; } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/config.php b/wp-content/plugins/nextgen-gallery/freemius/config.php index 3d5bb8a454508ff58794b075aadaedd95e1ba95c..eb8526aec1df5ad2bf261ec1cdc33607bfba0266 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/config.php +++ b/wp-content/plugins/nextgen-gallery/freemius/config.php @@ -1,229 +1,229 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.4 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - define( 'WP_FS__SLUG', 'freemius' ); - if ( ! defined( 'WP_FS__DEV_MODE' ) ) { - define( 'WP_FS__DEV_MODE', false ); - } - - /** - * API Connectivity Simulation - */ - if ( ! defined( 'WP_FS__SIMULATE_NO_API_CONNECTIVITY' ) ) { - define( 'WP_FS__SIMULATE_NO_API_CONNECTIVITY', false ); - } - if ( ! defined( 'WP_FS__SIMULATE_NO_CURL' ) ) { - define( 'WP_FS__SIMULATE_NO_CURL', false ); - } - if ( ! defined( 'WP_FS__SIMULATE_NO_API_CONNECTIVITY_CLOUDFLARE' ) ) { - define( 'WP_FS__SIMULATE_NO_API_CONNECTIVITY_CLOUDFLARE', false ); - } - if ( ! defined( 'WP_FS__SIMULATE_NO_API_CONNECTIVITY_SQUID_ACL' ) ) { - define( 'WP_FS__SIMULATE_NO_API_CONNECTIVITY_SQUID_ACL', false ); - } - if ( WP_FS__SIMULATE_NO_CURL ) { - define( 'FS_SDK__SIMULATE_NO_CURL', true ); - } - if ( WP_FS__SIMULATE_NO_API_CONNECTIVITY_CLOUDFLARE ) { - define( 'FS_SDK__SIMULATE_NO_API_CONNECTIVITY_CLOUDFLARE', true ); - } - if ( WP_FS__SIMULATE_NO_API_CONNECTIVITY_SQUID_ACL ) { - define( 'FS_SDK__SIMULATE_NO_API_CONNECTIVITY_SQUID_ACL', true ); - } - - if ( ! defined( 'WP_FS__SIMULATE_FREEMIUS_OFF' ) ) { - define( 'WP_FS__SIMULATE_FREEMIUS_OFF', false ); - } - - if ( ! defined( 'WP_FS__PING_API_ON_IP_OR_HOST_CHANGES' ) ) { - /** - * @since 1.1.7.3 - * @author Vova Feldman (@svovaf) - * - * I'm not sure if shared servers periodically change IP, or the subdomain of the - * admin dashboard. Also, I've seen sites that have strange loop of switching - * between domains on a daily basis. Therefore, to eliminate the risk of - * multiple unwanted connectivity test pings, temporary ignore domain or - * server IP changes. - */ - define( 'WP_FS__PING_API_ON_IP_OR_HOST_CHANGES', false ); - } - - /** - * If your dev environment supports custom public network IP setup - * like VVV, please update WP_FS__LOCALHOST_IP with your public IP - * and uncomment it during dev. - */ - if ( ! defined( 'WP_FS__LOCALHOST_IP' ) ) { - // VVV default public network IP. - define( 'WP_FS__VVV_DEFAULT_PUBLIC_IP', '192.168.50.4' ); - -// define( 'WP_FS__LOCALHOST_IP', WP_FS__VVV_DEFAULT_PUBLIC_IP ); - } - - /** - * If true and running with secret key, the opt-in process - * will skip the email activation process which is invoked - * when the email of the context user already exist in Freemius - * database (as a security precaution, to prevent sharing user - * secret with unauthorized entity). - * - * IMPORTANT: - * AS A SECURITY PRECAUTION, WE VALIDATE THE TIMESTAMP OF THE OPT-IN REQUEST. - * THEREFORE, MAKE SURE THAT WHEN USING THIS PARAMETER,YOUR TESTING ENVIRONMENT'S - * CLOCK IS SYNCED. - */ - if ( ! defined( 'WP_FS__SKIP_EMAIL_ACTIVATION' ) ) { - define( 'WP_FS__SKIP_EMAIL_ACTIVATION', false ); - } - - - /** - * Directories - */ - define( 'WP_FS__DIR', dirname( __FILE__ ) ); - define( 'WP_FS__DIR_INCLUDES', WP_FS__DIR . '/includes' ); - define( 'WP_FS__DIR_TEMPLATES', WP_FS__DIR . '/templates' ); - define( 'WP_FS__DIR_ASSETS', WP_FS__DIR . '/assets' ); - define( 'WP_FS__DIR_CSS', WP_FS__DIR_ASSETS . '/css' ); - define( 'WP_FS__DIR_JS', WP_FS__DIR_ASSETS . '/js' ); - define( 'WP_FS__DIR_IMG', WP_FS__DIR_ASSETS . '/img' ); - define( 'WP_FS__DIR_SDK', WP_FS__DIR_INCLUDES . '/sdk' ); - - - /** - * Domain / URL / Address - */ - define( 'WP_FS__DOMAIN_PRODUCTION', 'wp.freemius.com' ); - define( 'WP_FS__ADDRESS_PRODUCTION', 'https://' . WP_FS__DOMAIN_PRODUCTION ); - - if ( ! defined( 'WP_FS__DOMAIN_LOCALHOST' ) ) { - define( 'WP_FS__DOMAIN_LOCALHOST', 'wp.freemius' ); - } - if ( ! defined( 'WP_FS__ADDRESS_LOCALHOST' ) ) { - define( 'WP_FS__ADDRESS_LOCALHOST', 'http://' . WP_FS__DOMAIN_LOCALHOST . ':8080' ); - } - - if ( ! defined( 'WP_FS__TESTING_DOMAIN' ) ) { - define( 'WP_FS__TESTING_DOMAIN', 'fswp' ); - } - - if ( ! defined( 'WP_FS__API_ADDRESS_LOCALHOST' ) ) { - define( 'WP_FS__API_ADDRESS_LOCALHOST', 'http://api.freemius:8080' ); - } - if ( ! defined( 'WP_FS__API_SANDBOX_ADDRESS_LOCALHOST' ) ) { - define( 'WP_FS__API_SANDBOX_ADDRESS_LOCALHOST', 'http://sandbox-api.freemius:8080' ); - } - - define( 'WP_FS__IS_HTTP_REQUEST', isset( $_SERVER['HTTP_HOST'] ) ); - define( 'WP_FS__REMOTE_ADDR', fs_get_ip() ); - - if ( ! defined( 'WP_FS__IS_PRODUCTION_MODE' ) ) { - // By default, run with Freemius production servers. - define( 'WP_FS__IS_PRODUCTION_MODE', true ); - } - - define( 'WP_FS__ADDRESS', ( WP_FS__IS_PRODUCTION_MODE ? WP_FS__ADDRESS_PRODUCTION : WP_FS__ADDRESS_LOCALHOST ) ); - - if ( defined( 'WP_FS__LOCALHOST_IP' ) ) { - define( 'WP_FS__IS_LOCALHOST', ( WP_FS__LOCALHOST_IP === WP_FS__REMOTE_ADDR ) ); - } else { - define( 'WP_FS__IS_LOCALHOST', WP_FS__IS_HTTP_REQUEST && - is_string( WP_FS__REMOTE_ADDR ) && - ( substr( WP_FS__REMOTE_ADDR, 0, 4 ) == '127.' || - WP_FS__REMOTE_ADDR == '::1' ) - ); - } - - define( 'WP_FS__IS_LOCALHOST_FOR_SERVER', ( ! WP_FS__IS_HTTP_REQUEST || - false !== strpos( $_SERVER['HTTP_HOST'], 'localhost' ) ) ); - - // Set API address for local testing. - if ( ! WP_FS__IS_PRODUCTION_MODE ) { - define( 'FS_API__ADDRESS', WP_FS__API_ADDRESS_LOCALHOST ); - define( 'FS_API__SANDBOX_ADDRESS', WP_FS__API_SANDBOX_ADDRESS_LOCALHOST ); - } - - define( 'WP_FS___OPTION_PREFIX', 'fs' . ( WP_FS__IS_PRODUCTION_MODE ? '' : '_dbg' ) . '_' ); - - if ( ! defined( 'WP_FS__ACCOUNTS_OPTION_NAME' ) ) { - define( 'WP_FS__ACCOUNTS_OPTION_NAME', WP_FS___OPTION_PREFIX . 'accounts' ); - } - if ( ! defined( 'WP_FS__API_CACHE_OPTION_NAME' ) ) { - define( 'WP_FS__API_CACHE_OPTION_NAME', WP_FS___OPTION_PREFIX . 'api_cache' ); - } - define( 'WP_FS__OPTIONS_OPTION_NAME', WP_FS___OPTION_PREFIX . 'options' ); - - define( 'WP_FS__IS_HTTPS', ( WP_FS__IS_HTTP_REQUEST && - // Checks if CloudFlare's HTTPS (Flexible SSL support) - isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && 'https' === strtolower( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) ) || - // Check if HTTPS request. - ( isset( $_SERVER['HTTPS'] ) && 'on' == $_SERVER['HTTPS'] ) || - ( isset( $_SERVER['SERVER_PORT'] ) && 443 == $_SERVER['SERVER_PORT'] ) - ); - - define( 'WP_FS__IS_POST_REQUEST', ( WP_FS__IS_HTTP_REQUEST && - strtoupper( $_SERVER['REQUEST_METHOD'] ) == 'POST' ) ); - - /** - * Billing Frequencies - */ - define( 'WP_FS__PERIOD_ANNUALLY', 'annual' ); - define( 'WP_FS__PERIOD_MONTHLY', 'monthly' ); - define( 'WP_FS__PERIOD_LIFETIME', 'lifetime' ); - - /** - * Plans - */ - define( 'WP_FS__PLAN_DEFAULT_PAID', false ); - define( 'WP_FS__PLAN_FREE', 'free' ); - define( 'WP_FS__PLAN_TRIAL', 'trial' ); - - /** - * Times in seconds - */ - define( 'WP_FS__TIME_5_MIN_IN_SEC', 300 ); - define( 'WP_FS__TIME_10_MIN_IN_SEC', 600 ); -// define( 'WP_FS__TIME_15_MIN_IN_SEC', 900 ); - define( 'WP_FS__TIME_24_HOURS_IN_SEC', 86400 ); - - /** - * Debugging - */ - if ( ! defined( 'WP_FS__DEBUG_SDK' ) ) { - $debug_mode = get_option( 'fs_debug_mode', null ); - - if ( $debug_mode === null ) { - $debug_mode = false; - add_option( 'fs_debug_mode', $debug_mode ); - } - - define( 'WP_FS__DEBUG_SDK', is_numeric( $debug_mode ) ? ( 0 < $debug_mode ) : WP_FS__DEV_MODE ); - } - - define( 'WP_FS__ECHO_DEBUG_SDK', WP_FS__DEV_MODE && ! empty( $_GET['fs_dbg_echo'] ) ); - define( 'WP_FS__LOG_DATETIME_FORMAT', 'Y-n-d H:i:s' ); - if ( ! defined( 'FS_API__LOGGER_ON' ) ) { - define( 'FS_API__LOGGER_ON', WP_FS__DEBUG_SDK ); - } - - if ( WP_FS__ECHO_DEBUG_SDK ) { - error_reporting( E_ALL ); - ini_set( 'error_reporting', E_ALL ); - ini_set( 'display_errors', true ); - ini_set( 'html_errors', true ); - } - - - define( 'WP_FS__SCRIPT_START_TIME', time() ); - define( 'WP_FS__DEFAULT_PRIORITY', 10 ); - define( 'WP_FS__LOWEST_PRIORITY', 999999999 ); +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.4 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + define( 'WP_FS__SLUG', 'freemius' ); + if ( ! defined( 'WP_FS__DEV_MODE' ) ) { + define( 'WP_FS__DEV_MODE', false ); + } + + /** + * API Connectivity Simulation + */ + if ( ! defined( 'WP_FS__SIMULATE_NO_API_CONNECTIVITY' ) ) { + define( 'WP_FS__SIMULATE_NO_API_CONNECTIVITY', false ); + } + if ( ! defined( 'WP_FS__SIMULATE_NO_CURL' ) ) { + define( 'WP_FS__SIMULATE_NO_CURL', false ); + } + if ( ! defined( 'WP_FS__SIMULATE_NO_API_CONNECTIVITY_CLOUDFLARE' ) ) { + define( 'WP_FS__SIMULATE_NO_API_CONNECTIVITY_CLOUDFLARE', false ); + } + if ( ! defined( 'WP_FS__SIMULATE_NO_API_CONNECTIVITY_SQUID_ACL' ) ) { + define( 'WP_FS__SIMULATE_NO_API_CONNECTIVITY_SQUID_ACL', false ); + } + if ( WP_FS__SIMULATE_NO_CURL ) { + define( 'FS_SDK__SIMULATE_NO_CURL', true ); + } + if ( WP_FS__SIMULATE_NO_API_CONNECTIVITY_CLOUDFLARE ) { + define( 'FS_SDK__SIMULATE_NO_API_CONNECTIVITY_CLOUDFLARE', true ); + } + if ( WP_FS__SIMULATE_NO_API_CONNECTIVITY_SQUID_ACL ) { + define( 'FS_SDK__SIMULATE_NO_API_CONNECTIVITY_SQUID_ACL', true ); + } + + if ( ! defined( 'WP_FS__SIMULATE_FREEMIUS_OFF' ) ) { + define( 'WP_FS__SIMULATE_FREEMIUS_OFF', false ); + } + + if ( ! defined( 'WP_FS__PING_API_ON_IP_OR_HOST_CHANGES' ) ) { + /** + * @since 1.1.7.3 + * @author Vova Feldman (@svovaf) + * + * I'm not sure if shared servers periodically change IP, or the subdomain of the + * admin dashboard. Also, I've seen sites that have strange loop of switching + * between domains on a daily basis. Therefore, to eliminate the risk of + * multiple unwanted connectivity test pings, temporary ignore domain or + * server IP changes. + */ + define( 'WP_FS__PING_API_ON_IP_OR_HOST_CHANGES', false ); + } + + /** + * If your dev environment supports custom public network IP setup + * like VVV, please update WP_FS__LOCALHOST_IP with your public IP + * and uncomment it during dev. + */ + if ( ! defined( 'WP_FS__LOCALHOST_IP' ) ) { + // VVV default public network IP. + define( 'WP_FS__VVV_DEFAULT_PUBLIC_IP', '192.168.50.4' ); + +// define( 'WP_FS__LOCALHOST_IP', WP_FS__VVV_DEFAULT_PUBLIC_IP ); + } + + /** + * If true and running with secret key, the opt-in process + * will skip the email activation process which is invoked + * when the email of the context user already exist in Freemius + * database (as a security precaution, to prevent sharing user + * secret with unauthorized entity). + * + * IMPORTANT: + * AS A SECURITY PRECAUTION, WE VALIDATE THE TIMESTAMP OF THE OPT-IN REQUEST. + * THEREFORE, MAKE SURE THAT WHEN USING THIS PARAMETER,YOUR TESTING ENVIRONMENT'S + * CLOCK IS SYNCED. + */ + if ( ! defined( 'WP_FS__SKIP_EMAIL_ACTIVATION' ) ) { + define( 'WP_FS__SKIP_EMAIL_ACTIVATION', false ); + } + + + /** + * Directories + */ + define( 'WP_FS__DIR', dirname( __FILE__ ) ); + define( 'WP_FS__DIR_INCLUDES', WP_FS__DIR . '/includes' ); + define( 'WP_FS__DIR_TEMPLATES', WP_FS__DIR . '/templates' ); + define( 'WP_FS__DIR_ASSETS', WP_FS__DIR . '/assets' ); + define( 'WP_FS__DIR_CSS', WP_FS__DIR_ASSETS . '/css' ); + define( 'WP_FS__DIR_JS', WP_FS__DIR_ASSETS . '/js' ); + define( 'WP_FS__DIR_IMG', WP_FS__DIR_ASSETS . '/img' ); + define( 'WP_FS__DIR_SDK', WP_FS__DIR_INCLUDES . '/sdk' ); + + + /** + * Domain / URL / Address + */ + define( 'WP_FS__DOMAIN_PRODUCTION', 'wp.freemius.com' ); + define( 'WP_FS__ADDRESS_PRODUCTION', 'https://' . WP_FS__DOMAIN_PRODUCTION ); + + if ( ! defined( 'WP_FS__DOMAIN_LOCALHOST' ) ) { + define( 'WP_FS__DOMAIN_LOCALHOST', 'wp.freemius' ); + } + if ( ! defined( 'WP_FS__ADDRESS_LOCALHOST' ) ) { + define( 'WP_FS__ADDRESS_LOCALHOST', 'http://' . WP_FS__DOMAIN_LOCALHOST . ':8080' ); + } + + if ( ! defined( 'WP_FS__TESTING_DOMAIN' ) ) { + define( 'WP_FS__TESTING_DOMAIN', 'fswp' ); + } + + if ( ! defined( 'WP_FS__API_ADDRESS_LOCALHOST' ) ) { + define( 'WP_FS__API_ADDRESS_LOCALHOST', 'http://api.freemius:8080' ); + } + if ( ! defined( 'WP_FS__API_SANDBOX_ADDRESS_LOCALHOST' ) ) { + define( 'WP_FS__API_SANDBOX_ADDRESS_LOCALHOST', 'http://sandbox-api.freemius:8080' ); + } + + define( 'WP_FS__IS_HTTP_REQUEST', isset( $_SERVER['HTTP_HOST'] ) ); + define( 'WP_FS__REMOTE_ADDR', fs_get_ip() ); + + if ( ! defined( 'WP_FS__IS_PRODUCTION_MODE' ) ) { + // By default, run with Freemius production servers. + define( 'WP_FS__IS_PRODUCTION_MODE', true ); + } + + define( 'WP_FS__ADDRESS', ( WP_FS__IS_PRODUCTION_MODE ? WP_FS__ADDRESS_PRODUCTION : WP_FS__ADDRESS_LOCALHOST ) ); + + if ( defined( 'WP_FS__LOCALHOST_IP' ) ) { + define( 'WP_FS__IS_LOCALHOST', ( WP_FS__LOCALHOST_IP === WP_FS__REMOTE_ADDR ) ); + } else { + define( 'WP_FS__IS_LOCALHOST', WP_FS__IS_HTTP_REQUEST && + is_string( WP_FS__REMOTE_ADDR ) && + ( substr( WP_FS__REMOTE_ADDR, 0, 4 ) == '127.' || + WP_FS__REMOTE_ADDR == '::1' ) + ); + } + + define( 'WP_FS__IS_LOCALHOST_FOR_SERVER', ( ! WP_FS__IS_HTTP_REQUEST || + false !== strpos( $_SERVER['HTTP_HOST'], 'localhost' ) ) ); + + // Set API address for local testing. + if ( ! WP_FS__IS_PRODUCTION_MODE ) { + define( 'FS_API__ADDRESS', WP_FS__API_ADDRESS_LOCALHOST ); + define( 'FS_API__SANDBOX_ADDRESS', WP_FS__API_SANDBOX_ADDRESS_LOCALHOST ); + } + + define( 'WP_FS___OPTION_PREFIX', 'fs' . ( WP_FS__IS_PRODUCTION_MODE ? '' : '_dbg' ) . '_' ); + + if ( ! defined( 'WP_FS__ACCOUNTS_OPTION_NAME' ) ) { + define( 'WP_FS__ACCOUNTS_OPTION_NAME', WP_FS___OPTION_PREFIX . 'accounts' ); + } + if ( ! defined( 'WP_FS__API_CACHE_OPTION_NAME' ) ) { + define( 'WP_FS__API_CACHE_OPTION_NAME', WP_FS___OPTION_PREFIX . 'api_cache' ); + } + define( 'WP_FS__OPTIONS_OPTION_NAME', WP_FS___OPTION_PREFIX . 'options' ); + + define( 'WP_FS__IS_HTTPS', ( WP_FS__IS_HTTP_REQUEST && + // Checks if CloudFlare's HTTPS (Flexible SSL support) + isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && 'https' === strtolower( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) ) || + // Check if HTTPS request. + ( isset( $_SERVER['HTTPS'] ) && 'on' == $_SERVER['HTTPS'] ) || + ( isset( $_SERVER['SERVER_PORT'] ) && 443 == $_SERVER['SERVER_PORT'] ) + ); + + define( 'WP_FS__IS_POST_REQUEST', ( WP_FS__IS_HTTP_REQUEST && + strtoupper( $_SERVER['REQUEST_METHOD'] ) == 'POST' ) ); + + /** + * Billing Frequencies + */ + define( 'WP_FS__PERIOD_ANNUALLY', 'annual' ); + define( 'WP_FS__PERIOD_MONTHLY', 'monthly' ); + define( 'WP_FS__PERIOD_LIFETIME', 'lifetime' ); + + /** + * Plans + */ + define( 'WP_FS__PLAN_DEFAULT_PAID', false ); + define( 'WP_FS__PLAN_FREE', 'free' ); + define( 'WP_FS__PLAN_TRIAL', 'trial' ); + + /** + * Times in seconds + */ + define( 'WP_FS__TIME_5_MIN_IN_SEC', 300 ); + define( 'WP_FS__TIME_10_MIN_IN_SEC', 600 ); +// define( 'WP_FS__TIME_15_MIN_IN_SEC', 900 ); + define( 'WP_FS__TIME_24_HOURS_IN_SEC', 86400 ); + + /** + * Debugging + */ + if ( ! defined( 'WP_FS__DEBUG_SDK' ) ) { + $debug_mode = get_option( 'fs_debug_mode', null ); + + if ( $debug_mode === null ) { + $debug_mode = false; + add_option( 'fs_debug_mode', $debug_mode ); + } + + define( 'WP_FS__DEBUG_SDK', is_numeric( $debug_mode ) ? ( 0 < $debug_mode ) : WP_FS__DEV_MODE ); + } + + define( 'WP_FS__ECHO_DEBUG_SDK', WP_FS__DEV_MODE && ! empty( $_GET['fs_dbg_echo'] ) ); + define( 'WP_FS__LOG_DATETIME_FORMAT', 'Y-n-d H:i:s' ); + if ( ! defined( 'FS_API__LOGGER_ON' ) ) { + define( 'FS_API__LOGGER_ON', WP_FS__DEBUG_SDK ); + } + + if ( WP_FS__ECHO_DEBUG_SDK ) { + error_reporting( E_ALL ); + ini_set( 'error_reporting', E_ALL ); + ini_set( 'display_errors', true ); + ini_set( 'html_errors', true ); + } + + + define( 'WP_FS__SCRIPT_START_TIME', time() ); + define( 'WP_FS__DEFAULT_PRIORITY', 10 ); + define( 'WP_FS__LOWEST_PRIORITY', 999999999 ); diff --git a/wp-content/plugins/nextgen-gallery/freemius/includes/class-freemius-abstract.php b/wp-content/plugins/nextgen-gallery/freemius/includes/class-freemius-abstract.php index 0b42c71bb6390d1bff6b7499777db48301d038cb..9d08494bb5b7ce80054b5ee22db1786117afd37e 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/includes/class-freemius-abstract.php +++ b/wp-content/plugins/nextgen-gallery/freemius/includes/class-freemius-abstract.php @@ -1,404 +1,404 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.7 - */ - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - - /** - * - Each instance of Freemius class represents a single plugin - * install by a single user (the installer of the plugin). - * - * - Each website can only have one install of the same plugin. - * - * - Install entity is only created after a user connects his account with Freemius. - * - * Class Freemius_Abstract - */ - abstract class Freemius_Abstract { - - #region Identity ------------------------------------------------------------------ - - /** - * Check if user registered with Freemius by connecting his account. - * - * @since 1.0.1 - * @return bool - */ - abstract function is_registered(); - - /** - * Check if the user skipped connecting the account with Freemius. - * - * @since 1.0.7 - * - * @return bool - */ - abstract function is_anonymous(); - - /** - * Check if the user currently in activation mode. - * - * @since 1.0.7 - * - * @return bool - */ - abstract function is_activation_mode(); - - #endregion Identity ------------------------------------------------------------------ - - #region Permissions ------------------------------------------------------------------ - - /** - * Check if plugin must be WordPress.org compliant. - * - * @since 1.0.7 - * - * @return bool - */ - abstract function is_org_repo_compliant(); - - /** - * Check if plugin is allowed to install executable files. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.5 - * - * @return bool - */ - function is_allowed_to_install() { - return ( $this->is_premium() || ! $this->is_org_repo_compliant() ); - } - - #endregion Permissions ------------------------------------------------------------------ - - /** - * Check if user in trial or in free plan (not paying). - * - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - * - * @return bool - */ - function is_not_paying() { - return ( $this->is_trial() || $this->is_free_plan() ); - } - - /** - * Check if the user has an activated and valid paid license on current plugin's install. - * - * @since 1.0.9 - * - * @return bool - */ - abstract function is_paying(); - - /** - * Check if the user is paying or in trial. - * - * @since 1.0.9 - * - * @return bool - */ - function is_paying_or_trial() { - return ( $this->is_paying() || $this->is_trial() ); - } - - #region Premium Only ------------------------------------------------------------------ - - /** - * All logic wrapped in methods with "__premium_only()" suffix will be only - * included in the premium code. - * - * Example: - * if ( freemius()->is__premium_only() ) { - * ... - * } - */ - - /** - * Returns true when running premium plugin code. - * - * @since 1.0.9 - * - * @return bool - */ - function is__premium_only() { - return $this->is_premium(); - } - - /** - * Check if the user has an activated and valid paid license on current plugin's install. - * - * @since 1.0.9 - * - * @return bool - * - */ - function is_paying__premium_only() { - return ( $this->is__premium_only() && $this->is_paying() ); - } - - /** - * All code wrapped in this statement will be only included in the premium code. - * - * @since 1.0.9 - * - * @param string $plan Plan name - * @param bool $exact If true, looks for exact plan. If false, also check "higher" plans. - * - * @return bool - */ - function is_plan__premium_only( $plan, $exact = false ) { - return ( $this->is_premium() && $this->is_plan( $plan, $exact ) ); - } - - /** - * Check if plan matches active license' plan or active trial license' plan. - * - * All code wrapped in this statement will be only included in the premium code. - * - * @since 1.0.9 - * - * @param string $plan Plan name - * @param bool $exact If true, looks for exact plan. If false, also check "higher" plans. - * - * @return bool - */ - function is_plan_or_trial__premium_only( $plan, $exact = false ) { - return ( $this->is_premium() && $this->is_plan_or_trial( $plan, $exact ) ); - } - - /** - * Check if the user is paying or in trial. - * - * All code wrapped in this statement will be only included in the premium code. - * - * @since 1.0.9 - * - * @return bool - */ - function is_paying_or_trial__premium_only() { - return $this->is_premium() && $this->is_paying_or_trial(); - } - - /** - * Check if the user has an activated and valid paid license on current plugin's install. - * - * @since 1.0.4 - * - * @return bool - * - * @deprecated Method name is confusing since it's not clear from the name the code will be removed. - * @using Alias to is_paying__premium_only() - */ - function is_paying__fs__() { - return $this->is_paying__premium_only(); - } - - #endregion Premium Only ------------------------------------------------------------------ - - #region Trial ------------------------------------------------------------------ - - /** - * Check if the user in a trial. - * - * @since 1.0.3 - * - * @return bool - */ - abstract function is_trial(); - - /** - * Check if trial already utilized. - * - * @since 1.0.9 - * - * @return bool - */ - abstract function is_trial_utilized(); - - #endregion Trial ------------------------------------------------------------------ - - #region Plans ------------------------------------------------------------------ - - /** - * Check if plugin using the free plan. - * - * @since 1.0.4 - * - * @return bool - */ - abstract function is_free_plan(); - - /** - * @since 1.0.2 - * - * @param string $plan Plan name - * @param bool $exact If true, looks for exact plan. If false, also check "higher" plans. - * - * @return bool - */ - abstract function is_plan( $plan, $exact = false ); - - /** - * Check if plan based on trial. If not in trial mode, should return false. - * - * @since 1.0.9 - * - * @param string $plan Plan name - * @param bool $exact If true, looks for exact plan. If false, also check "higher" plans. - * - * @return bool - */ - abstract function is_trial_plan( $plan, $exact = false ); - - /** - * Check if plan matches active license' plan or active trial license' plan. - * - * @since 1.0.9 - * - * @param string $plan Plan name - * @param bool $exact If true, looks for exact plan. If false, also check "higher" plans. - * - * @return bool - */ - function is_plan_or_trial( $plan, $exact = false ) { - return $this->is_plan( $plan, $exact ) || - $this->is_trial_plan( $plan, $exact ); - } - - /** - * Check if plugin has any paid plans. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - * - * @return bool - */ - abstract function has_paid_plan(); - - /** - * Check if plugin has any free plan, or is it premium only. - * - * Note: If no plans configured, assume plugin is free. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - * - * @return bool - */ - abstract function has_free_plan(); - - #endregion Plans ------------------------------------------------------------------ - - /** - * Check if running payments in sandbox mode. - * - * @since 1.0.4 - * - * @return bool - */ - abstract function is_payments_sandbox(); - - /** - * Check if running test vs. live plugin. - * - * @since 1.0.5 - * - * @return bool - */ - abstract function is_live(); - - /** - * Check if running premium plugin code. - * - * @since 1.0.5 - * - * @return bool - */ - abstract function is_premium(); - - /** - * Get upgrade URL. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.2 - * - * @param string $period Billing cycle - * - * @return string - */ - abstract function get_upgrade_url( $period = WP_FS__PERIOD_ANNUALLY ); - - /** - * Check if Freemius was first added in a plugin update. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.5 - * - * @return bool - */ - function is_plugin_update() { - return ! $this->is_plugin_new_install(); - } - - /** - * Check if Freemius was part of the plugin when the user installed it first. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.5 - * - * @return bool - */ - abstract function is_plugin_new_install(); - - #region Marketing ------------------------------------------------------------------ - - /** - * Check if current user purchased any other plugins before. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @return bool - */ - abstract function has_purchased_before(); - - /** - * Check if current user classified as an agency. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @return bool - */ - abstract function is_agency(); - - /** - * Check if current user classified as a developer. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @return bool - */ - abstract function is_developer(); - - /** - * Check if current user classified as a business. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @return bool - */ - abstract function is_business(); - - #endregion ------------------------------------------------------------------ +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.7 + */ + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + + /** + * - Each instance of Freemius class represents a single plugin + * install by a single user (the installer of the plugin). + * + * - Each website can only have one install of the same plugin. + * + * - Install entity is only created after a user connects his account with Freemius. + * + * Class Freemius_Abstract + */ + abstract class Freemius_Abstract { + + #region Identity ------------------------------------------------------------------ + + /** + * Check if user registered with Freemius by connecting his account. + * + * @since 1.0.1 + * @return bool + */ + abstract function is_registered(); + + /** + * Check if the user skipped connecting the account with Freemius. + * + * @since 1.0.7 + * + * @return bool + */ + abstract function is_anonymous(); + + /** + * Check if the user currently in activation mode. + * + * @since 1.0.7 + * + * @return bool + */ + abstract function is_activation_mode(); + + #endregion Identity ------------------------------------------------------------------ + + #region Permissions ------------------------------------------------------------------ + + /** + * Check if plugin must be WordPress.org compliant. + * + * @since 1.0.7 + * + * @return bool + */ + abstract function is_org_repo_compliant(); + + /** + * Check if plugin is allowed to install executable files. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.5 + * + * @return bool + */ + function is_allowed_to_install() { + return ( $this->is_premium() || ! $this->is_org_repo_compliant() ); + } + + #endregion Permissions ------------------------------------------------------------------ + + /** + * Check if user in trial or in free plan (not paying). + * + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + * + * @return bool + */ + function is_not_paying() { + return ( $this->is_trial() || $this->is_free_plan() ); + } + + /** + * Check if the user has an activated and valid paid license on current plugin's install. + * + * @since 1.0.9 + * + * @return bool + */ + abstract function is_paying(); + + /** + * Check if the user is paying or in trial. + * + * @since 1.0.9 + * + * @return bool + */ + function is_paying_or_trial() { + return ( $this->is_paying() || $this->is_trial() ); + } + + #region Premium Only ------------------------------------------------------------------ + + /** + * All logic wrapped in methods with "__premium_only()" suffix will be only + * included in the premium code. + * + * Example: + * if ( freemius()->is__premium_only() ) { + * ... + * } + */ + + /** + * Returns true when running premium plugin code. + * + * @since 1.0.9 + * + * @return bool + */ + function is__premium_only() { + return $this->is_premium(); + } + + /** + * Check if the user has an activated and valid paid license on current plugin's install. + * + * @since 1.0.9 + * + * @return bool + * + */ + function is_paying__premium_only() { + return ( $this->is__premium_only() && $this->is_paying() ); + } + + /** + * All code wrapped in this statement will be only included in the premium code. + * + * @since 1.0.9 + * + * @param string $plan Plan name + * @param bool $exact If true, looks for exact plan. If false, also check "higher" plans. + * + * @return bool + */ + function is_plan__premium_only( $plan, $exact = false ) { + return ( $this->is_premium() && $this->is_plan( $plan, $exact ) ); + } + + /** + * Check if plan matches active license' plan or active trial license' plan. + * + * All code wrapped in this statement will be only included in the premium code. + * + * @since 1.0.9 + * + * @param string $plan Plan name + * @param bool $exact If true, looks for exact plan. If false, also check "higher" plans. + * + * @return bool + */ + function is_plan_or_trial__premium_only( $plan, $exact = false ) { + return ( $this->is_premium() && $this->is_plan_or_trial( $plan, $exact ) ); + } + + /** + * Check if the user is paying or in trial. + * + * All code wrapped in this statement will be only included in the premium code. + * + * @since 1.0.9 + * + * @return bool + */ + function is_paying_or_trial__premium_only() { + return $this->is_premium() && $this->is_paying_or_trial(); + } + + /** + * Check if the user has an activated and valid paid license on current plugin's install. + * + * @since 1.0.4 + * + * @return bool + * + * @deprecated Method name is confusing since it's not clear from the name the code will be removed. + * @using Alias to is_paying__premium_only() + */ + function is_paying__fs__() { + return $this->is_paying__premium_only(); + } + + #endregion Premium Only ------------------------------------------------------------------ + + #region Trial ------------------------------------------------------------------ + + /** + * Check if the user in a trial. + * + * @since 1.0.3 + * + * @return bool + */ + abstract function is_trial(); + + /** + * Check if trial already utilized. + * + * @since 1.0.9 + * + * @return bool + */ + abstract function is_trial_utilized(); + + #endregion Trial ------------------------------------------------------------------ + + #region Plans ------------------------------------------------------------------ + + /** + * Check if plugin using the free plan. + * + * @since 1.0.4 + * + * @return bool + */ + abstract function is_free_plan(); + + /** + * @since 1.0.2 + * + * @param string $plan Plan name + * @param bool $exact If true, looks for exact plan. If false, also check "higher" plans. + * + * @return bool + */ + abstract function is_plan( $plan, $exact = false ); + + /** + * Check if plan based on trial. If not in trial mode, should return false. + * + * @since 1.0.9 + * + * @param string $plan Plan name + * @param bool $exact If true, looks for exact plan. If false, also check "higher" plans. + * + * @return bool + */ + abstract function is_trial_plan( $plan, $exact = false ); + + /** + * Check if plan matches active license' plan or active trial license' plan. + * + * @since 1.0.9 + * + * @param string $plan Plan name + * @param bool $exact If true, looks for exact plan. If false, also check "higher" plans. + * + * @return bool + */ + function is_plan_or_trial( $plan, $exact = false ) { + return $this->is_plan( $plan, $exact ) || + $this->is_trial_plan( $plan, $exact ); + } + + /** + * Check if plugin has any paid plans. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + * + * @return bool + */ + abstract function has_paid_plan(); + + /** + * Check if plugin has any free plan, or is it premium only. + * + * Note: If no plans configured, assume plugin is free. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + * + * @return bool + */ + abstract function has_free_plan(); + + #endregion Plans ------------------------------------------------------------------ + + /** + * Check if running payments in sandbox mode. + * + * @since 1.0.4 + * + * @return bool + */ + abstract function is_payments_sandbox(); + + /** + * Check if running test vs. live plugin. + * + * @since 1.0.5 + * + * @return bool + */ + abstract function is_live(); + + /** + * Check if running premium plugin code. + * + * @since 1.0.5 + * + * @return bool + */ + abstract function is_premium(); + + /** + * Get upgrade URL. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.2 + * + * @param string $period Billing cycle + * + * @return string + */ + abstract function get_upgrade_url( $period = WP_FS__PERIOD_ANNUALLY ); + + /** + * Check if Freemius was first added in a plugin update. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.5 + * + * @return bool + */ + function is_plugin_update() { + return ! $this->is_plugin_new_install(); + } + + /** + * Check if Freemius was part of the plugin when the user installed it first. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.5 + * + * @return bool + */ + abstract function is_plugin_new_install(); + + #region Marketing ------------------------------------------------------------------ + + /** + * Check if current user purchased any other plugins before. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @return bool + */ + abstract function has_purchased_before(); + + /** + * Check if current user classified as an agency. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @return bool + */ + abstract function is_agency(); + + /** + * Check if current user classified as a developer. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @return bool + */ + abstract function is_developer(); + + /** + * Check if current user classified as a business. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @return bool + */ + abstract function is_business(); + + #endregion ------------------------------------------------------------------ } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/includes/class-freemius.php b/wp-content/plugins/nextgen-gallery/freemius/includes/class-freemius.php index 9411e0148d64896aac3e8cc38377b1adcf65d80b..9e64158397c322a1386714e825d73abb79df84ce 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/includes/class-freemius.php +++ b/wp-content/plugins/nextgen-gallery/freemius/includes/class-freemius.php @@ -1,9452 +1,9452 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.3 - */ - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - // "final class" - class Freemius extends Freemius_Abstract { - /** - * SDK Version - * - * @var string - */ - public $version = WP_FS__SDK_VERSION; - - #region Plugin Info - - /** - * @since 1.0.1 - * - * @var string - */ - private $_slug; - - /** - * @since 1.0.0 - * - * @var string - */ - private $_plugin_basename; - /** - * @since 1.0.0 - * - * @var string - */ - private $_free_plugin_basename; - /** - * @since 1.0.0 - * - * @var string - */ - private $_plugin_dir_path; - /** - * @since 1.0.0 - * - * @var string - */ - private $_plugin_dir_name; - /** - * @since 1.0.0 - * - * @var string - */ - private $_plugin_main_file_path; - /** - * @var string[] - */ - private $_plugin_data; - /** - * @since 1.0.9 - * - * @var string - */ - private $_plugin_name; - - #endregion Plugin Info - - /** - * @since 1.0.9 - * - * @var bool If false, don't turn Freemius on. - */ - private $_is_on; - - /** - * @since 1.1.3 - * - * @var bool If false, don't turn Freemius on. - */ - private $_is_anonymous; - - /** - * @since 1.0.9 - * @var bool If false, issues with connectivity to Freemius API. - */ - private $_has_api_connection; - - /** - * @since 1.0.9 - * @var bool Hints the SDK if plugin can support anonymous mode (if skip connect is visible). - */ - private $_enable_anonymous; - - /** - * @since 1.1.7.5 - * @var bool Hints the SDK if plugin should run in anonymous mode (only adds feedback form). - */ - private $_anonymous_mode; - - /** - * @since 1.0.8 - * @var bool Hints the SDK if the plugin has any paid plans. - */ - private $_has_paid_plans; - - /** - * @since 1.0.7 - * @var bool Hints the SDK if the plugin is WordPress.org compliant. - */ - private $_is_org_compliant; - - /** - * @since 1.0.7 - * @var bool Hints the SDK if the plugin is has add-ons. - */ - private $_has_addons; - - /** - * @since 1.1.6 - * @var string[]bool. - */ - private $_permissions; - - /** - * @var FS_Key_Value_Storage - */ - private $_storage; - - /** - * @since 1.0.0 - * - * @var FS_Logger - */ - private $_logger; - /** - * @since 1.0.4 - * - * @var FS_Plugin - */ - private $_plugin = false; - /** - * @since 1.0.4 - * - * @var FS_Plugin - */ - private $_parent_plugin = false; - /** - * @since 1.1.1 - * - * @var Freemius - */ - private $_parent = false; - /** - * @since 1.0.1 - * - * @var FS_User - */ - private $_user = false; - /** - * @since 1.0.1 - * - * @var FS_Site - */ - private $_site = false; - /** - * @since 1.0.1 - * - * @var FS_Plugin_License - */ - private $_license; - /** - * @since 1.0.2 - * - * @var FS_Plugin_Plan[] - */ - private $_plans = false; - /** - * @var FS_Plugin_License[] - * @since 1.0.5 - */ - private $_licenses = false; - - /** - * @since 1.0.1 - * - * @var FS_Admin_Menu_Manager - */ - private $_menu; - - /** - * @var FS_Admin_Notice_Manager - */ - private $_admin_notices; - - /** - * @since 1.1.6 - * - * @var FS_Admin_Notice_Manager - */ - private static $_global_admin_notices; - - /** - * @var FS_Logger - * @since 1.0.0 - */ - private static $_static_logger; - - /** - * @var FS_Option_Manager - * @since 1.0.2 - */ - private static $_accounts; - - /** - * @var Freemius[] - */ - private static $_instances = array(); - - - /* Ctor -------------------------------------------------------------------------------------------------------------------*/ - - private function __construct( $slug ) { - $this->_slug = $slug; - - $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $slug, WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); - - $this->_storage = FS_Key_Value_Storage::instance( 'plugin_data', $this->_slug ); - - $this->_plugin_main_file_path = $this->_find_caller_plugin_file(); - $this->_plugin_dir_path = plugin_dir_path( $this->_plugin_main_file_path ); - $this->_plugin_basename = plugin_basename( $this->_plugin_main_file_path ); - $this->_free_plugin_basename = str_replace( '-premium/', '/', $this->_plugin_basename ); - - $base_name_split = explode( '/', $this->_plugin_basename ); - $this->_plugin_dir_name = $base_name_split[0]; - - if ( $this->_logger->is_on() ) { - $this->_logger->info( 'plugin_main_file_path = ' . $this->_plugin_main_file_path ); - $this->_logger->info( 'plugin_dir_path = ' . $this->_plugin_dir_path ); - $this->_logger->info( 'plugin_basename = ' . $this->_plugin_basename ); - $this->_logger->info( 'free_plugin_basename = ' . $this->_free_plugin_basename ); - $this->_logger->info( 'plugin_dir_name = ' . $this->_plugin_dir_name ); - } - - // Remember link between file to slug. - $this->store_file_slug_map(); - - // Store plugin's initial install timestamp. - if ( ! isset( $this->_storage->install_timestamp ) ) { - $this->_storage->install_timestamp = WP_FS__SCRIPT_START_TIME; - } - - $this->_plugin = FS_Plugin_Manager::instance( $this->_slug )->get(); - - $this->_admin_notices = FS_Admin_Notice_Manager::instance( - $slug, - is_object( $this->_plugin ) ? $this->_plugin->title : '' - ); - - if ( 'true' === fs_request_get( 'fs_clear_api_cache' ) || - 'true' === fs_request_is_action( 'restart_freemius' ) - ) { - FS_Api::clear_cache(); - } - - $this->_register_hooks(); - - $this->_load_account(); - - $this->_version_updates_handler(); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - */ - private function _version_updates_handler() { - if ( ! isset( $this->_storage->sdk_version ) || $this->_storage->sdk_version != $this->version ) { - // Freemius version upgrade mode. - $this->_storage->sdk_last_version = $this->_storage->sdk_version; - $this->_storage->sdk_version = $this->version; - - if ( empty( $this->_storage->sdk_last_version ) || - version_compare( $this->_storage->sdk_last_version, $this->version, '<' ) - ) { - $this->_storage->sdk_upgrade_mode = true; - $this->_storage->sdk_downgrade_mode = false; - } else { - $this->_storage->sdk_downgrade_mode = true; - $this->_storage->sdk_upgrade_mode = false; - - } - - $this->do_action( 'sdk_version_update', $this->_storage->sdk_last_version, $this->version ); - } - - $plugin_version = $this->get_plugin_version(); - if ( ! isset( $this->_storage->plugin_version ) || $this->_storage->plugin_version != $plugin_version ) { - // Plugin version upgrade mode. - $this->_storage->plugin_last_version = $this->_storage->plugin_version; - $this->_storage->plugin_version = $plugin_version; - - if ( empty( $this->_storage->plugin_last_version ) || - version_compare( $this->_storage->plugin_last_version, $plugin_version, '<' ) - ) { - $this->_storage->plugin_upgrade_mode = true; - $this->_storage->plugin_downgrade_mode = false; - } else { - $this->_storage->plugin_downgrade_mode = true; - $this->_storage->plugin_upgrade_mode = false; - } - - if ( ! empty( $this->_storage->plugin_last_version ) ) { - // Different version of the plugin was installed before, therefore it's an update. - $this->_storage->is_plugin_new_install = false; - } - - $this->do_action( 'plugin_version_update', $this->_storage->plugin_last_version, $plugin_version ); - } - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.5 - * - * @param string $sdk_prev_version - * @param string $sdk_version - */ - function _data_migration( $sdk_prev_version, $sdk_version ) { - /** - * @since 1.1.7.3 Fixed unwanted connectivity test cleanup. - */ - if ( empty( $sdk_prev_version ) ) { - return; - } - - if ( version_compare( $sdk_prev_version, '1.1.5', '<' ) && - version_compare( $sdk_version, '1.1.5', '>=' ) - ) { - // On version 1.1.5 merged connectivity and is_on data. - if ( isset( $this->_storage->connectivity_test ) ) { - if ( ! isset( $this->_storage->is_on ) ) { - unset( $this->_storage->connectivity_test ); - } else { - $connectivity_data = $this->_storage->connectivity_test; - $connectivity_data['is_active'] = $this->_storage->is_on['is_active']; - $connectivity_data['timestamp'] = $this->_storage->is_on['timestamp']; - - // Override. - $this->_storage->connectivity_test = $connectivity_data; - - // Remove previous structure. - unset( $this->_storage->is_on ); - } - - } - } - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - */ - private function _register_hooks() { - if ( is_admin() ) { - // Hook to plugin activation - register_activation_hook( $this->_plugin_main_file_path, array( - &$this, - '_activate_plugin_event_hook' - ) ); - - // Hook to plugin uninstall. - register_uninstall_hook( $this->_plugin_main_file_path, array( 'Freemius', '_uninstall_plugin_hook' ) ); - - if ( ! $this->is_ajax() ) { - if ( ! $this->is_addon() ) { - add_action( 'init', array( &$this, '_add_default_submenu_items' ), WP_FS__LOWEST_PRIORITY ); - add_action( 'admin_menu', array( &$this, '_prepare_admin_menu' ), WP_FS__LOWEST_PRIORITY ); - } - } - } - - register_deactivation_hook( $this->_plugin_main_file_path, array( &$this, '_deactivate_plugin_hook' ) ); - - add_action( 'init', array( &$this, '_redirect_on_clicked_menu_link' ), WP_FS__LOWEST_PRIORITY ); - - $this->add_action( 'after_plans_sync', array( &$this, '_check_for_trial_plans' ) ); - - $this->add_action( 'sdk_version_update', array( &$this, '_data_migration' ), WP_FS__DEFAULT_PRIORITY, 2 ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - */ - private function _register_account_hooks() { - if ( is_admin() ) { - if ( ! $this->is_ajax() ) { - if ( $this->apply_filters( 'show_trial', true ) && $this->has_trial_plan() ) { - $last_time_trial_promotion_shown = $this->_storage->get( 'trial_promotion_shown', false ); - if ( ! $this->_site->is_trial_utilized() && - ( - // Show promotion if never shown it yet and 24 hours after initial activation. - ( false === $last_time_trial_promotion_shown && $this->_storage->activation_timestamp < ( time() - WP_FS__TIME_24_HOURS_IN_SEC ) ) || - // Show promotion in every 30 days. - ( is_numeric( $last_time_trial_promotion_shown ) && 30 * WP_FS__TIME_24_HOURS_IN_SEC < time() - $last_time_trial_promotion_shown ) ) - ) { - $this->add_action( 'after_init_plugin_registered', array( &$this, '_add_trial_notice' ) ); - } - } - } - - // If user is paying or in trial and have the free version installed, - // assume that the deactivation is for the upgrade process. - if ( ! $this->is_paying_or_trial() || $this->is_premium() ) { - add_action( 'wp_ajax_submit-uninstall-reason', array( &$this, '_submit_uninstall_reason_action' ) ); - - global $pagenow; - if ( 'plugins.php' === $pagenow ) { - add_action( 'admin_footer', array( &$this, '_add_deactivation_feedback_dialog_box' ) ); - } - } - } - } - - /** - * Leverage backtrace to find caller plugin file path. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @return string - * - * @uses fs_find_caller_plugin_file - */ - private function _find_caller_plugin_file() { - // Try to load the cached value of the file path. - if ( isset( $this->_storage->plugin_main_file ) ) { - if ( file_exists( $this->_storage->plugin_main_file->path ) ) { - return $this->_storage->plugin_main_file->path; - } - } - - $plugin_file = fs_find_caller_plugin_file(); - - $this->_storage->plugin_main_file = (object) array( - 'path' => fs_normalize_path( $plugin_file ), - ); - - return $plugin_file; - } - - - #region Deactivation Feedback Form ------------------------------------------------------------------ - - /** - * Displays a confirmation and feedback dialog box when the user clicks on the "Deactivate" link on the plugins - * page. - * - * @author Vova Feldman (@svovaf) - * @author Leo Fajardo (@leorw) - * @since 1.1.2 - */ - function _add_deactivation_feedback_dialog_box() { - fs_enqueue_local_style( 'fs_deactivation_feedback', '/admin/deactivation-feedback.css' ); - - /* Check the type of user: - * 1. Long-term (long-term) - * 2. Non-registered and non-anonymous short-term (non-registered-and-non-anonymous-short-term). - * 3. Short-term (short-term) - */ - $is_long_term_user = true; - - // Check if the site is at least 2 days old. - $time_installed = $this->_storage->install_timestamp; - - // Difference in seconds. - $date_diff = time() - $time_installed; - - // Convert seconds to days. - $date_diff_days = floor( $date_diff / ( 60 * 60 * 24 ) ); - - if ( $date_diff_days < 2 ) { - $is_long_term_user = false; - } - - $is_long_term_user = $this->apply_filters( 'is_long_term_user', $is_long_term_user ); - - if ( $is_long_term_user ) { - $user_type = 'long-term'; - } else { - if ( ! $this->is_registered() && ! $this->is_anonymous() ) { - $user_type = 'non-registered-and-non-anonymous-short-term'; - } else { - $user_type = 'short-term'; - } - } - - $uninstall_reasons = $this->_get_uninstall_reasons( $user_type ); - - // Load the HTML template for the deactivation feedback dialog box. - $vars = array( - 'reasons' => $uninstall_reasons, - 'slug' => $this->_slug - ); - - /** - * @todo Deactivation form core functions should be loaded only once! Otherwise, when there are multiple Freemius powered plugins the same code is loaded multiple times. The only thing that should be loaded differently is the various deactivation reasons object based on the state of the plugin. - */ - fs_require_template( 'deactivation-feedback-modal.php', $vars ); - } - - /** - * @author Leo Fajardo (leorw) - * @since 1.1.2 - * - * @param string $user_type - * - * @return array The uninstall reasons for the specified user type. - */ - function _get_uninstall_reasons( $user_type = 'long-term' ) { - $reason_found_better_plugin = array( - 'id' => 2, - 'text' => __fs( 'reason-found-a-better-plugin', $this->_slug ), - 'input_type' => 'textfield', - 'input_placeholder' => __fs( 'placeholder-plugin-name', $this->_slug ) - ); - - $reason_temporary_deactivation = array( - 'id' => 15, - 'text' => __fs( 'reason-temporary-deactivation', $this->_slug ), - 'input_type' => '', - 'input_placeholder' => '' - ); - - $reason_other = array( - 'id' => 7, - 'text' => __fs( 'reason-other', $this->_slug ), - 'input_type' => 'textfield', - 'input_placeholder' => '' - ); - - $long_term_user_reasons = array( - array( - 'id' => 1, - 'text' => __fs( 'reason-no-longer-needed', $this->_slug ), - 'input_type' => '', - 'input_placeholder' => '' - ), - $reason_found_better_plugin, - array( - 'id' => 3, - 'text' => __fs( 'reason-needed-for-a-short-period', $this->_slug ), - 'input_type' => '', - 'input_placeholder' => '' - ), - array( - 'id' => 4, - 'text' => __fs( 'reason-broke-my-site', $this->_slug ), - 'input_type' => '', - 'input_placeholder' => '' - ), - array( - 'id' => 5, - 'text' => __fs( 'reason-suddenly-stopped-working', $this->_slug ), - 'input_type' => '', - 'input_placeholder' => '' - ) - ); - - if ( $this->is_paying() ) { - $long_term_user_reasons[] = array( - 'id' => 6, - 'text' => __fs( 'reason-cant-pay-anymore', $this->_slug ), - 'input_type' => 'textfield', - 'input_placeholder' => __fs( 'placeholder-comfortable-price', $this->_slug ) - ); - } - - $long_term_user_reasons[] = $reason_temporary_deactivation; - $long_term_user_reasons[] = $reason_other; - - $uninstall_reasons = array( - 'long-term' => $long_term_user_reasons, - 'non-registered-and-non-anonymous-short-term' => array( - array( - 'id' => 8, - 'text' => __fs( 'reason-didnt-work', $this->_slug ), - 'input_type' => '', - 'input_placeholder' => '' - ), - array( - 'id' => 9, - 'text' => __fs( 'reason-dont-like-to-share-my-information', $this->_slug ), - 'input_type' => '', - 'input_placeholder' => '' - ), - $reason_found_better_plugin, - $reason_temporary_deactivation, - $reason_other - ), - 'short-term' => array( - array( - 'id' => 10, - 'text' => __fs( 'reason-couldnt-make-it-work', $this->_slug ), - 'input_type' => '', - 'input_placeholder' => '' - ), - $reason_found_better_plugin, - array( - 'id' => 11, - 'text' => __fs( 'reason-great-but-need-specific-feature', $this->_slug ), - 'input_type' => 'textarea', - 'input_placeholder' => __fs( 'placeholder-feature', $this->_slug ) - ), - array( - 'id' => 12, - 'text' => __fs( 'reason-not-working', $this->_slug ), - 'input_type' => 'textarea', - 'input_placeholder' => __fs( 'placeholder-share-what-didnt-work', $this->_slug ) - ), - array( - 'id' => 13, - 'text' => __fs( 'reason-not-what-i-was-looking-for', $this->_slug ), - 'input_type' => 'textarea', - 'input_placeholder' => __fs( 'placeholder-what-youve-been-looking-for', $this->_slug ) - ), - array( - 'id' => 14, - 'text' => __fs( 'reason-didnt-work-as-expected', $this->_slug ), - 'input_type' => 'textarea', - 'input_placeholder' => __fs( 'placeholder-what-did-you-expect', $this->_slug ) - ), - $reason_temporary_deactivation, - $reason_other - ) - ); - - $uninstall_reasons = $this->apply_filters( 'uninstall_reasons', $uninstall_reasons ); - - return $uninstall_reasons[ $user_type ]; - } - - /** - * Called after the user has submitted his reason for deactivating the plugin. - * - * @author Leo Fajardo (@leorw) - * @since 1.1.2 - */ - function _submit_uninstall_reason_action() { - if ( ! isset( $_POST['reason_id'] ) ) { - exit; - } - - $reason_info = isset( $_REQUEST['reason_info'] ) ? trim( stripslashes( $_REQUEST['reason_info'] ) ) : ''; - - $reason = (object) array( - 'id' => $_POST['reason_id'], - 'info' => substr( $reason_info, 0, 128 ) - ); - - $this->_storage->store( 'uninstall_reason', $reason ); - - // Print '1' for successful operation. - echo 1; - exit; - } - - #endregion Deactivation Feedback Form ------------------------------------------------------------------ - - #region Instance ------------------------------------------------------------------ - - /** - * Main singleton instance. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.0 - * - * @param $slug - * - * @return Freemius - */ - static function instance( $slug ) { - $slug = strtolower( $slug ); - - if ( ! isset( self::$_instances[ $slug ] ) ) { - if ( 0 === count( self::$_instances ) ) { - self::_load_required_static(); - } - - self::$_instances[ $slug ] = new Freemius( $slug ); - } - - return self::$_instances[ $slug ]; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @param string|number $slug_or_id - * - * @return bool - */ - private static function has_instance( $slug_or_id ) { - return ! is_numeric( $slug_or_id ) ? - isset( self::$_instances[ strtolower( $slug_or_id ) ] ) : - ( false !== self::get_instance_by_id( $slug_or_id ) ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @param $id - * - * @return false|Freemius - */ - static function get_instance_by_id( $id ) { - foreach ( self::$_instances as $slug => $instance ) { - if ( $id == $instance->get_id() ) { - return $instance; - } - } - - return false; - } - - /** - * - * @author Vova Feldman (@svovaf) - * @since 1.0.1 - * - * @param $plugin_file - * - * @return false|Freemius - */ - static function get_instance_by_file( $plugin_file ) { - $slug = self::find_slug_by_basename( $plugin_file ); - - return ( false !== $slug ) ? - self::instance( $slug ) : - false; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @return false|Freemius - */ - function get_parent_instance() { - return self::get_instance_by_id( $this->_plugin->parent_plugin_id ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @param $slug_or_id - * - * @return bool|Freemius - */ - function get_addon_instance( $slug_or_id ) { - return ! is_numeric( $slug_or_id ) ? - self::instance( strtolower( $slug_or_id ) ) : - self::get_instance_by_id( $slug_or_id ); - } - - #endregion ------------------------------------------------------------------ - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @return bool - */ - function is_parent_plugin_installed() { - return self::has_instance( $this->_plugin->parent_plugin_id ); - } - - /** - * Check if add-on parent plugin in activation mode. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - * - * @return bool - */ - function is_parent_in_activation() { - $parent_fs = $this->get_parent_instance(); - if ( ! is_object( $parent_fs ) ) { - return false; - } - - return ( $parent_fs->is_activation_mode() ); - } - - /** - * Is plugin in activation mode. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - * - * @return bool - */ - function is_activation_mode() { - return ( - $this->is_on() && - ! $this->is_registered() && - ( ! $this->enable_anonymous() || - ( ! $this->is_anonymous() && ! $this->is_pending_activation() ) ) - ); - } - - /** - * Get collection of all active plugins. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @return array[string]array - */ - private static function get_active_plugins() { - self::require_plugin_essentials(); - - $active_plugin = array(); - $all_plugins = get_plugins(); - $active_plugins_basenames = get_option( 'active_plugins' ); - - foreach ( $active_plugins_basenames as $plugin_basename ) { - $active_plugin[ $plugin_basename ] = $all_plugins[ $plugin_basename ]; - } - - return $active_plugin; - } - - /** - * Get collection of all plugins. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.8 - * - * @return array Key is the plugin file path and the value is an array of the plugin data. - */ - private static function get_all_plugins() { - self::require_plugin_essentials(); - - $all_plugins = get_plugins(); - $active_plugins_basenames = get_option( 'active_plugins' ); - - foreach ( $all_plugins as $basename => &$data ) { - // By default set to inactive (next foreach update the active plugins). - $data['is_active'] = false; - // Enrich with plugin slug. - $data['slug'] = self::get_plugin_slug( $basename ); - } - - // Flag active plugins. - foreach ( $active_plugins_basenames as $basename ) { - if ( isset( $all_plugins[ $basename ] ) ) { - $all_plugins[ $basename ]['is_active'] = true; - } - } - - return $all_plugins; - } - - - /** - * Cached result of get_site_transient( 'update_plugins' ) - * - * @author Vova Feldman (@svovaf) - * @since 1.1.8 - * - * @var object - */ - private static $_plugins_info; - - /** - * Helper function to get specified plugin's slug. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.8 - * - * @param $basename - * - * @return string - */ - private static function get_plugin_slug( $basename ) { - if ( ! isset( self::$_plugins_info ) ) { - self::$_plugins_info = get_site_transient( 'update_plugins' ); - } - - $slug = ''; - - if ( is_object( self::$_plugins_info ) ) { - if ( isset( self::$_plugins_info->no_update ) && - isset( self::$_plugins_info->no_update[ $basename ] ) && - ! empty( self::$_plugins_info->no_update[ $basename ]->slug ) - ) { - $slug = self::$_plugins_info->no_update[ $basename ]->slug; - } else if ( isset( self::$_plugins_info->response ) && - isset( self::$_plugins_info->response[ $basename ] ) && - ! empty( self::$_plugins_info->response[ $basename ]->slug ) - ) { - $slug = self::$_plugins_info->response[ $basename ]->slug; - } - } - - if ( empty( $slug ) ) { - // Try to find slug from FS data. - $slug = self::find_slug_by_basename( $basename ); - } - - if ( empty( $slug ) ) { - // Fallback to plugin's folder name. - $slug = dirname( $basename ); - } - - return $slug; - } - - private static $_statics_loaded = false; - - /** - * Load static resources. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.1 - */ - private static function _load_required_static() { - if ( self::$_statics_loaded ) { - return; - } - - self::$_static_logger = FS_Logger::get_logger( WP_FS__SLUG, WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); - - self::$_static_logger->entrance(); - - self::$_accounts = FS_Option_Manager::get_manager( WP_FS__ACCOUNTS_OPTION_NAME, true ); - - self::$_global_admin_notices = FS_Admin_Notice_Manager::instance( 'global' ); - - // Configure which Freemius powered plugins should be auto updated. -// add_filter( 'auto_update_plugin', '_include_plugins_in_auto_update', 10, 2 ); - - add_action( 'admin_menu', array( 'Freemius', 'add_debug_page' ) ); - - add_action( "wp_ajax_fs_toggle_debug_mode", array( 'Freemius', '_toggle_debug_mode' ) ); - - self::$_statics_loaded = true; - } - - #region Debugging ------------------------------------------------------------------ - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.8 - */ - static function add_debug_page() { - if ( ! current_user_can( 'activate_plugins' ) ) { - return; - } - - self::$_static_logger->entrance(); - - $title = sprintf( '%s [v.%s]', __fs( 'freemius-debug' ), WP_FS__SDK_VERSION ); - - if ( WP_FS__DEV_MODE ) { - // Add top-level debug menu item. - $hook = add_menu_page( - $title, - $title, - 'manage_options', - 'freemius', - array( 'Freemius', '_debug_page_render' ) - ); - } else { - // Add hidden debug page. - $hook = add_submenu_page( - null, - $title, - $title, - 'manage_options', - 'freemius', - array( 'Freemius', '_debug_page_render' ) - ); - } - - add_action( "load-$hook", array( 'Freemius', '_debug_page_actions' ) ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.7.3 - */ - static function _toggle_debug_mode() { - if ( in_array( $_POST['is_on'], array( 0, 1 ) ) ) { - update_option( 'fs_debug_mode', $_POST['is_on'] ); - } - - exit; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.8 - */ - static function _debug_page_actions() { - self::_clean_admin_content_section(); - - if ( fs_request_is_action( 'restart_freemius' ) ) { - check_admin_referer( 'restart_freemius' ); - - self::$_accounts->clear( true ); - - - return; - } - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.8 - */ - static function _debug_page_render() { - self::$_static_logger->entrance(); - - $sites = self::get_all_sites(); - $users = self::get_all_users(); - $addons = self::get_all_addons(); - $account_addons = self::get_all_account_addons(); - -// $plans = self::get_all_plans(); -// $licenses = self::get_all_licenses(); - - $vars = array( - 'sites' => $sites, - 'users' => $users, - 'addons' => $addons, - 'account_addons' => $account_addons, - ); - - fs_enqueue_local_style( 'fs_account', '/admin/debug.css' ); - fs_require_once_template( 'debug.php', $vars ); - } - - #endregion ------------------------------------------------------------------ - - #region Connectivity Issues ------------------------------------------------------------------ - - /** - * Check if Freemius should be turned on for the current plugin install. - * - * Note: - * $this->_is_on is updated in has_api_connectivity() - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @return bool - */ - function is_on() { - self::$_static_logger->entrance(); - - if ( isset( $this->_is_on ) ) { - return $this->_is_on; - } - - // If already installed or pending then sure it's on :) - if ( $this->is_registered() || $this->is_pending_activation() ) { - $this->_is_on = true; - - return true; - } - - return false; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.7.3 - * - * @param bool $flush_if_no_connectivity - * - * @return bool - */ - private function should_run_connectivity_test( $flush_if_no_connectivity = false ) { - if ( ! isset( $this->_storage->connectivity_test ) ) { - // Connectivity test was never executed, or cache was cleared. - return true; - } - - if ( WP_FS__PING_API_ON_IP_OR_HOST_CHANGES ) { - if ( WP_FS__IS_HTTP_REQUEST ) { - if ( $_SERVER['HTTP_HOST'] != $this->_storage->connectivity_test['host'] ) { - // Domain changed. - return true; - } - - if ( WP_FS__REMOTE_ADDR != $this->_storage->connectivity_test['server_ip'] ) { - // Server IP changed. - return true; - } - } - } - - if ( $this->_storage->connectivity_test['is_connected'] && - $this->_storage->connectivity_test['is_active'] - ) { - // API connected and Freemius is active - no need to run connectivity check. - return false; - } - - if ( $flush_if_no_connectivity ) { - /** - * If explicitly asked to flush when no connectivity - do it only - * if at least 10 sec passed from the last API connectivity test. - */ - return ( isset( $this->_storage->connectivity_test['timestamp'] ) && - ( WP_FS__SCRIPT_START_TIME - $this->_storage->connectivity_test['timestamp'] ) > 10 ); - } - - /** - * @since 1.1.7 Don't check for connectivity on plugin downgrade. - */ - $version = $this->get_plugin_version(); - if ( version_compare( $version, $this->_storage->connectivity_test['version'], '>' ) ) { - // If it's a plugin version upgrade and Freemius is off or no connectivity, run connectivity test. - return true; - } - - return false; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.7.4 - * - * @return object|false - */ - private function ping() { - if ( WP_FS__SIMULATE_NO_API_CONNECTIVITY ) { - return false; - } - - $version = $this->get_plugin_version(); - - $is_update = $this->apply_filters( 'is_plugin_update', $this->is_plugin_update() ); - - return $this->get_api_plugin_scope()->ping( - $this->get_anonymous_id(), - array( - 'is_update' => json_encode( $is_update ), - 'version' => $version, - 'sdk' => $this->version, - 'is_admin' => json_encode( is_admin() ), - 'is_ajax' => json_encode( $this->is_ajax() ), - 'is_cron' => json_encode( $this->is_cron() ), - 'is_http' => json_encode( WP_FS__IS_HTTP_REQUEST ), - ) - ); - } - - /** - * Check if there's any connectivity issue to Freemius API. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @param bool $flush_if_no_connectivity - * - * @return bool - */ - function has_api_connectivity( $flush_if_no_connectivity = false ) { - $this->_logger->entrance(); - - if ( isset( $this->_has_api_connection ) && ( $this->_has_api_connection || ! $flush_if_no_connectivity ) ) { - return $this->_has_api_connection; - } - - if ( WP_FS__SIMULATE_NO_API_CONNECTIVITY && - isset( $this->_storage->connectivity_test ) && - true === $this->_storage->connectivity_test['is_connected'] - ) { - unset( $this->_storage->connectivity_test ); - } - - if ( ! $this->should_run_connectivity_test( $flush_if_no_connectivity ) ) { - $this->_has_api_connection = $this->_storage->connectivity_test['is_connected']; - /** - * @since 1.1.6 During dev mode, if there's connectivity - turn Freemius on regardless the configuration. - */ - $this->_is_on = $this->_storage->connectivity_test['is_active'] || - ( WP_FS__DEV_MODE && $this->_has_api_connection && ! WP_FS__SIMULATE_FREEMIUS_OFF ); - - return $this->_has_api_connection; - } - - $pong = $this->ping(); - $is_connected = $this->get_api_plugin_scope()->is_valid_ping( $pong ); - - if ( ! $is_connected ) { - // API failure. - $this->_add_connectivity_issue_message( $pong ); - } - - $this->store_connectivity_info( $pong, $is_connected ); - - return $this->_has_api_connection; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.7.4 - * - * @param object $pong - * @param bool $is_connected - */ - private function store_connectivity_info( $pong, $is_connected ) { - $this->_logger->entrance(); - - $version = $this->get_plugin_version(); - - if ( ! $is_connected || WP_FS__SIMULATE_FREEMIUS_OFF ) { - $is_active = false; - } else { - $is_active = ( isset( $pong->is_active ) && true == $pong->is_active ); - } - - $is_active = $this->apply_filters( - 'is_on', - $is_active, - $this->is_plugin_update(), - $version - ); - - $this->_storage->connectivity_test = array( - 'is_connected' => $is_connected, - 'host' => $_SERVER['HTTP_HOST'], - 'server_ip' => WP_FS__REMOTE_ADDR, - 'is_active' => $is_active, - 'timestamp' => WP_FS__SCRIPT_START_TIME, - // Last version with connectivity attempt. - 'version' => $version, - ); - - $this->_has_api_connection = $is_connected; - $this->_is_on = $is_active || ( WP_FS__DEV_MODE && $is_connected && ! WP_FS__SIMULATE_FREEMIUS_OFF ); - } - - /** - * Force turning Freemius on. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.8.1 - * - * @return bool TRUE if successfully turned on. - */ - private function turn_on() { - $this->_logger->entrance(); - - if ($this->is_on() || ! isset( $this->_storage->connectivity_test['is_active'] ) ) { - return false; - } - - $updated_connectivity = $this->_storage->connectivity_test; - $updated_connectivity['is_active'] = true; - $updated_connectivity['timestamp'] = WP_FS__SCRIPT_START_TIME; - $this->_storage->connectivity_test = $updated_connectivity; - - $this->_is_on = true; - - return true; - } - - /** - * Anonymous and unique site identifier (Hash). - * - * @author Vova Feldman (@svovaf) - * @since 1.1.0 - * - * @return string - */ - function get_anonymous_id() { - $unique_id = self::$_accounts->get_option( 'unique_id' ); - - if ( empty( $unique_id ) || ! is_string( $unique_id ) ) { - $key = get_site_url(); - - // If localhost, assign microtime instead of domain. - if ( WP_FS__IS_LOCALHOST || - false !== strpos( $key, 'localhost' ) || - false === strpos( $key, '.' ) - ) { - $key = microtime(); - } - - $unique_id = md5( $key ); - - self::$_accounts->set_option( 'unique_id', $unique_id, true ); - } - - $this->_logger->departure( $unique_id ); - - return $unique_id; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.7.4 - * - * @return \WP_User - */ - static function _get_current_wp_user() { - self::require_pluggable_essentials(); - - return wp_get_current_user(); - } - - /** - * Generate API connectivity issue message. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @param mixed $api_result - * @param bool $is_first_failure - */ - function _add_connectivity_issue_message( $api_result, $is_first_failure = true ) { - if ( $this->_enable_anonymous ) { - // Don't add message if can run anonymously. - return; - } - - if ( ! function_exists( 'wp_nonce_url' ) ) { - require_once( ABSPATH . 'wp-includes/functions.php' ); - } - - $current_user = self::_get_current_wp_user(); -// $admin_email = get_option( 'admin_email' ); - $admin_email = $current_user->user_email; - - $message = false; - if ( is_object( $api_result ) && - isset( $api_result->error ) && - isset( $api_result->error->code ) - ) { - switch ( $api_result->error->code ) { - case 'curl_missing': - $message = sprintf( - __fs( 'x-requires-access-to-api', $this->_slug ) . ' ' . - __fs( 'curl-missing-message', $this->_slug ) . ' ' . - ' %s', - '<b>' . $this->get_plugin_name() . '</b>', - sprintf( - '<ol id="fs_firewall_issue_options"><li>%s</li><li>%s</li><li>%s</li></ol>', - sprintf( - '<a class="fs-resolve" data-type="curl" href="#"><b>%s</b></a>%s', - __fs( 'curl-missing-no-clue-title', $this->_slug ), - ' - ' . sprintf( - __fs( 'curl-missing-no-clue-desc', $this->_slug ), - '<a href="mailto:' . $admin_email . '">' . $admin_email . '</a>' - ) - ), - sprintf( - '<b>%s</b> - %s', - __fs( 'sysadmin-title', $this->_slug ), - __fs( 'curl-missing-sysadmin-desc', $this->_slug ) - ), - sprintf( - '<a href="%s"><b>%s</b></a>%s', - wp_nonce_url( 'plugins.php?action=deactivate&plugin=' . $this->_plugin_basename . '&plugin_status=' . 'all' . '&paged=' . '1' . '&s=' . '', 'deactivate-plugin_' . $this->_plugin_basename ), - __fs( 'deactivate-plugin-title', $this->_slug ), - ' - ' . __fs( 'deactivate-plugin-desc', 'freemius', $this->_slug ) - ) - ) - ); - break; - case 'cloudflare_ddos_protection': - $message = sprintf( - __fs( 'x-requires-access-to-api', $this->_slug ) . ' ' . - __fs( 'cloudflare-blocks-connection-message', $this->_slug ) . ' ' . - __fs( 'happy-to-resolve-issue-asap', $this->_slug ) . - ' %s', - '<b>' . $this->get_plugin_name() . '</b>', - sprintf( - '<ol id="fs_firewall_issue_options"><li>%s</li><li>%s</li><li>%s</li></ol>', - sprintf( - '<a class="fs-resolve" data-type="cloudflare" href="#"><b>%s</b></a>%s', - __fs( 'fix-issue-title', $this->_slug ), - ' - ' . sprintf( - __fs( 'fix-issue-desc', $this->_slug ), - '<a href="mailto:' . $admin_email . '">' . $admin_email . '</a>' - ) - ), - sprintf( - '<a href="%s" target="_blank"><b>%s</b></a>%s', - sprintf( 'https://wordpress.org/plugins/%s/download/', $this->_slug ), - __fs( 'install-previous-title', $this->_slug ), - ' - ' . __fs( 'install-previous-desc', $this->_slug ) - ), - sprintf( - '<a href="%s"><b>%s</b></a>%s', - wp_nonce_url( 'plugins.php?action=deactivate&plugin=' . $this->_plugin_basename . '&plugin_status=' . 'all' . '&paged=' . '1' . '&s=' . '', 'deactivate-plugin_' . $this->_plugin_basename ), - __fs( 'deactivate-plugin-title', $this->_slug ), - ' - ' . __fs( 'deactivate-plugin-desc', $this->_slug ) - ) - ) - ); - break; - case 'squid_cache_block': - $message = sprintf( - __fs( 'x-requires-access-to-api', $this->_slug ) . ' ' . - __fs( 'squid-blocks-connection-message', $this->_slug ) . - ' %s', - '<b>' . $this->get_plugin_name() . '</b>', - sprintf( - '<ol id="fs_firewall_issue_options"><li>%s</li><li>%s</li><li>%s</li></ol>', - sprintf( - '<a class="fs-resolve" data-type="squid" href="#"><b>%s</b></a>%s', - __fs( 'squid-no-clue-title', $this->_slug ), - ' - ' . sprintf( - __fs( 'squid-no-clue-desc', $this->_slug ), - '<a href="mailto:' . $admin_email . '">' . $admin_email . '</a>' - ) - ), - sprintf( - '<b>%s</b> - %s', - __fs( 'sysadmin-title', $this->_slug ), - sprintf( - __fs( 'squid-sysadmin-desc', $this->_slug ), - // We use a filter since the plugin might require additional API connectivity. - '<b>' . implode( ', ', $this->apply_filters( 'api_domains', array( 'api.freemius.com' ) ) ) . '</b>' ) - ), - sprintf( - '<a href="%s"><b>%s</b></a>%s', - wp_nonce_url( 'plugins.php?action=deactivate&plugin=' . $this->_plugin_basename . '&plugin_status=' . 'all' . '&paged=' . '1' . '&s=' . '', 'deactivate-plugin_' . $this->_plugin_basename ), - __fs( 'deactivate-plugin-title', $this->_slug ), - ' - ' . __fs( 'deactivate-plugin-desc', $this->_slug ) - ) - ) - ); - break; -// default: -// $message = __fs( 'connectivity-test-fails-message', $this->_slug ); -// break; - } - } - - $message_id = 'failed_connect_api'; - $type = 'error'; - - if ( false === $message ) { - if ( $is_first_failure ) { - // First attempt failed. - $message = sprintf( - __fs( 'x-requires-access-to-api', $this->_slug ) . ' ' . - __fs( 'connectivity-test-fails-message', $this->_slug ) . ' ' . - __fs( 'connectivity-test-maybe-temporary', $this->_slug ) . '<br><br>' . - '%s', - '<b>' . $this->get_plugin_name() . '</b>', - sprintf( - '<div id="fs_firewall_issue_options">%s %s</div>', - sprintf( - '<a class="button button-primary fs-resolve" data-type="retry_ping" href="#">%s</a>', - __fs( 'yes-do-your-thing', $this->_slug ) - ), - sprintf( - '<a href="%s" class="button">%s</a>', - wp_nonce_url( 'plugins.php?action=deactivate&plugin=' . $this->_plugin_basename . '&plugin_status=' . 'all' . '&paged=' . '1' . '&s=' . '', 'deactivate-plugin_' . $this->_plugin_basename ), - __fs( 'no-deactivate', $this->_slug ) - ) - ) - ); - - $message_id = 'failed_connect_api_first'; - $type = 'promotion'; - } else { - // Second connectivity attempt failed. - $message = sprintf( - __fs( 'x-requires-access-to-api', $this->_slug ) . ' ' . - __fs( 'connectivity-test-fails-message', $this->_slug ) . ' ' . - __fs( 'happy-to-resolve-issue-asap', $this->_slug ) . - ' %s', - '<b>' . $this->get_plugin_name() . '</b>', - sprintf( - '<ol id="fs_firewall_issue_options"><li>%s</li><li>%s</li><li>%s</li></ol>', - sprintf( - '<a class="fs-resolve" data-type="general" href="#"><b>%s</b></a>%s', - __fs( 'fix-issue-title', $this->_slug ), - ' - ' . sprintf( - __fs( 'fix-issue-desc', $this->_slug ), - '<a href="mailto:' . $admin_email . '">' . $admin_email . '</a>' - ) - ), - sprintf( - '<a href="%s" target="_blank"><b>%s</b></a>%s', - sprintf( 'https://wordpress.org/plugins/%s/download/', $this->_slug ), - __fs( 'install-previous-title', $this->_slug ), - ' - ' . __fs( 'install-previous-desc', $this->_slug ) - ), - sprintf( - '<a href="%s"><b>%s</b></a>%s', - wp_nonce_url( 'plugins.php?action=deactivate&plugin=' . $this->_plugin_basename . '&plugin_status=' . 'all' . '&paged=' . '1' . '&s=' . '', 'deactivate-plugin_' . $this->_plugin_basename ), - __fs( 'deactivate-plugin-title', $this->_slug ), - ' - ' . __fs( 'deactivate-plugin-desc', $this->_slug ) - ) - ) - ); - } - } - - $this->_admin_notices->add_sticky( - $message, - $message_id, - __fs( 'oops', $this->_slug ) . '...', - $type - ); - } - - /** - * Handle user request to resolve connectivity issue. - * This method will send an email to Freemius API technical staff for resolution. - * The email will contain server's info and installed plugins (might be caching issue). - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - */ - function _email_about_firewall_issue() { - $this->_admin_notices->remove_sticky( 'failed_connect_api' ); - - $pong = $this->ping(); - - $is_connected = $this->get_api_plugin_scope()->is_valid_ping( $pong ); - - if ( $is_connected ) { - $this->store_connectivity_info( $pong, $is_connected ); - - echo $this->get_after_plugin_activation_redirect_url(); - exit; - } - - $current_user = self::_get_current_wp_user(); - $admin_email = $current_user->user_email; - - $error_type = fs_request_get( 'error_type', 'general' ); - - switch ( $error_type ) { - case 'squid': - $title = 'Squid ACL Blocking Issue'; - break; - case 'cloudflare': - $title = 'CloudFlare Blocking Issue'; - break; - default: - $title = 'API Connectivity Issue'; - break; - } - - $custom_email_sections = array(); - - if ( 'squid' === $error_type ) { - // Override the 'Site' email section. - $custom_email_sections['site'] = array( - 'rows' => array( - 'hosting_company' => array( 'Hosting Company', fs_request_get( 'hosting_company' ) ) - ) - ); - } - - // Add 'API Error' custom email section. - $custom_email_sections['api_error'] = array( - 'title' => 'API Error', - 'rows' => array( - 'ping' => array( is_string( $pong ) ? htmlentities( $pong ) : json_encode( $pong ) ) - ) - ); - - // Add PHP info for deeper investigation. - ob_start(); - phpinfo(); - $php_info = ob_get_clean(); - $custom_email_sections['php_info'] = array( - 'title' => 'PHP Info', - 'rows' => array( - 'info' => array( $php_info ) - ) - ); - - // Send email with technical details to resolve CloudFlare's firewall unnecessary protection. - $this->send_email( - 'api@freemius.com', // recipient - $title . ' [' . $this->get_plugin_name() . ']', // subject - $custom_email_sections, - array( "Reply-To: $admin_email <$admin_email>" ) // headers - ); - - $this->_admin_notices->add_sticky( - sprintf( - __fs( 'fix-request-sent-message', $this->_slug ), - '<a href="mailto:' . $admin_email . '">' . $admin_email . '</a>' - ), - 'server_details_sent' - ); - - // Action was taken, tell that API connectivity troubleshooting should be off now. - - echo "1"; - exit; - } - - /** - * Handle connectivity test retry approved by the user. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.7.4 - */ - function _retry_connectivity_test() { - $this->_admin_notices->remove_sticky( 'failed_connect_api_first' ); - - $pong = $this->ping(); - - $is_connected = $this->get_api_plugin_scope()->is_valid_ping( $pong ); - - if ( $is_connected ) { - $this->store_connectivity_info( $pong, $is_connected ); - - echo $this->get_after_plugin_activation_redirect_url(); - } else { - // Add connectivity issue message after 2nd failed attempt. - $this->_add_connectivity_issue_message( $pong, false ); - - echo "1"; - } - - exit; - } - - static function _add_firewall_issues_javascript() { - $params = array(); - fs_require_once_template( 'firewall-issues-js.php', $params ); - } - - #endregion Connectivity Issues ------------------------------------------------------------------ - - #region Email ------------------------------------------------------------------ - - /** - * Generates and sends an HTML email with customizable sections. - * - * @author Leo Fajardo (@leorw) - * @since 1.1.2 - * - * @param string $to_address - * @param string $subject - * @param array $sections - * @param array $headers - * - * @return bool Whether the email contents were sent successfully. - */ - private function send_email( - $to_address, - $subject, - $sections = array(), - $headers = array() - ) { - $default_sections = $this->get_email_sections(); - - // Insert new sections or replace the default email sections. - if ( is_array( $sections ) && ! empty( $sections ) ) { - foreach ( $sections as $section_id => $custom_section ) { - if ( ! isset( $default_sections[ $section_id ] ) ) { - // If the section does not exist, add it. - $default_sections[ $section_id ] = $custom_section; - } else { - // If the section already exists, override it. - $current_section = $default_sections[ $section_id ]; - - // Replace the current section's title if a custom section title exists. - if ( isset( $custom_section['title'] ) ) { - $current_section['title'] = $custom_section['title']; - } - - // Insert new rows under the current section or replace the default rows. - if ( isset( $custom_section['rows'] ) && is_array( $custom_section['rows'] ) && ! empty( $custom_section['rows'] ) ) { - foreach ( $custom_section['rows'] as $row_id => $row ) { - $current_section['rows'][ $row_id ] = $row; - } - } - - $default_sections[ $section_id ] = $current_section; - } - } - } - - $vars = array( 'sections' => $default_sections ); - $message = fs_get_template( 'email.php', $vars ); - - // Set the type of email to HTML. - $headers[] = 'Content-type: text/html'; - - $header_string = implode( "\r\n", $headers ); - - return wp_mail( - $to_address, - $subject, - $message, - $header_string - ); - } - - /** - * Generates the data for the sections of the email content. - * - * @author Leo Fajardo (@leorw) - * @since 1.1.2 - * - * @return array - */ - private function get_email_sections() { - // Retrieve the current user's information so that we can get the user's email, first name, and last name below. - $current_user = self::_get_current_wp_user(); - - // Retrieve the cURL version information so that we can get the version number below. - $curl_version_information = curl_version(); - - $active_plugin = self::get_active_plugins(); - - // Generate the list of active plugins separated by new line. - $active_plugin_string = ''; - foreach ( $active_plugin as $plugin ) { - $active_plugin_string .= sprintf( - '<a href="%s">%s</a> [v%s]<br>', - $plugin['PluginURI'], - $plugin['Name'], - $plugin['Version'] - ); - } - - $server_ip = WP_FS__REMOTE_ADDR; - - // Generate the default email sections. - $sections = array( - 'sdk' => array( - 'title' => 'SDK', - 'rows' => array( - 'fs_version' => array( 'FS Version', $this->version ), - 'curl_version' => array( 'cURL Version', $curl_version_information['version'] ) - ) - ), - 'plugin' => array( - 'title' => 'Plugin', - 'rows' => array( - 'name' => array( 'Name', $this->get_plugin_name() ), - 'version' => array( 'Version', $this->get_plugin_version() ) - ) - ), - 'site' => array( - 'title' => 'Site', - 'rows' => array( - 'unique_id' => array( 'Address', $this->get_anonymous_id() ), - 'address' => array( 'Address', site_url() ), - 'host' => array( - 'HTTP_HOST', - ( ! empty( $_SERVER['HTTP_HOST'] ) ? $_SERVER['HTTP_HOST'] : '' ) - ), - 'server_addr' => array( - 'SERVER_ADDR', - '<a href="http://www.projecthoneypot.org/ip_' . $server_ip . '">' . $server_ip . '</a>' - ) - ) - ), - 'user' => array( - 'title' => 'User', - 'rows' => array( - 'email' => array( 'Email', $current_user->user_email ), - 'first' => array( 'First', $current_user->user_firstname ), - 'last' => array( 'Last', $current_user->user_lastname ) - ) - ), - 'plugins' => array( - 'title' => 'Plugins', - 'rows' => array( - 'active_plugins' => array( 'Active Plugins', $active_plugin_string ) - ) - ), - ); - - // Allow the sections to be modified by other code. - $sections = $this->apply_filters( 'email_template_sections', $sections ); - - return $sections; - } - - #endregion Email ------------------------------------------------------------------ - - #region Initialization ------------------------------------------------------------------ - - /** - * Init plugin's Freemius instance. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.1 - * - * @param number $id - * @param string $public_key - * @param bool $is_live - * @param bool $is_premium - */ - function init( $id, $public_key, $is_live = true, $is_premium = true ) { - $this->_logger->entrance(); - - $this->dynamic_init( array( - 'id' => $id, - 'public_key' => $public_key, - 'is_live' => $is_live, - 'is_premium' => $is_premium, - ) ); - } - - /** - * Dynamic initiator, originally created to support initiation - * with parent_id for add-ons. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @param array $plugin_info - * - * @throws Freemius_Exception - */ - function dynamic_init( array $plugin_info ) { - $this->_logger->entrance(); - - $this->parse_settings( $plugin_info ); - - if ( $this->should_stop_execution() ) { - return; - } - - if ( ! $this->is_registered() ) { - if ( $this->is_anonymous() ) { - // If user skipped, no need to test connectivity. - $this->_has_api_connection = true; - $this->_is_on = true; - } else { - if ( ! $this->has_api_connectivity() ) { - if ( $this->_admin_notices->has_sticky( 'failed_connect_api_first' ) || - $this->_admin_notices->has_sticky( 'failed_connect_api' ) - ) { - if ( ! $this->_enable_anonymous ) { - // If anonymous mode is disabled, add firewall admin-notice message. - add_action( 'admin_footer', array( 'Freemius', '_add_firewall_issues_javascript' ) ); - - add_action( "wp_ajax_{$this->_slug}_resolve_firewall_issues", array( - &$this, - '_email_about_firewall_issue' - ) ); - - add_action( "wp_ajax_{$this->_slug}_retry_connectivity_test", array( - &$this, - '_retry_connectivity_test' - ) ); - } - } - - return; - } else { - $this->_admin_notices->remove_sticky( array( - 'failed_connect_api_first', - 'failed_connect_api', - ) ); - - if ( $this->_anonymous_mode ) { - // Simulate anonymous mode. - $this->_is_anonymous = true; - } - } - } - - // Check if Freemius is on for the current plugin. - // This MUST be executed after all the plugin variables has been loaded. - if ( ! $this->is_on() ) { - return; - } - } - - if ( $this->has_api_connectivity() && $this->is_user_in_admin() ) { - /** - * Schedule daily data sync cron if: - * - * 1. User opted-in (for tracking). - * 2. If plugin has add-ons (update add-ons data). - * 3. If skipped, but later upgraded (opted-in via upgrade). - * - * @author Vova Feldman (@svovaf) - * @since 1.1.7.3 - * - */ - if ( $this->is_registered() || - ( ! $this->is_activation_mode() && $this->_has_addons ) - ) { - - $this->hook_callback_to_sync_cron(); - - if ( ! $this->is_sync_cron_on() ) { - $this->schedule_sync_cron(); - } - } - - /** - * Check if requested for manual blocking background sync. - */ - if ( fs_request_has( 'background_sync' ) ) { - $this->run_manual_sync(); - } - } - - if ( $this->is_registered() ) { - $this->hook_callback_to_install_sync(); - } - - if ( $this->is_addon() ) { - if ( $this->is_parent_plugin_installed() ) { - // Link to parent FS. - $this->_parent = self::get_instance_by_id( $this->_plugin->parent_plugin_id ); - - // Get parent plugin reference. - $this->_parent_plugin = $this->_parent->get_plugin(); - } - } - - if ( $this->is_user_in_admin() ) { - global $pagenow; - if ( 'plugins.php' === $pagenow ) { - $this->hook_plugin_action_links(); - } - - if ( $this->is_addon() ) { - if ( ! $this->is_parent_plugin_installed() ) { - $parent_name = $this->get_option( $plugin_info, 'parent_name', null ); - - if ( isset( $plugin_info['parent'] ) ) { - $parent_name = $this->get_option( $plugin_info['parent'], 'name', null ); - } - - $this->_admin_notices->add( - ( ! empty( $parent_name ) ? - sprintf( __fs( 'addon-x-cannot-run-without-y', $this->_slug ), $this->get_plugin_name(), $parent_name ) : - sprintf( __fs( 'addon-x-cannot-run-without-parent', $this->_slug ), $this->get_plugin_name() ) - ), - __fs( 'oops', $this->_slug ) . '...', - 'error' - ); - - return; - } else { - if ( $this->_parent->is_registered() && ! $this->is_registered() ) { - // If parent plugin activated, automatically install add-on for the user. - $this->_activate_addon_account( $this->_parent ); - } - - // @todo This should be only executed on activation. It should be migrated to register_activation_hook() together with other activation related logic. - if ( $this->is_premium() ) { - // Remove add-on download admin-notice. - $this->_parent->_admin_notices->remove_sticky( 'addon_plan_upgraded_' . $this->_slug ); - } - - $this->deactivate_premium_only_addon_without_license(); - } - } else { - add_action( 'admin_init', array( &$this, '_admin_init_action' ) ); - - if ( $this->has_addons() && - 'plugin-information' === fs_request_get( 'tab', false ) && - $this->get_id() == fs_request_get( 'parent_plugin_id', false ) - ) { - require_once WP_FS__DIR_INCLUDES . '/fs-plugin-info-dialog.php'; - - new FS_Plugin_Info_Dialog( $this ); - } - } - - if ( $this->is_premium() ) { - new FS_Plugin_Updater( $this ); - } - -// if ( $this->is_registered() || -// $this->is_anonymous() || -// $this->is_pending_activation() -// ) { -// $this->_init_admin(); -// } - } - - $this->do_action( 'initiated' ); - - if ( ! $this->is_addon() ) { - if ( $this->is_registered() ) { - // Fix for upgrade from versions < 1.0.9. - if ( ! isset( $this->_storage->activation_timestamp ) ) { - $this->_storage->activation_timestamp = WP_FS__SCRIPT_START_TIME; - } - if ( $this->_storage->prev_is_premium !== $this->_plugin->is_premium ) { - if ( isset( $this->_storage->prev_is_premium ) ) { - add_action( is_admin() ? 'admin_init' : 'init', array( - &$this, - '_plugin_code_type_changed' - ) ); - } else { - // Set for code type for the first time. - $this->_storage->prev_is_premium = $this->_plugin->is_premium; - } - } - - $this->do_action( 'after_init_plugin_registered' ); - } else if ( $this->is_anonymous() ) { - $this->do_action( 'after_init_plugin_anonymous' ); - } else if ( $this->is_pending_activation() ) { - $this->do_action( 'after_init_plugin_pending_activations' ); - } - } else { - if ( $this->is_registered() ) { - $this->do_action( 'after_init_addon_registered' ); - } else if ( $this->is_anonymous() ) { - $this->do_action( 'after_init_addon_anonymous' ); - } else if ( $this->is_pending_activation() ) { - $this->do_action( 'after_init_addon_pending_activations' ); - } - } - } - - /** - * Parse plugin's settings (as defined by the plugin dev). - * - * @author Vova Feldman (@svovaf) - * @since 1.1.7.3 - * - * @param array $plugin_info - * - * @throws \Freemius_Exception - */ - private function parse_settings( &$plugin_info ) { - $this->_logger->entrance(); - - $id = $this->get_numeric_option( $plugin_info, 'id', false ); - $public_key = $this->get_option( $plugin_info, 'public_key', false ); - $secret_key = $this->get_option( $plugin_info, 'secret_key', null ); - $parent_id = $this->get_numeric_option( $plugin_info, 'parent_id', null ); - $parent_name = $this->get_option( $plugin_info, 'parent_name', null ); - - if ( isset( $plugin_info['parent'] ) ) { - $parent_id = $this->get_numeric_option( $plugin_info['parent'], 'id', null ); -// $parent_slug = $this->get_option( $plugin_info['parent'], 'slug', null ); -// $parent_public_key = $this->get_option( $plugin_info['parent'], 'public_key', null ); - $parent_name = $this->get_option( $plugin_info['parent'], 'name', null ); - } - - if ( false === $id ) { - throw new Freemius_Exception( 'Plugin id parameter is not set.' ); - } - if ( false === $public_key ) { - throw new Freemius_Exception( 'Plugin public_key parameter is not set.' ); - } - - $plugin = ( $this->_plugin instanceof FS_Plugin ) ? - $this->_plugin : - new FS_Plugin(); - - $plugin->update( array( - 'id' => $id, - 'public_key' => $public_key, - 'slug' => $this->_slug, - 'parent_plugin_id' => $parent_id, - 'version' => $this->get_plugin_version(), - 'title' => $this->get_plugin_name(), - 'file' => $this->_plugin_basename, - 'is_premium' => $this->get_bool_option( $plugin_info, 'is_premium', true ), - 'is_live' => $this->get_bool_option( $plugin_info, 'is_live', true ), -// 'secret_key' => $secret_key, - ) ); - - if ( $plugin->is_updated() ) { - // Update plugin details. - $this->_plugin = FS_Plugin_Manager::instance( $this->_slug )->store( $plugin ); - } - // Set the secret key after storing the plugin, we don't want to store the key in the storage. - $this->_plugin->secret_key = $secret_key; - - if ( ! isset( $plugin_info['menu'] ) ) { - // Back compatibility to 1.1.2 - $plugin_info['menu'] = array( - 'slug' => isset( $plugin_info['menu_slug'] ) ? - $plugin_info['menu_slug'] : - $this->_slug - ); - } - - $this->_menu = FS_Admin_Menu_Manager::instance( $this->_slug ); - $this->_menu->init( $plugin_info['menu'], $this->is_addon() ); - - $this->_has_addons = $this->get_bool_option( $plugin_info, 'has_addons', false ); - $this->_has_paid_plans = $this->get_bool_option( $plugin_info, 'has_paid_plans', true ); - $this->_is_org_compliant = $this->get_bool_option( $plugin_info, 'is_org_compliant', true ); - $this->_enable_anonymous = $this->get_bool_option( $plugin_info, 'enable_anonymous', true ); - $this->_anonymous_mode = $this->get_bool_option( $plugin_info, 'anonymous_mode', false ); - $this->_permissions = $this->get_option( $plugin_info, 'permissions', array() ); - } - - /** - * @param string[] $options - * @param string $key - * @param mixed $default - * - * @return bool - */ - private function get_option( &$options, $key, $default = false ) { - return ! empty( $options[ $key ] ) ? $options[ $key ] : $default; - } - - private function get_bool_option( &$options, $key, $default = false ) { - return isset( $options[ $key ] ) && is_bool( $options[ $key ] ) ? $options[ $key ] : $default; - } - - private function get_numeric_option( &$options, $key, $default = false ) { - return isset( $options[ $key ] ) && is_numeric( $options[ $key ] ) ? $options[ $key ] : $default; - } - - /** - * Gate keeper. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.7.3 - * - * @return bool - */ - private function should_stop_execution() { - if ( $this->is_activation_mode() ) { - if ( ! is_admin() ) { - /** - * If in activation mode, don't execute Freemius outside of the - * admin dashboard. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.7.3 - */ - return true; - } - - if ( ! WP_FS__IS_HTTP_REQUEST ) { - /** - * If in activation and executed without HTTP context (e.g. CLI, Cronjob), - * then don't start Freemius. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.6.3 - * - * @link https://wordpress.org/support/topic/errors-in-the-freemius-class-when-running-in-wordpress-in-cli - */ - return true; - } - - if ( $this->is_cron() ) { - /** - * If in activation mode, don't execute Freemius during wp crons - * (wp crons have HTTP context - called as HTTP request). - * - * @author Vova Feldman (@svovaf) - * @since 1.1.7.3 - */ - return true; - } - - if ( $this->is_ajax() && - ! $this->_admin_notices->has_sticky( 'failed_connect_api_first' ) && - ! $this->_admin_notices->has_sticky( 'failed_connect_api' ) - ) { - /** - * During activation, if running in AJAX mode, unless there's a sticky - * connectivity issue notice, don't run Freemius. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.7.3 - */ - return true; - } - } - - return false; - } - - /** - * Handles plugin's code type change (free <--> premium). - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - */ - function _plugin_code_type_changed() { - // Schedule code type changes event. -// $this->sync_install(); - $this->schedule_install_sync(); - - if ( $this->is_premium() ) { - // Activated premium code. - $this->do_action( 'after_premium_version_activation' ); - - // Remove all sticky messages related to download of the premium version. - $this->_admin_notices->remove_sticky( array( - 'trial_started', - 'plan_upgraded', - 'plan_changed', - ) ); - - $this->_admin_notices->add_sticky( - __fs( 'premium-activated-message', $this->_slug ), - 'premium_activated', - __fs( 'woot', $this->_slug ) . '!' - ); - } else { - // Activated free code (after had the premium before). - $this->do_action( 'after_free_version_reactivation' ); - - if ( $this->is_paying() && ! $this->is_premium() ) { - $this->_admin_notices->add_sticky( - sprintf( - __fs( 'you-have-x-license', $this->_slug ), - $this->_site->plan->title - ) . ' ' . $this->_get_latest_download_link( sprintf( - __fs( 'download-x-version-now', $this->_slug ), - $this->_site->plan->title - ) ), - 'plan_upgraded', - __fs( 'yee-haw', $this->_slug ) . '!' - ); - } - } - - // Update is_premium of latest version. - $this->_storage->prev_is_premium = $this->_plugin->is_premium; - } - - #endregion Initialization ------------------------------------------------------------------ - - #region Add-ons ------------------------------------------------------------------------- - - /** - * Check if add-on installed and activated on site. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @param string|number $slug_or_id - * - * @return bool - */ - function is_addon_activated( $slug_or_id ) { - return self::has_instance( $slug_or_id ); - } - - /** - * Check if add-on was connected to install - * - * @author Vova Feldman (@svovaf) - * @since 1.1.7 - * - * @param string $slug - * - * @return bool - */ - function is_addon_connected( $slug ) { - $sites = self::get_all_sites(); - - if ( ! isset( $sites[ $slug ] ) ) { - return false; - } - - $site = $sites[ $slug ]; - - $plugin = FS_Plugin_Manager::instance( $slug )->get(); - - if ( $plugin->parent_plugin_id != $this->_plugin->id ) { - // The given slug do NOT belong to any of the plugin's add-ons. - return false; - } - - return ( is_object( $site ) && - is_numeric( $site->id ) && - is_numeric( $site->user_id ) && - is_object( $site->plan ) - ); - } - - /** - * Determines if add-on installed. - * - * NOTE: This is a heuristic and only works if the folder/file named as the slug. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @param string $slug - * - * @return bool - */ - function is_addon_installed( $slug ) { - return file_exists( fs_normalize_path( WP_PLUGIN_DIR . '/' . $this->get_addon_basename( $slug ) ) ); - } - - /** - * Get add-on basename. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @param string $slug - * - * @return string - */ - function get_addon_basename( $slug ) { - if ( $this->is_addon_activated( $slug ) ) { - self::instance( $slug )->get_plugin_basename(); - } - - $premium_basename = $slug . '-premium/' . $slug . '.php'; - - if ( file_exists( fs_normalize_path( WP_PLUGIN_DIR . '/' . $premium_basename ) ) ) { - return $premium_basename; - } - - $free_basename = $slug . '/' . $slug . '.php'; - - return $free_basename; - } - - /** - * Get installed add-ons instances. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @return Freemius[] - */ - function get_installed_addons() { - $installed_addons = array(); - foreach ( self::$_instances as $slug => $instance ) { - if ( $instance->is_addon() && is_object( $instance->_parent_plugin ) ) { - if ( $this->_plugin->id == $instance->_parent_plugin->id ) { - $installed_addons[] = $instance; - } - } - } - - return $installed_addons; - } - - /** - * Check if any add-ons of the plugin are installed. - * - * @author Leo Fajardo (@leorw) - * @since 1.1.1 - * - * @return bool - */ - function has_installed_addons() { - if ( ! $this->has_addons() ) { - return false; - } - - foreach ( self::$_instances as $slug => $instance ) { - if ( $instance->is_addon() && is_object( $instance->_parent_plugin ) ) { - if ( $this->_plugin->id == $instance->_parent_plugin->id ) { - return true; - } - } - } - - return false; - } - - /** - * Tell Freemius that the current plugin is an add-on. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @param number $parent_plugin_id The parent plugin ID - */ - function init_addon( $parent_plugin_id ) { - $this->_plugin->parent_plugin_id = $parent_plugin_id; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @return bool - */ - function is_addon() { - return isset( $this->_plugin->parent_plugin_id ) && is_numeric( $this->_plugin->parent_plugin_id ); - } - - /** - * Deactivate add-on if it's premium only and the user does't have a valid license. - * - * @param bool $is_after_trial_cancel - * - * @return bool If add-on was deactivated. - */ - private function deactivate_premium_only_addon_without_license( $is_after_trial_cancel = false ) { - if ( ! $this->has_free_plan() && - ! $this->has_features_enabled_license() && - ! $this->_has_premium_license() - ) { - deactivate_plugins( array( $this->_plugin_basename ), true ); - - $this->_parent->_admin_notices->add_sticky( - sprintf( - __fs( ( $is_after_trial_cancel ? - 'addon-trial-cancelled-message' : - 'addon-no-license-message' ), - $this->_parent->_slug - ), - '<b>' . $this->_plugin->title . '</b>' - ) . ' ' . sprintf( - '<a href="%s" aria-label="%s" class="button button-primary" style="margin-left: 10px; vertical-align: middle;">%s ➜</a>', - $this->_parent->addon_url( $this->_slug ), - esc_attr( sprintf( __fs( 'more-information-about-x', $this->_parent->_slug ), $this->_plugin->title ) ), - __fs( 'purchase-license', $this->_parent->_slug ) - ), - 'no_addon_license', - ( $is_after_trial_cancel ? '' : __fs( 'oops', $this->_parent->_slug ) . '...' ), - ( $is_after_trial_cancel ? 'success' : 'error' ) - ); - - return true; - } - - return false; - } - - #endregion ------------------------------------------------------------------ - - #region Sandbox ------------------------------------------------------------------ - - /** - * Set Freemius into sandbox mode for debugging. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - * - * @param string $secret_key - */ - function init_sandbox( $secret_key ) { - $this->_plugin->secret_key = $secret_key; - - // Update plugin details. - FS_Plugin_Manager::instance( $this->_slug )->update( $this->_plugin, true ); - } - - /** - * Check if running payments in sandbox mode. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - * - * @return bool - */ - function is_payments_sandbox() { - return ( ! $this->is_live() ) || isset( $this->_plugin->secret_key ); - } - - #endregion Sandbox ------------------------------------------------------------------ - - /** - * Check if running test vs. live plugin. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.5 - * - * @return bool - */ - function is_live() { - return $this->_plugin->is_live; - } - - /** - * Check if the user skipped connecting the account with Freemius. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - * - * @return bool - */ - function is_anonymous() { - if ( ! isset( $this->_is_anonymous ) ) { - if ( ! isset( $this->_storage->is_anonymous ) ) { - // Not skipped. - $this->_is_anonymous = false; - } else if ( is_bool( $this->_storage->is_anonymous ) ) { - // For back compatibility, since the variable was boolean before. - $this->_is_anonymous = $this->_storage->is_anonymous; - - // Upgrade stored data format to 1.1.3 format. - $this->set_anonymous_mode( $this->_storage->is_anonymous ); - } else { - // Version 1.1.3 and later. - $this->_is_anonymous = $this->_storage->is_anonymous['is']; - } - } - - return $this->_is_anonymous; - } - - /** - * Check if user connected his account and install pending email activation. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - * - * @return bool - */ - function is_pending_activation() { - return $this->_storage->get( 'is_pending_activation', false ); - } - - /** - * Check if plugin must be WordPress.org compliant. - * - * @since 1.0.7 - * - * @return bool - */ - function is_org_repo_compliant() { - return $this->_is_org_compliant; - } - - #region Daily Sync Cron ------------------------------------------------------------------ - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.7.3 - */ - private function run_manual_sync() { - $this->require_pluggable_essentials(); - - if ( ! current_user_can( 'activate_plugins' ) ) { - return; - } - - // Run manual sync. - $this->_sync_cron(); - - // Reschedule next cron to run 24 hours from now (performance optimization). - $this->clear_sync_cron(); - - $this->schedule_sync_cron( time() + WP_FS__TIME_24_HOURS_IN_SEC, false ); - } - - /** - * Data sync cron job. Replaces the background sync non blocking HTTP request - * that doesn't halt page loading. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.7.3 - */ - function _sync_cron() { - $this->_logger->entrance(); - - // Store the last time data sync was executed. - $this->_storage->sync_timestamp = time(); - - // Check if API is temporary down. - if ( FS_Api::is_temporary_down() ) { - return; - } - - // @todo Add logic that identifies API latency, and reschedule the next background sync randomly between 8-16 hours. - - if ( $this->is_registered() ) { - if ( $this->has_paid_plan() ) { - // Initiate background plan sync. - $this->_sync_license( true ); - - if ( $this->is_paying() ) { - // Check for premium plugin updates. - $this->_check_updates( true ); - } - } else { - // Sync install (only if something changed locally). - $this->sync_install(); - } - } - - if ( ! $this->is_addon() && $this->_has_addons ) { - // Sync add-ons collection. - $this->_sync_addons( true ); - } - } - - /** - * Check if sync was executed in the last $period of seconds. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.7.3 - * - * @param int $period In seconds - * - * @return bool - */ - private function is_sync_executed( $period = WP_FS__TIME_24_HOURS_IN_SEC ) { - if ( ! isset( $this->_storage->sync_timestamp ) ) { - return false; - } - - return ( $this->_storage->sync_timestamp > ( WP_FS__SCRIPT_START_TIME - $period ) ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.7.3 - * - * @return bool - */ - private function is_sync_cron_on() { - /** - * @var object $sync_cron_data - */ - $sync_cron_data = $this->_storage->get( 'sync_cron', null ); - - return ( ! is_null( $sync_cron_data ) && true === $sync_cron_data->on ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.7.3 - * - * @param int $start_at Defaults to now. - * @param bool $randomize_start If true, schedule first job randomly during the next 12 hours. Otherwise, - * schedule job to start right away. - */ - private function schedule_sync_cron( $start_at = WP_FS__SCRIPT_START_TIME, $randomize_start = true ) { - $this->_logger->entrance(); - - if ( $randomize_start ) { - // Schedule first sync with a random 12 hour time range from now. - $start_at += rand( 0, ( WP_FS__TIME_24_HOURS_IN_SEC / 2 ) ); - } - - // Schedule daily WP cron. - wp_schedule_event( - $start_at, - 'daily', - $this->get_action_tag( 'data_sync' ) - ); - - $this->_storage->store( 'sync_cron', (object) array( - 'version' => $this->get_plugin_version(), - 'sdk_version' => $this->version, - 'timestamp' => WP_FS__SCRIPT_START_TIME, - 'on' => true, - ) ); - } - - /** - * Add the actual sync function to the cron job hook. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.7.3 - */ - private function hook_callback_to_sync_cron() { - $this->add_action( 'data_sync', array( &$this, '_sync_cron' ) ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.7.3 - */ - private function clear_sync_cron() { - $this->_logger->entrance(); - - if ( ! $this->is_sync_cron_on() ) { - return; - } - - $this->_storage->remove( 'sync_cron' ); - - wp_clear_scheduled_hook( $this->get_action_tag( 'data_sync' ) ); - } - - /** - * Unix timestamp for next sync cron execution or false if not scheduled. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.7.3 - * - * @return int|false - */ - function next_sync_cron() { - $this->_logger->entrance(); - - if ( ! $this->is_sync_cron_on() ) { - return false; - } - - return wp_next_scheduled( $this->get_action_tag( 'data_sync' ) ); - } - - /** - * Unix timestamp for previous sync cron execution or false if never executed. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.7.3 - * - * @return int|false - */ - function last_sync_cron() { - $this->_logger->entrance(); - - return $this->_storage->get( 'sync_timestamp' ); - } - - #endregion Daily Sync Cron ------------------------------------------------------------------ - - #region Async Install Sync ------------------------------------------------------------------ - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.7.3 - * - * @return bool - */ - private function is_install_sync_scheduled() { - /** - * @var object $cron_data - */ - $cron_data = $this->_storage->get( 'install_sync_cron', null ); - - return ( ! is_null( $cron_data ) && true === $cron_data->on ); - } - - /** - * Instead of running blocking install sync event, execute non blocking scheduled wp-cron. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.7.3 - */ - private function schedule_install_sync() { - $this->_logger->entrance(); - - $this->clear_install_sync_cron(); - - // Schedule immediate install sync. - wp_schedule_single_event( - WP_FS__SCRIPT_START_TIME, - $this->get_action_tag( 'install_sync' ) - ); - - $this->_storage->store( 'install_sync_cron', (object) array( - 'version' => $this->get_plugin_version(), - 'sdk_version' => $this->version, - 'timestamp' => WP_FS__SCRIPT_START_TIME, - 'on' => true, - ) ); - } - - /** - * Unix timestamp for previous install sync cron execution or false if never executed. - * - * @todo There's some very strange bug that $this->_storage->install_sync_timestamp value is not being - * updated. But for sure the sync event is working. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.7.3 - * - * @return int|false - */ - function last_install_sync() { - $this->_logger->entrance(); - - return $this->_storage->get( 'install_sync_timestamp' ); - } - - /** - * Unix timestamp for next install sync cron execution or false if not scheduled. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.7.3 - * - * @return int|false - */ - function next_install_sync() { - $this->_logger->entrance(); - - if ( ! $this->is_install_sync_scheduled() ) { - return false; - } - - return wp_next_scheduled( $this->get_action_tag( 'install_sync' ) ); - } - - /** - * Add the actual install sync function to the cron job hook. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.7.3 - */ - private function hook_callback_to_install_sync() { - $this->add_action( 'install_sync', array( &$this, '_run_sync_install' ) ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.7.3 - */ - private function clear_install_sync_cron() { - $this->_logger->entrance(); - - if ( ! $this->is_install_sync_scheduled() ) { - return; - } - - $this->_storage->remove( 'install_sync_cron' ); - - wp_clear_scheduled_hook( $this->get_action_tag( 'install_sync' ) ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.7.3 - */ - public function _run_sync_install() { - $this->_logger->entrance(); - - // Update last install sync timestamp. - $this->_storage->install_sync_timestamp = time(); - - $this->sync_install( array(), true ); - } - - #endregion Async Install Sync ------------------------------------------------------------------ - - /** - * Show a notice that activation is currently pending. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - * - * @param bool|string $email - */ - function _add_pending_activation_notice( $email = false ) { - if ( ! is_string( $email ) ) { - $current_user = self::_get_current_wp_user(); - $email = $current_user->user_email; - } - - $this->_admin_notices->add_sticky( - sprintf( - __fs( 'pending-activation-message', $this->_slug ), - '<b>' . $this->get_plugin_name() . '</b>', - '<b>' . $email . '</b>' - ), - 'activation_pending', - 'Thanks!' - ); - } - - /** - * Check if currently in plugin activation. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.4 - * - * @return bool - */ - function is_plugin_activation() { - return get_option( "fs_{$this->_slug}_activated", false ); - } - - /** - * - * NOTE: admin_menu action executed before admin_init. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - */ - function _admin_init_action() { - /** - * Automatically redirect to connect/activation page after plugin activation. - * - * @since 1.1.7 Do NOT redirect to opt-in when running in network admin mode. - */ - if ( $this->is_plugin_activation() ) { - delete_option( "fs_{$this->_slug}_activated" ); - - if ( ! function_exists( 'is_network_admin' ) || ! is_network_admin() ) { - $this->_redirect_on_activation_hook(); - - return; - } - } - - if ( fs_request_is_action( $this->_slug . '_skip_activation' ) ) { - check_admin_referer( $this->_slug . '_skip_activation' ); - - $this->skip_connection(); - - if ( fs_redirect( $this->get_after_activation_url( 'after_skip_url' ) ) ) { - exit(); - } - } - - if ( ! $this->is_addon() && ! $this->is_registered() && ! $this->is_anonymous() ) { - if ( ! $this->is_pending_activation() ) { - if ( ! $this->_menu->is_activation_page() ) { - if ( $this->is_plugin_new_install() ) { - // Show notice for new plugin installations. - $this->_admin_notices->add( - sprintf( - __fs( 'you-are-step-away', $this->_slug ), - sprintf( '<b><a href="%s">%s</a></b>', - $this->get_activation_url(), - sprintf( __fs( 'activate-x-now', $this->_slug ), $this->get_plugin_name() ) - ) - ), - '', - 'update-nag' - ); - } else { - if ( ! isset( $this->_storage->sticky_optin_added ) ) { - $this->_storage->sticky_optin_added = true; - - // Show notice for new plugin installations. - $this->_admin_notices->add_sticky( - sprintf( - __fs( 'few-plugin-tweaks', $this->_slug ), - sprintf( '<b><a href="%s">%s</a></b>', - $this->get_activation_url(), - sprintf( __fs( 'optin-x-now', $this->_slug ), $this->get_plugin_name() ) - ) - ), - 'connect_account', - '', - 'update-nag' - ); - } - - if ( $this->has_filter( 'optin_pointer_element' ) ) { - // Don't show admin nag if plugin update. - wp_enqueue_script( 'wp-pointer' ); - wp_enqueue_style( 'wp-pointer' ); - - $this->_enqueue_connect_essentials(); - - add_action( 'admin_print_footer_scripts', array( - $this, - '_add_connect_pointer_script' - ) ); - } - - } - } - } - } - - $this->_add_upgrade_action_link(); - } - - /** - * Enqueue connect requires scripts and styles. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.4 - */ - function _enqueue_connect_essentials() { - wp_enqueue_script( 'jquery' ); - wp_enqueue_script( 'json2' ); - - fs_enqueue_local_script( 'postmessage', 'nojquery.ba-postmessage.min.js' ); - fs_enqueue_local_script( 'fs-postmessage', 'postmessage.js' ); - - fs_enqueue_local_style( 'fs_connect', '/admin/connect.css' ); - } - - /** - * Add connect / opt-in pointer. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.4 - */ - function _add_connect_pointer_script() { - $vars = array( 'slug' => $this->_slug ); - $pointer_content = fs_get_template( 'connect.php', $vars ); - ?> - <script type="text/javascript">// <![CDATA[ - jQuery(document).ready(function ($) { - if ('undefined' !== typeof(jQuery().pointer)) { - - var element = <?php echo $this->apply_filters('optin_pointer_element', '$("#non_existing_element");') ?>; - - if (element.length > 0) { - var optin = $(element).pointer($.extend(true, {}, { - content : <?php echo json_encode($pointer_content) ?>, - position : { - edge : 'left', - align: 'center' - }, - buttons : function () { - // Don't show pointer buttons. - return ''; - }, - pointerWidth: 482 - }, <?php echo $this->apply_filters('optin_pointer_options_json', '{}') ?>)); - - <?php - echo $this->apply_filters('optin_pointer_execute', " - - optin.pointer('open'); - - // Tag the opt-in pointer with custom class. - $('.wp-pointer #fs_connect') - .parents('.wp-pointer.wp-pointer-top') - .addClass('fs-opt-in-pointer'); - - ", 'element', 'optin') ?> - } - } - }); - // ]]></script> - <?php - } - - /** - * Return current page's URL. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - * - * @return string - */ - function current_page_url() { - $url = 'http'; - - if ( isset( $_SERVER["HTTPS"] ) ) { - if ( $_SERVER["HTTPS"] == "on" ) { - $url .= "s"; - } - } - $url .= "://"; - if ( $_SERVER["SERVER_PORT"] != "80" ) { - $url .= $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . $_SERVER["REQUEST_URI"]; - } else { - $url .= $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"]; - } - - return esc_url( $url ); - } - - /** - * Check if the current page is the plugin's main admin settings page. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - * - * @return bool - */ - function _is_plugin_page() { - return fs_is_plugin_page( $this->_menu->get_raw_slug() ) || - fs_is_plugin_page( $this->_slug ); - } - - /* Events - ------------------------------------------------------------------------------------------------------------------*/ - /** - * Delete site install from Database. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.1 - * - * @param bool $store - */ - function _delete_site( $store = true ) { - $sites = self::get_all_sites(); - - if ( isset( $sites[ $this->_slug ] ) ) { - unset( $sites[ $this->_slug ] ); - } - - self::$_accounts->set_option( 'sites', $sites, $store ); - } - - /** - * Delete plugin's plans information. - * - * @param bool $store Flush to Database if true. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - */ - private function _delete_plans( $store = true ) { - $this->_logger->entrance(); - - $plans = self::get_all_plans(); - - unset( $plans[ $this->_slug ] ); - - self::$_accounts->set_option( 'plans', $plans, $store ); - } - - /** - * Delete all plugin licenses. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @param bool $store - * @param string|bool $plugin_slug - */ - private function _delete_licenses( $store = true, $plugin_slug = false ) { - $this->_logger->entrance(); - - $all_licenses = self::get_all_licenses(); - - if ( ! is_string( $plugin_slug ) ) { - $plugin_slug = $this->_slug; - } - - unset( $all_licenses[ $plugin_slug ] ); - - self::$_accounts->set_option( 'licenses', $all_licenses, $store ); - } - - /** - * Check if Freemius was added on new plugin installation. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.5 - * - * @return bool - */ - function is_plugin_new_install() { - return isset( $this->_storage->is_plugin_new_install ) && - $this->_storage->is_plugin_new_install; - } - - /** - * Plugin activated hook. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.1 - * - * @uses FS_Api - */ - function _activate_plugin_event_hook() { - $this->_logger->entrance( 'slug = ' . $this->_slug ); - - if ( ! current_user_can( 'activate_plugins' ) ) { - return; - } - - // Clear API cache on activation. - FS_Api::clear_cache(); - - if ( $this->is_registered() ) { - // Schedule re-activation event and sync. -// $this->sync_install( array(), true ); - $this->schedule_install_sync(); - - /** - * @todo Work on automatic deactivation of the Free plugin version. It doesn't work since the slug of the free & premium versions is identical. Therefore, only one instance of Freemius is created and the activation hook of the premium version is not being added. - */ - if ( $this->_plugin_basename !== $this->_free_plugin_basename ) { - // Deactivate Free plugin version on premium plugin activation. - deactivate_plugins( $this->_free_plugin_basename ); - - $this->_admin_notices->add( - sprintf( __fs( 'successful-version-upgrade-message', $this->_slug ), sprintf( '<b>%s</b>', $this->_plugin->title ) ), - __fs( 'woot', $this->_slug ) . '!' - ); - } - } else if ( $this->is_anonymous() ) { - /** - * Reset "skipped" click cache on the following: - * 1. Development mode. - * 2. If the user skipped the exact same version before. - * - * @todo 3. If explicitly asked to retry after every activation. - */ - if ( WP_FS__DEV_MODE || - $this->get_plugin_version() == $this->_storage->is_anonymous['version'] - ) { - $this->reset_anonymous_mode(); - } - } - - if ( ! isset( $this->_storage->is_plugin_new_install ) ) { - /** - * If no previous version of plugin's version exist, it means that it's either - * the first time that the plugin installed on the site, or the plugin was installed - * before but didn't have Freemius integrated. - * - * Since register_activation_hook() do NOT fires on updates since 3.1, and only fires - * on manual activation via the dashboard, is_plugin_activation() is TRUE - * only after immediate activation. - * - * @since 1.1.4 - * @link https://make.wordpress.org/core/2010/10/27/plugin-activation-hooks-no-longer-fire-for-updates/ - */ - $this->_storage->is_plugin_new_install = empty( $this->_storage->plugin_last_version ); - } - - if ( ! $this->_anonymous_mode && $this->has_api_connectivity( WP_FS__DEV_MODE ) ) { - // Store hint that the plugin was just activated to enable auto-redirection to settings. - add_option( "fs_{$this->_slug}_activated", true ); - } - } - - /** - * Delete account. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.3 - * - * @param bool $check_user Enforce checking if user have plugins activation privileges. - */ - function delete_account_event( $check_user = true ) { - $this->_logger->entrance( 'slug = ' . $this->_slug ); - - if ( $check_user && ! current_user_can( 'activate_plugins' ) ) { - return; - } - - $this->do_action( 'before_account_delete' ); - - // Clear all admin notices. - $this->_admin_notices->clear_all_sticky(); - - $this->_delete_site( false ); - - $this->_delete_plans( false ); - - $this->_delete_licenses( false ); - - // Delete add-ons related to plugin's account. - $this->_delete_account_addons( false ); - - // @todo Delete plans and licenses of add-ons. - - self::$_accounts->store(); - - /** - * IMPORTANT: - * Clear crons must be executed before clearing all storage. - * Otherwise, the cron will not be cleared. - */ - $this->clear_sync_cron(); - $this->clear_install_sync_cron(); - - // Clear all storage data. - $this->_storage->clear_all( true, array( - 'connectivity_test', - 'is_on', - ) ); - - // Send delete event. - $this->get_api_site_scope()->call( '/', 'delete' ); - - $this->do_action( 'after_account_delete' ); - } - - /** - * Plugin deactivation hook. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.1 - */ - function _deactivate_plugin_hook() { - $this->_logger->entrance( 'slug = ' . $this->_slug ); - - if ( ! current_user_can( 'activate_plugins' ) ) { - return; - } - - $this->_admin_notices->clear_all_sticky(); - if ( isset( $this->_storage->sticky_optin_added ) ) { - unset( $this->_storage->sticky_optin_added ); - } - - if ( ! isset( $this->_storage->is_plugin_new_install ) ) { - // Remember that plugin was already installed. - $this->_storage->is_plugin_new_install = false; - } - - $this->clear_sync_cron(); - $this->clear_install_sync_cron(); - - if ( $this->is_registered() ) { - // Send deactivation event. - $this->sync_install( array( - 'is_active' => false, - ) ); - } else { - if ( ! $this->has_api_connectivity() ) { - // Reset connectivity test cache. - unset( $this->_storage->connectivity_test ); - } - } - - // Clear API cache on deactivation. - FS_Api::clear_cache(); - - $this->remove_sdk_reference(); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.6 - */ - private function remove_sdk_reference() { - global $fs_active_plugins; - - foreach ( $fs_active_plugins->plugins as $sdk_path => &$data ) { - if ( $this->_plugin_basename == $data->plugin_path ) { - unset( $fs_active_plugins->plugins[ $sdk_path ] ); - break; - } - } - - fs_fallback_to_newest_active_sdk(); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.3 - * - * @param bool $is_anonymous - */ - private function set_anonymous_mode( $is_anonymous = true ) { - // Store information regarding skip to try and opt-in the user - // again in the future. - $this->_storage->is_anonymous = array( - 'is' => $is_anonymous, - 'timestamp' => WP_FS__SCRIPT_START_TIME, - 'version' => $this->get_plugin_version(), - ); - - // Update anonymous mode cache. - $this->_is_anonymous = $is_anonymous; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.3 - */ - private function reset_anonymous_mode() { - unset( $this->_storage->is_anonymous ); - } - - /** - * Clears the anonymous mode and redirects to the opt-in screen. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.7 - */ - function connect_again() { - if ( ! $this->is_anonymous() ) { - return; - } - - $this->reset_anonymous_mode(); - - if ( fs_redirect( $this->get_activation_url() ) ) { - exit(); - } - } - - /** - * Skip account connect, and set anonymous mode. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.1 - */ - private function skip_connection() { - $this->_logger->entrance(); - - $this->_admin_notices->remove_sticky( 'connect_account' ); - - $this->set_anonymous_mode(); - - // Send anonymous skip event. - // No user identified info nor any tracking will be sent after the user skips the opt-in. - $this->get_api_plugin_scope()->call( 'skip.json', 'put', array( - 'uid' => $this->get_anonymous_id(), - ) ); - } - - /** - * Plugin version update hook. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - */ - private function update_plugin_version_event() { - $this->_logger->entrance(); - - if ( ! $this->is_registered() ) { - return; - } - - $this->schedule_install_sync(); -// $this->sync_install( array(), true ); - } - - /** - * Return a list of modified plugins since the last sync. - * - * Note: - * There's no point to store a plugins counter since even if the number of - * plugins didn't change, we still need to check if the versions are all the - * same and the activity state is similar. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.8 - * - * @return array|false - */ - private function get_plugins_data_for_api() { - // Alias. - $option_name = 'all_plugins'; - - $all_cached_plugins = self::$_accounts->get_option( $option_name ); - - if ( ! is_object( $all_cached_plugins ) ) { - $all_cached_plugins = (object) array( - 'timestamp' => '', - 'md5' => '', - 'plugins' => array(), - ); - } - - $time = time(); - - if ( ! empty( $all_cached_plugins->timestamp ) && - ( $time - $all_cached_plugins->timestamp ) < WP_FS__TIME_5_MIN_IN_SEC - ) { - // Don't send plugin updates if last update was in the past 5 min. - return false; - } - - // Write timestamp to lock the logic. - $all_cached_plugins->timestamp = $time; - self::$_accounts->set_option( $option_name, $all_cached_plugins, true ); - - // Reload options from DB. - self::$_accounts->load( true ); - $all_cached_plugins = self::$_accounts->get_option( $option_name ); - - if ( $time != $all_cached_plugins->timestamp ) { - // If timestamp is different, then another thread captured the lock. - return false; - } - - // Check if there's a change in plugins. - $all_plugins = self::get_all_plugins(); - - // Check if plugins changed. - ksort( $all_plugins ); - - $plugins_signature = ''; - foreach ( $all_plugins as $basename => $data ) { - $plugins_signature .= $data['slug'] . ',' . - $data['Version'] . ',' . - ( $data['is_active'] ? '1' : '0' ) . ';'; - } - - // Check if plugins status changed (version or active/inactive). - $plugins_changed = ( $all_cached_plugins->md5 !== md5( $plugins_signature ) ); - - $plugins_update_data = array(); - - if ( $plugins_changed ) { - // Change in plugins, report changes. - - // Update existing plugins info. - foreach ( $all_cached_plugins->plugins as $basename => $data ) { - if ( ! isset( $all_plugins[ $basename ] ) ) { - // Plugin uninstalled. - $uninstalled_plugin_data = $data; - $uninstalled_plugin_data['is_active'] = false; - $uninstalled_plugin_data['is_uninstalled'] = true; - $plugins_update_data[] = $uninstalled_plugin_data; - - unset( $all_plugins[ $basename ] ); - unset( $all_cached_plugins->plugins[ $basename ] ); - } else if ( $data['is_active'] !== $all_plugins[ $basename ]['is_active'] || - $data['version'] !== $all_plugins[ $basename ]['Version'] - ) { - // Plugin activated or deactivated, or version changed. - $all_cached_plugins->plugins[ $basename ]['is_active'] = $all_plugins[ $basename ]['is_active']; - $all_cached_plugins->plugins[ $basename ]['version'] = $all_plugins[ $basename ]['Version']; - - $plugins_update_data[] = $all_cached_plugins->plugins[ $basename ]; - } - } - - // Find new plugins that weren't yet seen before. - foreach ( $all_plugins as $basename => $data ) { - if ( ! isset( $all_cached_plugins->plugins[ $basename ] ) ) { - // New plugin. - $new_plugin = array( - 'slug' => $data['slug'], - 'version' => $data['Version'], - 'title' => $data['Name'], - 'is_active' => $data['is_active'], - 'is_uninstalled' => false, - ); - - $plugins_update_data[] = $new_plugin; - $all_cached_plugins->plugins[ $basename ] = $new_plugin; - } - } - - $all_cached_plugins->md5 = md5( $plugins_signature ); - $all_cached_plugins->timestamp = $time; - self::$_accounts->set_option( $option_name, $all_cached_plugins, true ); - } - - return $plugins_update_data; - } - - /** - * Return a list of modified themes since the last sync. - * - * Note: - * There's no point to store a themes counter since even if the number of - * themes didn't change, we still need to check if the versions are all the - * same and the activity state is similar. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.8 - * - * @return array|false - */ - private function get_themes_data_for_api() { - // Alias. - $option_name = 'all_themes'; - - $all_cached_themes = self::$_accounts->get_option( $option_name ); - - if ( ! is_object( $all_cached_themes ) ) { - $all_cached_themes = (object) array( - 'timestamp' => '', - 'md5' => '', - 'themes' => array(), - ); - } - - $time = time(); - - if ( ! empty( $all_cached_themes->timestamp ) && - ( $time - $all_cached_themes->timestamp ) < WP_FS__TIME_5_MIN_IN_SEC - ) { - // Don't send theme updates if last update was in the past 5 min. - return false; - } - - // Write timestamp to lock the logic. - $all_cached_themes->timestamp = $time; - self::$_accounts->set_option( $option_name, $all_cached_themes, true ); - - // Reload options from DB. - self::$_accounts->load( true ); - $all_cached_themes = self::$_accounts->get_option( $option_name ); - - if ( $time != $all_cached_themes->timestamp ) { - // If timestamp is different, then another thread captured the lock. - return false; - } - - // Get active theme. - $active_theme = wp_get_theme(); - - // Check if there's a change in themes. - $all_themes = wp_get_themes(); - - // Check if themes changed. - ksort( $all_themes ); - - $themes_signature = ''; - foreach ( $all_themes as $slug => $data ) { - $is_active = ( $slug === $active_theme->stylesheet ); - $themes_signature .= $slug . ',' . - $data->version . ',' . - ( $is_active ? '1' : '0' ) . ';'; - } - - // Check if themes status changed (version or active/inactive). - $themes_changed = ( $all_cached_themes->md5 !== md5( $themes_signature ) ); - - $themes_update_data = array(); - - if ( $themes_changed ) { - // Change in themes, report changes. - - // Update existing themes info. - foreach ( $all_cached_themes->themes as $slug => $data ) { - $is_active = ( $slug === $active_theme->stylesheet ); - - if ( ! isset( $all_themes[ $slug ] ) ) { - // Plugin uninstalled. - $uninstalled_theme_data = $data; - $uninstalled_theme_data['is_active'] = false; - $uninstalled_theme_data['is_uninstalled'] = true; - $themes_update_data[] = $uninstalled_theme_data; - - unset( $all_themes[ $slug ] ); - unset( $all_cached_themes->themes[ $slug ] ); - } else if ( $data['is_active'] !== $is_active || - $data['version'] !== $all_themes[ $slug ]->version - ) { - // Plugin activated or deactivated, or version changed. - - $all_cached_themes->themes[ $slug ]['is_active'] = $is_active; - $all_cached_themes->themes[ $slug ]['version'] = $all_themes[ $slug ]->version; - - $themes_update_data[] = $all_cached_themes->themes[ $slug ]; - } - } - - // Find new themes that weren't yet seen before. - foreach ( $all_themes as $slug => $data ) { - if ( ! isset( $all_cached_themes->themes[ $slug ] ) ) { - $is_active = ( $slug === $active_theme->stylesheet ); - - // New plugin. - $new_plugin = array( - 'slug' => $slug, - 'version' => $data->version, - 'title' => $data->name, - 'is_active' => $is_active, - 'is_uninstalled' => false, - ); - - $themes_update_data[] = $new_plugin; - $all_cached_themes->themes[ $slug ] = $new_plugin; - } - } - - $all_cached_themes->md5 = md5( $themes_signature ); - $all_cached_themes->timestamp = time(); - self::$_accounts->set_option( $option_name, $all_cached_themes, true ); - } - - return $themes_update_data; - } - - /** - * Update install details. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.2 - * - * @param string[] string $override - * @param bool $include_plugins Since 1.1.8 by default include plugin changes. - * @param bool $include_themes Since 1.1.8 by default include plugin changes. - * - * @return array - */ - private function get_install_data_for_api( - array $override, - $include_plugins = true, - $include_themes = true - ) { - /** - * @since 1.1.8 Also send plugin updates. - */ - if ( $include_plugins && ! isset( $override['plugins'] ) ) { - $plugins = $this->get_plugins_data_for_api(); - if ( ! empty( $plugins ) ) { - $override['plugins'] = $plugins; - } - } - /** - * @since 1.1.8 Also send themes updates. - */ - if ( $include_themes && ! isset( $override['themes'] ) ) { - $themes = $this->get_themes_data_for_api(); - if ( ! empty( $themes ) ) { - $override['themes'] = $themes; - } - } - - return array_merge( array( - 'version' => $this->get_plugin_version(), - 'is_premium' => $this->is_premium(), - 'language' => get_bloginfo( 'language' ), - 'charset' => get_bloginfo( 'charset' ), - 'platform_version' => get_bloginfo( 'version' ), - 'programming_language_version' => phpversion(), - 'title' => get_bloginfo( 'name' ), - 'url' => get_site_url(), - // Special params. - 'is_active' => true, - 'is_uninstalled' => false, - ), $override ); - } - - /** - * Update install only if changed. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @param string[] string $override - * @param bool $flush - * - * @return false|object|string - */ - private function send_install_update( $override = array(), $flush = false ) { - $this->_logger->entrance(); - - $check_properties = $this->get_install_data_for_api( $override ); - - if ( $flush ) { - $params = $check_properties; - } else { - $params = array(); - $special = array(); - $special_override = false; - - foreach ( $check_properties as $p => $v ) { - if ( property_exists( $this->_site, $p ) ) { - if ( ! empty( $this->_site->{$p} ) && - $this->_site->{$p} != $v - ) { - $this->_site->{$p} = $v; - $params[ $p ] = $v; - } - } else { - $special[ $p ] = $v; - - if ( isset( $override[ $p ] ) || - 'plugins' === $p || - 'themes' === $p - ) { - $special_override = true; - } - } - } - - if ( $special_override || 0 < count( $params ) ) { - // Add special params only if has at least one - // standard param, or if explicitly requested to - // override a special param or a param which is not exist - // in the install object. - $params = array_merge( $params, $special ); - } - } - - if ( 0 < count( $params ) ) { - // Update last install sync timestamp. - $this->_storage->install_sync_timestamp = time(); - - $params['uid'] = $this->get_anonymous_id(); - - // Send updated values to FS. - $site = $this->get_api_site_scope()->call( '/', 'put', $params ); - - if ( ! $this->is_api_error( $site ) ) { - // I successfully sent install update, clear scheduled sync if exist. - $this->clear_install_sync_cron(); - } - - return $site; - } - - return false; - } - - /** - * Update install only if changed. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @param string[] string $override - * @param bool $flush - * - * @return false|object|string - */ - private function sync_install( $override = array(), $flush = false ) { - $this->_logger->entrance(); - - $site = $this->send_install_update( $override, $flush ); - - if ( false === $site ) { - // No sync required. - return; - } - - if ( $this->is_api_error( $site ) ) { - // Failed to sync, don't update locally. - return; - } - - $plan = $this->get_plan(); - $this->_site = new FS_Site( $site ); - $this->_site->plan = $plan; - - $this->_store_site( true ); - } - - /** - * Plugin uninstall hook. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.1 - * - * @param bool $check_user Enforce checking if user have plugins activation privileges. - */ - function _uninstall_plugin_event( $check_user = true ) { - $this->_logger->entrance( 'slug = ' . $this->_slug ); - - if ( $check_user && ! current_user_can( 'activate_plugins' ) ) { - return; - } - - $params = array(); - if ( isset( $this->_storage->uninstall_reason ) ) { - $params['reason_id'] = $this->_storage->uninstall_reason->id; - $params['reason_info'] = $this->_storage->uninstall_reason->info; - } - - if ( ! $this->is_registered() && isset( $this->_storage->uninstall_reason ) ) { - // Send anonymous uninstall event only if user submitted a feedback. - $params['uid'] = $this->get_anonymous_id(); - $this->get_api_plugin_scope()->call( 'uninstall.json', 'put', $params ); - } else { - // Send uninstall event. - $this->send_install_update( array_merge( $params, array( - 'is_active' => false, - 'is_uninstalled' => true, - ) ) ); - } - - // @todo Decide if we want to delete plugin information from db. - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.1 - * - * @return string - */ - private function premium_plugin_basename() { - return preg_replace( '/\//', '-premium/', $this->_free_plugin_basename, 1 ); - } - - /** - * Uninstall plugin hook. Called only when connected his account with Freemius for active sites tracking. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.2 - */ - public static function _uninstall_plugin_hook() { - self::_load_required_static(); - - self::$_static_logger->entrance(); - - if ( ! current_user_can( 'activate_plugins' ) ) { - return; - } - - $plugin_file = substr( current_filter(), strlen( 'uninstall_' ) ); - - self::$_static_logger->info( 'plugin = ' . $plugin_file ); - - define( 'WP_FS__UNINSTALL_MODE', true ); - - $fs = self::get_instance_by_file( $plugin_file ); - - if ( is_object( $fs ) ) { - self::require_plugin_essentials(); - - if ( is_plugin_active( $fs->_free_plugin_basename ) || - is_plugin_active( $fs->premium_plugin_basename() ) - ) { - // Deleting Free or Premium plugin version while the other version still installed. - return; - } - - $fs->_uninstall_plugin_event(); - - $fs->do_action( 'after_uninstall' ); - } - } - - #region Plugin Information ------------------------------------------------------------------ - - /** - * Load WordPress core plugin.php essential module. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.1 - */ - private static function require_plugin_essentials() { - if ( ! function_exists( 'get_plugins' ) ) { - require_once( ABSPATH . 'wp-admin/includes/plugin.php' ); - } - } - - /** - * Load WordPress core pluggable.php module. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.2 - */ - private static function require_pluggable_essentials() { - if ( ! function_exists( 'wp_get_current_user' ) ) { - require_once( ABSPATH . 'wp-includes/pluggable.php' ); - } - } - - /** - * Return plugin data. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.1 - * - * @return array - */ - function get_plugin_data() { - if ( ! isset( $this->_plugin_data ) ) { - self::require_plugin_essentials(); - - $this->_plugin_data = get_plugin_data( $this->_plugin_main_file_path ); - } - - return $this->_plugin_data; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.1 - * - * @return string Plugin slug. - */ - function get_slug() { - return $this->_slug; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.1 - * - * @return number Plugin ID. - */ - function get_id() { - return $this->_plugin->id; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.1 - * - * @return string Plugin public key. - */ - function get_public_key() { - return $this->_plugin->public_key; - } - - /** - * Will be available only on sandbox mode. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - * - * @return mixed Plugin secret key. - */ - function get_secret_key() { - return $this->_plugin->secret_key; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.1 - * - * @return bool - */ - function has_secret_key() { - return ! empty( $this->_plugin->secret_key ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @return string - */ - function get_plugin_name() { - $this->_logger->entrance(); - - if ( ! isset( $this->_plugin_name ) ) { - $plugin_data = $this->get_plugin_data(); - - // Get name. - $this->_plugin_name = $plugin_data['Name']; - - // Check if plugin name contains [Premium] suffix and remove it. - $suffix = '[premium]'; - $suffix_len = strlen( $suffix ); - - if ( strlen( $plugin_data['Name'] ) > $suffix_len && - $suffix === substr( strtolower( $plugin_data['Name'] ), - $suffix_len ) - ) { - $this->_plugin_name = substr( $plugin_data['Name'], 0, - $suffix_len ); - } - - $this->_logger->departure( 'Name = ' . $this->_plugin_name ); - } - - return $this->_plugin_name; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.0 - * - * @return string - */ - function get_plugin_version() { - $this->_logger->entrance(); - - $plugin_data = $this->get_plugin_data(); - - $this->_logger->departure( 'Version = ' . $plugin_data['Version'] ); - - return $this->apply_filters( 'plugin_version', $plugin_data['Version'] ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - * - * @return string - */ - function get_plugin_basename() { - return $this->_plugin_basename; - } - - function get_plugin_folder_name() { - $this->_logger->entrance(); - - $plugin_folder = $this->_plugin_basename; - - while ( '.' !== dirname( $plugin_folder ) ) { - $plugin_folder = dirname( $plugin_folder ); - } - - $this->_logger->departure( 'Folder Name = ' . $plugin_folder ); - - return $plugin_folder; - } - - #endregion ------------------------------------------------------------------ - - /* Account - ------------------------------------------------------------------------------------------------------------------*/ - - /** - * Find plugin's slug by plugin's basename. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @param string $plugin_base_name - * - * @return false|string - */ - private static function find_slug_by_basename( $plugin_base_name ) { - $file_slug_map = self::$_accounts->get_option( 'file_slug_map', array() ); - - if ( ! array( $file_slug_map ) || ! isset( $file_slug_map[ $plugin_base_name ] ) ) { - return false; - } - - return $file_slug_map[ $plugin_base_name ]; - } - - /** - * Store the map between the plugin's basename to the slug. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - */ - private function store_file_slug_map() { - $file_slug_map = self::$_accounts->get_option( 'file_slug_map', array() ); - - if ( ! array( $file_slug_map ) ) { - $file_slug_map = array(); - } - - if ( ! isset( $file_slug_map[ $this->_plugin_basename ] ) || - $file_slug_map[ $this->_plugin_basename ] !== $this->_slug - ) { - $file_slug_map[ $this->_plugin_basename ] = $this->_slug; - self::$_accounts->set_option( 'file_slug_map', $file_slug_map, true ); - } - } - - /** - * @return FS_User[] - */ - static function get_all_users() { - $users = self::$_accounts->get_option( 'users', array() ); - - if ( ! is_array( $users ) ) { - $users = array(); - } - - return $users; - } - - /** - * @return FS_Site[] - */ - private static function get_all_sites() { - $sites = self::$_accounts->get_option( 'sites', array() ); - - if ( ! is_array( $sites ) ) { - $sites = array(); - } - - return $sites; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @return FS_Plugin_License[] - */ - private static function get_all_licenses() { - $licenses = self::$_accounts->get_option( 'licenses', array() ); - - if ( ! is_array( $licenses ) ) { - $licenses = array(); - } - - return $licenses; - } - - /** - * @return FS_Plugin_Plan[] - */ - private static function get_all_plans() { - $plans = self::$_accounts->get_option( 'plans', array() ); - - if ( ! is_array( $plans ) ) { - $plans = array(); - } - - return $plans; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - * - * @return FS_Plugin_Tag[] - */ - private static function get_all_updates() { - $updates = self::$_accounts->get_option( 'updates', array() ); - - if ( ! is_array( $updates ) ) { - $updates = array(); - } - - return $updates; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @return FS_Plugin[]|false - */ - private static function get_all_addons() { - $addons = self::$_accounts->get_option( 'addons', array() ); - - if ( ! is_array( $addons ) ) { - $addons = array(); - } - - return $addons; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @return FS_Plugin[]|false - */ - private static function get_all_account_addons() { - $addons = self::$_accounts->get_option( 'account_addons', array() ); - - if ( ! is_array( $addons ) ) { - $addons = array(); - } - - return $addons; - } - - /** - * Check if user is registered. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.1 - * @return bool - */ - function is_registered() { - return is_object( $this->_user ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - * - * @return FS_Plugin - */ - function get_plugin() { - return $this->_plugin; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.3 - * - * @return FS_User - */ - function get_user() { - return $this->_user; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.3 - * - * @return FS_Site - */ - function get_site() { - return $this->_site; - } - - /** - * Get plugin add-ons. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @since 1.1.7.3 If not yet loaded, fetch data from the API. - * - * @return FS_Plugin[]|false - */ - function get_addons() { - $this->_logger->entrance(); - - $all_addons = self::get_all_addons(); - - /** - * @since 1.1.7.3 If not yet loaded, fetch data from the API. - */ - if ( ! is_array( $all_addons ) || - ! isset( $all_addons[ $this->_plugin->id ] ) || - ! is_array( $all_addons[ $this->_plugin->id ] ) || - empty( $all_addons[ $this->_plugin->id ] ) - ) { - if ( $this->_has_addons ) { - $addons = $this->_sync_addons(); - - if ( ! empty( $addons ) ) { - $all_addons = self::get_all_addons(); - } - } - } - - if ( ! is_array( $all_addons ) || - ! isset( $all_addons[ $this->_plugin->id ] ) || - ! is_array( $all_addons[ $this->_plugin->id ] ) || - empty( $all_addons[ $this->_plugin->id ] ) - ) { - return false; - } - - return $all_addons[ $this->_plugin->id ]; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @return FS_Plugin[]|false - */ - function get_account_addons() { - $this->_logger->entrance(); - - $addons = self::get_all_account_addons(); - - if ( ! is_array( $addons ) || - ! isset( $addons[ $this->_plugin->id ] ) || - ! is_array( $addons[ $this->_plugin->id ] ) || - 0 === count( $addons[ $this->_plugin->id ] ) - ) { - return false; - } - - return $addons[ $this->_plugin->id ]; - } - - /** - * Check if user has any - * - * @author Vova Feldman (@svovaf) - * @since 1.1.6 - * - * @return bool - */ - function has_account_addons() { - $addons = $this->get_account_addons(); - - return is_array( $addons ) && ( 0 < count( $addons ) ); - } - - - /** - * Get add-on by ID (from local data). - * - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @param number $id - * - * @return FS_Plugin|false - */ - function get_addon( $id ) { - $this->_logger->entrance(); - - $addons = $this->get_addons(); - - if ( is_array( $addons ) ) { - foreach ( $addons as $addon ) { - if ( $id == $addon->id ) { - return $addon; - } - } - } - - return false; - } - - /** - * Get add-on by slug (from local data). - * - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @param string $slug - * - * @return FS_Plugin|false - */ - function get_addon_by_slug( $slug ) { - $this->_logger->entrance(); - - $addons = $this->get_addons(); - - if ( is_array( $addons ) ) { - foreach ( $addons as $addon ) { - if ( $slug == $addon->slug ) { - return $addon; - } - } - } - - return false; - } - - #region Plans & Licensing ------------------------------------------------------------------ - - /** - * Check if running premium plugin code. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.5 - * - * @return bool - */ - function is_premium() { - return $this->_plugin->is_premium; - } - - /** - * Get site's plan ID. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.2 - * - * @return number - */ - function get_plan_id() { - return $this->_site->plan->id; - } - - /** - * Get site's plan title. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.2 - * - * @return string - */ - function get_plan_title() { - return $this->_site->plan->title; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @return FS_Plugin_Plan - */ - function get_plan() { - return is_object( $this->_site->plan ) ? $this->_site->plan : false; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.3 - * - * @return bool - */ - function is_trial() { - $this->_logger->entrance(); - - if ( ! $this->is_registered() ) { - return false; - } - - return $this->_site->is_trial(); - } - - /** - * Check if currently in a trial with payment method (credit card or paypal). - * - * @author Vova Feldman (@svovaf) - * @since 1.1.7 - * - * @return bool - */ - function is_paid_trial() { - $this->_logger->entrance(); - - if ( ! $this->is_trial() ) { - return false; - } - - return $this->has_active_license() && ( $this->_site->trial_plan_id == $this->_license->plan_id ); - } - - /** - * Check if trial already utilized. - * - * @since 1.0.9 - * - * @return bool - */ - function is_trial_utilized() { - $this->_logger->entrance(); - - if ( ! $this->is_registered() ) { - return false; - } - - return $this->_site->is_trial_utilized(); - } - - /** - * Get trial plan information (if in trial). - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @return bool|FS_Plugin_Plan - */ - function get_trial_plan() { - $this->_logger->entrance(); - - if ( ! $this->is_trial() ) { - return false; - } - - return $this->_storage->trial_plan; - } - - /** - * Check if the user has an activated and valid paid license on current plugin's install. - * - * @since 1.0.9 - * - * @return bool - */ - function is_paying() { - $this->_logger->entrance(); - - if ( ! $this->is_registered() ) { - return false; - } - - if ( ! $this->has_paid_plan() ) { - return false; - } - - return ( - ! $this->is_trial() && - 'free' !== $this->_site->plan->name && - $this->has_features_enabled_license() - ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - * - * @return bool - */ - function is_free_plan() { - if ( ! $this->is_registered() ) { - return true; - } - - if ( ! $this->has_paid_plan() ) { - return true; - } - - return ( - 'free' === $this->_site->plan->name || - ! $this->has_features_enabled_license() - ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.5 - * - * @return bool - */ - function _has_premium_license() { - $this->_logger->entrance(); - - $premium_license = $this->_get_available_premium_license(); - - return ( false !== $premium_license ); - } - - /** - * Check if user has any licenses associated with the plugin (including expired or blocking). - * - * @author Vova Feldman (@svovaf) - * @since 1.1.7.3 - * - * @return bool - */ - private function has_any_license() { - return is_array( $this->_licenses ) && ( 0 < count( $this->_licenses ) ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.5 - * - * @return FS_Plugin_License - */ - function _get_available_premium_license() { - $this->_logger->entrance(); - - if ( ! $this->has_paid_plan() ) { - return false; - } - - if ( is_array( $this->_licenses ) ) { - foreach ( $this->_licenses as $license ) { - if ( ! $license->is_utilized() && $license->is_features_enabled() ) { - return $license; - } - } - } - - return false; - } - - /** - * Sync local plugin plans with remote server. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.5 - * - * @return FS_Plugin_Plan[]|object - */ - function _sync_plans() { - $plans = $this->_fetch_plugin_plans(); - if ( ! $this->is_api_error( $plans ) ) { - $this->_plans = $plans; - $this->_store_plans(); - } - - $this->do_action( 'after_plans_sync', $plans ); - - return $this->_plans; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.5 - * - * @param number $id - * - * @return FS_Plugin_Plan - */ - function _get_plan_by_id( $id ) { - $this->_logger->entrance(); - - if ( ! is_array( $this->_plans ) || 0 === count( $this->_plans ) ) { - $this->_sync_plans(); - } - - foreach ( $this->_plans as $plan ) { - if ( $id == $plan->id ) { - return $plan; - } - } - - return false; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.8.1 - * - * @param string $name - * - * @return FS_Plugin_Plan|false - */ - private function get_plan_by_name( $name ) { - $this->_logger->entrance(); - - if ( ! is_array( $this->_plans ) || 0 === count( $this->_plans ) ) { - $this->_sync_plans(); - } - - foreach ( $this->_plans as $plan ) { - if ( $name == $plan->name ) { - return $plan; - } - } - - return false; - } - - /** - * Sync local plugin plans with remote server. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @return FS_Plugin_License[]|object - */ - function _sync_licenses() { - $licenses = $this->_fetch_licenses(); - if ( ! $this->is_api_error( $licenses ) ) { - $this->_licenses = $licenses; - $this->_store_licenses(); - } - - // Update current license. - if ( is_object( $this->_license ) ) { - $this->_license = $this->_get_license_by_id( $this->_license->id ); - } - - return $this->_licenses; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.5 - * - * @param number $id - * - * @return FS_Plugin_License - */ - function _get_license_by_id( $id ) { - $this->_logger->entrance(); - - if ( ! is_numeric( $id ) ) { - return false; - } - - if ( ! is_array( $this->_licenses ) || 0 === count( $this->_licenses ) ) { - $this->_sync_licenses(); - } - - foreach ( $this->_licenses as $license ) { - if ( $id == $license->id ) { - return $license; - } - } - - return false; - } - - /** - * Sync site's license with user licenses. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @param FS_Plugin_License|null $new_license - */ - function _update_site_license( $new_license ) { - $this->_logger->entrance(); - - $this->_license = $new_license; - - if ( ! is_object( $new_license ) ) { - $this->_site->license_id = null; - $this->_sync_site_subscription( null ); - - return; - } - - $this->_site->license_id = $this->_license->id; - - if ( ! is_array( $this->_licenses ) ) { - $this->_licenses = array(); - } - - $is_license_found = false; - for ( $i = 0, $len = count( $this->_licenses ); $i < $len; $i ++ ) { - if ( $new_license->id == $this->_licenses[ $i ]->id ) { - $this->_licenses[ $i ] = $new_license; - - $is_license_found = true; - break; - } - } - - // If new license just append. - if ( ! $is_license_found ) { - $this->_licenses[] = $new_license; - } - - $this->_sync_site_subscription( $new_license ); - } - - /** - * Sync site's subscription. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @param FS_Plugin_License|null $license - * - * @return bool|\FS_Subscription - */ - private function _sync_site_subscription( $license ) { - if ( ! is_object( $license ) ) { - unset( $this->_storage->subscription ); - - return false; - } - - // Load subscription details if not lifetime. - $subscription = $license->is_lifetime() ? - false : - $this->_fetch_site_license_subscription(); - - if ( is_object( $subscription ) && ! isset( $subscription->error ) ) { - $this->_storage->subscription = $subscription; - } else { - unset( $this->_storage->subscription ); - } - - return $subscription; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @return bool|\FS_Plugin_License - */ - function _get_license() { - return $this->_license; - } - - /** - * @return bool|\FS_Subscription - */ - function _get_subscription() { - return isset( $this->_storage->subscription ) ? - $this->_storage->subscription : - false; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.2 - * - * @param string $plan Plan name - * @param bool $exact If true, looks for exact plan. If false, also check "higher" plans. - * - * @return bool - */ - function is_plan( $plan, $exact = false ) { - $this->_logger->entrance(); - - if ( ! $this->is_registered() ) { - return false; - } - - $plan = strtolower( $plan ); - - if ( $this->_site->plan->name === $plan ) // Exact plan. - { - return true; - } else if ( $exact ) // Required exact, but plans are different. - { - return false; - } - - $current_plan_order = - 1; - $required_plan_order = - 1; - for ( $i = 0, $len = count( $this->_plans ); $i < $len; $i ++ ) { - if ( $plan === $this->_plans[ $i ]->name ) { - $required_plan_order = $i; - } else if ( $this->_site->plan->name === $this->_plans[ $i ]->name ) { - $current_plan_order = $i; - } - } - - return ( $current_plan_order > $required_plan_order ); - } - - /** - * Check if plan based on trial. If not in trial mode, should return false. - * - * @since 1.0.9 - * - * @param string $plan Plan name - * @param bool $exact If true, looks for exact plan. If false, also check "higher" plans. - * - * @return bool - */ - function is_trial_plan( $plan, $exact = false ) { - $this->_logger->entrance(); - - if ( ! $this->is_registered() ) { - return false; - } - - if ( ! $this->is_trial() ) { - return false; - } - - if ( ! isset( $this->_storage->trial_plan ) ) { - // Store trial plan information. - $this->_enrich_site_trial_plan( true ); - } - - if ( $this->_storage->trial_plan->name === $plan ) // Exact plan. - { - return true; - } else if ( $exact ) // Required exact, but plans are different. - { - return false; - } - - $current_plan_order = - 1; - $required_plan_order = - 1; - for ( $i = 0, $len = count( $this->_plans ); $i < $len; $i ++ ) { - if ( $plan === $this->_plans[ $i ]->name ) { - $required_plan_order = $i; - } else if ( $this->_storage->trial_plan->name === $this->_plans[ $i ]->name ) { - $current_plan_order = $i; - } - } - - return ( $current_plan_order > $required_plan_order ); - } - - /** - * Check if plugin has any paid plans. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - * - * @return bool - */ - function has_paid_plan() { - return $this->_has_paid_plans || FS_Plan_Manager::instance()->has_paid_plan( $this->_plans ); - } - - /** - * Check if plugin has any plan with a trail. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @return bool - */ - function has_trial_plan() { - if ( ! $this->is_registered() ) { - return false; - } - - return $this->_storage->get( 'has_trial_plan', false ); - } - - /** - * Check if plugin has any free plan, or is it premium only. - * - * Note: If no plans configured, assume plugin is free. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - * - * @return bool - */ - function has_free_plan() { - return FS_Plan_Manager::instance()->has_free_plan( $this->_plans ); - } - - #region URL Generators - - /** - * Alias to pricing_url(). - * - * @author Vova Feldman (@svovaf) - * @since 1.0.2 - * - * @uses pricing_url() - * - * @param string $period Billing cycle - * @param bool $is_trial - * - * @return string - */ - function get_upgrade_url( $period = WP_FS__PERIOD_ANNUALLY, $is_trial = false ) { - return $this->pricing_url( $period, $is_trial ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @uses get_upgrade_url() - * - * @return string - */ - function get_trial_url() { - return $this->get_upgrade_url( WP_FS__PERIOD_ANNUALLY, true ); - } - - /** - * Plugin's pricing URL. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - * - * @param string $billing_cycle Billing cycle - * - * @param bool $is_trial - * - * @return string - */ - function pricing_url( $billing_cycle = WP_FS__PERIOD_ANNUALLY, $is_trial = false ) { - $this->_logger->entrance(); - - $params = array( - 'billing_cycle' => $billing_cycle - ); - - if ( $is_trial ) { - $params['trial'] = 'true'; - } - - return $this->_get_admin_page_url( 'pricing', $params ); - } - - /** - * Checkout page URL. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @param string $billing_cycle Billing cycle - * @param bool $is_trial - * @param array $extra (optional) Extra parameters, override other query params. - * - * @return string - */ - function checkout_url( - $billing_cycle = WP_FS__PERIOD_ANNUALLY, - $is_trial = false, - $extra = array() - ) { - $this->_logger->entrance(); - - $params = array( - 'checkout' => 'true', - 'billing_cycle' => $billing_cycle, - ); - - if ( $is_trial ) { - $params['trial'] = 'true'; - } - - /** - * Params in extra override other params. - */ - $params = array_merge( $params, $extra ); - - return $this->_get_admin_page_url( 'pricing', $params ); - } - - /** - * Add-on checkout URL. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.7 - * - * @param number $addon_id - * @param number $pricing_id - * @param string $billing_cycle - * @param bool $is_trial - * - * @return string - */ - function addon_checkout_url( - $addon_id, - $pricing_id, - $billing_cycle = WP_FS__PERIOD_ANNUALLY, - $is_trial = false - ) { - return $this->checkout_url( $billing_cycle, $is_trial, array( - 'plugin_id' => $addon_id, - 'pricing_id' => $pricing_id, - ) ); - } - - #endregion - - #endregion ------------------------------------------------------------------ - - /** - * Check if plugin has any add-ons. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.5 - * - * @since 1.1.7.3 Base logic only on the parameter provided by the developer in the init function. - * - * @return bool - */ - function has_addons() { - $this->_logger->entrance(); - - return $this->_has_addons; - } - - /** - * Check if plugin can work in anonymous mode. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @return bool - */ - function enable_anonymous() { - return $this->_enable_anonymous; - } - - /** - * Check if feature supported with current site's plan. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.1 - * - * @todo IMPLEMENT - * - * @param number $feature_id - * - * @throws Exception - */ - function is_feature_supported( $feature_id ) { - throw new Exception( 'not implemented' ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.1 - * - * @return bool Is running in SSL/HTTPS - */ - function is_ssl() { - return WP_FS__IS_HTTPS; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @return bool Is running in AJAX call. - * - * @link http://wordpress.stackexchange.com/questions/70676/how-to-check-if-i-am-in-admin-ajax - */ - function is_ajax() { - return ( defined( 'DOING_AJAX' ) && DOING_AJAX ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.7 - * - * @return bool - */ - function is_cron() { - return ( defined( 'DOING_CRON' ) && DOING_CRON ); - } - - /** - * Check if a real user is visiting the admin dashboard. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.7 - * - * @return bool - */ - function is_user_in_admin() { - return is_admin() && ! $this->is_ajax() && ! $this->is_cron(); - } - - /** - * Check if running in HTTPS and if site's plan matching the specified plan. - * - * @param string $plan - * @param bool $exact - * - * @return bool - */ - function is_ssl_and_plan( $plan, $exact = false ) { - return ( $this->is_ssl() && $this->is_plan( $plan, $exact ) ); - } - - /** - * Construct plugin's settings page URL. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - * - * @param string $page - * @param array $params - * - * @return string - */ - function _get_admin_page_url( $page = '', $params = array() ) { - if ( ! $this->_menu->is_top_level() ) { - $parent_slug = $this->_menu->get_parent_slug(); - $menu_file = ( false !== strpos( $parent_slug, '.php' ) ) ? - $parent_slug : - 'admin.php'; - - return add_query_arg( array_merge( $params, array( - 'page' => $this->_menu->get_slug( $page ), - ) ), admin_url( $menu_file, 'admin' ) ); - } - - if ( $this->_menu->is_cpt() ) { - if ( empty( $page ) && $this->is_activation_mode() ) { - return add_query_arg( array_merge( $params, array( - 'page' => $this->_menu->get_slug() - ) ), admin_url( 'admin.php', 'admin' ) ); - } else { - if ( ! empty( $page ) ) { - $params['page'] = $this->_menu->get_slug( $page ); - } - - return add_query_arg( $params, admin_url( $this->_menu->get_raw_slug(), 'admin' ) ); - } - } else { - return add_query_arg( array_merge( $params, array( - 'page' => $this->_menu->get_slug( $page ), - ) ), admin_url( 'admin.php', 'admin' ) ); - } - } - - - /** - * Plugin's account URL. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - * - * @param bool|string $action - * @param array $params - * - * @param bool $add_action_nonce - * - * @return string - */ - function get_account_url( $action = false, $params = array(), $add_action_nonce = true ) { - if ( is_string( $action ) ) { - $params['fs_action'] = $action; - } - - self::require_pluggable_essentials(); - - return ( $add_action_nonce && is_string( $action ) ) ? - wp_nonce_url( $this->_get_admin_page_url( 'account', $params ), $action ) : - $this->_get_admin_page_url( 'account', $params ); - } - - /** - * Plugin's account URL. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - * - * @param bool|string $topic - * @param bool|string $message - * - * @return string - */ - function contact_url( $topic = false, $message = false ) { - $params = array(); - if ( is_string( $topic ) ) { - $params['topic'] = $topic; - } - if ( is_string( $message ) ) { - $params['message'] = $message; - } - - if ( $this->is_addon() ) { - $params['addon_id'] = $this->get_id(); - - return $this->get_parent_instance()->_get_admin_page_url( 'contact', $params ); - } else { - return $this->_get_admin_page_url( 'contact', $params ); - } - } - - /** - * Add-on direct info URL. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.0 - * - * @param string $slug - * - * @return string - */ - function addon_url( $slug ) { - return $this->_get_admin_page_url( 'addons', array( - 'slug' => $slug - ) ); - } - - /* Logger - ------------------------------------------------------------------------------------------------------------------*/ - /** - * @param string $id - * @param bool $prefix_slug - * - * @return FS_Logger - */ - function get_logger( $id = '', $prefix_slug = true ) { - return FS_Logger::get_logger( ( $prefix_slug ? $this->_slug : '' ) . ( ( ! $prefix_slug || empty( $id ) ) ? '' : '_' ) . $id ); - } - - /** - * @param $id - * @param bool $load_options - * @param bool $prefix_slug - * - * @return FS_Option_Manager - */ - function get_options_manager( $id, $load_options = false, $prefix_slug = true ) { - return FS_Option_Manager::get_manager( ( $prefix_slug ? $this->_slug : '' ) . ( ( ! $prefix_slug || empty( $id ) ) ? '' : '_' ) . $id, $load_options ); - } - - /* Security - ------------------------------------------------------------------------------------------------------------------*/ - private function _encrypt( $str ) { - if ( is_null( $str ) ) { - return null; - } - - return base64_encode( $str ); - } - - private function _decrypt( $str ) { - if ( is_null( $str ) ) { - return null; - } - - return base64_decode( $str ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.5 - * - * @param FS_Entity $entity - * - * @return FS_Entity Return an encrypted clone entity. - */ - private function _encrypt_entity( FS_Entity $entity ) { - $clone = clone $entity; - $props = get_object_vars( $entity ); - - foreach ( $props as $key => $val ) { - $clone->{$key} = $this->_encrypt( $val ); - } - - return $clone; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.5 - * - * @param FS_Entity $entity - * - * @return FS_Entity Return an decrypted clone entity. - */ - private function _decrypt_entity( FS_Entity $entity ) { - $clone = clone $entity; - $props = get_object_vars( $entity ); - - foreach ( $props as $key => $val ) { - $clone->{$key} = $this->_decrypt( $val ); - } - - return $clone; - } - - /** - * Tries to activate account based on POST params. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.2 - */ - function _activate_account() { - if ( $this->is_registered() ) { - // Already activated. - return; - } - - self::_clean_admin_content_section(); - - if ( fs_request_is_action( 'activate' ) && fs_request_is_post() ) { -// check_admin_referer( 'activate_' . $this->_plugin->public_key ); - - // Verify matching plugin details. - if ( $this->_plugin->id != fs_request_get( 'plugin_id' ) || $this->_slug != fs_request_get( 'plugin_slug' ) ) { - return; - } - - $user = new FS_User(); - $user->id = fs_request_get( 'user_id' ); - $user->public_key = fs_request_get( 'user_public_key' ); - $user->secret_key = fs_request_get( 'user_secret_key' ); - $user->email = fs_request_get( 'user_email' ); - $user->first = fs_request_get( 'user_first' ); - $user->last = fs_request_get( 'user_last' ); - $user->is_verified = fs_request_get_bool( 'user_is_verified' ); - - $site = new FS_Site(); - $site->id = fs_request_get( 'install_id' ); - $site->public_key = fs_request_get( 'install_public_key' ); - $site->secret_key = fs_request_get( 'install_secret_key' ); - $site->plan->id = fs_request_get( 'plan_id' ); - $site->plan->title = fs_request_get( 'plan_title' ); - $site->plan->name = fs_request_get( 'plan_name' ); - - $plans = array(); - $plans_data = json_decode( urldecode( fs_request_get( 'plans' ) ) ); - foreach ( $plans_data as $p ) { - $plans[] = new FS_Plugin_Plan( $p ); - } - - $this->_set_account( $user, $site, $plans ); - - // Reload the page with the keys. - if ( fs_redirect( $this->_get_admin_page_url() ) ) { - exit(); - } - } - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - * - * @param string $email - * - * @return FS_User|bool - */ - static function _get_user_by_email( $email ) { - self::$_static_logger->entrance(); - - $email = trim( strtolower( $email ) ); - $users = self::get_all_users(); - if ( is_array( $users ) ) { - foreach ( $users as $u ) { - if ( $email === trim( strtolower( $u->email ) ) ) { - return $u; - } - } - } - - return false; - } - - #region Account (Loading, Updates & Activation) ------------------------------------------------------------------ - - /*** - * Load account information (user + site). - * - * @author Vova Feldman (@svovaf) - * @since 1.0.1 - */ - private function _load_account() { - $this->_logger->entrance(); - - $this->do_action( 'before_account_load' ); - - $sites = self::get_all_sites(); - $users = self::get_all_users(); - $plans = self::get_all_plans(); - $licenses = self::get_all_licenses(); - - if ( $this->_logger->is_on() && is_admin() ) { - $this->_logger->log( 'sites = ' . var_export( $sites, true ) ); - $this->_logger->log( 'users = ' . var_export( $users, true ) ); - $this->_logger->log( 'plans = ' . var_export( $plans, true ) ); - $this->_logger->log( 'licenses = ' . var_export( $licenses, true ) ); - } - - $site = isset( $sites[ $this->_slug ] ) ? $sites[ $this->_slug ] : false; - - if ( is_object( $site ) && - is_numeric( $site->id ) && - is_numeric( $site->user_id ) && - is_object( $site->plan ) - ) { - // Load site. - $this->_site = clone $site; - $this->_site->plan = $this->_decrypt_entity( $this->_site->plan ); - - // Load relevant user. - $this->_user = clone $users[ $this->_site->user_id ]; - - // Load plans. - $this->_plans = $plans[ $this->_slug ]; - if ( ! is_array( $this->_plans ) || empty( $this->_plans ) ) { - $this->_sync_plans( true ); - } else { - for ( $i = 0, $len = count( $this->_plans ); $i < $len; $i ++ ) { - if ( $this->_plans[ $i ] instanceof FS_Plugin_Plan ) { - $this->_plans[ $i ] = $this->_decrypt_entity( $this->_plans[ $i ] ); - } else { - unset( $this->_plans[ $i ] ); - } - } - } - - // Load licenses. - $this->_licenses = array(); - if ( is_array( $licenses ) && - isset( $licenses[ $this->_slug ] ) && - isset( $licenses[ $this->_slug ][ $this->_user->id ] ) - ) { - $this->_licenses = $licenses[ $this->_slug ][ $this->_user->id ]; - } - - $this->_license = $this->_get_license_by_id( $this->_site->license_id ); - - if ( $this->_site->version != $this->get_plugin_version() ) { - // If stored install version is different than current installed plugin version, - // then update plugin version event. - $this->update_plugin_version_event(); - } - } - - $this->_register_account_hooks(); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.1 - * - * @param FS_User $user - * @param FS_Site $site - * @param bool|array $plans - */ - private function _set_account( FS_User $user, FS_Site $site, $plans = false ) { - $site->slug = $this->_slug; - $site->user_id = $user->id; - - $this->_site = $site; - $this->_user = $user; - if ( false !== $plans ) { - $this->_plans = $plans; - } - - $this->send_install_update(); - - $this->_store_account(); - - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.7.4 - * - * @param array $override_with - * - * @return array - */ - function get_opt_in_params( $override_with = array() ) { - $this->_logger->entrance(); - - $current_user = self::_get_current_wp_user(); - - $params = array( - 'user_firstname' => $current_user->user_firstname, - 'user_lastname' => $current_user->user_lastname, - 'user_nickname' => $current_user->user_nicename, - 'user_email' => $current_user->user_email, - 'user_ip' => WP_FS__REMOTE_ADDR, - 'plugin_slug' => $this->_slug, - 'plugin_id' => $this->get_id(), - 'plugin_public_key' => $this->get_public_key(), - 'plugin_version' => $this->get_plugin_version(), - 'return_url' => wp_nonce_url( $this->_get_admin_page_url( - '', - array( 'fs_action' => $this->_slug . '_activate_new' ) - ), $this->_slug . '_activate_new' ), - 'account_url' => wp_nonce_url( $this->_get_admin_page_url( - 'account', - array( 'fs_action' => 'sync_user' ) - ), 'sync_user' ), - 'site_uid' => $this->get_anonymous_id(), - 'site_url' => get_site_url(), - 'site_name' => get_bloginfo( 'name' ), - 'platform_version' => get_bloginfo( 'version' ), - 'php_version' => phpversion(), - 'language' => get_bloginfo( 'language' ), - 'charset' => get_bloginfo( 'charset' ), - ); - - if ( WP_FS__SKIP_EMAIL_ACTIVATION && $this->has_secret_key() ) { - // Even though rand() is known for its security issues, - // the timestamp adds another layer of protection. - // It would be very hard for an attacker to get the secret key form here. - // Plus, this should never run in production since the secret should never - // be included in the production version. - $params['ts'] = WP_FS__SCRIPT_START_TIME; - $params['salt'] = md5( uniqid( rand() ) ); - $params['secure'] = md5( - $params['ts'] . - $params['salt'] . - $this->get_secret_key() - ); - } - - return array_merge( $params, $override_with ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.7.4 - * - * @param string|bool $email - * @param string|bool $first - * @param string|bool $last - * - * @return bool Is successful opt-in (or set to pending). - */ - function opt_in( $email = false, $first = false, $last = false ) { - $this->_logger->entrance(); - - if ( false === $email ) { - $current_user = self::_get_current_wp_user(); - $email = $current_user->user_email; - } - - $fs_user = Freemius::_get_user_by_email( $email ); - if ( is_object( $fs_user ) && ! $this->is_pending_activation() ) { - $this->install_with_current_user( false ); - - return true; - } - - $user_info = array(); - if ( ! empty( $email ) ) { - $user_info['user_email'] = $email; - } - if ( ! empty( $first ) ) { - $user_info['user_firstname'] = $first; - } - if ( ! empty( $last ) ) { - $user_info['user_lastname'] = $last; - } - - $params = $this->get_opt_in_params( $user_info ); - $params['format'] = 'json'; - - $url = WP_FS__ADDRESS . '/action/service/user/install/'; - if ( isset( $_COOKIE['XDEBUG_SESSION'] ) ) { - $url = add_query_arg( 'XDEBUG_SESSION', 'PHPSTORM', $url ); - } - - $response = wp_remote_post( $url, array( - 'method' => 'POST', - 'body' => $params, - 'timeout' => 15, - ) ); - - if ( $response instanceof WP_Error ) { - if ( 'https://' === substr( $url, 0, 8 ) && - isset( $response->errors ) && - isset( $response->errors['http_request_failed'] ) && - false !== strpos( $response->errors['http_request_failed'][0], 'sslv3 alert handshake' ) - ) { - // Failed due to old version of cURL or Open SSL (SSLv3 is not supported by CloudFlare). - $url = 'http://' . substr( $url, 8 ); - - $response = wp_remote_post( $url, array( - 'method' => 'POST', - 'body' => $params, - 'timeout' => 15, - ) ); - } - - if ( $response instanceof WP_Error ) { - return false; - } - } - - if ( is_wp_error( $response ) ) { - return false; - } - - $decoded = @json_decode( $response['body'] ); - - if ( empty( $decoded ) ) { - return false; - } - - if ( isset( $decoded->error ) ) { - return false; - } else if ( isset( $decoded->pending_activation ) && $decoded->pending_activation ) { - // Pending activation, add message. - $this->set_pending_confirmation( false, false ); - - return true; - } else if ( isset( $decoded->install_secret_key ) ) { - $this->install_with_new_user( - $decoded->user_id, - $decoded->user_public_key, - $decoded->user_secret_key, - $decoded->install_id, - $decoded->install_public_key, - $decoded->install_secret_key, - false - ); - - return true; - } - - return false; - } - - /** - * Set user and site identities. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @param FS_User $user - * @param FS_Site $site - * @param bool $redirect - * - * @return bool False if account already set. - */ - function setup_account( FS_User $user, FS_Site $site, $redirect = true ) { - $this->_user = $user; - $this->_site = $site; - - $this->_sync_plans(); - - $this->_enrich_site_plan( false ); - - $this->_set_account( $user, $site ); - - if ( $this->is_trial() ) { - // Store trial plan information. - $this->_enrich_site_trial_plan( true ); - } - - // If Freemius was OFF before, turn it on. - $this->turn_on(); - - $this->do_action( 'after_account_connection', $user, $site ); - - if ( is_numeric( $site->license_id ) ) { - $this->_license = $this->_get_license_by_id( $site->license_id ); - } - - if ( $this->is_pending_activation() ) { - // Remove pending activation sticky notice (if still exist). - $this->_admin_notices->remove_sticky( 'activation_pending' ); - - // Remove plugin from pending activation mode. - unset( $this->_storage->is_pending_activation ); - - if ( ! $this->is_paying() ) { - $this->_admin_notices->add_sticky( - sprintf( __fs( 'plugin-x-activation-message', $this->_slug ), '<b>' . $this->get_plugin_name() . '</b>' ), - 'activation_complete' - ); - } - } - - if ( $this->is_paying() && ! $this->is_premium() ) { - $this->_admin_notices->add_sticky( - sprintf( - __fs( 'activation-with-plan-x-message', $this->_slug ), - $this->_site->plan->title - ) . ' ' . $this->_get_latest_download_link( sprintf( - __fs( 'download-latest-x-version', $this->_slug ), - $this->_site->plan->title - ) ), - 'plan_upgraded', - __fs( 'yee-haw', $this->_slug ) . '!' - ); - } - - $plugin_id = fs_request_get( 'plugin_id', false ); - - // Store activation time ONLY for plugins (not add-ons). - if ( ! is_numeric( $plugin_id ) || ( $plugin_id == $this->_plugin->id ) ) { - $this->_storage->activation_timestamp = WP_FS__SCRIPT_START_TIME; - } - - if ( is_numeric( $plugin_id ) ) { - if ( $plugin_id != $this->_plugin->id ) { - // Add-on was installed - sync license right after install. - if ( $redirect && fs_redirect( fs_nonce_url( $this->_get_admin_page_url( - 'account', - array( - 'fs_action' => $this->_slug . '_sync_license', - 'plugin_id' => $plugin_id - ) - ), $this->_slug . '_sync_license' ) ) - ) { - exit(); - } - - } - } else { - // Reload the page with the keys. - if ( $redirect && fs_redirect( $this->get_after_activation_url( 'after_connect_url' ) ) ) { - exit(); - } - } - } - - /** - * Install plugin with new user information after approval. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - */ - function _install_with_new_user() { - $this->_logger->entrance(); - - if ( $this->is_registered() ) { - return; - } - - if ( fs_request_is_action( $this->_slug . '_activate_new' ) ) { -// check_admin_referer( $this->_slug . '_activate_new' ); - - $this->_admin_notices->remove_sticky( 'connect_account' ); - - if ( fs_request_has( 'user_secret_key' ) ) { - $this->install_with_new_user( - fs_request_get( 'user_id' ), - fs_request_get( 'user_public_key' ), - fs_request_get( 'user_secret_key' ), - fs_request_get( 'install_id' ), - fs_request_get( 'install_public_key' ), - fs_request_get( 'install_secret_key' ) - ); - } else if ( fs_request_has( 'pending_activation' ) ) { - $this->set_pending_confirmation( fs_request_get( 'user_email' ), true ); - } - } - } - - /** - * Install plugin with new user. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.7.4 - * - * @param number $user_id - * @param string $user_public_key - * @param string $user_secret_key - * @param number $install_id - * @param string $install_public_key - * @param string $install_secret_key - * @param bool $redirect - */ - private function install_with_new_user( - $user_id, - $user_public_key, - $user_secret_key, - $install_id, - $install_public_key, - $install_secret_key, - $redirect = true - ) { - $user = new FS_User(); - $user->id = $user_id; - $user->public_key = $user_public_key; - $user->secret_key = $user_secret_key; - - $this->_user = $user; - $user_result = $this->get_api_user_scope()->get(); - $user = new FS_User( $user_result ); - $this->_user = $user; - - $site = new FS_Site(); - $site->id = $install_id; - $site->public_key = $install_public_key; - $site->secret_key = $install_secret_key; - - $this->_site = $site; - $site_result = $this->get_api_site_scope()->get(); - $site = new FS_Site( $site_result ); - $this->_site = $site; - - $this->setup_account( $this->_user, $this->_site, $redirect ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.7.4 - * - * @param bool $email - * @param bool $redirect - */ - private function set_pending_confirmation( $email = false, $redirect = true ) { - // Install must be activated via email since - // user with the same email already exist. - $this->_storage->is_pending_activation = true; - $this->_add_pending_activation_notice( $email ); - - // Reload the page with with pending activation message. - if ( $redirect && fs_redirect( $this->get_after_activation_url( 'after_pending_connect_url' ) ) ) { - exit(); - } - } - - /** - * Install plugin with current logged WP user info. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - */ - function _install_with_current_user() { - $this->_logger->entrance(); - - if ( $this->is_registered() ) { - return; - } - - if ( fs_request_is_action( $this->_slug . '_activate_existing' ) && fs_request_is_post() ) { -// check_admin_referer( 'activate_existing_' . $this->_plugin->public_key ); - - $this->install_with_current_user(); - } - } - - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.7.4 - * - * @param bool $redirect - */ - private function install_with_current_user( $redirect = true ) { - $this->_admin_notices->remove_sticky( 'connect_account' ); - - // Get current logged WP user. - $current_user = self::_get_current_wp_user(); - - // Find the relevant FS user by the email. - $user = self::_get_user_by_email( $current_user->user_email ); - - // We have to set the user before getting user scope API handler. - $this->_user = $user; - - // Install the plugin. - $install = $this->get_api_user_scope()->call( - "/plugins/{$this->get_id()}/installs.json", - 'post', - $this->get_install_data_for_api( array( - 'uid' => $this->get_anonymous_id(), - ), false, false ) - ); - - if ( isset( $install->error ) ) { - $this->_admin_notices->add( - sprintf( __fs( 'could-not-activate-x', $this->_slug ), $this->get_plugin_name() ) . ' ' . - __fs( 'contact-us-with-error-message', $this->_slug ) . ' ' . '<b>' . $install->error->message . '</b>', - __fs( 'oops', $this->_slug ) . '...', - 'error' - ); - - return; - } - - $site = new FS_Site( $install ); - $this->_site = $site; -// $this->_enrich_site_plan( false ); - -// $this->_set_account( $user, $site ); -// $this->_sync_plans(); - - $this->setup_account( $this->_user, $this->_site, $redirect ); - } - - /** - * Tries to activate add-on account based on parent plugin info. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @param Freemius $parent_fs - */ - private function _activate_addon_account( Freemius $parent_fs ) { - if ( $this->is_registered() ) { - // Already activated. - return; - } - - // Activate add-on with parent plugin credentials. - $addon_install = $parent_fs->get_api_site_scope()->call( - "/addons/{$this->_plugin->id}/installs.json", - 'post', - $this->get_install_data_for_api( array( - 'uid' => $this->get_anonymous_id(), - ), false, false ) - ); - - if ( isset( $addon_install->error ) ) { - $this->_admin_notices->add( - sprintf( __fs( 'could-not-activate-x', $this->_slug ), $this->get_plugin_name() ) . ' ' . - __fs( 'contact-us-with-error-message', $this->_slug ) . ' ' . '<b>' . $addon_install->error->message . '</b>', - __fs( 'oops', $this->_slug ) . '...', - 'error' - ); - - return; - } - - // First of all, set site info - otherwise we won't - // be able to invoke API calls. - $this->_site = new FS_Site( $addon_install ); - - // Sync add-on plans. - $this->_sync_plans(); - - // Get site's current plan. - $this->_site->plan = $this->_get_plan_by_id( $this->_site->plan->id ); - - // Get user information based on parent's plugin. - $user = $parent_fs->get_user(); - - $this->_set_account( $user, $this->_site ); - - // Sync licenses. - $this->_sync_licenses(); - - // Try to activate premium license. - $this->_activate_license( true ); - } - - #endregion ------------------------------------------------------------------ - - #region Admin Menu Items ------------------------------------------------------------------ - - private $_menu_items = array(); - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - * - * @return string - */ - function get_menu_slug() { - return $this->_menu->get_slug(); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - */ - function _prepare_admin_menu() { -// if ( ! $this->is_on() ) { -// return; -// } - - if ( ! $this->has_api_connectivity() && ! $this->enable_anonymous() ) { - $this->_menu->remove_menu_item(); - } else { - $this->add_submenu_items(); - $this->add_menu_action(); - } - } - - /** - * Admin dashboard menu items modifications. - * - * NOTE: admin_menu action executed before admin_init. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - * - */ - private function add_menu_action() { - if ( $this->is_activation_mode() ) { - $this->override_plugin_menu_with_activation(); - } else { - // If not registered try to install user. - if ( ! $this->is_registered() && - fs_request_is_action( $this->_slug . '_activate_new' ) - ) { - $this->_install_with_new_user(); - } - } - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.1 - * - * @return string - */ - function _redirect_on_clicked_menu_link() { - $this->_logger->entrance(); - - $page = strtolower( isset( $_REQUEST['page'] ) ? $_REQUEST['page'] : '' ); - - $this->_logger->log( 'page = ' . $page ); - - foreach ( $this->_menu_items as $priority => $items ) { - foreach ( $items as $item ) { - if ( isset( $item['url'] ) ) { - if ( $page === strtolower( $item['menu_slug'] ) ) { - $this->_logger->log( 'Redirecting to ' . $item['url'] ); - - fs_redirect( $item['url'] ); - } - } - } - } - } - - /** - * Remove plugin's all admin menu items & pages, and replace with activation page. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.1 - */ - private function override_plugin_menu_with_activation() { - $this->_logger->entrance(); - - $hook = false; - - if ( $this->_menu->is_top_level() ) { - $hook = $this->_menu->override_menu_item( array( &$this, '_connect_page_render' ) ); - - if ( false === $hook ) { - // Create new menu item just for the opt-in. - $hook = add_menu_page( - $this->get_plugin_name(), - $this->get_plugin_name(), - 'manage_options', - $this->_menu->get_slug(), - array( &$this, '_connect_page_render' ) - ); - } - } else { - $menus = array( $this->_menu->get_parent_slug() ); - - if ( $this->_menu->is_override_exact() ) { - // Make sure the current page is matching the activation page. - $activation_url = strtolower( $this->get_activation_url() ); - $request_url = strtolower( $_SERVER['REQUEST_URI'] ); - - if ( parse_url( $activation_url, PHP_URL_PATH ) !== parse_url( $request_url, PHP_URL_PATH ) ) { - // Different path - DO NOT OVERRIDE PAGE. - return; - } - - $activation_url_params = array(); - parse_str( parse_url( $activation_url, PHP_URL_QUERY ), $activation_url_params ); - - $request_url_params = array(); - parse_str( parse_url( $request_url, PHP_URL_QUERY ), $request_url_params ); - - - foreach ( $activation_url_params as $key => $val ) { - if ( ! isset( $request_url_params[ $key ] ) || $val != $request_url_params[ $key ] ) { - // Not matching query string - DO NOT OVERRIDE PAGE. - return; - } - } - } - - foreach ( $menus as $parent_slug ) { - $hook = $this->_menu->override_submenu_action( - $parent_slug, - $this->_menu->get_raw_slug(), - array( &$this, '_connect_page_render' ) - ); - - if ( false !== $hook ) { - // Found plugin's submenu item. - break; - } - } - } - - if ( $this->_menu->is_activation_page() ) { - // Clean admin page from distracting content. - self::_clean_admin_content_section(); - } - - if ( false !== $hook ) { - if ( fs_request_is_action( $this->_slug . '_activate_existing' ) ) { - add_action( "load-$hook", array( &$this, '_install_with_current_user' ) ); - } else if ( fs_request_is_action( $this->_slug . '_activate_new' ) ) { - add_action( "load-$hook", array( &$this, '_install_with_new_user' ) ); - } - } - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.0 - * - * @return string - */ - private function get_top_level_menu_slug() { - return ( $this->is_addon() ? - $this->get_parent_instance()->_menu->get_top_level_menu_slug() : - $this->_menu->get_top_level_menu_slug() ); - } - - /** - * Add default Freemius menu items. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.0 - */ - private function add_submenu_items() { - $this->_logger->entrance(); - - $this->do_action( 'before_admin_menu_init' ); - - if ( ! $this->is_addon() ) { - if ( ! $this->is_activation_mode() ) { - if ( $this->is_registered() ) { - // Add user account page. - $this->add_submenu_item( - __fs( 'account', $this->_slug ), - array( &$this, '_account_page_render' ), - $this->get_plugin_name() . ' – ' . __fs( 'account', $this->_slug ), - 'manage_options', - 'account', - array( &$this, '_account_page_load' ), - WP_FS__DEFAULT_PRIORITY, - $this->_menu->is_submenu_item_visible( 'account' ) - ); - } - - // Add contact page. - $this->add_submenu_item( - __fs( 'contact-us', $this->_slug ), - array( &$this, '_contact_page_render' ), - $this->get_plugin_name() . ' – ' . __fs( 'contact-us', $this->_slug ), - 'manage_options', - 'contact', - 'Freemius::_clean_admin_content_section', - WP_FS__DEFAULT_PRIORITY, - $this->_menu->is_submenu_item_visible( 'contact' ) - ); - - if ( $this->has_addons() ) { - $this->add_submenu_item( - __fs( 'add-ons', $this->_slug ), - array( &$this, '_addons_page_render' ), - $this->get_plugin_name() . ' – ' . __fs( 'add-ons', $this->_slug ), - 'manage_options', - 'addons', - array( &$this, '_addons_page_load' ), - WP_FS__LOWEST_PRIORITY - 1, - $this->_menu->is_submenu_item_visible( 'addons' ) - ); - } - - $show_pricing = ( $this->has_paid_plan() && $this->_menu->is_submenu_item_visible( 'pricing' ) ); - // If user don't have paid plans, add pricing page - // to support add-ons checkout but don't add the submenu item. - // || (isset( $_GET['page'] ) && $this->_menu->get_slug( 'pricing' ) == $_GET['page']); - - // Add upgrade/pricing page. - $this->add_submenu_item( - ( $this->is_paying() ? __fs( 'pricing', $this->_slug ) : __fs( 'upgrade', $this->_slug ) . ' ➤' ), - array( &$this, '_pricing_page_render' ), - $this->get_plugin_name() . ' – ' . __fs( 'pricing', $this->_slug ), - 'manage_options', - 'pricing', - 'Freemius::_clean_admin_content_section', - WP_FS__LOWEST_PRIORITY, - $show_pricing - ); - } - } - - - if ( 0 < count( $this->_menu_items ) ) { - if ( ! $this->_menu->is_top_level() ) { - fs_enqueue_local_style( 'fs_common', '/admin/common.css' ); - - // Append submenu items right after the plugin's submenu item. - $this->order_sub_submenu_items(); - } else { - // Append submenu items. - $this->embed_submenu_items(); - } - } - } - - /** - * Moved the actual submenu item additions to a separated function, - * in order to support sub-submenu items when the plugin's settings - * only have a submenu and not top-level menu item. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.4 - */ - private function embed_submenu_items() { - $item_template = $this->_menu->is_top_level() ? - '<span class="fs-submenu-item">%s</span>' : - '<span class="fs-submenu-item fs-sub">%s</span>'; - - ksort( $this->_menu_items ); - - foreach ( $this->_menu_items as $priority => $items ) { - foreach ( $items as $item ) { - if ( ! isset( $item['url'] ) ) { - $hook = add_submenu_page( - $item['show_submenu'] ? - $this->get_top_level_menu_slug() : - null, - $item['page_title'], - sprintf( $item_template, $item['menu_title'] ), - $item['capability'], - $item['menu_slug'], - $item['render_function'] - ); - - if ( false !== $item['before_render_function'] ) { - add_action( "load-$hook", $item['before_render_function'] ); - } - } else { - add_submenu_page( - $this->get_top_level_menu_slug(), - $item['page_title'], - sprintf( $item_template, $item['menu_title'] ), - $item['capability'], - $item['menu_slug'], - array( $this, '' ) - ); - } - } - } - } - - /** - * Re-order the submenu items so all Freemius added new submenu items - * are added right after the plugin's settings submenu item. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.4 - */ - private function order_sub_submenu_items() { - global $submenu; - - $top_level_menu = &$submenu[ $this->_menu->get_top_level_menu_slug() ]; - - $all_submenu_items_after = array(); - - $found_submenu_item = false; - - foreach ( $top_level_menu as $submenu_id => $meta ) { - if ( $found_submenu_item ) { - // Remove all submenu items after the plugin's submenu item. - $all_submenu_items_after[] = $meta; - unset( $top_level_menu[ $submenu_id ] ); - } - - if ( $this->_menu->get_raw_slug() === $meta[2] ) { - // Found the submenu item, put all below. - $found_submenu_item = true; - continue; - } - } - - // Embed all plugin's new submenu items. - $this->embed_submenu_items(); - - // Start with specially high number to make sure it's appended. - $i = max( 10000, max( array_keys( $top_level_menu ) ) + 1 ); - foreach ( $all_submenu_items_after as $meta ) { - $top_level_menu[ $i ] = $meta; - $i ++; - } - - // Sort submenu items. - ksort( $top_level_menu ); - } - - /** - * Displays the Support Forum link when enabled. - * - * Can be filtered like so: - * - * function _fs_show_support_menu( $is_visible, $menu_id ) { - * if ( 'support' === $menu_id ) { - * return _fs->is_registered(); - * } - * return $is_visible; - * } - * _fs()->add_filter('is_submenu_visible', '_fs_show_support_menu', 10, 2); - * - */ - function _add_default_submenu_items() { - if ( ! $this->is_on() ) { - return; - } - - if ( ! $this->is_activation_mode() ) { - if ( $this->_menu->is_submenu_item_visible( 'support' ) ) { - $this->add_submenu_link_item( - $this->apply_filters( 'support_forum_submenu', __fs( 'support-forum', $this->_slug ) ), - $this->apply_filters( 'support_forum_url', 'https://wordpress.org/support/plugin/' . $this->_slug ), - 'wp-support-forum', - 'read', - 50 - ); - } - } - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.1 - * - * @param string $menu_title - * @param callable $render_function - * @param bool|string $page_title - * @param string $capability - * @param bool|string $menu_slug - * @param bool|callable $before_render_function - * @param int $priority - * @param bool $show_submenu - */ - function add_submenu_item( - $menu_title, - $render_function, - $page_title = false, - $capability = 'manage_options', - $menu_slug = false, - $before_render_function = false, - $priority = WP_FS__DEFAULT_PRIORITY, - $show_submenu = true - ) { - $this->_logger->entrance( 'Title = ' . $menu_title ); - - if ( $this->is_addon() ) { - $parent_fs = $this->get_parent_instance(); - - if ( is_object( $parent_fs ) ) { - $parent_fs->add_submenu_item( - $menu_title, - $render_function, - $page_title, - $capability, - $menu_slug, - $before_render_function, - $priority, - $show_submenu - ); - - return; - } - } - - if ( ! isset( $this->_menu_items[ $priority ] ) ) { - $this->_menu_items[ $priority ] = array(); - } - - $this->_menu_items[ $priority ][] = array( - 'page_title' => is_string( $page_title ) ? $page_title : $menu_title, - 'menu_title' => $menu_title, - 'capability' => $capability, - 'menu_slug' => $this->_menu->get_slug( is_string( $menu_slug ) ? $menu_slug : strtolower( $menu_title ) ), - 'render_function' => $render_function, - 'before_render_function' => $before_render_function, - 'show_submenu' => $show_submenu, - ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.1 - * - * @param string $menu_title - * @param string $url - * @param bool $menu_slug - * @param string $capability - * @param int $priority - * - */ - function add_submenu_link_item( - $menu_title, - $url, - $menu_slug = false, - $capability = 'read', - $priority = WP_FS__DEFAULT_PRIORITY - ) { - $this->_logger->entrance( 'Title = ' . $menu_title . '; Url = ' . $url ); - - if ( $this->is_addon() ) { - $parent_fs = $this->get_parent_instance(); - - if ( is_object( $parent_fs ) ) { - $parent_fs->add_submenu_link_item( - $menu_title, - $url, - $menu_slug, - $capability, - $priority - ); - - return; - } - } - - if ( ! isset( $this->_menu_items[ $priority ] ) ) { - $this->_menu_items[ $priority ] = array(); - } - - $this->_menu_items[ $priority ][] = array( - 'menu_title' => $menu_title, - 'capability' => $capability, - 'menu_slug' => $this->_menu->get_slug( is_string( $menu_slug ) ? $menu_slug : strtolower( $menu_title ) ), - 'url' => $url, - 'page_title' => $menu_title, - 'render_function' => 'fs_dummy', - 'before_render_function' => '', - ); - } - - #endregion ------------------------------------------------------------------ - - /* Actions / Hooks / Filters - ------------------------------------------------------------------------------------------------------------------*/ - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.7 - * - * @param string $tag - * - * @return string - */ - private function get_action_tag( $tag ) { - return 'fs_' . $tag . '_' . $this->_slug; - } - - /** - * Do action, specific for the current context plugin. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.1 - * - * @param string $tag The name of the action to be executed. - * @param mixed $arg,... Optional. Additional arguments which are passed on to the - * functions hooked to the action. Default empty. - * - * @uses do_action() - */ - function do_action( $tag, $arg = '' ) { - $this->_logger->entrance( $tag ); - - $args = func_get_args(); - - call_user_func_array( 'do_action', array_merge( - array( $this->get_action_tag( $tag ) ), - array_slice( $args, 1 ) ) - ); - } - - /** - * Add action, specific for the current context plugin. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.1 - * - * @param string $tag - * @param callable $function_to_add - * @param int $priority - * @param int $accepted_args - * - * @uses add_action() - */ - function add_action( $tag, $function_to_add, $priority = WP_FS__DEFAULT_PRIORITY, $accepted_args = 1 ) { - $this->_logger->entrance( $tag ); - - add_action( $this->get_action_tag( $tag ), $function_to_add, $priority, $accepted_args ); - } - - /** - * Apply filter, specific for the current context plugin. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @param string $tag The name of the filter hook. - * @param mixed $value The value on which the filters hooked to `$tag` are applied on. - * - * @return mixed The filtered value after all hooked functions are applied to it. - * - * @uses apply_filters() - */ - function apply_filters( $tag, $value ) { - $this->_logger->entrance( $tag ); - - $args = func_get_args(); - array_unshift( $args, $this->_slug ); - - return call_user_func_array( 'fs_apply_filter', $args ); - } - - /** - * Add filter, specific for the current context plugin. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @param string $tag - * @param callable $function_to_add - * @param int $priority - * @param int $accepted_args - * - * @uses add_filter() - */ - function add_filter( $tag, $function_to_add, $priority = WP_FS__DEFAULT_PRIORITY, $accepted_args = 1 ) { - $this->_logger->entrance( $tag ); - - add_filter( $this->get_action_tag( $tag ), $function_to_add, $priority, $accepted_args ); - } - - /** - * Check if has filter. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.4 - * - * @param string $tag - * @param callable|bool $function_to_check Optional. The callback to check for. Default false. - * - * @return false|int - * - * @uses has_filter() - */ - function has_filter( $tag, $function_to_check = false ) { - $this->_logger->entrance( $tag ); - - return has_filter( $this->get_action_tag( $tag ), $function_to_check ); - } - - /** - * Override default i18n text phrases. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.6 - * - * @param string[] string $key_value - * - * @uses fs_override_i18n() - */ - function override_i18n( $key_value ) { - fs_override_i18n( $key_value, $this->_slug ); - } - - /* Account Page - ------------------------------------------------------------------------------------------------------------------*/ - /** - * Update site information. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.1 - * - * @param bool $store Flush to Database if true. - */ - private function _store_site( $store = true ) { - $this->_logger->entrance(); - - $encrypted_site = clone $this->_site; - $encrypted_site->plan = $this->_encrypt_entity( $this->_site->plan ); - - $sites = self::get_all_sites(); - $sites[ $this->_slug ] = $encrypted_site; - self::$_accounts->set_option( 'sites', $sites, $store ); - } - - /** - * Update plugin's plans information. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.2 - * - * @param bool $store Flush to Database if true. - */ - private function _store_plans( $store = true ) { - $this->_logger->entrance(); - - $plans = self::get_all_plans(); - - // Copy plans. - $encrypted_plans = array(); - for ( $i = 0, $len = count( $this->_plans ); $i < $len; $i ++ ) { - $encrypted_plans[] = $this->_encrypt_entity( $this->_plans[ $i ] ); - } - - $plans[ $this->_slug ] = $encrypted_plans; - self::$_accounts->set_option( 'plans', $plans, $store ); - } - - /** - * Update user's plugin licenses. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.5 - * - * @param bool $store - * @param string|bool $plugin_slug - * @param FS_Plugin_License[] $licenses - */ - private function _store_licenses( $store = true, $plugin_slug = false, $licenses = array() ) { - $this->_logger->entrance(); - - $all_licenses = self::get_all_licenses(); - - if ( ! is_string( $plugin_slug ) ) { - $plugin_slug = $this->_slug; - $licenses = $this->_licenses; - } - - if ( ! isset( $all_licenses[ $plugin_slug ] ) ) { - $all_licenses[ $plugin_slug ] = array(); - } - - $all_licenses[ $plugin_slug ][ $this->_user->id ] = $licenses; - - self::$_accounts->set_option( 'licenses', $all_licenses, $store ); - } - - /** - * Update user information. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.1 - * - * @param bool $store Flush to Database if true. - */ - private function _store_user( $store = true ) { - $this->_logger->entrance(); - - $users = self::get_all_users(); - $users[ $this->_user->id ] = $this->_user; - self::$_accounts->set_option( 'users', $users, $store ); - } - - /** - * Update new updates information. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - * - * @param FS_Plugin_Tag|null $update - * @param bool $store Flush to Database if true. - * @param bool|number $plugin_id - */ - private function _store_update( $update, $store = true, $plugin_id = false ) { - $this->_logger->entrance(); - - if ( $update instanceof FS_Plugin_Tag ) { - $update->updated = time(); - } - - if ( ! is_numeric( $plugin_id ) ) { - $plugin_id = $this->_plugin->id; - } - - $updates = self::get_all_updates(); - $updates[ $plugin_id ] = $update; - self::$_accounts->set_option( 'updates', $updates, $store ); - } - - /** - * Update new updates information. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @param FS_Plugin[] $plugin_addons - * @param bool $store Flush to Database if true. - */ - private function _store_addons( $plugin_addons, $store = true ) { - $this->_logger->entrance(); - - $addons = self::get_all_addons(); - $addons[ $this->_plugin->id ] = $plugin_addons; - self::$_accounts->set_option( 'addons', $addons, $store ); - } - - /** - * Delete plugin's associated add-ons. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.8 - * - * @param bool $store - * - * @return bool - */ - private function _delete_account_addons( $store = true ) { - $all_addons = self::get_all_account_addons(); - - if ( ! isset( $all_addons[ $this->_plugin->id ] ) ) { - return false; - } - - unset( $all_addons[ $this->_plugin->id ] ); - - self::$_accounts->set_option( 'account_addons', $all_addons, $store ); - - return true; - } - - /** - * Update account add-ons list. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @param FS_Plugin[] $addons - * @param bool $store Flush to Database if true. - */ - private function _store_account_addons( $addons, $store = true ) { - $this->_logger->entrance(); - - $all_addons = self::get_all_account_addons(); - $all_addons[ $this->_plugin->id ] = $addons; - self::$_accounts->set_option( 'account_addons', $all_addons, $store ); - } - - /** - * Store account params in the Database. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.1 - */ - private function _store_account() { - $this->_logger->entrance(); - - $this->_store_site( false ); - $this->_store_user( false ); - $this->_store_plans( false ); - $this->_store_licenses( false ); - - self::$_accounts->store(); - } - - /** - * Sync user's information. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.3 - * @uses FS_Api - */ - private function _handle_account_user_sync() { - $this->_logger->entrance(); - - $api = $this->get_api_user_scope(); - - // Get user's information. - $user = $api->get( '/', true ); - - if ( isset( $user->id ) ) { - $this->_user->first = $user->first; - $this->_user->last = $user->last; - $this->_user->email = $user->email; - - $is_menu_item_account_visible = $this->_menu->is_submenu_item_visible( 'account' ); - - if ( $user->is_verified && - ( ! isset( $this->_user->is_verified ) || false === $this->_user->is_verified ) - ) { - $this->_user->is_verified = true; - - $this->do_action( 'account_email_verified', $user->email ); - - $this->_admin_notices->add( - __fs( 'email-verified-message', $this->_slug ), - __fs( 'right-on', $this->_slug ) . '!', - 'success', - // Make admin sticky if account menu item is invisible, - // since the page will be auto redirected to the plugin's - // main settings page, and the non-sticky message - // will disappear. - ! $is_menu_item_account_visible, - false, - 'email_verified' - ); - } - - // Flush user details to DB. - $this->_store_user(); - - $this->do_action( 'after_account_user_sync', $user ); - - /** - * If account menu item is hidden, redirect to plugin's main settings page. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.6 - * - * @link https://github.com/Freemius/wordpress-sdk/issues/6 - */ - if ( ! $is_menu_item_account_visible ) { - if ( fs_redirect( $this->_get_admin_page_url() ) ) { - exit(); - } - } - } - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.5 - * @uses FS_Api - * - * @param bool $flush - * - * @return object|\FS_Site - */ - private function _fetch_site( $flush = false ) { - $this->_logger->entrance(); - $api = $this->get_api_site_scope(); - - $site = $api->get( '/', $flush ); - - if ( ! isset( $site->error ) ) { - $site = new FS_Site( $site ); - $site->slug = $this->_slug; - $site->version = $this->get_plugin_version(); - } - - return $site; - } - - /** - * @param bool $store - * - * @return FS_Plugin_Plan|object|false - */ - private function _enrich_site_plan( $store = true ) { - // Try to load plan from local cache. - $plan = $this->_get_plan_by_id( $this->_site->plan->id ); - - if ( false === $plan ) { - $plan = $this->_fetch_site_plan(); - } - - if ( $plan instanceof FS_Plugin_Plan ) { - $this->_update_plan( $plan, $store ); - } - - return $plan; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * @uses FS_Api - * - * @param bool $store - * - * @return FS_Plugin_Plan|object|false - */ - private function _enrich_site_trial_plan( $store = true ) { - // Try to load plan from local cache. - $trial_plan = $this->_get_plan_by_id( $this->_site->trial_plan_id ); - - if ( false === $trial_plan ) { - $trial_plan = $this->_fetch_site_plan( $this->_site->trial_plan_id ); - } - - if ( $trial_plan instanceof FS_Plugin_Plan ) { - $this->_storage->store( 'trial_plan', $trial_plan, $store ); - } - - return $trial_plan; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * @uses FS_Api - * - * @param number|bool $license_id - * - * @return FS_Subscription|object|bool - */ - private function _fetch_site_license_subscription( $license_id = false ) { - $this->_logger->entrance(); - $api = $this->get_api_site_scope(); - - if ( ! is_numeric( $license_id ) ) { - $license_id = $this->_license->id; - } - - $result = $api->get( "/licenses/{$license_id}/subscriptions.json", true ); - - return ! isset( $result->error ) ? - ( ( is_array( $result->subscriptions ) && 0 < count( $result->subscriptions ) ) ? - new FS_Subscription( $result->subscriptions[0] ) : - false - ) : - $result; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - * @uses FS_Api - * - * @param number|bool $plan_id - * - * @return FS_Plugin_Plan|object - */ - private function _fetch_site_plan( $plan_id = false ) { - $this->_logger->entrance(); - $api = $this->get_api_site_scope(); - - if ( ! is_numeric( $plan_id ) ) { - $plan_id = $this->_site->plan->id; - } - - $plan = $api->get( "/plans/{$plan_id}.json", true ); - - return ! isset( $plan->error ) ? new FS_Plugin_Plan( $plan ) : $plan; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.5 - * @uses FS_Api - * - * @return FS_Plugin_Plan[]|object - */ - private function _fetch_plugin_plans() { - $this->_logger->entrance(); - $api = $this->get_api_site_scope(); - - $result = $api->get( '/plans.json', true ); - - if ( ! $this->is_api_error( $result ) ) { - for ( $i = 0, $len = count( $result->plans ); $i < $len; $i ++ ) { - $result->plans[ $i ] = new FS_Plugin_Plan( $result->plans[ $i ] ); - } - - $result = $result->plans; - } - - return $result; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.5 - * @uses FS_Api - * - * @param number|bool $plugin_id - * - * @return FS_Plugin_License[]|object - */ - private function _fetch_licenses( $plugin_id = false ) { - $this->_logger->entrance(); - - $api = $this->get_api_user_scope(); - - if ( ! is_numeric( $plugin_id ) ) { - $plugin_id = $this->_plugin->id; - } - - $result = $api->get( "/plugins/{$plugin_id}/licenses.json", true ); - - if ( ! isset( $result->error ) ) { - for ( $i = 0, $len = count( $result->licenses ); $i < $len; $i ++ ) { - $result->licenses[ $i ] = new FS_Plugin_License( $result->licenses[ $i ] ); - } - - $result = $result->licenses; - } - - return $result; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - * - * @param FS_Plugin_Plan $plan - * @param bool $store - */ - private function _update_plan( $plan, $store = false ) { - $this->_logger->entrance(); - - $this->_site->plan = $plan; - $this->_store_site( $store ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.5 - * - * @param FS_Plugin_License[] $licenses - * @param string|bool $plugin_slug - */ - private function _update_licenses( $licenses, $plugin_slug = false ) { - $this->_logger->entrance(); - - if ( is_array( $licenses ) ) { - for ( $i = 0, $len = count( $licenses ); $i < $len; $i ++ ) { - $licenses[ $i ]->updated = time(); - } - } - - if ( ! is_string( $plugin_slug ) ) { - $this->_licenses = $licenses; - } - - $this->_store_licenses( true, $plugin_slug, $licenses ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - * - * @param bool|number $plugin_id - * @param bool $flush Since 1.1.7.3 - * - * @return object|false New plugin tag info if exist. - */ - private function _fetch_newer_version( $plugin_id = false, $flush = true ) { - $latest_tag = $this->_fetch_latest_version( $plugin_id, $flush ); - - if ( ! is_object( $latest_tag ) ) { - return false; - } - - // Check if version is actually newer. - $has_new_version = - // If it's an non-installed add-on then always return latest. - ( $this->_is_addon_id( $plugin_id ) && ! $this->is_addon_activated( $plugin_id ) ) || - // Compare versions. - version_compare( $this->get_plugin_version(), $latest_tag->version, '<' ); - - $this->_logger->departure( $has_new_version ? 'Found newer plugin version ' . $latest_tag->version : 'No new version' ); - - return $has_new_version ? $latest_tag : false; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.5 - * - * @param bool|number $plugin_id - * @param bool $flush Since 1.1.7.3 - * - * @return bool|FS_Plugin_Tag - */ - function get_update( $plugin_id = false, $flush = true ) { - $this->_logger->entrance(); - - if ( ! is_numeric( $plugin_id ) ) { - $plugin_id = $this->_plugin->id; - } - - $this->_check_updates( true, $plugin_id, $flush ); - $updates = $this->get_all_updates(); - - return isset( $updates[ $plugin_id ] ) && is_object( $updates[ $plugin_id ] ) ? $updates[ $plugin_id ] : false; - } - - /** - * Check if site assigned with active license. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - */ - function has_active_license() { - return ( - is_object( $this->_license ) && - is_numeric( $this->_license->id ) && - ! $this->_license->is_expired() - ); - } - - /** - * Check if site assigned with license with enabled features. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @return bool - */ - function has_features_enabled_license() { - return ( - is_object( $this->_license ) && - is_numeric( $this->_license->id ) && - $this->_license->is_features_enabled() - ); - } - - /** - * Check if user is a trial or have feature enabled license. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.7 - * - * @return bool - */ - function can_use_premium_code() { - return $this->is_trial() || $this->has_features_enabled_license(); - } - - /** - * Sync site's plan. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.3 - * - * @uses FS_Api - * - * @param bool $background Hints the method if it's a background sync. If false, it means that was initiated by - * the admin. - */ - private function _sync_license( $background = false ) { - $this->_logger->entrance(); - - $plugin_id = fs_request_get( 'plugin_id', $this->get_id() ); - - $is_addon_sync = ( ! $this->_plugin->is_addon() && $plugin_id != $this->get_id() ); - - if ( $is_addon_sync ) { - $this->_sync_addon_license( $plugin_id, $background ); - } else { - $this->_sync_plugin_license( $background ); - } - - $this->do_action( 'after_account_plan_sync', $this->_site->plan->name ); - } - - /** - * Sync plugin's add-on license. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * @uses FS_Api - * - * @param number $addon_id - * @param bool $background - */ - private function _sync_addon_license( $addon_id, $background ) { - $this->_logger->entrance(); - - if ( $this->is_addon_activated( $addon_id ) ) { - // If already installed, use add-on sync. - $fs_addon = self::get_instance_by_id( $addon_id ); - $fs_addon->_sync_license( $background ); - - return; - } - - // Validate add-on exists. - $addon = $this->get_addon( $addon_id ); - - if ( ! is_object( $addon ) ) { - return; - } - - // Add add-on into account add-ons. - $account_addons = $this->get_account_addons(); - if ( ! is_array( $account_addons ) ) { - $account_addons = array(); - } - $account_addons[] = $addon->id; - $account_addons = array_unique( $account_addons ); - $this->_store_account_addons( $account_addons ); - - // Load add-on licenses. - $licenses = $this->_fetch_licenses( $addon->id ); - - // Sync add-on licenses. - if ( ! isset( $licenses->error ) ) { - $this->_update_licenses( $licenses, $addon->slug ); - - if ( ! $this->is_addon_installed( $addon->slug ) && FS_License_Manager::has_premium_license( $licenses ) ) { - $plans_result = $this->get_api_site_or_plugin_scope()->get( "/addons/{$addon_id}/plans.json" ); - - if ( ! isset( $plans_result->error ) ) { - $plans = array(); - foreach ( $plans_result->plans as $plan ) { - $plans[] = new FS_Plugin_Plan( $plan ); - } - - $this->_admin_notices->add_sticky( - FS_Plan_Manager::instance()->has_free_plan( $plans ) ? - sprintf( - __fs( 'addon-successfully-upgraded-message', $this->_slug ), - $addon->title - ) . ' ' . $this->_get_latest_download_link( - __fs( 'download-latest-version', $this->_slug ), - $addon_id - ) - : - sprintf( - __fs( 'addon-successfully-purchased-message', $this->_slug ), - $addon->title - ) . ' ' . $this->_get_latest_download_link( - __fs( 'download-latest-version', $this->_slug ), - $addon_id - ), - 'addon_plan_upgraded_' . $addon->slug, - __fs( 'yee-haw', $this->_slug ) . '!' - ); - } - } - } - } - - /** - * Sync site's plugin plan. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * @uses FS_Api - * - * @param bool $background Hints the method if it's a background sync. If false, it means that was initiated by - * the admin. - */ - private function _sync_plugin_license( $background = false ) { - $this->_logger->entrance(); - - // Sync site info. - $site = $this->send_install_update( array(), true ); - - $plan_change = 'none'; - - if ( $this->is_api_error( $site ) ) { - // Show API messages only if not background sync or if paying customer. - if ( ! $background || $this->is_paying() ) { - // Try to ping API to see if not blocked. - if ( ! FS_Api::test() ) { - /** - * Failed to ping API - blocked! - * - * @author Vova Feldman (@svovaf) - * @since 1.1.6 Only show message related to one of the Freemius powered plugins. Once it will be resolved it will fix the issue for all plugins anyways. There's no point to scare users with multiple error messages. - */ - $api = $this->get_api_site_scope(); - - if ( ! self::$_global_admin_notices->has_sticky( 'api_blocked' ) ) { - self::$_global_admin_notices->add( - sprintf( - __fs( 'server-blocking-access', $this->_slug ), - $this->get_plugin_name(), - '<a href="' . $api->get_url() . '" target="_blank">' . $api->get_url() . '</a>' - ) . '<br> ' . __fs( 'server-error-message', $this->_slug ) . var_export( $site->error, true ), - __fs( 'oops', $this->_slug ) . '...', - 'error', - $background, - false, - 'api_blocked' - ); - } - } else { - // Authentication params are broken. - $this->_admin_notices->add( - __fs( 'wrong-authentication-param-message', $this->_slug ), - __fs( 'oops', $this->_slug ) . '...', - 'error' - ); - } - } - - // No reason to continue with license sync while there are API issues. - return; - } - - // Remove sticky API connectivity message. - self::$_global_admin_notices->remove_sticky( 'api_blocked' ); - - $site = new FS_Site( $site ); - - // Sync plans. - $this->_sync_plans(); - - if ( ! $this->has_paid_plan() ) { - $this->_site = $site; - $this->_enrich_site_plan( true ); - $this->_store_site(); - } else { - // Sync licenses. - $this->_sync_licenses(); - - // Check if plan / license changed. - if ( ! FS_Entity::equals( $site->plan, $this->_site->plan ) || - // Check if trial started. - $site->trial_plan_id != $this->_site->trial_plan_id || - $site->trial_ends != $this->_site->trial_ends || - // Check if license changed. - $site->license_id != $this->_site->license_id - ) { - if ( $site->is_trial() && ( ! $this->_site->is_trial() || $site->trial_ends != $this->_site->trial_ends ) ) { - // New trial started. - $this->_site = $site; - $plan_change = 'trial_started'; - - // Store trial plan information. - $this->_enrich_site_trial_plan( true ); - - // For trial with subscription use-case. - $new_license = is_null( $site->license_id ) ? null : $this->_get_license_by_id( $site->license_id ); - - if ( is_object( $new_license ) && ! $new_license->is_expired() ) { - $this->_site = $site; - $this->_update_site_license( $new_license ); - $this->_store_licenses(); - $this->_enrich_site_plan( true ); - - $this->_sync_site_subscription( $this->_license ); - } - } else if ( $this->_site->is_trial() && ! $site->is_trial() && ! is_numeric( $site->license_id ) ) { - // Was in trial, but now trial expired and no license ID. - // New trial started. - $this->_site = $site; - $plan_change = 'trial_expired'; - - // Clear trial plan information. - $this->_storage->trial_plan = null; - - } else { - $is_free = $this->is_free_plan(); - - // Make sure license exist and not expired. - $new_license = is_null( $site->license_id ) ? null : $this->_get_license_by_id( $site->license_id ); - - if ( $is_free && ( ( ! is_object( $new_license ) || $new_license->is_expired() ) ) ) { - // The license is expired, so ignore upgrade method. - } else { - // License changed. - $this->_site = $site; - $this->_update_site_license( $new_license ); - $this->_store_licenses(); - $this->_enrich_site_plan( true ); - - $plan_change = $is_free ? - 'upgraded' : - ( is_object( $new_license ) ? - 'changed' : - 'downgraded' ); - } - } - - // Store updated site info. - $this->_store_site(); - } else { - if ( is_object( $this->_license ) && $this->_license->is_expired() ) { - if ( ! $this->has_features_enabled_license() ) { - $this->_deactivate_license(); - $plan_change = 'downgraded'; - } else { - $plan_change = 'expired'; - } - } - - if ( is_numeric( $site->license_id ) && is_object( $this->_license ) ) { - $this->_sync_site_subscription( $this->_license ); - } - } - } - - if ( $this->has_paid_plan() ) { - switch ( $plan_change ) { - case 'none': - if ( ! $background && is_admin() ) { - $plan = $this->is_trial() ? - $this->_storage->trial_plan : - $this->_site->plan; - - $this->_admin_notices->add( - sprintf( - __fs( 'plan-did-not-change-message', $this->_slug ) . ' ' . - sprintf( - '<a href="%s">%s</a>', - $this->contact_url( - 'bug', - sprintf( __fs( 'plan-did-not-change-email-message', $this->_slug ), - strtoupper( $plan->name ) - ) - ), - __fs( 'contact-us-here', $this->_slug ) - ), - '<i>' . $plan->title . ( $this->is_trial() ? ' ' . __fs( 'trial', $this->_slug ) : '' ) . '</i>' - ), - __fs( 'hmm', $this->_slug ) . '...', - 'error' - ); - } - break; - case 'upgraded': - $this->_admin_notices->add_sticky( - sprintf( - __fs( 'plan-upgraded-message', $this->_slug ), - '<i>' . $this->get_plugin_name() . '</i>' - ) . ( $this->is_premium() ? '' : ' ' . $this->_get_latest_download_link( sprintf( - __fs( 'download-latest-x-version', $this->_slug ), - $this->_site->plan->title - ) ) - ), - 'plan_upgraded', - __fs( 'yee-haw', $this->_slug ) . '!' - ); - - $this->_admin_notices->remove_sticky( array( - 'trial_started', - 'trial_promotion', - 'trial_expired', - 'activation_complete', - ) ); - break; - case 'changed': - $this->_admin_notices->add_sticky( - sprintf( - __fs( 'plan-changed-to-x-message', $this->_slug ), - $this->_site->plan->title - ), - 'plan_changed' - ); - - $this->_admin_notices->remove_sticky( array( - 'trial_started', - 'trial_promotion', - 'trial_expired', - 'activation_complete', - ) ); - break; - case 'downgraded': - $this->_admin_notices->add_sticky( - sprintf( __fs( 'license-expired-blocking-message', $this->_slug ) ), - 'license_expired', - __fs( 'hmm', $this->_slug ) . '...' - ); - $this->_admin_notices->remove_sticky( 'plan_upgraded' ); - break; - case 'expired': - $this->_admin_notices->add_sticky( - sprintf( __fs( 'license-expired-non-blocking-message', $this->_slug ), $this->_site->plan->title ), - 'license_expired', - __fs( 'hmm', $this->_slug ) . '...' - ); - $this->_admin_notices->remove_sticky( 'plan_upgraded' ); - break; - case 'trial_started': - $this->_admin_notices->add_sticky( - sprintf( - __fs( 'trial-started-message', $this->_slug ), - '<i>' . $this->get_plugin_name() . '</i>' - ) . ( $this->is_premium() ? '' : ' ' . $this->_get_latest_download_link( sprintf( - __fs( 'download-latest-x-version', $this->_slug ), - $this->_storage->trial_plan->title - ) ) ), - 'trial_started', - __fs( 'yee-haw', $this->_slug ) . '!' - ); - - $this->_admin_notices->remove_sticky( array( - 'trial_promotion', - ) ); - break; - case 'trial_expired': - $this->_admin_notices->add_sticky( - __fs( 'trial-expired-message', $this->_slug ), - 'trial_expired', - __fs( 'hmm', $this->_slug ) . '...' - ); - $this->_admin_notices->remove_sticky( array( - 'trial_started', - 'trial_promotion', - 'plan_upgraded', - ) ); - break; - } - } - - if ( 'none' !== $plan_change ) { - $this->do_action( 'after_license_change', $plan_change, $this->_site->plan ); - } - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.5 - * - * @param bool $background - */ - protected function _activate_license( $background = false ) { - $this->_logger->entrance(); - - $license_id = fs_request_get( 'license_id' ); - - if ( FS_Plugin_License::is_valid_id( $license_id ) && $license_id == $this->_site->license_id ) { - // License is already activated. - return; - } - - $premium_license = FS_Plugin_License::is_valid_id( $license_id ) ? - $this->_get_license_by_id( $license_id ) : - $this->_get_available_premium_license(); - - if ( ! is_object( $premium_license ) ) { - return; - } - - $api = $this->get_api_site_scope(); - $license = $api->call( "/licenses/{$premium_license->id}.json", 'put' ); - - if ( $this->is_api_error( $license ) ) { - if ( ! $background ) { - $this->_admin_notices->add( - __fs( 'license-activation-failed-message', $this->_slug ) . '<br> ' . - __fs( 'server-error-message', $this->_slug ) . ' ' . var_export( $license, true ), - __fs( 'hmm', $this->_slug ) . '...', - 'error' - ); - } - - return; - } - - $premium_license = new FS_Plugin_License( $license ); - - // Updated site plan. - $site = $this->get_api_site_scope()->get( '/', true ); - if ( ! $this->is_api_error( $site ) ) { - $this->_site = new FS_Site( $site ); - } - $this->_update_site_license( $premium_license ); - $this->_enrich_site_plan( false ); - - $this->_store_account(); - - if ( ! $background ) { - $this->_admin_notices->add_sticky( - __fs( 'license-activated-message', $this->_slug ) . - ( $this->is_premium() ? '' : ' ' . $this->_get_latest_download_link( sprintf( - __fs( 'download-latest-x-version', $this->_slug ), - $this->_site->plan->title - ) ) ), - 'license_activated', - __fs( 'yee-haw', $this->_slug ) . '!' - ); - } - - $this->_admin_notices->remove_sticky( array( - 'trial_promotion', - 'license_expired', - ) ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.5 - * - * @param bool $show_notice - */ - protected function _deactivate_license( $show_notice = true ) { - $this->_logger->entrance(); - - if ( ! is_object( $this->_license ) ) { - $this->_admin_notices->add( - sprintf( __fs( 'no-active-license-message', $this->_slug ), $this->_site->plan->title ), - __fs( 'hmm', $this->_slug ) . '...' - ); - - return; - } - - $api = $this->get_api_site_scope(); - $license = $api->call( "/licenses/{$this->_site->license_id}.json", 'delete' ); - - if ( isset( $license->error ) ) { - $this->_admin_notices->add( - __fs( 'license-deactivation-failed-message', $this->_slug ) . '<br> ' . - __fs( 'server-error-message', $this->_slug ) . ' ' . var_export( $license->error, true ), - __fs( 'hmm', $this->_slug ) . '...', - 'error' - ); - - return; - } - - // Update license cache. - for ( $i = 0, $len = count( $this->_licenses ); $i < $len; $i ++ ) { - if ( $license->id == $this->_licenses[ $i ]->id ) { - $this->_licenses[ $i ] = new FS_Plugin_License( $license ); - } - } - - // Updated site plan to default. - $this->_sync_plans(); - $this->_site->plan->id = $this->_plans[0]->id; - // Unlink license from site. - $this->_update_site_license( null ); - $this->_enrich_site_plan( false ); - - $this->_store_account(); - - if ( $show_notice ) { - $this->_admin_notices->add( - sprintf( __fs( 'license-deactivation-message', $this->_slug ), $this->_site->plan->title ), - __fs( 'ok', $this->_slug ) - ); - } - - $this->_admin_notices->remove_sticky( array( - 'plan_upgraded', - 'license_activated', - ) ); - } - - /** - * Site plan downgrade. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - * - * @uses FS_Api - */ - private function _downgrade_site() { - $this->_logger->entrance(); - - $api = $this->get_api_site_scope(); - $site = $api->call( 'downgrade.json', 'put' ); - - $plan_downgraded = false; - $plan = false; - if ( ! isset( $site->error ) ) { - $prev_plan_id = $this->_site->plan->id; - - // Update new site plan id. - $this->_site->plan->id = $site->plan_id; - - $plan = $this->_enrich_site_plan(); - $subscription = $this->_sync_site_subscription( $this->_license ); - - // Plan downgraded if plan was changed or subscription was cancelled. - $plan_downgraded = ( $plan instanceof FS_Plugin_Plan && $prev_plan_id != $plan->id ) || - ( is_object( $subscription ) && ! isset( $subscription->error ) && ! $subscription->is_active() ); - } else { - // handle different error cases. - - } - - if ( $plan_downgraded ) { - // Remove previous sticky message about upgrade (if exist). - $this->_admin_notices->remove_sticky( 'plan_upgraded' ); - - $this->_admin_notices->add( - sprintf( __fs( 'plan-x-downgraded-message', $this->_slug ), - $plan->title, - human_time_diff( time(), strtotime( $this->_license->expiration ) ) - ) - ); - - // Store site updates. - $this->_store_site(); - } else { - $this->_admin_notices->add( - __fs( 'plan-downgraded-failure-message', $this->_slug ), - __fs( 'oops', $this->_slug ) . '...', - 'error' - ); - } - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.8.1 - * - * @param bool|string $plan_name - * - * @return bool If trial was successfully started. - */ - function start_trial($plan_name = false) { - $this->_logger->entrance(); - - if ( $this->is_trial() ) { - // Already in trial mode. - $this->_admin_notices->add( - __fs( 'in-trial-mode', $this->_slug ), - __fs( 'oops', $this->_slug ) . '...', - 'error' - ); - - return false; - } - - if ( $this->_site->is_trial_utilized() ) { - // Trial was already utilized. - $this->_admin_notices->add( - __fs( 'trial-utilized', $this->_slug ), - __fs( 'oops', $this->_slug ) . '...', - 'error' - ); - - return false; - } - - if ( false !== $plan_name ) { - $plan = $this->get_plan_by_name( $plan_name ); - - if ( false === $plan ) { - // Plan doesn't exist. - $this->_admin_notices->add( - sprintf( __fs( 'trial-plan-x-not-exist', $this->_slug ), $plan_name ), - __fs( 'oops', $this->_slug ) . '...', - 'error' - ); - - return false; - } - - if ( ! $plan->has_trial() ) { - // Plan doesn't exist. - $this->_admin_notices->add( - sprintf( __fs( 'plan-x-no-trial', $this->_slug ), $plan_name ), - __fs( 'oops', $this->_slug ) . '...', - 'error' - ); - - return false; - } - } else { - if ( ! $this->has_trial_plan() ) { - // None of the plans have a trial. - $this->_admin_notices->add( - __fs( 'no-trials', $this->_slug ), - __fs( 'oops', $this->_slug ) . '...', - 'error' - ); - - return false; - } - - $plans_with_trial = FS_Plan_Manager::instance()->get_trial_plans( $this->_plans ); - - $plan = $plans_with_trial[0]; - } - - $api = $this->get_api_site_scope(); - $plan = $api->call( "plans/{$plan->id}/trials.json", 'post' ); - - if ( $this->is_api_error( $plan ) ) { - // Some API error while trying to start the trial. - $this->_admin_notices->add( - __fs( 'unexpected-api-error', $this->_slug ) . ' ' . var_export( $plan, true ), - __fs( 'oops', $this->_slug ) . '...', - 'error' - ); - - return false; - } - - // Sync license. - $this->_sync_license(); - - return $this->is_trial(); - } - - /** - * Cancel site trial. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @uses FS_Api - */ - private function _cancel_trial() { - $this->_logger->entrance(); - - if ( ! $this->is_trial() ) { - $this->_admin_notices->add( - __fs( 'trial-cancel-no-trial-message', $this->_slug ), - __fs( 'oops', $this->_slug ) . '...', - 'error' - ); - - return; - } - - $api = $this->get_api_site_scope(); - $site = $api->call( 'trials.json', 'delete' ); - - $trial_cancelled = false; - - if ( ! $this->is_api_error( $site ) ) { - $prev_trial_ends = $this->_site->trial_ends; - - if ( $this->is_paid_trial() ) { - $this->_license->expiration = $site->trial_ends; - $this->_license->is_cancelled = true; - $this->_update_site_license( $this->_license ); - $this->_store_licenses(); - - // Clear subscription reference. - $this->_sync_site_subscription( null ); - } - - // Update site info. - $this->_site = new FS_Site( $site ); - $this->_enrich_site_plan(); - - $trial_cancelled = ( $prev_trial_ends != $site->trial_ends ); - } else { - // handle different error cases. - - } - - if ( $trial_cancelled ) { - // Remove previous sticky messages about upgrade or trial (if exist). - $this->_admin_notices->remove_sticky( array( - 'trial_started', - 'trial_promotion', - 'plan_upgraded', - ) ); - - // Store site updates. - $this->_store_site(); - - // Clear trial plan information. - unset( $this->_storage->trial_plan ); - - if ( ! $this->is_addon() || - ! $this->deactivate_premium_only_addon_without_license( true ) - ) { - $this->_admin_notices->add( - sprintf( __fs( 'trial-cancel-message', $this->_slug ), $this->_storage->trial_plan->title ) - ); - } - } else { - $this->_admin_notices->add( - __fs( 'trial-cancel-failure-message', $this->_slug ), - __fs( 'oops', $this->_slug ) . '...', - 'error' - ); - } - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @param bool|number $plugin_id - * - * @return bool - */ - private function _is_addon_id( $plugin_id ) { - return is_numeric( $plugin_id ) && ( $this->get_id() != $plugin_id ); - } - - /** - * Check if user eligible to download premium version updates. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @return bool - */ - private function _can_download_premium() { - return $this->has_active_license() || - ( $this->is_trial() && ! $this->get_trial_plan()->is_free() ); - } - - /** - * - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @param bool|number $addon_id - * @param string $type "json" or "zip" - * - * @return string - */ - private function _get_latest_version_endpoint( $addon_id = false, $type = 'json' ) { - - $is_addon = $this->_is_addon_id( $addon_id ); - - $is_premium = null; - if ( ! $is_addon ) { - $is_premium = $this->_can_download_premium(); - } else if ( $this->is_addon_activated( $addon_id ) ) { - $is_premium = self::get_instance_by_id( $addon_id )->_can_download_premium(); - } - - return // If add-on, then append add-on ID. - ( $is_addon ? "/addons/$addon_id" : '' ) . - '/updates/latest.' . $type . - // If add-on and not yet activated, try to fetch based on server licensing. - ( is_bool( $is_premium ) ? '?is_premium=' . json_encode( $is_premium ) : '' ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - * - * @param bool|number $addon_id - * @param bool $flush Since 1.1.7.3 - * - * @return object|false Plugin latest tag info. - */ - function _fetch_latest_version( $addon_id = false, $flush = true ) { - $this->_logger->entrance(); - - /** - * @since 1.1.7.3 Check for plugin updates from Freemius only if opted-in. - * @since 1.1.7.4 Also check updates for add-ons. - */ - if ( ! $this->is_registered() && - ! $this->_is_addon_id( $addon_id ) - ) { - return false; - } - - $tag = $this->get_api_site_or_plugin_scope()->get( - $this->_get_latest_version_endpoint( $addon_id, 'json' ), - $flush - ); - - $latest_version = ( is_object( $tag ) && isset( $tag->version ) ) ? $tag->version : 'couldn\'t get'; - - $this->_logger->departure( 'Latest version ' . $latest_version ); - - return ( is_object( $tag ) && isset( $tag->version ) ) ? $tag : false; - } - - #region Download Plugin ------------------------------------------------------------------ - - /** - * Download latest plugin version, based on plan. - * The download will be fetched via the API first. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - * - * @param bool|number $plugin_id - * - * @uses FS_Api - * - * @deprecated - */ - private function _download_latest( $plugin_id = false ) { - $this->_logger->entrance(); - - $is_addon = $this->_is_addon_id( $plugin_id ); - - $is_premium = $this->_can_download_premium(); - - $latest = $this->get_api_site_scope()->call( - $this->_get_latest_version_endpoint( $plugin_id, 'zip' ) - ); - - $slug = $this->_slug; - if ( $is_addon ) { - $addon = $this->get_addon( $plugin_id ); - $slug = is_object( $addon ) ? $addon->slug : 'addon'; - } - - if ( ! is_object( $latest ) ) { - header( "Content-Type: application/zip" ); - header( "Content-Disposition: attachment; filename={$slug}" . ( ! $is_addon && $is_premium ? '-premium' : '' ) . ".zip" ); - header( "Content-Length: " . strlen( $latest ) ); - echo $latest; - - exit(); - } - } - - /** - * Download latest plugin version, based on plan. - * - * Not like _download_latest(), this will redirect the page - * to secure download url to prevent dual download (from FS to WP server, - * and then from WP server to the client / browser). - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @param bool|number $plugin_id - * - * @uses FS_Api - * @uses wp_redirect() - */ - private function _download_latest_directly( $plugin_id = false ) { - $this->_logger->entrance(); - - wp_redirect( $this->_get_latest_download_api_url( $plugin_id ) ); - } - - /** - * Get latest plugin FS API download URL. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @param bool|number $plugin_id - * - * @return string - */ - private function _get_latest_download_api_url( $plugin_id = false ) { - $this->_logger->entrance(); - - return $this->get_api_site_scope()->get_signed_url( - $this->_get_latest_version_endpoint( $plugin_id, 'zip' ) - ); - } - - /** - * Get latest plugin download link. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @param string $label - * @param bool|number $plugin_id - * - * @return string - */ - private function _get_latest_download_link( $label, $plugin_id = false ) { - return sprintf( - '<a target="_blank" href="%s">%s</a>', - $this->_get_latest_download_local_url( $plugin_id ), - $label - ); - } - - /** - * Get latest plugin download local URL. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @param bool|number $plugin_id - * - * @return string - */ - function _get_latest_download_local_url( $plugin_id = false ) { - // Add timestamp to protect from caching. - $params = array( 'ts' => WP_FS__SCRIPT_START_TIME ); - - if ( ! empty( $plugin_id ) ) { - $params['plugin_id'] = $plugin_id; - } - - return $this->get_account_url( 'download_latest', $params ); - } - - #endregion Download Plugin ------------------------------------------------------------------ - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - * - * @uses FS_Api - * - * @param bool $background Hints the method if it's a background updates check. If false, it means that - * was initiated by the admin. - * @param bool|number $plugin_id - * @param bool $flush Since 1.1.7.3 - */ - private function _check_updates( $background = false, $plugin_id = false, $flush = true ) { - $this->_logger->entrance(); - - // Check if there's a newer version for download. - $new_version = $this->_fetch_newer_version( $plugin_id, $flush ); - - $update = null; - if ( is_object( $new_version ) ) { - $update = new FS_Plugin_Tag( $new_version ); - - if ( ! $background ) { - $this->_admin_notices->add( - sprintf( - __fs( 'version-x-released', $this->_slug ) . ' ' . __fs( 'please-download-x', $this->_slug ), - $update->version, - sprintf( - '<a href="%s" target="_blank">%s</a>', - $this->get_account_url( 'download_latest' ), - sprintf( __fs( 'latest-x-version', $this->_slug ), $this->_site->plan->title ) - ) - ), - __fs( 'new', $this->_slug ) . '!' - ); - } - } else if ( false === $new_version && ! $background ) { - $this->_admin_notices->add( - __fs( 'you-have-latest', $this->_slug ), - __fs( 'you-are-good', $this->_slug ) - ); - } - - $this->_store_update( $update, true, $plugin_id ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - * - * @param bool $flush Since 1.1.7.3 by default add 24 hour cache. - * - * @return FS_Plugin[] - * - * @uses FS_Api - */ - private function _sync_addons( $flush = false ) { - $this->_logger->entrance(); - - $result = $this->get_api_site_or_plugin_scope()->get( '/addons.json?enriched=true', $flush ); - - $addons = array(); - if ( ! $this->is_api_error( $result ) ) { - for ( $i = 0, $len = count( $result->plugins ); $i < $len; $i ++ ) { - $addons[ $i ] = new FS_Plugin( $result->plugins[ $i ] ); - } - - $this->_store_addons( $addons, true ); - } - - return $addons; - } - - /** - * Handle user email update. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.3 - * @uses FS_Api - * - * @param string $new_email - * - * @return object - */ - private function _update_email( $new_email ) { - $this->_logger->entrance(); - - - $api = $this->get_api_user_scope(); - $user = $api->call( "?plugin_id={$this->_plugin->id}&fields=id,email,is_verified", 'put', array( - 'email' => $new_email, - 'after_email_confirm_url' => $this->_get_admin_page_url( - 'account', - array( 'fs_action' => 'sync_user' ) - ), - ) ); - - if ( ! isset( $user->error ) ) { - $this->_user->email = $user->email; - $this->_user->is_verified = $user->is_verified; - $this->_store_user(); - } else { - // handle different error cases. - - } - - return $user; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.1 - * - * @param mixed $result - * - * @return bool Is API result contains an error. - */ - private function is_api_error( $result ) { - return ( is_object( $result ) && isset( $result->error ) ) || - is_string( $result ); - } - - /** - * Start install ownership change. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.1 - * @uses FS_Api - * - * @param string $candidate_email - * - * @return bool Is ownership change successfully initiated. - */ - private function init_change_owner( $candidate_email ) { - $this->_logger->entrance(); - - $api = $this->get_api_site_scope(); - $result = $api->call( "/users/{$this->_user->id}.json", 'put', array( - 'email' => $candidate_email, - 'after_confirm_url' => $this->_get_admin_page_url( - 'account', - array( 'fs_action' => 'change_owner' ) - ), - ) ); - - return ! $this->is_api_error( $result ); - } - - /** - * Handle install ownership change. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.1 - * @uses FS_Api - * - * @return bool Was ownership change successfully complete. - */ - private function complete_change_owner() { - $this->_logger->entrance(); - - $site_result = $this->get_api_site_scope( true )->get(); - $site = new FS_Site( $site_result ); - $this->_site = $site; - - $user = new FS_User(); - $user->id = fs_request_get( 'user_id' ); - - // Validate install's user and given user. - if ( $user->id != $this->_site->user_id ) { - return false; - } - - $user->public_key = fs_request_get( 'user_public_key' ); - $user->secret_key = fs_request_get( 'user_secret_key' ); - - // Fetch new user information. - $this->_user = $user; - $user_result = $this->get_api_user_scope( true )->get(); - $user = new FS_User( $user_result ); - $this->_user = $user; - - $this->_set_account( $user, $site ); - - return true; - } - - /** - * Handle user name update. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * @uses FS_Api - * - * @return object - */ - private function update_user_name() { - $this->_logger->entrance(); - $name = fs_request_get( 'fs_user_name_' . $this->_slug, '' ); - - $api = $this->get_api_user_scope(); - $user = $api->call( "?plugin_id={$this->_plugin->id}&fields=id,first,last", 'put', array( - 'name' => $name, - ) ); - - if ( ! isset( $user->error ) ) { - $this->_user->first = $user->first; - $this->_user->last = $user->last; - $this->_store_user(); - } else { - // handle different error cases. - - } - - return $user; - } - - /** - * Verify user email. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.3 - * @uses FS_Api - */ - private function verify_email() { - $this->_handle_account_user_sync(); - - if ( $this->_user->is_verified() ) { - return; - } - - $api = $this->get_api_site_scope(); - $result = $api->call( "/users/{$this->_user->id}/verify.json", 'put', array( - 'after_email_confirm_url' => $this->_get_admin_page_url( - 'account', - array( 'fs_action' => 'sync_user' ) - ) - ) ); - - if ( ! isset( $result->error ) ) { - $this->_admin_notices->add( sprintf( - __fs( 'verification-email-sent-message', $this->_slug ), - sprintf( '<a href="mailto:%1s">%2s</a>', esc_url( $this->_user->email ), $this->_user->email ) - ) ); - } else { - // handle different error cases. - - } - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.2 - * - * @return string - */ - private function get_activation_url() { - return $this->apply_filters( 'connect_url', $this->_get_admin_page_url() ); - } - - /** - * Get the URL of the page that should be loaded after the user connect or skip in the opt-in screen. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.3 - * - * @param string $filter Filter name. - * - * @return string - */ - private function get_after_activation_url( $filter ) { - $first_time_path = $this->_menu->get_first_time_path(); - - return $this->apply_filters( - $filter, - empty( $first_time_path ) ? - $this->_get_admin_page_url() : - $first_time_path - ); - } - - /** - * Handle account page updates / edits / actions. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.2 - * - */ - private function _handle_account_edits() { - if ( ! current_user_can( 'activate_plugins' ) ) { - return; - } - - $plugin_id = fs_request_get( 'plugin_id', $this->get_id() ); - $action = fs_get_action(); - - switch ( $action ) { - case 'delete_account': - check_admin_referer( $action ); - - if ( $plugin_id == $this->get_id() ) { - $this->delete_account_event(); - - // Clear user and site. - $this->_site = null; - $this->_user = null; - - if ( fs_redirect( $this->get_activation_url() ) ) { - exit(); - } - } else { - if ( $this->is_addon_activated( $plugin_id ) ) { - $fs_addon = self::get_instance_by_id( $plugin_id ); - $fs_addon->delete_account_event(); - - if ( fs_redirect( $this->_get_admin_page_url( 'account' ) ) ) { - exit(); - } - } - } - - return; - - case 'downgrade_account': - check_admin_referer( $action ); - $this->_downgrade_site(); - - return; - - case 'activate_license': - check_admin_referer( $action ); - - if ( $plugin_id == $this->get_id() ) { - $this->_activate_license(); - } else { - if ( $this->is_addon_activated( $plugin_id ) ) { - $fs_addon = self::get_instance_by_id( $plugin_id ); - $fs_addon->_activate_license(); - } - } - - return; - - case 'deactivate_license': - check_admin_referer( $action ); - - if ( $plugin_id == $this->get_id() ) { - $this->_deactivate_license(); - } else { - if ( $this->is_addon_activated( $plugin_id ) ) { - $fs_addon = self::get_instance_by_id( $plugin_id ); - $fs_addon->_deactivate_license(); - } - } - - return; - - case 'check_updates': - check_admin_referer( $action ); - $this->_check_updates(); - - return; - - case 'change_owner': - $state = fs_request_get( 'state', 'init' ); - switch ( $state ) { - case 'init': - $candidate_email = fs_request_get( 'candidate_email', '' ); - - if ( $this->init_change_owner( $candidate_email ) ) { - $this->_admin_notices->add( sprintf( __fs( 'change-owner-request-sent-x', $this->_slug ), '<b>' . $this->_user->email . '</b>' ) ); - } - break; - case 'owner_confirmed': - $candidate_email = fs_request_get( 'candidate_email', '' ); - - $this->_admin_notices->add( sprintf( __fs( 'change-owner-request_owner-confirmed', $this->_slug ), '<b>' . $candidate_email . '</b>' ) ); - break; - case 'candidate_confirmed': - if ( $this->complete_change_owner() ) { - $this->_admin_notices->add_sticky( - sprintf( __fs( 'change-owner-request_candidate-confirmed', $this->_slug ), '<b>' . $this->_user->email . '</b>' ), - 'ownership_changed', - __fs( 'congrats', $this->_slug ) . '!' - ); - } else { - // @todo Handle failed ownership change message. - } - break; - } - - return; - - case 'update_email': - check_admin_referer( 'update_email' ); - - $new_email = fs_request_get( 'fs_email_' . $this->_slug, '' ); - $result = $this->_update_email( $new_email ); - - if ( isset( $result->error ) ) { - switch ( $result->error->code ) { - case 'user_exist': - $this->_admin_notices->add( - __fs( 'user-exist-message', $this->_slug ) . ' ' . - sprintf( __fs( 'user-exist-message_ownership', $this->_slug ), '<b>' . $new_email . '</b>' ) . - sprintf( - '<a style="margin-left: 10px;" href="%s"><button class="button button-primary">%s ➜</button></a>', - $this->get_account_url( 'change_owner', array( - 'state' => 'init', - 'candidate_email' => $new_email - ) ), - __fs( 'change-ownership', $this->_slug ) - ), - __fs( 'oops', $this->_slug ) . '...', - 'error' - ); - break; - } - } else { - $this->_admin_notices->add( __fs( 'email-updated-message', $this->_slug ) ); - } - - return; - - case 'update_user_name': - check_admin_referer( 'update_user_name' ); - - $result = $this->update_user_name(); - - if ( isset( $result->error ) ) { - $this->_admin_notices->add( - __fs( 'name-update-failed-message', $this->_slug ), - __fs( 'oops', $this->_slug ) . '...', - 'error' - ); - } else { - $this->_admin_notices->add( __fs( 'name-updated-message', $this->_slug ) ); - } - - return; - - #region Actions that might be called from external links (e.g. email) - - case 'cancel_trial': - if ( $plugin_id == $this->get_id() ) { - $this->_cancel_trial(); - } else { - if ( $this->is_addon_activated( $plugin_id ) ) { - $fs_addon = self::get_instance_by_id( $plugin_id ); - $fs_addon->_cancel_trial(); - } - } - - return; - - case 'verify_email': - $this->verify_email(); - - return; - - case 'sync_user': - $this->_handle_account_user_sync(); - - return; - - case $this->_slug . '_sync_license': - $this->_sync_license(); - - return; - - case 'download_latest': - $this->_download_latest_directly( $plugin_id ); - - return; - - #endregion - } - - if ( WP_FS__IS_POST_REQUEST ) { - $properties = array( 'site_secret_key', 'site_id', 'site_public_key' ); - foreach ( $properties as $p ) { - if ( 'update_' . $p === $action ) { - check_admin_referer( $action ); - - $this->_logger->log( $action ); - - $site_property = substr( $p, strlen( 'site_' ) ); - $site_property_value = fs_request_get( 'fs_' . $p . '_' . $this->_slug, '' ); - $this->get_site()->{$site_property} = $site_property_value; - - // Store account after modification. - $this->_store_site(); - - $this->do_action( 'account_property_edit', 'site', $site_property, $site_property_value ); - - $this->_admin_notices->add( sprintf( - __fs( 'x-updated', $this->_slug ), - '<b>' . str_replace( '_', ' ', $p ) . '</b>' ) ); - - return; - } - } - } - } - - /** - * Account page resources load. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - */ - function _account_page_load() { - $this->_logger->entrance(); - - $this->_logger->info( var_export( $_REQUEST, true ) ); - - fs_enqueue_local_style( 'fs_account', '/admin/account.css' ); - - if ( $this->has_addons() ) { - wp_enqueue_script( 'plugin-install' ); - add_thickbox(); - - function fs_addons_body_class( $classes ) { - $classes .= ' plugins-php'; - - return $classes; - } - - add_filter( 'admin_body_class', 'fs_addons_body_class' ); - } - - if ( $this->has_paid_plan() && - ! $this->has_any_license() && - ! $this->is_sync_executed() - ) { - /** - * If no licenses found and no sync job was executed during the last 24 hours, - * just execute the sync job right away (blocking execution). - * - * @since 1.1.7.3 - */ - $this->run_manual_sync(); - } - - $this->_handle_account_edits(); - - $this->do_action( 'account_page_load_before_departure' ); - } - - /** - * Render account page. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.0 - */ - function _account_page_render() { - $this->_logger->entrance(); - - $vars = array( 'slug' => $this->_slug ); - fs_require_once_template( 'account.php', $vars ); - } - - /** - * Render account connect page. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - */ - function _connect_page_render() { - $this->_logger->entrance(); - - $vars = array( 'slug' => $this->_slug ); - fs_require_once_template( 'connect.php', $vars ); - } - - /** - * Load required resources before add-ons page render. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - */ - function _addons_page_load() { - $this->_logger->entrance(); - - fs_enqueue_local_style( 'fs_addons', '/admin/add-ons.css' ); - - wp_enqueue_script( 'plugin-install' ); - add_thickbox(); - - function fs_addons_body_class( $classes ) { - $classes .= ' plugins-php'; - - return $classes; - } - - add_filter( 'admin_body_class', 'fs_addons_body_class' ); - - if ( ! $this->is_registered() && $this->is_org_repo_compliant() ) { - $this->_admin_notices->add( - sprintf( __fs( 'addons-info-external-message', $this->_slug ), '<b>' . $this->get_plugin_name() . '</b>' ), - __fs( 'heads-up', $this->_slug ), - 'update-nag' - ); - } - } - - /** - * Render add-ons page. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - */ - function _addons_page_render() { - $this->_logger->entrance(); - - $vars = array( 'slug' => $this->_slug ); - fs_require_once_template( 'add-ons.php', $vars ); - } - - /* Pricing & Upgrade - ------------------------------------------------------------------------------------------------------------------*/ - /** - * Render pricing page. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.0 - */ - function _pricing_page_render() { - $this->_logger->entrance(); - - $vars = array( 'slug' => $this->_slug ); - - if ( 'true' === fs_request_get( 'checkout', false ) ) { - fs_require_once_template( 'checkout.php', $vars ); - } else { - fs_require_once_template( 'pricing.php', $vars ); - } - } - - #region Contact Us ------------------------------------------------------------------ - - /** - * Render contact-us page. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.3 - */ - function _contact_page_render() { - $this->_logger->entrance(); - - $vars = array( 'slug' => $this->_slug ); - fs_require_once_template( 'contact.php', $vars ); - } - - #endregion ------------------------------------------------------------------ - - /** - * Hide all admin notices to prevent distractions. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.3 - * - * @uses remove_all_actions() - */ - private static function _hide_admin_notices() { - remove_all_actions( 'admin_notices' ); - remove_all_actions( 'network_admin_notices' ); - remove_all_actions( 'all_admin_notices' ); - remove_all_actions( 'user_admin_notices' ); - } - - static function _clean_admin_content_section_hook() { - self::_hide_admin_notices(); - - // Hide footer. - echo '<style>#wpfooter { display: none !important; }</style>'; - } - - /** - * Attach to admin_head hook to hide all admin notices. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.3 - */ - static function _clean_admin_content_section() { - add_action( 'admin_head', 'Freemius::_clean_admin_content_section_hook' ); - } - - /* CSS & JavaScript - ------------------------------------------------------------------------------------------------------------------*/ - /* function _enqueue_script($handle, $src) { - $url = plugins_url( substr( WP_FS__DIR_JS, strlen( $this->_plugin_dir_path ) ) . '/assets/js/' . $src ); - - $this->_logger->entrance( 'script = ' . $url ); - - wp_enqueue_script( $handle, $url ); - }*/ - - /* SDK - ------------------------------------------------------------------------------------------------------------------*/ - private $_user_api; - - /** - * - * @author Vova Feldman (@svovaf) - * @since 1.0.2 - * - * @param bool $flush - * - * @return FS_Api - */ - function get_api_user_scope( $flush = false ) { - if ( ! isset( $this->_user_api ) || $flush ) { - $this->_user_api = FS_Api::instance( - $this->_slug, - 'user', - $this->_user->id, - $this->_user->public_key, - ! $this->is_live(), - $this->_user->secret_key - ); - } - - return $this->_user_api; - } - - private $_site_api; - - /** - * - * @author Vova Feldman (@svovaf) - * @since 1.0.2 - * - * @param bool $flush - * - * @return FS_Api - */ - function get_api_site_scope( $flush = false ) { - if ( ! isset( $this->_site_api ) || $flush ) { - $this->_site_api = FS_Api::instance( - $this->_slug, - 'install', - $this->_site->id, - $this->_site->public_key, - ! $this->is_live(), - $this->_site->secret_key - ); - } - - return $this->_site_api; - } - - private $_plugin_api; - - /** - * Get plugin public API scope. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - * - * @return FS_Api - */ - function get_api_plugin_scope() { - if ( ! isset( $this->_plugin_api ) ) { - $this->_plugin_api = FS_Api::instance( - $this->_slug, - 'plugin', - $this->_plugin->id, - $this->_plugin->public_key, - ! $this->is_live() - ); - } - - return $this->_plugin_api; - } - - /** - * Get site API scope object (fallback to public plugin scope when not registered). - * - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - * - * @return FS_Api - */ - function get_api_site_or_plugin_scope() { - return $this->is_registered() ? - $this->get_api_site_scope() : - $this->get_api_plugin_scope(); - } - - /** - * Show trial promotional notice (if any trial exist). - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @param $plans - */ - function _check_for_trial_plans( $plans ) { - $this->_storage->has_trial_plan = FS_Plan_Manager::instance()->has_trial_plan( $plans ); - } - - /** - * Show trial promotional notice (if any trial exist). - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - */ - function _add_trial_notice() { - // Check if trial already utilized. - if ( $this->_site->is_trial_utilized() ) { - return; - } - - // Check if already paying. - if ( $this->is_paying() ) { - return; - } - - // Check if trial message is already shown. - if ( $this->_admin_notices->has_sticky( 'trial_promotion' ) ) { - return; - } - - $trial_plans = FS_Plan_Manager::instance()->get_trial_plans( $this->_plans ); - $trial_plans_count = count( $trial_plans ); - - // Check if any of the plans contains trial. - if ( 0 === $trial_plans_count ) { - return; - } - - /** - * @var FS_Plugin_Plan $paid_plan - */ - $paid_plan = $trial_plans[0]; - $require_subscription = $paid_plan->is_require_subscription; - $upgrade_url = $this->get_trial_url(); - $cc_string = $require_subscription ? - sprintf( __fs( 'no-commitment-for-x-days', $this->_slug ), $paid_plan->trial_period ) : - __fs( 'no-cc-required', $this->_slug ) . '!'; - - - $total_paid_plans = count( $this->_plans ) - ( FS_Plan_Manager::instance()->has_free_plan( $this->_plans ) ? 1 : 0 ); - - if ( $total_paid_plans === $trial_plans_count ) { - // All paid plans have trials. - $message = sprintf( - __fs( 'hey', $this->_slug ) . '! ' . __fs( 'trial-x-promotion-message', $this->_slug ), - sprintf( '<b>%s</b>', $this->get_plugin_name() ), - strtolower( __fs( 'awesome', $this->_slug ) ), - $paid_plan->trial_period - ); - } else { - $plans_string = ''; - for ( $i = 0; $i < $trial_plans_count; $i ++ ) { - $plans_string .= sprintf( '<a href="%s">%s</a>', $upgrade_url, $trial_plans[ $i ]->title ); - - if ( $i < $trial_plans_count - 2 ) { - $plans_string .= ', '; - } else if ( $i == $trial_plans_count - 2 ) { - $plans_string .= ' and '; - } - } - - // Not all paid plans have trials. - $message = sprintf( - __fs( 'hey', $this->_slug ) . '! ' . __fs( 'trial-x-promotion-message', $this->_slug ), - sprintf( '<b>%s</b>', $this->get_plugin_name() ), - $plans_string, - $paid_plan->trial_period - ); - } - - $message .= ' ' . $cc_string; - - // Add start trial button. - $message .= ' ' . sprintf( - '<a style="margin-left: 10px; vertical-align: super;" href="%s"><button class="button button-primary">%s ➜</button></a>', - $upgrade_url, - __fs( 'start-free-trial', $this->_slug ) - ); - - $this->_admin_notices->add_sticky( - $this->apply_filters( 'trial_promotion_message', $message ), - 'trial_promotion', - '', - 'promotion' - ); - - $this->_storage->trial_promotion_shown = WP_FS__SCRIPT_START_TIME; - } - - /* Action Links - ------------------------------------------------------------------------------------------------------------------*/ - private $_action_links_hooked = false; - private $_action_links = array(); - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.0 - * - * @return bool - */ - private function is_plugin_action_links_hooked() { - $this->_logger->entrance( json_encode( $this->_action_links_hooked ) ); - - return $this->_action_links_hooked; - } - - /** - * Hook to plugin action links filter. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.0 - */ - private function hook_plugin_action_links() { - $this->_logger->entrance(); - - $this->_action_links_hooked = true; - - $this->_logger->log( 'Adding action links hooks.' ); - - // Add action link to settings page. - add_filter( 'plugin_action_links_' . $this->_plugin_basename, array( - &$this, - '_modify_plugin_action_links_hook' - ), WP_FS__DEFAULT_PRIORITY, 2 ); - add_filter( 'network_admin_plugin_action_links_' . $this->_plugin_basename, array( - &$this, - '_modify_plugin_action_links_hook' - ), WP_FS__DEFAULT_PRIORITY, 2 ); - } - - /** - * Add plugin action link. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.0 - * - * @param $label - * @param $url - * @param bool $external - * @param int $priority - * @param bool $key - */ - function add_plugin_action_link( $label, $url, $external = false, $priority = WP_FS__DEFAULT_PRIORITY, $key = false ) { - $this->_logger->entrance(); - - if ( ! isset( $this->_action_links[ $priority ] ) ) { - $this->_action_links[ $priority ] = array(); - } - - if ( false === $key ) { - $key = preg_replace( "/[^A-Za-z0-9 ]/", '', strtolower( $label ) ); - } - - $this->_action_links[ $priority ][] = array( - 'label' => $label, - 'href' => $url, - 'key' => $key, - 'external' => $external - ); - } - - /** - * Adds Upgrade and Add-Ons links to the main Plugins page link actions collection. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.0 - */ - function _add_upgrade_action_link() { - $this->_logger->entrance(); - - if ( $this->is_registered() ) { - if ( ! $this->is_paying() && $this->has_paid_plan() ) { - $this->add_plugin_action_link( - __fs( 'upgrade', $this->_slug ), - $this->get_upgrade_url(), - false, - 7, - 'upgrade' - ); - } - - if ( $this->has_addons() ) { - $this->add_plugin_action_link( - __fs( 'add-ons', $this->_slug ), - $this->_get_admin_page_url( 'addons' ), - false, - 9, - 'addons' - ); - } - } - } - - /** - * Get the URL of the page that should be loaded right after the plugin activation. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.7.4 - * - * @return string - */ - function get_after_plugin_activation_redirect_url() { - $url = false; - $plugin_fs = false; - - if ( ! $this->is_addon() ) { - $first_time_path = $this->_menu->get_first_time_path(); - $plugin_fs = $this; - $url = $plugin_fs->is_activation_mode() ? - $plugin_fs->get_activation_url() : - ( empty( $first_time_path ) ? - $this->_get_admin_page_url() : - $first_time_path ); - } else { - if ( $this->is_parent_plugin_installed() ) { - $plugin_fs = self::get_parent_instance(); - } - - if ( is_object( $plugin_fs ) ) { - if ( ! $plugin_fs->is_registered() ) { - // Forward to parent plugin connect when parent not registered. - $url = $plugin_fs->get_activation_url(); - } else { - // Forward to account page. - $url = $plugin_fs->_get_admin_page_url( 'account' ); - } - } - } - - return $url; - } - - /** - * Forward page to activation page. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.3 - */ - function _redirect_on_activation_hook() { - $url = $this->get_after_plugin_activation_redirect_url(); - - if ( is_string( $url ) ) { - fs_redirect( $url ); - exit(); - } - } - - /** - * Modify plugin's page action links collection. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.0 - * - * @param array $links - * @param $file - * - * @return array - */ - function _modify_plugin_action_links_hook( $links, $file ) { - $this->_logger->entrance(); - - $passed_deactivate = false; - $deactivate_link = ''; - $before_deactivate = array(); - $after_deactivate = array(); - foreach ( $links as $key => $link ) { - if ( 'deactivate' === $key ) { - $deactivate_link = $link; - $passed_deactivate = true; - continue; - } - - if ( ! $passed_deactivate ) { - $before_deactivate[ $key ] = $link; - } else { - $after_deactivate[ $key ] = $link; - } - } - - ksort( $this->_action_links ); - - foreach ( $this->_action_links as $new_links ) { - foreach ( $new_links as $link ) { - $before_deactivate[ $link['key'] ] = '<a href="' . $link['href'] . '"' . ( $link['external'] ? ' target="_blank"' : '' ) . '>' . $link['label'] . '</a>'; - } - } - - if ( ! empty( $deactivate_link ) ) { - if ( ! $this->is_paying_or_trial() || $this->is_premium() ) { - /* - * This HTML element is used to identify the correct plugin when attaching an event to its Deactivate link. - * - * If user is paying or in trial and have the free version installed, - * assume that the deactivation is for the upgrade process, so this is not needed. - */ - $deactivate_link .= '<i class="fs-slug" data-slug="' . $this->_slug . '"></i>'; - } - - // Append deactivation link. - $before_deactivate['deactivate'] = $deactivate_link; - } - - return array_merge( $before_deactivate, $after_deactivate ); - } - - /** - * Adds admin message. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - * - * @param string $message - * @param string $title - * @param string $type - */ - function add_admin_message( $message, $title = '', $type = 'success' ) { - $this->_admin_notices->add( $message, $title, $type ); - } - - /** - * Adds sticky admin message. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.0 - * - * @param string $message - * @param string $id - * @param string $title - * @param string $type - */ - function add_sticky_admin_message( $message, $id, $title = '', $type = 'success' ) { - $this->_admin_notices->add_sticky( $message, $id, $title, $type ); - } - - /* Plugin Auto-Updates (@since 1.0.4) - ------------------------------------------------------------------------------------------------------------------*/ - /** - * @var string[] - */ - private static $_auto_updated_plugins; - - /** - * @todo TEST IF IT WORKS!!! - * - * Include plugins for automatic updates based on stored settings. - * - * @see http://wordpress.stackexchange.com/questions/131394/how-do-i-exclude-plugins-from-getting-automatically-updated/131404#131404 - * - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - * - * @param bool $update Whether to update (not used for plugins) - * @param object $item The plugin's info - * - * @return bool - */ - static function _include_plugins_in_auto_update( $update, $item ) { - // Before version 3.8.2 the $item was the file name of the plugin, - // while in 3.8.2 statistics were added (https://core.trac.wordpress.org/changeset/27905). - $by_slug = ( (int) str_replace( '.', '', get_bloginfo( 'version' ) ) >= 382 ); - - if ( ! isset( self::$_auto_updated_plugins ) ) { - $plugins = self::$_accounts->get_option( 'plugins', array() ); - - $identifiers = array(); - foreach ( $plugins as $p ) { - /** - * @var FS_Plugin $p - */ - if ( isset( $p->auto_update ) && $p->auto_update ) { - $identifiers[] = ( $by_slug ? $p->slug : plugin_basename( $p->file ) ); - } - } - - self::$_auto_updated_plugins = $identifiers; - } - - if ( in_array( $by_slug ? $item->slug : $item, self::$_auto_updated_plugins ) ) { - return true; - } - - // Pass update decision to next filters - return $update; - } - - #region Versioning ------------------------------------------------------------------ - - /** - * Check if Freemius in SDK upgrade mode. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @return bool - */ - function is_sdk_upgrade_mode() { - return isset( $this->_storage->sdk_upgrade_mode ) ? - $this->_storage->sdk_upgrade_mode : - false; - } - - /** - * Turn SDK upgrade mode off. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @return bool - */ - function set_sdk_upgrade_complete() { - $this->_storage->sdk_upgrade_mode = false; - } - - /** - * Check if plugin upgrade mode. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @return bool - */ - function is_plugin_upgrade_mode() { - return isset( $this->_storage->plugin_upgrade_mode ) ? - $this->_storage->plugin_upgrade_mode : - false; - } - - /** - * Turn plugin upgrade mode off. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @return bool - */ - function set_plugin_upgrade_complete() { - $this->_storage->plugin_upgrade_mode = false; - } - - #endregion ------------------------------------------------------------------ - - #region Permissions ------------------------------------------------------------------ - - /** - * Check if specific permission requested. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.6 - * - * @param string $permission - * - * @return bool - */ - function is_permission_requested( $permission ) { - return isset( $this->_permissions[ $permission ] ) && ( true === $this->_permissions[ $permission ] ); - } - - #endregion Permissions ------------------------------------------------------------------ - - #region Marketing ------------------------------------------------------------------ - - /** - * Check if current user purchased any other plugins before. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @return bool - */ - function has_purchased_before() { - // TODO: Implement has_purchased_before() method. - } - - /** - * Check if current user classified as an agency. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @return bool - */ - function is_agency() { - // TODO: Implement is_agency() method. - } - - /** - * Check if current user classified as a developer. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @return bool - */ - function is_developer() { - // TODO: Implement is_developer() method. - } - - /** - * Check if current user classified as a business. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @return bool - */ - function is_business() { - // TODO: Implement is_business() method. - } - - #endregion ------------------------------------------------------------------ +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.3 + */ + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + // "final class" + class Freemius extends Freemius_Abstract { + /** + * SDK Version + * + * @var string + */ + public $version = WP_FS__SDK_VERSION; + + #region Plugin Info + + /** + * @since 1.0.1 + * + * @var string + */ + private $_slug; + + /** + * @since 1.0.0 + * + * @var string + */ + private $_plugin_basename; + /** + * @since 1.0.0 + * + * @var string + */ + private $_free_plugin_basename; + /** + * @since 1.0.0 + * + * @var string + */ + private $_plugin_dir_path; + /** + * @since 1.0.0 + * + * @var string + */ + private $_plugin_dir_name; + /** + * @since 1.0.0 + * + * @var string + */ + private $_plugin_main_file_path; + /** + * @var string[] + */ + private $_plugin_data; + /** + * @since 1.0.9 + * + * @var string + */ + private $_plugin_name; + + #endregion Plugin Info + + /** + * @since 1.0.9 + * + * @var bool If false, don't turn Freemius on. + */ + private $_is_on; + + /** + * @since 1.1.3 + * + * @var bool If false, don't turn Freemius on. + */ + private $_is_anonymous; + + /** + * @since 1.0.9 + * @var bool If false, issues with connectivity to Freemius API. + */ + private $_has_api_connection; + + /** + * @since 1.0.9 + * @var bool Hints the SDK if plugin can support anonymous mode (if skip connect is visible). + */ + private $_enable_anonymous; + + /** + * @since 1.1.7.5 + * @var bool Hints the SDK if plugin should run in anonymous mode (only adds feedback form). + */ + private $_anonymous_mode; + + /** + * @since 1.0.8 + * @var bool Hints the SDK if the plugin has any paid plans. + */ + private $_has_paid_plans; + + /** + * @since 1.0.7 + * @var bool Hints the SDK if the plugin is WordPress.org compliant. + */ + private $_is_org_compliant; + + /** + * @since 1.0.7 + * @var bool Hints the SDK if the plugin is has add-ons. + */ + private $_has_addons; + + /** + * @since 1.1.6 + * @var string[]bool. + */ + private $_permissions; + + /** + * @var FS_Key_Value_Storage + */ + private $_storage; + + /** + * @since 1.0.0 + * + * @var FS_Logger + */ + private $_logger; + /** + * @since 1.0.4 + * + * @var FS_Plugin + */ + private $_plugin = false; + /** + * @since 1.0.4 + * + * @var FS_Plugin + */ + private $_parent_plugin = false; + /** + * @since 1.1.1 + * + * @var Freemius + */ + private $_parent = false; + /** + * @since 1.0.1 + * + * @var FS_User + */ + private $_user = false; + /** + * @since 1.0.1 + * + * @var FS_Site + */ + private $_site = false; + /** + * @since 1.0.1 + * + * @var FS_Plugin_License + */ + private $_license; + /** + * @since 1.0.2 + * + * @var FS_Plugin_Plan[] + */ + private $_plans = false; + /** + * @var FS_Plugin_License[] + * @since 1.0.5 + */ + private $_licenses = false; + + /** + * @since 1.0.1 + * + * @var FS_Admin_Menu_Manager + */ + private $_menu; + + /** + * @var FS_Admin_Notice_Manager + */ + private $_admin_notices; + + /** + * @since 1.1.6 + * + * @var FS_Admin_Notice_Manager + */ + private static $_global_admin_notices; + + /** + * @var FS_Logger + * @since 1.0.0 + */ + private static $_static_logger; + + /** + * @var FS_Option_Manager + * @since 1.0.2 + */ + private static $_accounts; + + /** + * @var Freemius[] + */ + private static $_instances = array(); + + + /* Ctor +------------------------------------------------------------------------------------------------------------------*/ + + private function __construct( $slug ) { + $this->_slug = $slug; + + $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $slug, WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); + + $this->_storage = FS_Key_Value_Storage::instance( 'plugin_data', $this->_slug ); + + $this->_plugin_main_file_path = $this->_find_caller_plugin_file(); + $this->_plugin_dir_path = plugin_dir_path( $this->_plugin_main_file_path ); + $this->_plugin_basename = plugin_basename( $this->_plugin_main_file_path ); + $this->_free_plugin_basename = str_replace( '-premium/', '/', $this->_plugin_basename ); + + $base_name_split = explode( '/', $this->_plugin_basename ); + $this->_plugin_dir_name = $base_name_split[0]; + + if ( $this->_logger->is_on() ) { + $this->_logger->info( 'plugin_main_file_path = ' . $this->_plugin_main_file_path ); + $this->_logger->info( 'plugin_dir_path = ' . $this->_plugin_dir_path ); + $this->_logger->info( 'plugin_basename = ' . $this->_plugin_basename ); + $this->_logger->info( 'free_plugin_basename = ' . $this->_free_plugin_basename ); + $this->_logger->info( 'plugin_dir_name = ' . $this->_plugin_dir_name ); + } + + // Remember link between file to slug. + $this->store_file_slug_map(); + + // Store plugin's initial install timestamp. + if ( ! isset( $this->_storage->install_timestamp ) ) { + $this->_storage->install_timestamp = WP_FS__SCRIPT_START_TIME; + } + + $this->_plugin = FS_Plugin_Manager::instance( $this->_slug )->get(); + + $this->_admin_notices = FS_Admin_Notice_Manager::instance( + $slug, + is_object( $this->_plugin ) ? $this->_plugin->title : '' + ); + + if ( 'true' === fs_request_get( 'fs_clear_api_cache' ) || + 'true' === fs_request_is_action( 'restart_freemius' ) + ) { + FS_Api::clear_cache(); + } + + $this->_register_hooks(); + + $this->_load_account(); + + $this->_version_updates_handler(); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + */ + private function _version_updates_handler() { + if ( ! isset( $this->_storage->sdk_version ) || $this->_storage->sdk_version != $this->version ) { + // Freemius version upgrade mode. + $this->_storage->sdk_last_version = $this->_storage->sdk_version; + $this->_storage->sdk_version = $this->version; + + if ( empty( $this->_storage->sdk_last_version ) || + version_compare( $this->_storage->sdk_last_version, $this->version, '<' ) + ) { + $this->_storage->sdk_upgrade_mode = true; + $this->_storage->sdk_downgrade_mode = false; + } else { + $this->_storage->sdk_downgrade_mode = true; + $this->_storage->sdk_upgrade_mode = false; + + } + + $this->do_action( 'sdk_version_update', $this->_storage->sdk_last_version, $this->version ); + } + + $plugin_version = $this->get_plugin_version(); + if ( ! isset( $this->_storage->plugin_version ) || $this->_storage->plugin_version != $plugin_version ) { + // Plugin version upgrade mode. + $this->_storage->plugin_last_version = $this->_storage->plugin_version; + $this->_storage->plugin_version = $plugin_version; + + if ( empty( $this->_storage->plugin_last_version ) || + version_compare( $this->_storage->plugin_last_version, $plugin_version, '<' ) + ) { + $this->_storage->plugin_upgrade_mode = true; + $this->_storage->plugin_downgrade_mode = false; + } else { + $this->_storage->plugin_downgrade_mode = true; + $this->_storage->plugin_upgrade_mode = false; + } + + if ( ! empty( $this->_storage->plugin_last_version ) ) { + // Different version of the plugin was installed before, therefore it's an update. + $this->_storage->is_plugin_new_install = false; + } + + $this->do_action( 'plugin_version_update', $this->_storage->plugin_last_version, $plugin_version ); + } + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.5 + * + * @param string $sdk_prev_version + * @param string $sdk_version + */ + function _data_migration( $sdk_prev_version, $sdk_version ) { + /** + * @since 1.1.7.3 Fixed unwanted connectivity test cleanup. + */ + if ( empty( $sdk_prev_version ) ) { + return; + } + + if ( version_compare( $sdk_prev_version, '1.1.5', '<' ) && + version_compare( $sdk_version, '1.1.5', '>=' ) + ) { + // On version 1.1.5 merged connectivity and is_on data. + if ( isset( $this->_storage->connectivity_test ) ) { + if ( ! isset( $this->_storage->is_on ) ) { + unset( $this->_storage->connectivity_test ); + } else { + $connectivity_data = $this->_storage->connectivity_test; + $connectivity_data['is_active'] = $this->_storage->is_on['is_active']; + $connectivity_data['timestamp'] = $this->_storage->is_on['timestamp']; + + // Override. + $this->_storage->connectivity_test = $connectivity_data; + + // Remove previous structure. + unset( $this->_storage->is_on ); + } + + } + } + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + */ + private function _register_hooks() { + if ( is_admin() ) { + // Hook to plugin activation + register_activation_hook( $this->_plugin_main_file_path, array( + &$this, + '_activate_plugin_event_hook' + ) ); + + // Hook to plugin uninstall. + register_uninstall_hook( $this->_plugin_main_file_path, array( 'Freemius', '_uninstall_plugin_hook' ) ); + + if ( ! $this->is_ajax() ) { + if ( ! $this->is_addon() ) { + add_action( 'init', array( &$this, '_add_default_submenu_items' ), WP_FS__LOWEST_PRIORITY ); + add_action( 'admin_menu', array( &$this, '_prepare_admin_menu' ), WP_FS__LOWEST_PRIORITY ); + } + } + } + + register_deactivation_hook( $this->_plugin_main_file_path, array( &$this, '_deactivate_plugin_hook' ) ); + + add_action( 'init', array( &$this, '_redirect_on_clicked_menu_link' ), WP_FS__LOWEST_PRIORITY ); + + $this->add_action( 'after_plans_sync', array( &$this, '_check_for_trial_plans' ) ); + + $this->add_action( 'sdk_version_update', array( &$this, '_data_migration' ), WP_FS__DEFAULT_PRIORITY, 2 ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + */ + private function _register_account_hooks() { + if ( is_admin() ) { + if ( ! $this->is_ajax() ) { + if ( $this->apply_filters( 'show_trial', true ) && $this->has_trial_plan() ) { + $last_time_trial_promotion_shown = $this->_storage->get( 'trial_promotion_shown', false ); + if ( ! $this->_site->is_trial_utilized() && + ( + // Show promotion if never shown it yet and 24 hours after initial activation. + ( false === $last_time_trial_promotion_shown && $this->_storage->activation_timestamp < ( time() - WP_FS__TIME_24_HOURS_IN_SEC ) ) || + // Show promotion in every 30 days. + ( is_numeric( $last_time_trial_promotion_shown ) && 30 * WP_FS__TIME_24_HOURS_IN_SEC < time() - $last_time_trial_promotion_shown ) ) + ) { + $this->add_action( 'after_init_plugin_registered', array( &$this, '_add_trial_notice' ) ); + } + } + } + + // If user is paying or in trial and have the free version installed, + // assume that the deactivation is for the upgrade process. + if ( ! $this->is_paying_or_trial() || $this->is_premium() ) { + add_action( 'wp_ajax_submit-uninstall-reason', array( &$this, '_submit_uninstall_reason_action' ) ); + + global $pagenow; + if ( 'plugins.php' === $pagenow ) { + add_action( 'admin_footer', array( &$this, '_add_deactivation_feedback_dialog_box' ) ); + } + } + } + } + + /** + * Leverage backtrace to find caller plugin file path. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @return string + * + * @uses fs_find_caller_plugin_file + */ + private function _find_caller_plugin_file() { + // Try to load the cached value of the file path. + if ( isset( $this->_storage->plugin_main_file ) ) { + if ( file_exists( $this->_storage->plugin_main_file->path ) ) { + return $this->_storage->plugin_main_file->path; + } + } + + $plugin_file = fs_find_caller_plugin_file(); + + $this->_storage->plugin_main_file = (object) array( + 'path' => fs_normalize_path( $plugin_file ), + ); + + return $plugin_file; + } + + + #region Deactivation Feedback Form ------------------------------------------------------------------ + + /** + * Displays a confirmation and feedback dialog box when the user clicks on the "Deactivate" link on the plugins + * page. + * + * @author Vova Feldman (@svovaf) + * @author Leo Fajardo (@leorw) + * @since 1.1.2 + */ + function _add_deactivation_feedback_dialog_box() { + fs_enqueue_local_style( 'fs_deactivation_feedback', '/admin/deactivation-feedback.css' ); + + /* Check the type of user: + * 1. Long-term (long-term) + * 2. Non-registered and non-anonymous short-term (non-registered-and-non-anonymous-short-term). + * 3. Short-term (short-term) + */ + $is_long_term_user = true; + + // Check if the site is at least 2 days old. + $time_installed = $this->_storage->install_timestamp; + + // Difference in seconds. + $date_diff = time() - $time_installed; + + // Convert seconds to days. + $date_diff_days = floor( $date_diff / ( 60 * 60 * 24 ) ); + + if ( $date_diff_days < 2 ) { + $is_long_term_user = false; + } + + $is_long_term_user = $this->apply_filters( 'is_long_term_user', $is_long_term_user ); + + if ( $is_long_term_user ) { + $user_type = 'long-term'; + } else { + if ( ! $this->is_registered() && ! $this->is_anonymous() ) { + $user_type = 'non-registered-and-non-anonymous-short-term'; + } else { + $user_type = 'short-term'; + } + } + + $uninstall_reasons = $this->_get_uninstall_reasons( $user_type ); + + // Load the HTML template for the deactivation feedback dialog box. + $vars = array( + 'reasons' => $uninstall_reasons, + 'slug' => $this->_slug + ); + + /** + * @todo Deactivation form core functions should be loaded only once! Otherwise, when there are multiple Freemius powered plugins the same code is loaded multiple times. The only thing that should be loaded differently is the various deactivation reasons object based on the state of the plugin. + */ + fs_require_template( 'deactivation-feedback-modal.php', $vars ); + } + + /** + * @author Leo Fajardo (leorw) + * @since 1.1.2 + * + * @param string $user_type + * + * @return array The uninstall reasons for the specified user type. + */ + function _get_uninstall_reasons( $user_type = 'long-term' ) { + $reason_found_better_plugin = array( + 'id' => 2, + 'text' => __fs( 'reason-found-a-better-plugin', $this->_slug ), + 'input_type' => 'textfield', + 'input_placeholder' => __fs( 'placeholder-plugin-name', $this->_slug ) + ); + + $reason_temporary_deactivation = array( + 'id' => 15, + 'text' => __fs( 'reason-temporary-deactivation', $this->_slug ), + 'input_type' => '', + 'input_placeholder' => '' + ); + + $reason_other = array( + 'id' => 7, + 'text' => __fs( 'reason-other', $this->_slug ), + 'input_type' => 'textfield', + 'input_placeholder' => '' + ); + + $long_term_user_reasons = array( + array( + 'id' => 1, + 'text' => __fs( 'reason-no-longer-needed', $this->_slug ), + 'input_type' => '', + 'input_placeholder' => '' + ), + $reason_found_better_plugin, + array( + 'id' => 3, + 'text' => __fs( 'reason-needed-for-a-short-period', $this->_slug ), + 'input_type' => '', + 'input_placeholder' => '' + ), + array( + 'id' => 4, + 'text' => __fs( 'reason-broke-my-site', $this->_slug ), + 'input_type' => '', + 'input_placeholder' => '' + ), + array( + 'id' => 5, + 'text' => __fs( 'reason-suddenly-stopped-working', $this->_slug ), + 'input_type' => '', + 'input_placeholder' => '' + ) + ); + + if ( $this->is_paying() ) { + $long_term_user_reasons[] = array( + 'id' => 6, + 'text' => __fs( 'reason-cant-pay-anymore', $this->_slug ), + 'input_type' => 'textfield', + 'input_placeholder' => __fs( 'placeholder-comfortable-price', $this->_slug ) + ); + } + + $long_term_user_reasons[] = $reason_temporary_deactivation; + $long_term_user_reasons[] = $reason_other; + + $uninstall_reasons = array( + 'long-term' => $long_term_user_reasons, + 'non-registered-and-non-anonymous-short-term' => array( + array( + 'id' => 8, + 'text' => __fs( 'reason-didnt-work', $this->_slug ), + 'input_type' => '', + 'input_placeholder' => '' + ), + array( + 'id' => 9, + 'text' => __fs( 'reason-dont-like-to-share-my-information', $this->_slug ), + 'input_type' => '', + 'input_placeholder' => '' + ), + $reason_found_better_plugin, + $reason_temporary_deactivation, + $reason_other + ), + 'short-term' => array( + array( + 'id' => 10, + 'text' => __fs( 'reason-couldnt-make-it-work', $this->_slug ), + 'input_type' => '', + 'input_placeholder' => '' + ), + $reason_found_better_plugin, + array( + 'id' => 11, + 'text' => __fs( 'reason-great-but-need-specific-feature', $this->_slug ), + 'input_type' => 'textarea', + 'input_placeholder' => __fs( 'placeholder-feature', $this->_slug ) + ), + array( + 'id' => 12, + 'text' => __fs( 'reason-not-working', $this->_slug ), + 'input_type' => 'textarea', + 'input_placeholder' => __fs( 'placeholder-share-what-didnt-work', $this->_slug ) + ), + array( + 'id' => 13, + 'text' => __fs( 'reason-not-what-i-was-looking-for', $this->_slug ), + 'input_type' => 'textarea', + 'input_placeholder' => __fs( 'placeholder-what-youve-been-looking-for', $this->_slug ) + ), + array( + 'id' => 14, + 'text' => __fs( 'reason-didnt-work-as-expected', $this->_slug ), + 'input_type' => 'textarea', + 'input_placeholder' => __fs( 'placeholder-what-did-you-expect', $this->_slug ) + ), + $reason_temporary_deactivation, + $reason_other + ) + ); + + $uninstall_reasons = $this->apply_filters( 'uninstall_reasons', $uninstall_reasons ); + + return $uninstall_reasons[ $user_type ]; + } + + /** + * Called after the user has submitted his reason for deactivating the plugin. + * + * @author Leo Fajardo (@leorw) + * @since 1.1.2 + */ + function _submit_uninstall_reason_action() { + if ( ! isset( $_POST['reason_id'] ) ) { + exit; + } + + $reason_info = isset( $_REQUEST['reason_info'] ) ? trim( stripslashes( $_REQUEST['reason_info'] ) ) : ''; + + $reason = (object) array( + 'id' => $_POST['reason_id'], + 'info' => substr( $reason_info, 0, 128 ) + ); + + $this->_storage->store( 'uninstall_reason', $reason ); + + // Print '1' for successful operation. + echo 1; + exit; + } + + #endregion Deactivation Feedback Form ------------------------------------------------------------------ + + #region Instance ------------------------------------------------------------------ + + /** + * Main singleton instance. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.0 + * + * @param $slug + * + * @return Freemius + */ + static function instance( $slug ) { + $slug = strtolower( $slug ); + + if ( ! isset( self::$_instances[ $slug ] ) ) { + if ( 0 === count( self::$_instances ) ) { + self::_load_required_static(); + } + + self::$_instances[ $slug ] = new Freemius( $slug ); + } + + return self::$_instances[ $slug ]; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @param string|number $slug_or_id + * + * @return bool + */ + private static function has_instance( $slug_or_id ) { + return ! is_numeric( $slug_or_id ) ? + isset( self::$_instances[ strtolower( $slug_or_id ) ] ) : + ( false !== self::get_instance_by_id( $slug_or_id ) ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @param $id + * + * @return false|Freemius + */ + static function get_instance_by_id( $id ) { + foreach ( self::$_instances as $slug => $instance ) { + if ( $id == $instance->get_id() ) { + return $instance; + } + } + + return false; + } + + /** + * + * @author Vova Feldman (@svovaf) + * @since 1.0.1 + * + * @param $plugin_file + * + * @return false|Freemius + */ + static function get_instance_by_file( $plugin_file ) { + $slug = self::find_slug_by_basename( $plugin_file ); + + return ( false !== $slug ) ? + self::instance( $slug ) : + false; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @return false|Freemius + */ + function get_parent_instance() { + return self::get_instance_by_id( $this->_plugin->parent_plugin_id ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @param $slug_or_id + * + * @return bool|Freemius + */ + function get_addon_instance( $slug_or_id ) { + return ! is_numeric( $slug_or_id ) ? + self::instance( strtolower( $slug_or_id ) ) : + self::get_instance_by_id( $slug_or_id ); + } + + #endregion ------------------------------------------------------------------ + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @return bool + */ + function is_parent_plugin_installed() { + return self::has_instance( $this->_plugin->parent_plugin_id ); + } + + /** + * Check if add-on parent plugin in activation mode. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + * + * @return bool + */ + function is_parent_in_activation() { + $parent_fs = $this->get_parent_instance(); + if ( ! is_object( $parent_fs ) ) { + return false; + } + + return ( $parent_fs->is_activation_mode() ); + } + + /** + * Is plugin in activation mode. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + * + * @return bool + */ + function is_activation_mode() { + return ( + $this->is_on() && + ! $this->is_registered() && + ( ! $this->enable_anonymous() || + ( ! $this->is_anonymous() && ! $this->is_pending_activation() ) ) + ); + } + + /** + * Get collection of all active plugins. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @return array[string]array + */ + private static function get_active_plugins() { + self::require_plugin_essentials(); + + $active_plugin = array(); + $all_plugins = get_plugins(); + $active_plugins_basenames = get_option( 'active_plugins' ); + + foreach ( $active_plugins_basenames as $plugin_basename ) { + $active_plugin[ $plugin_basename ] = $all_plugins[ $plugin_basename ]; + } + + return $active_plugin; + } + + /** + * Get collection of all plugins. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.8 + * + * @return array Key is the plugin file path and the value is an array of the plugin data. + */ + private static function get_all_plugins() { + self::require_plugin_essentials(); + + $all_plugins = get_plugins(); + $active_plugins_basenames = get_option( 'active_plugins' ); + + foreach ( $all_plugins as $basename => &$data ) { + // By default set to inactive (next foreach update the active plugins). + $data['is_active'] = false; + // Enrich with plugin slug. + $data['slug'] = self::get_plugin_slug( $basename ); + } + + // Flag active plugins. + foreach ( $active_plugins_basenames as $basename ) { + if ( isset( $all_plugins[ $basename ] ) ) { + $all_plugins[ $basename ]['is_active'] = true; + } + } + + return $all_plugins; + } + + + /** + * Cached result of get_site_transient( 'update_plugins' ) + * + * @author Vova Feldman (@svovaf) + * @since 1.1.8 + * + * @var object + */ + private static $_plugins_info; + + /** + * Helper function to get specified plugin's slug. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.8 + * + * @param $basename + * + * @return string + */ + private static function get_plugin_slug( $basename ) { + if ( ! isset( self::$_plugins_info ) ) { + self::$_plugins_info = get_site_transient( 'update_plugins' ); + } + + $slug = ''; + + if ( is_object( self::$_plugins_info ) ) { + if ( isset( self::$_plugins_info->no_update ) && + isset( self::$_plugins_info->no_update[ $basename ] ) && + ! empty( self::$_plugins_info->no_update[ $basename ]->slug ) + ) { + $slug = self::$_plugins_info->no_update[ $basename ]->slug; + } else if ( isset( self::$_plugins_info->response ) && + isset( self::$_plugins_info->response[ $basename ] ) && + ! empty( self::$_plugins_info->response[ $basename ]->slug ) + ) { + $slug = self::$_plugins_info->response[ $basename ]->slug; + } + } + + if ( empty( $slug ) ) { + // Try to find slug from FS data. + $slug = self::find_slug_by_basename( $basename ); + } + + if ( empty( $slug ) ) { + // Fallback to plugin's folder name. + $slug = dirname( $basename ); + } + + return $slug; + } + + private static $_statics_loaded = false; + + /** + * Load static resources. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.1 + */ + private static function _load_required_static() { + if ( self::$_statics_loaded ) { + return; + } + + self::$_static_logger = FS_Logger::get_logger( WP_FS__SLUG, WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); + + self::$_static_logger->entrance(); + + self::$_accounts = FS_Option_Manager::get_manager( WP_FS__ACCOUNTS_OPTION_NAME, true ); + + self::$_global_admin_notices = FS_Admin_Notice_Manager::instance( 'global' ); + + // Configure which Freemius powered plugins should be auto updated. +// add_filter( 'auto_update_plugin', '_include_plugins_in_auto_update', 10, 2 ); + + add_action( 'admin_menu', array( 'Freemius', 'add_debug_page' ) ); + + add_action( "wp_ajax_fs_toggle_debug_mode", array( 'Freemius', '_toggle_debug_mode' ) ); + + self::$_statics_loaded = true; + } + + #region Debugging ------------------------------------------------------------------ + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.8 + */ + static function add_debug_page() { + if ( ! current_user_can( 'activate_plugins' ) ) { + return; + } + + self::$_static_logger->entrance(); + + $title = sprintf( '%s [v.%s]', __fs( 'freemius-debug' ), WP_FS__SDK_VERSION ); + + if ( WP_FS__DEV_MODE ) { + // Add top-level debug menu item. + $hook = add_menu_page( + $title, + $title, + 'manage_options', + 'freemius', + array( 'Freemius', '_debug_page_render' ) + ); + } else { + // Add hidden debug page. + $hook = add_submenu_page( + null, + $title, + $title, + 'manage_options', + 'freemius', + array( 'Freemius', '_debug_page_render' ) + ); + } + + add_action( "load-$hook", array( 'Freemius', '_debug_page_actions' ) ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.7.3 + */ + static function _toggle_debug_mode() { + if ( in_array( $_POST['is_on'], array( 0, 1 ) ) ) { + update_option( 'fs_debug_mode', $_POST['is_on'] ); + } + + exit; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.8 + */ + static function _debug_page_actions() { + self::_clean_admin_content_section(); + + if ( fs_request_is_action( 'restart_freemius' ) ) { + check_admin_referer( 'restart_freemius' ); + + self::$_accounts->clear( true ); + + + return; + } + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.8 + */ + static function _debug_page_render() { + self::$_static_logger->entrance(); + + $sites = self::get_all_sites(); + $users = self::get_all_users(); + $addons = self::get_all_addons(); + $account_addons = self::get_all_account_addons(); + +// $plans = self::get_all_plans(); +// $licenses = self::get_all_licenses(); + + $vars = array( + 'sites' => $sites, + 'users' => $users, + 'addons' => $addons, + 'account_addons' => $account_addons, + ); + + fs_enqueue_local_style( 'fs_account', '/admin/debug.css' ); + fs_require_once_template( 'debug.php', $vars ); + } + + #endregion ------------------------------------------------------------------ + + #region Connectivity Issues ------------------------------------------------------------------ + + /** + * Check if Freemius should be turned on for the current plugin install. + * + * Note: + * $this->_is_on is updated in has_api_connectivity() + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @return bool + */ + function is_on() { + self::$_static_logger->entrance(); + + if ( isset( $this->_is_on ) ) { + return $this->_is_on; + } + + // If already installed or pending then sure it's on :) + if ( $this->is_registered() || $this->is_pending_activation() ) { + $this->_is_on = true; + + return true; + } + + return false; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.7.3 + * + * @param bool $flush_if_no_connectivity + * + * @return bool + */ + private function should_run_connectivity_test( $flush_if_no_connectivity = false ) { + if ( ! isset( $this->_storage->connectivity_test ) ) { + // Connectivity test was never executed, or cache was cleared. + return true; + } + + if ( WP_FS__PING_API_ON_IP_OR_HOST_CHANGES ) { + if ( WP_FS__IS_HTTP_REQUEST ) { + if ( $_SERVER['HTTP_HOST'] != $this->_storage->connectivity_test['host'] ) { + // Domain changed. + return true; + } + + if ( WP_FS__REMOTE_ADDR != $this->_storage->connectivity_test['server_ip'] ) { + // Server IP changed. + return true; + } + } + } + + if ( $this->_storage->connectivity_test['is_connected'] && + $this->_storage->connectivity_test['is_active'] + ) { + // API connected and Freemius is active - no need to run connectivity check. + return false; + } + + if ( $flush_if_no_connectivity ) { + /** + * If explicitly asked to flush when no connectivity - do it only + * if at least 10 sec passed from the last API connectivity test. + */ + return ( isset( $this->_storage->connectivity_test['timestamp'] ) && + ( WP_FS__SCRIPT_START_TIME - $this->_storage->connectivity_test['timestamp'] ) > 10 ); + } + + /** + * @since 1.1.7 Don't check for connectivity on plugin downgrade. + */ + $version = $this->get_plugin_version(); + if ( version_compare( $version, $this->_storage->connectivity_test['version'], '>' ) ) { + // If it's a plugin version upgrade and Freemius is off or no connectivity, run connectivity test. + return true; + } + + return false; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.7.4 + * + * @return object|false + */ + private function ping() { + if ( WP_FS__SIMULATE_NO_API_CONNECTIVITY ) { + return false; + } + + $version = $this->get_plugin_version(); + + $is_update = $this->apply_filters( 'is_plugin_update', $this->is_plugin_update() ); + + return $this->get_api_plugin_scope()->ping( + $this->get_anonymous_id(), + array( + 'is_update' => json_encode( $is_update ), + 'version' => $version, + 'sdk' => $this->version, + 'is_admin' => json_encode( is_admin() ), + 'is_ajax' => json_encode( $this->is_ajax() ), + 'is_cron' => json_encode( $this->is_cron() ), + 'is_http' => json_encode( WP_FS__IS_HTTP_REQUEST ), + ) + ); + } + + /** + * Check if there's any connectivity issue to Freemius API. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @param bool $flush_if_no_connectivity + * + * @return bool + */ + function has_api_connectivity( $flush_if_no_connectivity = false ) { + $this->_logger->entrance(); + + if ( isset( $this->_has_api_connection ) && ( $this->_has_api_connection || ! $flush_if_no_connectivity ) ) { + return $this->_has_api_connection; + } + + if ( WP_FS__SIMULATE_NO_API_CONNECTIVITY && + isset( $this->_storage->connectivity_test ) && + true === $this->_storage->connectivity_test['is_connected'] + ) { + unset( $this->_storage->connectivity_test ); + } + + if ( ! $this->should_run_connectivity_test( $flush_if_no_connectivity ) ) { + $this->_has_api_connection = $this->_storage->connectivity_test['is_connected']; + /** + * @since 1.1.6 During dev mode, if there's connectivity - turn Freemius on regardless the configuration. + */ + $this->_is_on = $this->_storage->connectivity_test['is_active'] || + ( WP_FS__DEV_MODE && $this->_has_api_connection && ! WP_FS__SIMULATE_FREEMIUS_OFF ); + + return $this->_has_api_connection; + } + + $pong = $this->ping(); + $is_connected = $this->get_api_plugin_scope()->is_valid_ping( $pong ); + + if ( ! $is_connected ) { + // API failure. + $this->_add_connectivity_issue_message( $pong ); + } + + $this->store_connectivity_info( $pong, $is_connected ); + + return $this->_has_api_connection; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.7.4 + * + * @param object $pong + * @param bool $is_connected + */ + private function store_connectivity_info( $pong, $is_connected ) { + $this->_logger->entrance(); + + $version = $this->get_plugin_version(); + + if ( ! $is_connected || WP_FS__SIMULATE_FREEMIUS_OFF ) { + $is_active = false; + } else { + $is_active = ( isset( $pong->is_active ) && true == $pong->is_active ); + } + + $is_active = $this->apply_filters( + 'is_on', + $is_active, + $this->is_plugin_update(), + $version + ); + + $this->_storage->connectivity_test = array( + 'is_connected' => $is_connected, + 'host' => $_SERVER['HTTP_HOST'], + 'server_ip' => WP_FS__REMOTE_ADDR, + 'is_active' => $is_active, + 'timestamp' => WP_FS__SCRIPT_START_TIME, + // Last version with connectivity attempt. + 'version' => $version, + ); + + $this->_has_api_connection = $is_connected; + $this->_is_on = $is_active || ( WP_FS__DEV_MODE && $is_connected && ! WP_FS__SIMULATE_FREEMIUS_OFF ); + } + + /** + * Force turning Freemius on. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.8.1 + * + * @return bool TRUE if successfully turned on. + */ + private function turn_on() { + $this->_logger->entrance(); + + if ($this->is_on() || ! isset( $this->_storage->connectivity_test['is_active'] ) ) { + return false; + } + + $updated_connectivity = $this->_storage->connectivity_test; + $updated_connectivity['is_active'] = true; + $updated_connectivity['timestamp'] = WP_FS__SCRIPT_START_TIME; + $this->_storage->connectivity_test = $updated_connectivity; + + $this->_is_on = true; + + return true; + } + + /** + * Anonymous and unique site identifier (Hash). + * + * @author Vova Feldman (@svovaf) + * @since 1.1.0 + * + * @return string + */ + function get_anonymous_id() { + $unique_id = self::$_accounts->get_option( 'unique_id' ); + + if ( empty( $unique_id ) || ! is_string( $unique_id ) ) { + $key = get_site_url(); + + // If localhost, assign microtime instead of domain. + if ( WP_FS__IS_LOCALHOST || + false !== strpos( $key, 'localhost' ) || + false === strpos( $key, '.' ) + ) { + $key = microtime(); + } + + $unique_id = md5( $key ); + + self::$_accounts->set_option( 'unique_id', $unique_id, true ); + } + + $this->_logger->departure( $unique_id ); + + return $unique_id; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.7.4 + * + * @return \WP_User + */ + static function _get_current_wp_user() { + self::require_pluggable_essentials(); + + return wp_get_current_user(); + } + + /** + * Generate API connectivity issue message. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @param mixed $api_result + * @param bool $is_first_failure + */ + function _add_connectivity_issue_message( $api_result, $is_first_failure = true ) { + if ( $this->_enable_anonymous ) { + // Don't add message if can run anonymously. + return; + } + + if ( ! function_exists( 'wp_nonce_url' ) ) { + require_once( ABSPATH . 'wp-includes/functions.php' ); + } + + $current_user = self::_get_current_wp_user(); +// $admin_email = get_option( 'admin_email' ); + $admin_email = $current_user->user_email; + + $message = false; + if ( is_object( $api_result ) && + isset( $api_result->error ) && + isset( $api_result->error->code ) + ) { + switch ( $api_result->error->code ) { + case 'curl_missing': + $message = sprintf( + __fs( 'x-requires-access-to-api', $this->_slug ) . ' ' . + __fs( 'curl-missing-message', $this->_slug ) . ' ' . + ' %s', + '<b>' . $this->get_plugin_name() . '</b>', + sprintf( + '<ol id="fs_firewall_issue_options"><li>%s</li><li>%s</li><li>%s</li></ol>', + sprintf( + '<a class="fs-resolve" data-type="curl" href="#"><b>%s</b></a>%s', + __fs( 'curl-missing-no-clue-title', $this->_slug ), + ' - ' . sprintf( + __fs( 'curl-missing-no-clue-desc', $this->_slug ), + '<a href="mailto:' . $admin_email . '">' . $admin_email . '</a>' + ) + ), + sprintf( + '<b>%s</b> - %s', + __fs( 'sysadmin-title', $this->_slug ), + __fs( 'curl-missing-sysadmin-desc', $this->_slug ) + ), + sprintf( + '<a href="%s"><b>%s</b></a>%s', + wp_nonce_url( 'plugins.php?action=deactivate&plugin=' . $this->_plugin_basename . '&plugin_status=' . 'all' . '&paged=' . '1' . '&s=' . '', 'deactivate-plugin_' . $this->_plugin_basename ), + __fs( 'deactivate-plugin-title', $this->_slug ), + ' - ' . __fs( 'deactivate-plugin-desc', 'freemius', $this->_slug ) + ) + ) + ); + break; + case 'cloudflare_ddos_protection': + $message = sprintf( + __fs( 'x-requires-access-to-api', $this->_slug ) . ' ' . + __fs( 'cloudflare-blocks-connection-message', $this->_slug ) . ' ' . + __fs( 'happy-to-resolve-issue-asap', $this->_slug ) . + ' %s', + '<b>' . $this->get_plugin_name() . '</b>', + sprintf( + '<ol id="fs_firewall_issue_options"><li>%s</li><li>%s</li><li>%s</li></ol>', + sprintf( + '<a class="fs-resolve" data-type="cloudflare" href="#"><b>%s</b></a>%s', + __fs( 'fix-issue-title', $this->_slug ), + ' - ' . sprintf( + __fs( 'fix-issue-desc', $this->_slug ), + '<a href="mailto:' . $admin_email . '">' . $admin_email . '</a>' + ) + ), + sprintf( + '<a href="%s" target="_blank"><b>%s</b></a>%s', + sprintf( 'https://wordpress.org/plugins/%s/download/', $this->_slug ), + __fs( 'install-previous-title', $this->_slug ), + ' - ' . __fs( 'install-previous-desc', $this->_slug ) + ), + sprintf( + '<a href="%s"><b>%s</b></a>%s', + wp_nonce_url( 'plugins.php?action=deactivate&plugin=' . $this->_plugin_basename . '&plugin_status=' . 'all' . '&paged=' . '1' . '&s=' . '', 'deactivate-plugin_' . $this->_plugin_basename ), + __fs( 'deactivate-plugin-title', $this->_slug ), + ' - ' . __fs( 'deactivate-plugin-desc', $this->_slug ) + ) + ) + ); + break; + case 'squid_cache_block': + $message = sprintf( + __fs( 'x-requires-access-to-api', $this->_slug ) . ' ' . + __fs( 'squid-blocks-connection-message', $this->_slug ) . + ' %s', + '<b>' . $this->get_plugin_name() . '</b>', + sprintf( + '<ol id="fs_firewall_issue_options"><li>%s</li><li>%s</li><li>%s</li></ol>', + sprintf( + '<a class="fs-resolve" data-type="squid" href="#"><b>%s</b></a>%s', + __fs( 'squid-no-clue-title', $this->_slug ), + ' - ' . sprintf( + __fs( 'squid-no-clue-desc', $this->_slug ), + '<a href="mailto:' . $admin_email . '">' . $admin_email . '</a>' + ) + ), + sprintf( + '<b>%s</b> - %s', + __fs( 'sysadmin-title', $this->_slug ), + sprintf( + __fs( 'squid-sysadmin-desc', $this->_slug ), + // We use a filter since the plugin might require additional API connectivity. + '<b>' . implode( ', ', $this->apply_filters( 'api_domains', array( 'api.freemius.com' ) ) ) . '</b>' ) + ), + sprintf( + '<a href="%s"><b>%s</b></a>%s', + wp_nonce_url( 'plugins.php?action=deactivate&plugin=' . $this->_plugin_basename . '&plugin_status=' . 'all' . '&paged=' . '1' . '&s=' . '', 'deactivate-plugin_' . $this->_plugin_basename ), + __fs( 'deactivate-plugin-title', $this->_slug ), + ' - ' . __fs( 'deactivate-plugin-desc', $this->_slug ) + ) + ) + ); + break; +// default: +// $message = __fs( 'connectivity-test-fails-message', $this->_slug ); +// break; + } + } + + $message_id = 'failed_connect_api'; + $type = 'error'; + + if ( false === $message ) { + if ( $is_first_failure ) { + // First attempt failed. + $message = sprintf( + __fs( 'x-requires-access-to-api', $this->_slug ) . ' ' . + __fs( 'connectivity-test-fails-message', $this->_slug ) . ' ' . + __fs( 'connectivity-test-maybe-temporary', $this->_slug ) . '<br><br>' . + '%s', + '<b>' . $this->get_plugin_name() . '</b>', + sprintf( + '<div id="fs_firewall_issue_options">%s %s</div>', + sprintf( + '<a class="button button-primary fs-resolve" data-type="retry_ping" href="#">%s</a>', + __fs( 'yes-do-your-thing', $this->_slug ) + ), + sprintf( + '<a href="%s" class="button">%s</a>', + wp_nonce_url( 'plugins.php?action=deactivate&plugin=' . $this->_plugin_basename . '&plugin_status=' . 'all' . '&paged=' . '1' . '&s=' . '', 'deactivate-plugin_' . $this->_plugin_basename ), + __fs( 'no-deactivate', $this->_slug ) + ) + ) + ); + + $message_id = 'failed_connect_api_first'; + $type = 'promotion'; + } else { + // Second connectivity attempt failed. + $message = sprintf( + __fs( 'x-requires-access-to-api', $this->_slug ) . ' ' . + __fs( 'connectivity-test-fails-message', $this->_slug ) . ' ' . + __fs( 'happy-to-resolve-issue-asap', $this->_slug ) . + ' %s', + '<b>' . $this->get_plugin_name() . '</b>', + sprintf( + '<ol id="fs_firewall_issue_options"><li>%s</li><li>%s</li><li>%s</li></ol>', + sprintf( + '<a class="fs-resolve" data-type="general" href="#"><b>%s</b></a>%s', + __fs( 'fix-issue-title', $this->_slug ), + ' - ' . sprintf( + __fs( 'fix-issue-desc', $this->_slug ), + '<a href="mailto:' . $admin_email . '">' . $admin_email . '</a>' + ) + ), + sprintf( + '<a href="%s" target="_blank"><b>%s</b></a>%s', + sprintf( 'https://wordpress.org/plugins/%s/download/', $this->_slug ), + __fs( 'install-previous-title', $this->_slug ), + ' - ' . __fs( 'install-previous-desc', $this->_slug ) + ), + sprintf( + '<a href="%s"><b>%s</b></a>%s', + wp_nonce_url( 'plugins.php?action=deactivate&plugin=' . $this->_plugin_basename . '&plugin_status=' . 'all' . '&paged=' . '1' . '&s=' . '', 'deactivate-plugin_' . $this->_plugin_basename ), + __fs( 'deactivate-plugin-title', $this->_slug ), + ' - ' . __fs( 'deactivate-plugin-desc', $this->_slug ) + ) + ) + ); + } + } + + $this->_admin_notices->add_sticky( + $message, + $message_id, + __fs( 'oops', $this->_slug ) . '...', + $type + ); + } + + /** + * Handle user request to resolve connectivity issue. + * This method will send an email to Freemius API technical staff for resolution. + * The email will contain server's info and installed plugins (might be caching issue). + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + */ + function _email_about_firewall_issue() { + $this->_admin_notices->remove_sticky( 'failed_connect_api' ); + + $pong = $this->ping(); + + $is_connected = $this->get_api_plugin_scope()->is_valid_ping( $pong ); + + if ( $is_connected ) { + $this->store_connectivity_info( $pong, $is_connected ); + + echo $this->get_after_plugin_activation_redirect_url(); + exit; + } + + $current_user = self::_get_current_wp_user(); + $admin_email = $current_user->user_email; + + $error_type = fs_request_get( 'error_type', 'general' ); + + switch ( $error_type ) { + case 'squid': + $title = 'Squid ACL Blocking Issue'; + break; + case 'cloudflare': + $title = 'CloudFlare Blocking Issue'; + break; + default: + $title = 'API Connectivity Issue'; + break; + } + + $custom_email_sections = array(); + + if ( 'squid' === $error_type ) { + // Override the 'Site' email section. + $custom_email_sections['site'] = array( + 'rows' => array( + 'hosting_company' => array( 'Hosting Company', fs_request_get( 'hosting_company' ) ) + ) + ); + } + + // Add 'API Error' custom email section. + $custom_email_sections['api_error'] = array( + 'title' => 'API Error', + 'rows' => array( + 'ping' => array( is_string( $pong ) ? htmlentities( $pong ) : json_encode( $pong ) ) + ) + ); + + // Add PHP info for deeper investigation. + ob_start(); + phpinfo(); + $php_info = ob_get_clean(); + $custom_email_sections['php_info'] = array( + 'title' => 'PHP Info', + 'rows' => array( + 'info' => array( $php_info ) + ) + ); + + // Send email with technical details to resolve CloudFlare's firewall unnecessary protection. + $this->send_email( + 'api@freemius.com', // recipient + $title . ' [' . $this->get_plugin_name() . ']', // subject + $custom_email_sections, + array( "Reply-To: $admin_email <$admin_email>" ) // headers + ); + + $this->_admin_notices->add_sticky( + sprintf( + __fs( 'fix-request-sent-message', $this->_slug ), + '<a href="mailto:' . $admin_email . '">' . $admin_email . '</a>' + ), + 'server_details_sent' + ); + + // Action was taken, tell that API connectivity troubleshooting should be off now. + + echo "1"; + exit; + } + + /** + * Handle connectivity test retry approved by the user. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.7.4 + */ + function _retry_connectivity_test() { + $this->_admin_notices->remove_sticky( 'failed_connect_api_first' ); + + $pong = $this->ping(); + + $is_connected = $this->get_api_plugin_scope()->is_valid_ping( $pong ); + + if ( $is_connected ) { + $this->store_connectivity_info( $pong, $is_connected ); + + echo $this->get_after_plugin_activation_redirect_url(); + } else { + // Add connectivity issue message after 2nd failed attempt. + $this->_add_connectivity_issue_message( $pong, false ); + + echo "1"; + } + + exit; + } + + static function _add_firewall_issues_javascript() { + $params = array(); + fs_require_once_template( 'firewall-issues-js.php', $params ); + } + + #endregion Connectivity Issues ------------------------------------------------------------------ + + #region Email ------------------------------------------------------------------ + + /** + * Generates and sends an HTML email with customizable sections. + * + * @author Leo Fajardo (@leorw) + * @since 1.1.2 + * + * @param string $to_address + * @param string $subject + * @param array $sections + * @param array $headers + * + * @return bool Whether the email contents were sent successfully. + */ + private function send_email( + $to_address, + $subject, + $sections = array(), + $headers = array() + ) { + $default_sections = $this->get_email_sections(); + + // Insert new sections or replace the default email sections. + if ( is_array( $sections ) && ! empty( $sections ) ) { + foreach ( $sections as $section_id => $custom_section ) { + if ( ! isset( $default_sections[ $section_id ] ) ) { + // If the section does not exist, add it. + $default_sections[ $section_id ] = $custom_section; + } else { + // If the section already exists, override it. + $current_section = $default_sections[ $section_id ]; + + // Replace the current section's title if a custom section title exists. + if ( isset( $custom_section['title'] ) ) { + $current_section['title'] = $custom_section['title']; + } + + // Insert new rows under the current section or replace the default rows. + if ( isset( $custom_section['rows'] ) && is_array( $custom_section['rows'] ) && ! empty( $custom_section['rows'] ) ) { + foreach ( $custom_section['rows'] as $row_id => $row ) { + $current_section['rows'][ $row_id ] = $row; + } + } + + $default_sections[ $section_id ] = $current_section; + } + } + } + + $vars = array( 'sections' => $default_sections ); + $message = fs_get_template( 'email.php', $vars ); + + // Set the type of email to HTML. + $headers[] = 'Content-type: text/html'; + + $header_string = implode( "\r\n", $headers ); + + return wp_mail( + $to_address, + $subject, + $message, + $header_string + ); + } + + /** + * Generates the data for the sections of the email content. + * + * @author Leo Fajardo (@leorw) + * @since 1.1.2 + * + * @return array + */ + private function get_email_sections() { + // Retrieve the current user's information so that we can get the user's email, first name, and last name below. + $current_user = self::_get_current_wp_user(); + + // Retrieve the cURL version information so that we can get the version number below. + $curl_version_information = curl_version(); + + $active_plugin = self::get_active_plugins(); + + // Generate the list of active plugins separated by new line. + $active_plugin_string = ''; + foreach ( $active_plugin as $plugin ) { + $active_plugin_string .= sprintf( + '<a href="%s">%s</a> [v%s]<br>', + $plugin['PluginURI'], + $plugin['Name'], + $plugin['Version'] + ); + } + + $server_ip = WP_FS__REMOTE_ADDR; + + // Generate the default email sections. + $sections = array( + 'sdk' => array( + 'title' => 'SDK', + 'rows' => array( + 'fs_version' => array( 'FS Version', $this->version ), + 'curl_version' => array( 'cURL Version', $curl_version_information['version'] ) + ) + ), + 'plugin' => array( + 'title' => 'Plugin', + 'rows' => array( + 'name' => array( 'Name', $this->get_plugin_name() ), + 'version' => array( 'Version', $this->get_plugin_version() ) + ) + ), + 'site' => array( + 'title' => 'Site', + 'rows' => array( + 'unique_id' => array( 'Address', $this->get_anonymous_id() ), + 'address' => array( 'Address', site_url() ), + 'host' => array( + 'HTTP_HOST', + ( ! empty( $_SERVER['HTTP_HOST'] ) ? $_SERVER['HTTP_HOST'] : '' ) + ), + 'server_addr' => array( + 'SERVER_ADDR', + '<a href="http://www.projecthoneypot.org/ip_' . $server_ip . '">' . $server_ip . '</a>' + ) + ) + ), + 'user' => array( + 'title' => 'User', + 'rows' => array( + 'email' => array( 'Email', $current_user->user_email ), + 'first' => array( 'First', $current_user->user_firstname ), + 'last' => array( 'Last', $current_user->user_lastname ) + ) + ), + 'plugins' => array( + 'title' => 'Plugins', + 'rows' => array( + 'active_plugins' => array( 'Active Plugins', $active_plugin_string ) + ) + ), + ); + + // Allow the sections to be modified by other code. + $sections = $this->apply_filters( 'email_template_sections', $sections ); + + return $sections; + } + + #endregion Email ------------------------------------------------------------------ + + #region Initialization ------------------------------------------------------------------ + + /** + * Init plugin's Freemius instance. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.1 + * + * @param number $id + * @param string $public_key + * @param bool $is_live + * @param bool $is_premium + */ + function init( $id, $public_key, $is_live = true, $is_premium = true ) { + $this->_logger->entrance(); + + $this->dynamic_init( array( + 'id' => $id, + 'public_key' => $public_key, + 'is_live' => $is_live, + 'is_premium' => $is_premium, + ) ); + } + + /** + * Dynamic initiator, originally created to support initiation + * with parent_id for add-ons. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @param array $plugin_info + * + * @throws Freemius_Exception + */ + function dynamic_init( array $plugin_info ) { + $this->_logger->entrance(); + + $this->parse_settings( $plugin_info ); + + if ( $this->should_stop_execution() ) { + return; + } + + if ( ! $this->is_registered() ) { + if ( $this->is_anonymous() ) { + // If user skipped, no need to test connectivity. + $this->_has_api_connection = true; + $this->_is_on = true; + } else { + if ( ! $this->has_api_connectivity() ) { + if ( $this->_admin_notices->has_sticky( 'failed_connect_api_first' ) || + $this->_admin_notices->has_sticky( 'failed_connect_api' ) + ) { + if ( ! $this->_enable_anonymous ) { + // If anonymous mode is disabled, add firewall admin-notice message. + add_action( 'admin_footer', array( 'Freemius', '_add_firewall_issues_javascript' ) ); + + add_action( "wp_ajax_{$this->_slug}_resolve_firewall_issues", array( + &$this, + '_email_about_firewall_issue' + ) ); + + add_action( "wp_ajax_{$this->_slug}_retry_connectivity_test", array( + &$this, + '_retry_connectivity_test' + ) ); + } + } + + return; + } else { + $this->_admin_notices->remove_sticky( array( + 'failed_connect_api_first', + 'failed_connect_api', + ) ); + + if ( $this->_anonymous_mode ) { + // Simulate anonymous mode. + $this->_is_anonymous = true; + } + } + } + + // Check if Freemius is on for the current plugin. + // This MUST be executed after all the plugin variables has been loaded. + if ( ! $this->is_on() ) { + return; + } + } + + if ( $this->has_api_connectivity() && $this->is_user_in_admin() ) { + /** + * Schedule daily data sync cron if: + * + * 1. User opted-in (for tracking). + * 2. If plugin has add-ons (update add-ons data). + * 3. If skipped, but later upgraded (opted-in via upgrade). + * + * @author Vova Feldman (@svovaf) + * @since 1.1.7.3 + * + */ + if ( $this->is_registered() || + ( ! $this->is_activation_mode() && $this->_has_addons ) + ) { + + $this->hook_callback_to_sync_cron(); + + if ( ! $this->is_sync_cron_on() ) { + $this->schedule_sync_cron(); + } + } + + /** + * Check if requested for manual blocking background sync. + */ + if ( fs_request_has( 'background_sync' ) ) { + $this->run_manual_sync(); + } + } + + if ( $this->is_registered() ) { + $this->hook_callback_to_install_sync(); + } + + if ( $this->is_addon() ) { + if ( $this->is_parent_plugin_installed() ) { + // Link to parent FS. + $this->_parent = self::get_instance_by_id( $this->_plugin->parent_plugin_id ); + + // Get parent plugin reference. + $this->_parent_plugin = $this->_parent->get_plugin(); + } + } + + if ( $this->is_user_in_admin() ) { + global $pagenow; + if ( 'plugins.php' === $pagenow ) { + $this->hook_plugin_action_links(); + } + + if ( $this->is_addon() ) { + if ( ! $this->is_parent_plugin_installed() ) { + $parent_name = $this->get_option( $plugin_info, 'parent_name', null ); + + if ( isset( $plugin_info['parent'] ) ) { + $parent_name = $this->get_option( $plugin_info['parent'], 'name', null ); + } + + $this->_admin_notices->add( + ( ! empty( $parent_name ) ? + sprintf( __fs( 'addon-x-cannot-run-without-y', $this->_slug ), $this->get_plugin_name(), $parent_name ) : + sprintf( __fs( 'addon-x-cannot-run-without-parent', $this->_slug ), $this->get_plugin_name() ) + ), + __fs( 'oops', $this->_slug ) . '...', + 'error' + ); + + return; + } else { + if ( $this->_parent->is_registered() && ! $this->is_registered() ) { + // If parent plugin activated, automatically install add-on for the user. + $this->_activate_addon_account( $this->_parent ); + } + + // @todo This should be only executed on activation. It should be migrated to register_activation_hook() together with other activation related logic. + if ( $this->is_premium() ) { + // Remove add-on download admin-notice. + $this->_parent->_admin_notices->remove_sticky( 'addon_plan_upgraded_' . $this->_slug ); + } + + $this->deactivate_premium_only_addon_without_license(); + } + } else { + add_action( 'admin_init', array( &$this, '_admin_init_action' ) ); + + if ( $this->has_addons() && + 'plugin-information' === fs_request_get( 'tab', false ) && + $this->get_id() == fs_request_get( 'parent_plugin_id', false ) + ) { + require_once WP_FS__DIR_INCLUDES . '/fs-plugin-info-dialog.php'; + + new FS_Plugin_Info_Dialog( $this ); + } + } + + if ( $this->is_premium() ) { + new FS_Plugin_Updater( $this ); + } + +// if ( $this->is_registered() || +// $this->is_anonymous() || +// $this->is_pending_activation() +// ) { +// $this->_init_admin(); +// } + } + + $this->do_action( 'initiated' ); + + if ( ! $this->is_addon() ) { + if ( $this->is_registered() ) { + // Fix for upgrade from versions < 1.0.9. + if ( ! isset( $this->_storage->activation_timestamp ) ) { + $this->_storage->activation_timestamp = WP_FS__SCRIPT_START_TIME; + } + if ( $this->_storage->prev_is_premium !== $this->_plugin->is_premium ) { + if ( isset( $this->_storage->prev_is_premium ) ) { + add_action( is_admin() ? 'admin_init' : 'init', array( + &$this, + '_plugin_code_type_changed' + ) ); + } else { + // Set for code type for the first time. + $this->_storage->prev_is_premium = $this->_plugin->is_premium; + } + } + + $this->do_action( 'after_init_plugin_registered' ); + } else if ( $this->is_anonymous() ) { + $this->do_action( 'after_init_plugin_anonymous' ); + } else if ( $this->is_pending_activation() ) { + $this->do_action( 'after_init_plugin_pending_activations' ); + } + } else { + if ( $this->is_registered() ) { + $this->do_action( 'after_init_addon_registered' ); + } else if ( $this->is_anonymous() ) { + $this->do_action( 'after_init_addon_anonymous' ); + } else if ( $this->is_pending_activation() ) { + $this->do_action( 'after_init_addon_pending_activations' ); + } + } + } + + /** + * Parse plugin's settings (as defined by the plugin dev). + * + * @author Vova Feldman (@svovaf) + * @since 1.1.7.3 + * + * @param array $plugin_info + * + * @throws \Freemius_Exception + */ + private function parse_settings( &$plugin_info ) { + $this->_logger->entrance(); + + $id = $this->get_numeric_option( $plugin_info, 'id', false ); + $public_key = $this->get_option( $plugin_info, 'public_key', false ); + $secret_key = $this->get_option( $plugin_info, 'secret_key', null ); + $parent_id = $this->get_numeric_option( $plugin_info, 'parent_id', null ); + $parent_name = $this->get_option( $plugin_info, 'parent_name', null ); + + if ( isset( $plugin_info['parent'] ) ) { + $parent_id = $this->get_numeric_option( $plugin_info['parent'], 'id', null ); +// $parent_slug = $this->get_option( $plugin_info['parent'], 'slug', null ); +// $parent_public_key = $this->get_option( $plugin_info['parent'], 'public_key', null ); + $parent_name = $this->get_option( $plugin_info['parent'], 'name', null ); + } + + if ( false === $id ) { + throw new Freemius_Exception( 'Plugin id parameter is not set.' ); + } + if ( false === $public_key ) { + throw new Freemius_Exception( 'Plugin public_key parameter is not set.' ); + } + + $plugin = ( $this->_plugin instanceof FS_Plugin ) ? + $this->_plugin : + new FS_Plugin(); + + $plugin->update( array( + 'id' => $id, + 'public_key' => $public_key, + 'slug' => $this->_slug, + 'parent_plugin_id' => $parent_id, + 'version' => $this->get_plugin_version(), + 'title' => $this->get_plugin_name(), + 'file' => $this->_plugin_basename, + 'is_premium' => $this->get_bool_option( $plugin_info, 'is_premium', true ), + 'is_live' => $this->get_bool_option( $plugin_info, 'is_live', true ), +// 'secret_key' => $secret_key, + ) ); + + if ( $plugin->is_updated() ) { + // Update plugin details. + $this->_plugin = FS_Plugin_Manager::instance( $this->_slug )->store( $plugin ); + } + // Set the secret key after storing the plugin, we don't want to store the key in the storage. + $this->_plugin->secret_key = $secret_key; + + if ( ! isset( $plugin_info['menu'] ) ) { + // Back compatibility to 1.1.2 + $plugin_info['menu'] = array( + 'slug' => isset( $plugin_info['menu_slug'] ) ? + $plugin_info['menu_slug'] : + $this->_slug + ); + } + + $this->_menu = FS_Admin_Menu_Manager::instance( $this->_slug ); + $this->_menu->init( $plugin_info['menu'], $this->is_addon() ); + + $this->_has_addons = $this->get_bool_option( $plugin_info, 'has_addons', false ); + $this->_has_paid_plans = $this->get_bool_option( $plugin_info, 'has_paid_plans', true ); + $this->_is_org_compliant = $this->get_bool_option( $plugin_info, 'is_org_compliant', true ); + $this->_enable_anonymous = $this->get_bool_option( $plugin_info, 'enable_anonymous', true ); + $this->_anonymous_mode = $this->get_bool_option( $plugin_info, 'anonymous_mode', false ); + $this->_permissions = $this->get_option( $plugin_info, 'permissions', array() ); + } + + /** + * @param string[] $options + * @param string $key + * @param mixed $default + * + * @return bool + */ + private function get_option( &$options, $key, $default = false ) { + return ! empty( $options[ $key ] ) ? $options[ $key ] : $default; + } + + private function get_bool_option( &$options, $key, $default = false ) { + return isset( $options[ $key ] ) && is_bool( $options[ $key ] ) ? $options[ $key ] : $default; + } + + private function get_numeric_option( &$options, $key, $default = false ) { + return isset( $options[ $key ] ) && is_numeric( $options[ $key ] ) ? $options[ $key ] : $default; + } + + /** + * Gate keeper. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.7.3 + * + * @return bool + */ + private function should_stop_execution() { + if ( $this->is_activation_mode() ) { + if ( ! is_admin() ) { + /** + * If in activation mode, don't execute Freemius outside of the + * admin dashboard. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.7.3 + */ + return true; + } + + if ( ! WP_FS__IS_HTTP_REQUEST ) { + /** + * If in activation and executed without HTTP context (e.g. CLI, Cronjob), + * then don't start Freemius. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.6.3 + * + * @link https://wordpress.org/support/topic/errors-in-the-freemius-class-when-running-in-wordpress-in-cli + */ + return true; + } + + if ( $this->is_cron() ) { + /** + * If in activation mode, don't execute Freemius during wp crons + * (wp crons have HTTP context - called as HTTP request). + * + * @author Vova Feldman (@svovaf) + * @since 1.1.7.3 + */ + return true; + } + + if ( $this->is_ajax() && + ! $this->_admin_notices->has_sticky( 'failed_connect_api_first' ) && + ! $this->_admin_notices->has_sticky( 'failed_connect_api' ) + ) { + /** + * During activation, if running in AJAX mode, unless there's a sticky + * connectivity issue notice, don't run Freemius. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.7.3 + */ + return true; + } + } + + return false; + } + + /** + * Handles plugin's code type change (free <--> premium). + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + */ + function _plugin_code_type_changed() { + // Schedule code type changes event. +// $this->sync_install(); + $this->schedule_install_sync(); + + if ( $this->is_premium() ) { + // Activated premium code. + $this->do_action( 'after_premium_version_activation' ); + + // Remove all sticky messages related to download of the premium version. + $this->_admin_notices->remove_sticky( array( + 'trial_started', + 'plan_upgraded', + 'plan_changed', + ) ); + + $this->_admin_notices->add_sticky( + __fs( 'premium-activated-message', $this->_slug ), + 'premium_activated', + __fs( 'woot', $this->_slug ) . '!' + ); + } else { + // Activated free code (after had the premium before). + $this->do_action( 'after_free_version_reactivation' ); + + if ( $this->is_paying() && ! $this->is_premium() ) { + $this->_admin_notices->add_sticky( + sprintf( + __fs( 'you-have-x-license', $this->_slug ), + $this->_site->plan->title + ) . ' ' . $this->_get_latest_download_link( sprintf( + __fs( 'download-x-version-now', $this->_slug ), + $this->_site->plan->title + ) ), + 'plan_upgraded', + __fs( 'yee-haw', $this->_slug ) . '!' + ); + } + } + + // Update is_premium of latest version. + $this->_storage->prev_is_premium = $this->_plugin->is_premium; + } + + #endregion Initialization ------------------------------------------------------------------ + + #region Add-ons ------------------------------------------------------------------------- + + /** + * Check if add-on installed and activated on site. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @param string|number $slug_or_id + * + * @return bool + */ + function is_addon_activated( $slug_or_id ) { + return self::has_instance( $slug_or_id ); + } + + /** + * Check if add-on was connected to install + * + * @author Vova Feldman (@svovaf) + * @since 1.1.7 + * + * @param string $slug + * + * @return bool + */ + function is_addon_connected( $slug ) { + $sites = self::get_all_sites(); + + if ( ! isset( $sites[ $slug ] ) ) { + return false; + } + + $site = $sites[ $slug ]; + + $plugin = FS_Plugin_Manager::instance( $slug )->get(); + + if ( $plugin->parent_plugin_id != $this->_plugin->id ) { + // The given slug do NOT belong to any of the plugin's add-ons. + return false; + } + + return ( is_object( $site ) && + is_numeric( $site->id ) && + is_numeric( $site->user_id ) && + is_object( $site->plan ) + ); + } + + /** + * Determines if add-on installed. + * + * NOTE: This is a heuristic and only works if the folder/file named as the slug. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @param string $slug + * + * @return bool + */ + function is_addon_installed( $slug ) { + return file_exists( fs_normalize_path( WP_PLUGIN_DIR . '/' . $this->get_addon_basename( $slug ) ) ); + } + + /** + * Get add-on basename. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @param string $slug + * + * @return string + */ + function get_addon_basename( $slug ) { + if ( $this->is_addon_activated( $slug ) ) { + self::instance( $slug )->get_plugin_basename(); + } + + $premium_basename = $slug . '-premium/' . $slug . '.php'; + + if ( file_exists( fs_normalize_path( WP_PLUGIN_DIR . '/' . $premium_basename ) ) ) { + return $premium_basename; + } + + $free_basename = $slug . '/' . $slug . '.php'; + + return $free_basename; + } + + /** + * Get installed add-ons instances. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @return Freemius[] + */ + function get_installed_addons() { + $installed_addons = array(); + foreach ( self::$_instances as $slug => $instance ) { + if ( $instance->is_addon() && is_object( $instance->_parent_plugin ) ) { + if ( $this->_plugin->id == $instance->_parent_plugin->id ) { + $installed_addons[] = $instance; + } + } + } + + return $installed_addons; + } + + /** + * Check if any add-ons of the plugin are installed. + * + * @author Leo Fajardo (@leorw) + * @since 1.1.1 + * + * @return bool + */ + function has_installed_addons() { + if ( ! $this->has_addons() ) { + return false; + } + + foreach ( self::$_instances as $slug => $instance ) { + if ( $instance->is_addon() && is_object( $instance->_parent_plugin ) ) { + if ( $this->_plugin->id == $instance->_parent_plugin->id ) { + return true; + } + } + } + + return false; + } + + /** + * Tell Freemius that the current plugin is an add-on. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @param number $parent_plugin_id The parent plugin ID + */ + function init_addon( $parent_plugin_id ) { + $this->_plugin->parent_plugin_id = $parent_plugin_id; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @return bool + */ + function is_addon() { + return isset( $this->_plugin->parent_plugin_id ) && is_numeric( $this->_plugin->parent_plugin_id ); + } + + /** + * Deactivate add-on if it's premium only and the user does't have a valid license. + * + * @param bool $is_after_trial_cancel + * + * @return bool If add-on was deactivated. + */ + private function deactivate_premium_only_addon_without_license( $is_after_trial_cancel = false ) { + if ( ! $this->has_free_plan() && + ! $this->has_features_enabled_license() && + ! $this->_has_premium_license() + ) { + deactivate_plugins( array( $this->_plugin_basename ), true ); + + $this->_parent->_admin_notices->add_sticky( + sprintf( + __fs( ( $is_after_trial_cancel ? + 'addon-trial-cancelled-message' : + 'addon-no-license-message' ), + $this->_parent->_slug + ), + '<b>' . $this->_plugin->title . '</b>' + ) . ' ' . sprintf( + '<a href="%s" aria-label="%s" class="button button-primary" style="margin-left: 10px; vertical-align: middle;">%s ➜</a>', + $this->_parent->addon_url( $this->_slug ), + esc_attr( sprintf( __fs( 'more-information-about-x', $this->_parent->_slug ), $this->_plugin->title ) ), + __fs( 'purchase-license', $this->_parent->_slug ) + ), + 'no_addon_license', + ( $is_after_trial_cancel ? '' : __fs( 'oops', $this->_parent->_slug ) . '...' ), + ( $is_after_trial_cancel ? 'success' : 'error' ) + ); + + return true; + } + + return false; + } + + #endregion ------------------------------------------------------------------ + + #region Sandbox ------------------------------------------------------------------ + + /** + * Set Freemius into sandbox mode for debugging. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + * + * @param string $secret_key + */ + function init_sandbox( $secret_key ) { + $this->_plugin->secret_key = $secret_key; + + // Update plugin details. + FS_Plugin_Manager::instance( $this->_slug )->update( $this->_plugin, true ); + } + + /** + * Check if running payments in sandbox mode. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + * + * @return bool + */ + function is_payments_sandbox() { + return ( ! $this->is_live() ) || isset( $this->_plugin->secret_key ); + } + + #endregion Sandbox ------------------------------------------------------------------ + + /** + * Check if running test vs. live plugin. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.5 + * + * @return bool + */ + function is_live() { + return $this->_plugin->is_live; + } + + /** + * Check if the user skipped connecting the account with Freemius. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + * + * @return bool + */ + function is_anonymous() { + if ( ! isset( $this->_is_anonymous ) ) { + if ( ! isset( $this->_storage->is_anonymous ) ) { + // Not skipped. + $this->_is_anonymous = false; + } else if ( is_bool( $this->_storage->is_anonymous ) ) { + // For back compatibility, since the variable was boolean before. + $this->_is_anonymous = $this->_storage->is_anonymous; + + // Upgrade stored data format to 1.1.3 format. + $this->set_anonymous_mode( $this->_storage->is_anonymous ); + } else { + // Version 1.1.3 and later. + $this->_is_anonymous = $this->_storage->is_anonymous['is']; + } + } + + return $this->_is_anonymous; + } + + /** + * Check if user connected his account and install pending email activation. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + * + * @return bool + */ + function is_pending_activation() { + return $this->_storage->get( 'is_pending_activation', false ); + } + + /** + * Check if plugin must be WordPress.org compliant. + * + * @since 1.0.7 + * + * @return bool + */ + function is_org_repo_compliant() { + return $this->_is_org_compliant; + } + + #region Daily Sync Cron ------------------------------------------------------------------ + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.7.3 + */ + private function run_manual_sync() { + $this->require_pluggable_essentials(); + + if ( ! current_user_can( 'activate_plugins' ) ) { + return; + } + + // Run manual sync. + $this->_sync_cron(); + + // Reschedule next cron to run 24 hours from now (performance optimization). + $this->clear_sync_cron(); + + $this->schedule_sync_cron( time() + WP_FS__TIME_24_HOURS_IN_SEC, false ); + } + + /** + * Data sync cron job. Replaces the background sync non blocking HTTP request + * that doesn't halt page loading. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.7.3 + */ + function _sync_cron() { + $this->_logger->entrance(); + + // Store the last time data sync was executed. + $this->_storage->sync_timestamp = time(); + + // Check if API is temporary down. + if ( FS_Api::is_temporary_down() ) { + return; + } + + // @todo Add logic that identifies API latency, and reschedule the next background sync randomly between 8-16 hours. + + if ( $this->is_registered() ) { + if ( $this->has_paid_plan() ) { + // Initiate background plan sync. + $this->_sync_license( true ); + + if ( $this->is_paying() ) { + // Check for premium plugin updates. + $this->_check_updates( true ); + } + } else { + // Sync install (only if something changed locally). + $this->sync_install(); + } + } + + if ( ! $this->is_addon() && $this->_has_addons ) { + // Sync add-ons collection. + $this->_sync_addons( true ); + } + } + + /** + * Check if sync was executed in the last $period of seconds. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.7.3 + * + * @param int $period In seconds + * + * @return bool + */ + private function is_sync_executed( $period = WP_FS__TIME_24_HOURS_IN_SEC ) { + if ( ! isset( $this->_storage->sync_timestamp ) ) { + return false; + } + + return ( $this->_storage->sync_timestamp > ( WP_FS__SCRIPT_START_TIME - $period ) ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.7.3 + * + * @return bool + */ + private function is_sync_cron_on() { + /** + * @var object $sync_cron_data + */ + $sync_cron_data = $this->_storage->get( 'sync_cron', null ); + + return ( ! is_null( $sync_cron_data ) && true === $sync_cron_data->on ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.7.3 + * + * @param int $start_at Defaults to now. + * @param bool $randomize_start If true, schedule first job randomly during the next 12 hours. Otherwise, + * schedule job to start right away. + */ + private function schedule_sync_cron( $start_at = WP_FS__SCRIPT_START_TIME, $randomize_start = true ) { + $this->_logger->entrance(); + + if ( $randomize_start ) { + // Schedule first sync with a random 12 hour time range from now. + $start_at += rand( 0, ( WP_FS__TIME_24_HOURS_IN_SEC / 2 ) ); + } + + // Schedule daily WP cron. + wp_schedule_event( + $start_at, + 'daily', + $this->get_action_tag( 'data_sync' ) + ); + + $this->_storage->store( 'sync_cron', (object) array( + 'version' => $this->get_plugin_version(), + 'sdk_version' => $this->version, + 'timestamp' => WP_FS__SCRIPT_START_TIME, + 'on' => true, + ) ); + } + + /** + * Add the actual sync function to the cron job hook. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.7.3 + */ + private function hook_callback_to_sync_cron() { + $this->add_action( 'data_sync', array( &$this, '_sync_cron' ) ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.7.3 + */ + private function clear_sync_cron() { + $this->_logger->entrance(); + + if ( ! $this->is_sync_cron_on() ) { + return; + } + + $this->_storage->remove( 'sync_cron' ); + + wp_clear_scheduled_hook( $this->get_action_tag( 'data_sync' ) ); + } + + /** + * Unix timestamp for next sync cron execution or false if not scheduled. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.7.3 + * + * @return int|false + */ + function next_sync_cron() { + $this->_logger->entrance(); + + if ( ! $this->is_sync_cron_on() ) { + return false; + } + + return wp_next_scheduled( $this->get_action_tag( 'data_sync' ) ); + } + + /** + * Unix timestamp for previous sync cron execution or false if never executed. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.7.3 + * + * @return int|false + */ + function last_sync_cron() { + $this->_logger->entrance(); + + return $this->_storage->get( 'sync_timestamp' ); + } + + #endregion Daily Sync Cron ------------------------------------------------------------------ + + #region Async Install Sync ------------------------------------------------------------------ + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.7.3 + * + * @return bool + */ + private function is_install_sync_scheduled() { + /** + * @var object $cron_data + */ + $cron_data = $this->_storage->get( 'install_sync_cron', null ); + + return ( ! is_null( $cron_data ) && true === $cron_data->on ); + } + + /** + * Instead of running blocking install sync event, execute non blocking scheduled wp-cron. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.7.3 + */ + private function schedule_install_sync() { + $this->_logger->entrance(); + + $this->clear_install_sync_cron(); + + // Schedule immediate install sync. + wp_schedule_single_event( + WP_FS__SCRIPT_START_TIME, + $this->get_action_tag( 'install_sync' ) + ); + + $this->_storage->store( 'install_sync_cron', (object) array( + 'version' => $this->get_plugin_version(), + 'sdk_version' => $this->version, + 'timestamp' => WP_FS__SCRIPT_START_TIME, + 'on' => true, + ) ); + } + + /** + * Unix timestamp for previous install sync cron execution or false if never executed. + * + * @todo There's some very strange bug that $this->_storage->install_sync_timestamp value is not being + * updated. But for sure the sync event is working. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.7.3 + * + * @return int|false + */ + function last_install_sync() { + $this->_logger->entrance(); + + return $this->_storage->get( 'install_sync_timestamp' ); + } + + /** + * Unix timestamp for next install sync cron execution or false if not scheduled. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.7.3 + * + * @return int|false + */ + function next_install_sync() { + $this->_logger->entrance(); + + if ( ! $this->is_install_sync_scheduled() ) { + return false; + } + + return wp_next_scheduled( $this->get_action_tag( 'install_sync' ) ); + } + + /** + * Add the actual install sync function to the cron job hook. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.7.3 + */ + private function hook_callback_to_install_sync() { + $this->add_action( 'install_sync', array( &$this, '_run_sync_install' ) ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.7.3 + */ + private function clear_install_sync_cron() { + $this->_logger->entrance(); + + if ( ! $this->is_install_sync_scheduled() ) { + return; + } + + $this->_storage->remove( 'install_sync_cron' ); + + wp_clear_scheduled_hook( $this->get_action_tag( 'install_sync' ) ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.7.3 + */ + public function _run_sync_install() { + $this->_logger->entrance(); + + // Update last install sync timestamp. + $this->_storage->install_sync_timestamp = time(); + + $this->sync_install( array(), true ); + } + + #endregion Async Install Sync ------------------------------------------------------------------ + + /** + * Show a notice that activation is currently pending. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + * + * @param bool|string $email + */ + function _add_pending_activation_notice( $email = false ) { + if ( ! is_string( $email ) ) { + $current_user = self::_get_current_wp_user(); + $email = $current_user->user_email; + } + + $this->_admin_notices->add_sticky( + sprintf( + __fs( 'pending-activation-message', $this->_slug ), + '<b>' . $this->get_plugin_name() . '</b>', + '<b>' . $email . '</b>' + ), + 'activation_pending', + 'Thanks!' + ); + } + + /** + * Check if currently in plugin activation. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.4 + * + * @return bool + */ + function is_plugin_activation() { + return get_option( "fs_{$this->_slug}_activated", false ); + } + + /** + * + * NOTE: admin_menu action executed before admin_init. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + */ + function _admin_init_action() { + /** + * Automatically redirect to connect/activation page after plugin activation. + * + * @since 1.1.7 Do NOT redirect to opt-in when running in network admin mode. + */ + if ( $this->is_plugin_activation() ) { + delete_option( "fs_{$this->_slug}_activated" ); + + if ( ! function_exists( 'is_network_admin' ) || ! is_network_admin() ) { + $this->_redirect_on_activation_hook(); + + return; + } + } + + if ( fs_request_is_action( $this->_slug . '_skip_activation' ) ) { + check_admin_referer( $this->_slug . '_skip_activation' ); + + $this->skip_connection(); + + if ( fs_redirect( $this->get_after_activation_url( 'after_skip_url' ) ) ) { + exit(); + } + } + + if ( ! $this->is_addon() && ! $this->is_registered() && ! $this->is_anonymous() ) { + if ( ! $this->is_pending_activation() ) { + if ( ! $this->_menu->is_activation_page() ) { + if ( $this->is_plugin_new_install() ) { + // Show notice for new plugin installations. + $this->_admin_notices->add( + sprintf( + __fs( 'you-are-step-away', $this->_slug ), + sprintf( '<b><a href="%s">%s</a></b>', + $this->get_activation_url(), + sprintf( __fs( 'activate-x-now', $this->_slug ), $this->get_plugin_name() ) + ) + ), + '', + 'update-nag' + ); + } else { + if ( ! isset( $this->_storage->sticky_optin_added ) ) { + $this->_storage->sticky_optin_added = true; + + // Show notice for new plugin installations. + $this->_admin_notices->add_sticky( + sprintf( + __fs( 'few-plugin-tweaks', $this->_slug ), + sprintf( '<b><a href="%s">%s</a></b>', + $this->get_activation_url(), + sprintf( __fs( 'optin-x-now', $this->_slug ), $this->get_plugin_name() ) + ) + ), + 'connect_account', + '', + 'update-nag' + ); + } + + if ( $this->has_filter( 'optin_pointer_element' ) ) { + // Don't show admin nag if plugin update. + wp_enqueue_script( 'wp-pointer' ); + wp_enqueue_style( 'wp-pointer' ); + + $this->_enqueue_connect_essentials(); + + add_action( 'admin_print_footer_scripts', array( + $this, + '_add_connect_pointer_script' + ) ); + } + + } + } + } + } + + $this->_add_upgrade_action_link(); + } + + /** + * Enqueue connect requires scripts and styles. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.4 + */ + function _enqueue_connect_essentials() { + wp_enqueue_script( 'jquery' ); + wp_enqueue_script( 'json2' ); + + fs_enqueue_local_script( 'postmessage', 'nojquery.ba-postmessage.min.js' ); + fs_enqueue_local_script( 'fs-postmessage', 'postmessage.js' ); + + fs_enqueue_local_style( 'fs_connect', '/admin/connect.css' ); + } + + /** + * Add connect / opt-in pointer. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.4 + */ + function _add_connect_pointer_script() { + $vars = array( 'slug' => $this->_slug ); + $pointer_content = fs_get_template( 'connect.php', $vars ); + ?> + <script type="text/javascript">// <![CDATA[ + jQuery(document).ready(function ($) { + if ('undefined' !== typeof(jQuery().pointer)) { + + var element = <?php echo $this->apply_filters('optin_pointer_element', '$("#non_existing_element");') ?>; + + if (element.length > 0) { + var optin = $(element).pointer($.extend(true, {}, { + content : <?php echo json_encode($pointer_content) ?>, + position : { + edge : 'left', + align: 'center' + }, + buttons : function () { + // Don't show pointer buttons. + return ''; + }, + pointerWidth: 482 + }, <?php echo $this->apply_filters('optin_pointer_options_json', '{}') ?>)); + + <?php + echo $this->apply_filters('optin_pointer_execute', " + + optin.pointer('open'); + + // Tag the opt-in pointer with custom class. + $('.wp-pointer #fs_connect') + .parents('.wp-pointer.wp-pointer-top') + .addClass('fs-opt-in-pointer'); + + ", 'element', 'optin') ?> + } + } + }); + // ]]></script> + <?php + } + + /** + * Return current page's URL. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + * + * @return string + */ + function current_page_url() { + $url = 'http'; + + if ( isset( $_SERVER["HTTPS"] ) ) { + if ( $_SERVER["HTTPS"] == "on" ) { + $url .= "s"; + } + } + $url .= "://"; + if ( $_SERVER["SERVER_PORT"] != "80" ) { + $url .= $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . $_SERVER["REQUEST_URI"]; + } else { + $url .= $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"]; + } + + return esc_url( $url ); + } + + /** + * Check if the current page is the plugin's main admin settings page. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + * + * @return bool + */ + function _is_plugin_page() { + return fs_is_plugin_page( $this->_menu->get_raw_slug() ) || + fs_is_plugin_page( $this->_slug ); + } + + /* Events + ------------------------------------------------------------------------------------------------------------------*/ + /** + * Delete site install from Database. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.1 + * + * @param bool $store + */ + function _delete_site( $store = true ) { + $sites = self::get_all_sites(); + + if ( isset( $sites[ $this->_slug ] ) ) { + unset( $sites[ $this->_slug ] ); + } + + self::$_accounts->set_option( 'sites', $sites, $store ); + } + + /** + * Delete plugin's plans information. + * + * @param bool $store Flush to Database if true. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + */ + private function _delete_plans( $store = true ) { + $this->_logger->entrance(); + + $plans = self::get_all_plans(); + + unset( $plans[ $this->_slug ] ); + + self::$_accounts->set_option( 'plans', $plans, $store ); + } + + /** + * Delete all plugin licenses. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @param bool $store + * @param string|bool $plugin_slug + */ + private function _delete_licenses( $store = true, $plugin_slug = false ) { + $this->_logger->entrance(); + + $all_licenses = self::get_all_licenses(); + + if ( ! is_string( $plugin_slug ) ) { + $plugin_slug = $this->_slug; + } + + unset( $all_licenses[ $plugin_slug ] ); + + self::$_accounts->set_option( 'licenses', $all_licenses, $store ); + } + + /** + * Check if Freemius was added on new plugin installation. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.5 + * + * @return bool + */ + function is_plugin_new_install() { + return isset( $this->_storage->is_plugin_new_install ) && + $this->_storage->is_plugin_new_install; + } + + /** + * Plugin activated hook. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.1 + * + * @uses FS_Api + */ + function _activate_plugin_event_hook() { + $this->_logger->entrance( 'slug = ' . $this->_slug ); + + if ( ! current_user_can( 'activate_plugins' ) ) { + return; + } + + // Clear API cache on activation. + FS_Api::clear_cache(); + + if ( $this->is_registered() ) { + // Schedule re-activation event and sync. +// $this->sync_install( array(), true ); + $this->schedule_install_sync(); + + /** + * @todo Work on automatic deactivation of the Free plugin version. It doesn't work since the slug of the free & premium versions is identical. Therefore, only one instance of Freemius is created and the activation hook of the premium version is not being added. + */ + if ( $this->_plugin_basename !== $this->_free_plugin_basename ) { + // Deactivate Free plugin version on premium plugin activation. + deactivate_plugins( $this->_free_plugin_basename ); + + $this->_admin_notices->add( + sprintf( __fs( 'successful-version-upgrade-message', $this->_slug ), sprintf( '<b>%s</b>', $this->_plugin->title ) ), + __fs( 'woot', $this->_slug ) . '!' + ); + } + } else if ( $this->is_anonymous() ) { + /** + * Reset "skipped" click cache on the following: + * 1. Development mode. + * 2. If the user skipped the exact same version before. + * + * @todo 3. If explicitly asked to retry after every activation. + */ + if ( WP_FS__DEV_MODE || + $this->get_plugin_version() == $this->_storage->is_anonymous['version'] + ) { + $this->reset_anonymous_mode(); + } + } + + if ( ! isset( $this->_storage->is_plugin_new_install ) ) { + /** + * If no previous version of plugin's version exist, it means that it's either + * the first time that the plugin installed on the site, or the plugin was installed + * before but didn't have Freemius integrated. + * + * Since register_activation_hook() do NOT fires on updates since 3.1, and only fires + * on manual activation via the dashboard, is_plugin_activation() is TRUE + * only after immediate activation. + * + * @since 1.1.4 + * @link https://make.wordpress.org/core/2010/10/27/plugin-activation-hooks-no-longer-fire-for-updates/ + */ + $this->_storage->is_plugin_new_install = empty( $this->_storage->plugin_last_version ); + } + + if ( ! $this->_anonymous_mode && $this->has_api_connectivity( WP_FS__DEV_MODE ) ) { + // Store hint that the plugin was just activated to enable auto-redirection to settings. + add_option( "fs_{$this->_slug}_activated", true ); + } + } + + /** + * Delete account. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.3 + * + * @param bool $check_user Enforce checking if user have plugins activation privileges. + */ + function delete_account_event( $check_user = true ) { + $this->_logger->entrance( 'slug = ' . $this->_slug ); + + if ( $check_user && ! current_user_can( 'activate_plugins' ) ) { + return; + } + + $this->do_action( 'before_account_delete' ); + + // Clear all admin notices. + $this->_admin_notices->clear_all_sticky(); + + $this->_delete_site( false ); + + $this->_delete_plans( false ); + + $this->_delete_licenses( false ); + + // Delete add-ons related to plugin's account. + $this->_delete_account_addons( false ); + + // @todo Delete plans and licenses of add-ons. + + self::$_accounts->store(); + + /** + * IMPORTANT: + * Clear crons must be executed before clearing all storage. + * Otherwise, the cron will not be cleared. + */ + $this->clear_sync_cron(); + $this->clear_install_sync_cron(); + + // Clear all storage data. + $this->_storage->clear_all( true, array( + 'connectivity_test', + 'is_on', + ) ); + + // Send delete event. + $this->get_api_site_scope()->call( '/', 'delete' ); + + $this->do_action( 'after_account_delete' ); + } + + /** + * Plugin deactivation hook. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.1 + */ + function _deactivate_plugin_hook() { + $this->_logger->entrance( 'slug = ' . $this->_slug ); + + if ( ! current_user_can( 'activate_plugins' ) ) { + return; + } + + $this->_admin_notices->clear_all_sticky(); + if ( isset( $this->_storage->sticky_optin_added ) ) { + unset( $this->_storage->sticky_optin_added ); + } + + if ( ! isset( $this->_storage->is_plugin_new_install ) ) { + // Remember that plugin was already installed. + $this->_storage->is_plugin_new_install = false; + } + + $this->clear_sync_cron(); + $this->clear_install_sync_cron(); + + if ( $this->is_registered() ) { + // Send deactivation event. + $this->sync_install( array( + 'is_active' => false, + ) ); + } else { + if ( ! $this->has_api_connectivity() ) { + // Reset connectivity test cache. + unset( $this->_storage->connectivity_test ); + } + } + + // Clear API cache on deactivation. + FS_Api::clear_cache(); + + $this->remove_sdk_reference(); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.6 + */ + private function remove_sdk_reference() { + global $fs_active_plugins; + + foreach ( $fs_active_plugins->plugins as $sdk_path => &$data ) { + if ( $this->_plugin_basename == $data->plugin_path ) { + unset( $fs_active_plugins->plugins[ $sdk_path ] ); + break; + } + } + + fs_fallback_to_newest_active_sdk(); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.3 + * + * @param bool $is_anonymous + */ + private function set_anonymous_mode( $is_anonymous = true ) { + // Store information regarding skip to try and opt-in the user + // again in the future. + $this->_storage->is_anonymous = array( + 'is' => $is_anonymous, + 'timestamp' => WP_FS__SCRIPT_START_TIME, + 'version' => $this->get_plugin_version(), + ); + + // Update anonymous mode cache. + $this->_is_anonymous = $is_anonymous; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.3 + */ + private function reset_anonymous_mode() { + unset( $this->_storage->is_anonymous ); + } + + /** + * Clears the anonymous mode and redirects to the opt-in screen. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.7 + */ + function connect_again() { + if ( ! $this->is_anonymous() ) { + return; + } + + $this->reset_anonymous_mode(); + + if ( fs_redirect( $this->get_activation_url() ) ) { + exit(); + } + } + + /** + * Skip account connect, and set anonymous mode. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.1 + */ + private function skip_connection() { + $this->_logger->entrance(); + + $this->_admin_notices->remove_sticky( 'connect_account' ); + + $this->set_anonymous_mode(); + + // Send anonymous skip event. + // No user identified info nor any tracking will be sent after the user skips the opt-in. + $this->get_api_plugin_scope()->call( 'skip.json', 'put', array( + 'uid' => $this->get_anonymous_id(), + ) ); + } + + /** + * Plugin version update hook. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + */ + private function update_plugin_version_event() { + $this->_logger->entrance(); + + if ( ! $this->is_registered() ) { + return; + } + + $this->schedule_install_sync(); +// $this->sync_install( array(), true ); + } + + /** + * Return a list of modified plugins since the last sync. + * + * Note: + * There's no point to store a plugins counter since even if the number of + * plugins didn't change, we still need to check if the versions are all the + * same and the activity state is similar. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.8 + * + * @return array|false + */ + private function get_plugins_data_for_api() { + // Alias. + $option_name = 'all_plugins'; + + $all_cached_plugins = self::$_accounts->get_option( $option_name ); + + if ( ! is_object( $all_cached_plugins ) ) { + $all_cached_plugins = (object) array( + 'timestamp' => '', + 'md5' => '', + 'plugins' => array(), + ); + } + + $time = time(); + + if ( ! empty( $all_cached_plugins->timestamp ) && + ( $time - $all_cached_plugins->timestamp ) < WP_FS__TIME_5_MIN_IN_SEC + ) { + // Don't send plugin updates if last update was in the past 5 min. + return false; + } + + // Write timestamp to lock the logic. + $all_cached_plugins->timestamp = $time; + self::$_accounts->set_option( $option_name, $all_cached_plugins, true ); + + // Reload options from DB. + self::$_accounts->load( true ); + $all_cached_plugins = self::$_accounts->get_option( $option_name ); + + if ( $time != $all_cached_plugins->timestamp ) { + // If timestamp is different, then another thread captured the lock. + return false; + } + + // Check if there's a change in plugins. + $all_plugins = self::get_all_plugins(); + + // Check if plugins changed. + ksort( $all_plugins ); + + $plugins_signature = ''; + foreach ( $all_plugins as $basename => $data ) { + $plugins_signature .= $data['slug'] . ',' . + $data['Version'] . ',' . + ( $data['is_active'] ? '1' : '0' ) . ';'; + } + + // Check if plugins status changed (version or active/inactive). + $plugins_changed = ( $all_cached_plugins->md5 !== md5( $plugins_signature ) ); + + $plugins_update_data = array(); + + if ( $plugins_changed ) { + // Change in plugins, report changes. + + // Update existing plugins info. + foreach ( $all_cached_plugins->plugins as $basename => $data ) { + if ( ! isset( $all_plugins[ $basename ] ) ) { + // Plugin uninstalled. + $uninstalled_plugin_data = $data; + $uninstalled_plugin_data['is_active'] = false; + $uninstalled_plugin_data['is_uninstalled'] = true; + $plugins_update_data[] = $uninstalled_plugin_data; + + unset( $all_plugins[ $basename ] ); + unset( $all_cached_plugins->plugins[ $basename ] ); + } else if ( $data['is_active'] !== $all_plugins[ $basename ]['is_active'] || + $data['version'] !== $all_plugins[ $basename ]['Version'] + ) { + // Plugin activated or deactivated, or version changed. + $all_cached_plugins->plugins[ $basename ]['is_active'] = $all_plugins[ $basename ]['is_active']; + $all_cached_plugins->plugins[ $basename ]['version'] = $all_plugins[ $basename ]['Version']; + + $plugins_update_data[] = $all_cached_plugins->plugins[ $basename ]; + } + } + + // Find new plugins that weren't yet seen before. + foreach ( $all_plugins as $basename => $data ) { + if ( ! isset( $all_cached_plugins->plugins[ $basename ] ) ) { + // New plugin. + $new_plugin = array( + 'slug' => $data['slug'], + 'version' => $data['Version'], + 'title' => $data['Name'], + 'is_active' => $data['is_active'], + 'is_uninstalled' => false, + ); + + $plugins_update_data[] = $new_plugin; + $all_cached_plugins->plugins[ $basename ] = $new_plugin; + } + } + + $all_cached_plugins->md5 = md5( $plugins_signature ); + $all_cached_plugins->timestamp = $time; + self::$_accounts->set_option( $option_name, $all_cached_plugins, true ); + } + + return $plugins_update_data; + } + + /** + * Return a list of modified themes since the last sync. + * + * Note: + * There's no point to store a themes counter since even if the number of + * themes didn't change, we still need to check if the versions are all the + * same and the activity state is similar. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.8 + * + * @return array|false + */ + private function get_themes_data_for_api() { + // Alias. + $option_name = 'all_themes'; + + $all_cached_themes = self::$_accounts->get_option( $option_name ); + + if ( ! is_object( $all_cached_themes ) ) { + $all_cached_themes = (object) array( + 'timestamp' => '', + 'md5' => '', + 'themes' => array(), + ); + } + + $time = time(); + + if ( ! empty( $all_cached_themes->timestamp ) && + ( $time - $all_cached_themes->timestamp ) < WP_FS__TIME_5_MIN_IN_SEC + ) { + // Don't send theme updates if last update was in the past 5 min. + return false; + } + + // Write timestamp to lock the logic. + $all_cached_themes->timestamp = $time; + self::$_accounts->set_option( $option_name, $all_cached_themes, true ); + + // Reload options from DB. + self::$_accounts->load( true ); + $all_cached_themes = self::$_accounts->get_option( $option_name ); + + if ( $time != $all_cached_themes->timestamp ) { + // If timestamp is different, then another thread captured the lock. + return false; + } + + // Get active theme. + $active_theme = wp_get_theme(); + + // Check if there's a change in themes. + $all_themes = wp_get_themes(); + + // Check if themes changed. + ksort( $all_themes ); + + $themes_signature = ''; + foreach ( $all_themes as $slug => $data ) { + $is_active = ( $slug === $active_theme->stylesheet ); + $themes_signature .= $slug . ',' . + $data->version . ',' . + ( $is_active ? '1' : '0' ) . ';'; + } + + // Check if themes status changed (version or active/inactive). + $themes_changed = ( $all_cached_themes->md5 !== md5( $themes_signature ) ); + + $themes_update_data = array(); + + if ( $themes_changed ) { + // Change in themes, report changes. + + // Update existing themes info. + foreach ( $all_cached_themes->themes as $slug => $data ) { + $is_active = ( $slug === $active_theme->stylesheet ); + + if ( ! isset( $all_themes[ $slug ] ) ) { + // Plugin uninstalled. + $uninstalled_theme_data = $data; + $uninstalled_theme_data['is_active'] = false; + $uninstalled_theme_data['is_uninstalled'] = true; + $themes_update_data[] = $uninstalled_theme_data; + + unset( $all_themes[ $slug ] ); + unset( $all_cached_themes->themes[ $slug ] ); + } else if ( $data['is_active'] !== $is_active || + $data['version'] !== $all_themes[ $slug ]->version + ) { + // Plugin activated or deactivated, or version changed. + + $all_cached_themes->themes[ $slug ]['is_active'] = $is_active; + $all_cached_themes->themes[ $slug ]['version'] = $all_themes[ $slug ]->version; + + $themes_update_data[] = $all_cached_themes->themes[ $slug ]; + } + } + + // Find new themes that weren't yet seen before. + foreach ( $all_themes as $slug => $data ) { + if ( ! isset( $all_cached_themes->themes[ $slug ] ) ) { + $is_active = ( $slug === $active_theme->stylesheet ); + + // New plugin. + $new_plugin = array( + 'slug' => $slug, + 'version' => $data->version, + 'title' => $data->name, + 'is_active' => $is_active, + 'is_uninstalled' => false, + ); + + $themes_update_data[] = $new_plugin; + $all_cached_themes->themes[ $slug ] = $new_plugin; + } + } + + $all_cached_themes->md5 = md5( $themes_signature ); + $all_cached_themes->timestamp = time(); + self::$_accounts->set_option( $option_name, $all_cached_themes, true ); + } + + return $themes_update_data; + } + + /** + * Update install details. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.2 + * + * @param string[] string $override + * @param bool $include_plugins Since 1.1.8 by default include plugin changes. + * @param bool $include_themes Since 1.1.8 by default include plugin changes. + * + * @return array + */ + private function get_install_data_for_api( + array $override, + $include_plugins = true, + $include_themes = true + ) { + /** + * @since 1.1.8 Also send plugin updates. + */ + if ( $include_plugins && ! isset( $override['plugins'] ) ) { + $plugins = $this->get_plugins_data_for_api(); + if ( ! empty( $plugins ) ) { + $override['plugins'] = $plugins; + } + } + /** + * @since 1.1.8 Also send themes updates. + */ + if ( $include_themes && ! isset( $override['themes'] ) ) { + $themes = $this->get_themes_data_for_api(); + if ( ! empty( $themes ) ) { + $override['themes'] = $themes; + } + } + + return array_merge( array( + 'version' => $this->get_plugin_version(), + 'is_premium' => $this->is_premium(), + 'language' => get_bloginfo( 'language' ), + 'charset' => get_bloginfo( 'charset' ), + 'platform_version' => get_bloginfo( 'version' ), + 'programming_language_version' => phpversion(), + 'title' => get_bloginfo( 'name' ), + 'url' => get_site_url(), + // Special params. + 'is_active' => true, + 'is_uninstalled' => false, + ), $override ); + } + + /** + * Update install only if changed. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @param string[] string $override + * @param bool $flush + * + * @return false|object|string + */ + private function send_install_update( $override = array(), $flush = false ) { + $this->_logger->entrance(); + + $check_properties = $this->get_install_data_for_api( $override ); + + if ( $flush ) { + $params = $check_properties; + } else { + $params = array(); + $special = array(); + $special_override = false; + + foreach ( $check_properties as $p => $v ) { + if ( property_exists( $this->_site, $p ) ) { + if ( ! empty( $this->_site->{$p} ) && + $this->_site->{$p} != $v + ) { + $this->_site->{$p} = $v; + $params[ $p ] = $v; + } + } else { + $special[ $p ] = $v; + + if ( isset( $override[ $p ] ) || + 'plugins' === $p || + 'themes' === $p + ) { + $special_override = true; + } + } + } + + if ( $special_override || 0 < count( $params ) ) { + // Add special params only if has at least one + // standard param, or if explicitly requested to + // override a special param or a param which is not exist + // in the install object. + $params = array_merge( $params, $special ); + } + } + + if ( 0 < count( $params ) ) { + // Update last install sync timestamp. + $this->_storage->install_sync_timestamp = time(); + + $params['uid'] = $this->get_anonymous_id(); + + // Send updated values to FS. + $site = $this->get_api_site_scope()->call( '/', 'put', $params ); + + if ( ! $this->is_api_error( $site ) ) { + // I successfully sent install update, clear scheduled sync if exist. + $this->clear_install_sync_cron(); + } + + return $site; + } + + return false; + } + + /** + * Update install only if changed. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @param string[] string $override + * @param bool $flush + * + * @return false|object|string + */ + private function sync_install( $override = array(), $flush = false ) { + $this->_logger->entrance(); + + $site = $this->send_install_update( $override, $flush ); + + if ( false === $site ) { + // No sync required. + return; + } + + if ( $this->is_api_error( $site ) ) { + // Failed to sync, don't update locally. + return; + } + + $plan = $this->get_plan(); + $this->_site = new FS_Site( $site ); + $this->_site->plan = $plan; + + $this->_store_site( true ); + } + + /** + * Plugin uninstall hook. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.1 + * + * @param bool $check_user Enforce checking if user have plugins activation privileges. + */ + function _uninstall_plugin_event( $check_user = true ) { + $this->_logger->entrance( 'slug = ' . $this->_slug ); + + if ( $check_user && ! current_user_can( 'activate_plugins' ) ) { + return; + } + + $params = array(); + if ( isset( $this->_storage->uninstall_reason ) ) { + $params['reason_id'] = $this->_storage->uninstall_reason->id; + $params['reason_info'] = $this->_storage->uninstall_reason->info; + } + + if ( ! $this->is_registered() && isset( $this->_storage->uninstall_reason ) ) { + // Send anonymous uninstall event only if user submitted a feedback. + $params['uid'] = $this->get_anonymous_id(); + $this->get_api_plugin_scope()->call( 'uninstall.json', 'put', $params ); + } else { + // Send uninstall event. + $this->send_install_update( array_merge( $params, array( + 'is_active' => false, + 'is_uninstalled' => true, + ) ) ); + } + + // @todo Decide if we want to delete plugin information from db. + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.1 + * + * @return string + */ + private function premium_plugin_basename() { + return preg_replace( '/\//', '-premium/', $this->_free_plugin_basename, 1 ); + } + + /** + * Uninstall plugin hook. Called only when connected his account with Freemius for active sites tracking. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.2 + */ + public static function _uninstall_plugin_hook() { + self::_load_required_static(); + + self::$_static_logger->entrance(); + + if ( ! current_user_can( 'activate_plugins' ) ) { + return; + } + + $plugin_file = substr( current_filter(), strlen( 'uninstall_' ) ); + + self::$_static_logger->info( 'plugin = ' . $plugin_file ); + + define( 'WP_FS__UNINSTALL_MODE', true ); + + $fs = self::get_instance_by_file( $plugin_file ); + + if ( is_object( $fs ) ) { + self::require_plugin_essentials(); + + if ( is_plugin_active( $fs->_free_plugin_basename ) || + is_plugin_active( $fs->premium_plugin_basename() ) + ) { + // Deleting Free or Premium plugin version while the other version still installed. + return; + } + + $fs->_uninstall_plugin_event(); + + $fs->do_action( 'after_uninstall' ); + } + } + + #region Plugin Information ------------------------------------------------------------------ + + /** + * Load WordPress core plugin.php essential module. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.1 + */ + private static function require_plugin_essentials() { + if ( ! function_exists( 'get_plugins' ) ) { + require_once( ABSPATH . 'wp-admin/includes/plugin.php' ); + } + } + + /** + * Load WordPress core pluggable.php module. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.2 + */ + private static function require_pluggable_essentials() { + if ( ! function_exists( 'wp_get_current_user' ) ) { + require_once( ABSPATH . 'wp-includes/pluggable.php' ); + } + } + + /** + * Return plugin data. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.1 + * + * @return array + */ + function get_plugin_data() { + if ( ! isset( $this->_plugin_data ) ) { + self::require_plugin_essentials(); + + $this->_plugin_data = get_plugin_data( $this->_plugin_main_file_path ); + } + + return $this->_plugin_data; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.1 + * + * @return string Plugin slug. + */ + function get_slug() { + return $this->_slug; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.1 + * + * @return number Plugin ID. + */ + function get_id() { + return $this->_plugin->id; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.1 + * + * @return string Plugin public key. + */ + function get_public_key() { + return $this->_plugin->public_key; + } + + /** + * Will be available only on sandbox mode. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + * + * @return mixed Plugin secret key. + */ + function get_secret_key() { + return $this->_plugin->secret_key; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.1 + * + * @return bool + */ + function has_secret_key() { + return ! empty( $this->_plugin->secret_key ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @return string + */ + function get_plugin_name() { + $this->_logger->entrance(); + + if ( ! isset( $this->_plugin_name ) ) { + $plugin_data = $this->get_plugin_data(); + + // Get name. + $this->_plugin_name = $plugin_data['Name']; + + // Check if plugin name contains [Premium] suffix and remove it. + $suffix = '[premium]'; + $suffix_len = strlen( $suffix ); + + if ( strlen( $plugin_data['Name'] ) > $suffix_len && + $suffix === substr( strtolower( $plugin_data['Name'] ), - $suffix_len ) + ) { + $this->_plugin_name = substr( $plugin_data['Name'], 0, - $suffix_len ); + } + + $this->_logger->departure( 'Name = ' . $this->_plugin_name ); + } + + return $this->_plugin_name; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.0 + * + * @return string + */ + function get_plugin_version() { + $this->_logger->entrance(); + + $plugin_data = $this->get_plugin_data(); + + $this->_logger->departure( 'Version = ' . $plugin_data['Version'] ); + + return $this->apply_filters( 'plugin_version', $plugin_data['Version'] ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + * + * @return string + */ + function get_plugin_basename() { + return $this->_plugin_basename; + } + + function get_plugin_folder_name() { + $this->_logger->entrance(); + + $plugin_folder = $this->_plugin_basename; + + while ( '.' !== dirname( $plugin_folder ) ) { + $plugin_folder = dirname( $plugin_folder ); + } + + $this->_logger->departure( 'Folder Name = ' . $plugin_folder ); + + return $plugin_folder; + } + + #endregion ------------------------------------------------------------------ + + /* Account + ------------------------------------------------------------------------------------------------------------------*/ + + /** + * Find plugin's slug by plugin's basename. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @param string $plugin_base_name + * + * @return false|string + */ + private static function find_slug_by_basename( $plugin_base_name ) { + $file_slug_map = self::$_accounts->get_option( 'file_slug_map', array() ); + + if ( ! array( $file_slug_map ) || ! isset( $file_slug_map[ $plugin_base_name ] ) ) { + return false; + } + + return $file_slug_map[ $plugin_base_name ]; + } + + /** + * Store the map between the plugin's basename to the slug. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + */ + private function store_file_slug_map() { + $file_slug_map = self::$_accounts->get_option( 'file_slug_map', array() ); + + if ( ! array( $file_slug_map ) ) { + $file_slug_map = array(); + } + + if ( ! isset( $file_slug_map[ $this->_plugin_basename ] ) || + $file_slug_map[ $this->_plugin_basename ] !== $this->_slug + ) { + $file_slug_map[ $this->_plugin_basename ] = $this->_slug; + self::$_accounts->set_option( 'file_slug_map', $file_slug_map, true ); + } + } + + /** + * @return FS_User[] + */ + static function get_all_users() { + $users = self::$_accounts->get_option( 'users', array() ); + + if ( ! is_array( $users ) ) { + $users = array(); + } + + return $users; + } + + /** + * @return FS_Site[] + */ + private static function get_all_sites() { + $sites = self::$_accounts->get_option( 'sites', array() ); + + if ( ! is_array( $sites ) ) { + $sites = array(); + } + + return $sites; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @return FS_Plugin_License[] + */ + private static function get_all_licenses() { + $licenses = self::$_accounts->get_option( 'licenses', array() ); + + if ( ! is_array( $licenses ) ) { + $licenses = array(); + } + + return $licenses; + } + + /** + * @return FS_Plugin_Plan[] + */ + private static function get_all_plans() { + $plans = self::$_accounts->get_option( 'plans', array() ); + + if ( ! is_array( $plans ) ) { + $plans = array(); + } + + return $plans; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + * + * @return FS_Plugin_Tag[] + */ + private static function get_all_updates() { + $updates = self::$_accounts->get_option( 'updates', array() ); + + if ( ! is_array( $updates ) ) { + $updates = array(); + } + + return $updates; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @return FS_Plugin[]|false + */ + private static function get_all_addons() { + $addons = self::$_accounts->get_option( 'addons', array() ); + + if ( ! is_array( $addons ) ) { + $addons = array(); + } + + return $addons; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @return FS_Plugin[]|false + */ + private static function get_all_account_addons() { + $addons = self::$_accounts->get_option( 'account_addons', array() ); + + if ( ! is_array( $addons ) ) { + $addons = array(); + } + + return $addons; + } + + /** + * Check if user is registered. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.1 + * @return bool + */ + function is_registered() { + return is_object( $this->_user ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + * + * @return FS_Plugin + */ + function get_plugin() { + return $this->_plugin; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.3 + * + * @return FS_User + */ + function get_user() { + return $this->_user; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.3 + * + * @return FS_Site + */ + function get_site() { + return $this->_site; + } + + /** + * Get plugin add-ons. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @since 1.1.7.3 If not yet loaded, fetch data from the API. + * + * @return FS_Plugin[]|false + */ + function get_addons() { + $this->_logger->entrance(); + + $all_addons = self::get_all_addons(); + + /** + * @since 1.1.7.3 If not yet loaded, fetch data from the API. + */ + if ( ! is_array( $all_addons ) || + ! isset( $all_addons[ $this->_plugin->id ] ) || + ! is_array( $all_addons[ $this->_plugin->id ] ) || + empty( $all_addons[ $this->_plugin->id ] ) + ) { + if ( $this->_has_addons ) { + $addons = $this->_sync_addons(); + + if ( ! empty( $addons ) ) { + $all_addons = self::get_all_addons(); + } + } + } + + if ( ! is_array( $all_addons ) || + ! isset( $all_addons[ $this->_plugin->id ] ) || + ! is_array( $all_addons[ $this->_plugin->id ] ) || + empty( $all_addons[ $this->_plugin->id ] ) + ) { + return false; + } + + return $all_addons[ $this->_plugin->id ]; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @return FS_Plugin[]|false + */ + function get_account_addons() { + $this->_logger->entrance(); + + $addons = self::get_all_account_addons(); + + if ( ! is_array( $addons ) || + ! isset( $addons[ $this->_plugin->id ] ) || + ! is_array( $addons[ $this->_plugin->id ] ) || + 0 === count( $addons[ $this->_plugin->id ] ) + ) { + return false; + } + + return $addons[ $this->_plugin->id ]; + } + + /** + * Check if user has any + * + * @author Vova Feldman (@svovaf) + * @since 1.1.6 + * + * @return bool + */ + function has_account_addons() { + $addons = $this->get_account_addons(); + + return is_array( $addons ) && ( 0 < count( $addons ) ); + } + + + /** + * Get add-on by ID (from local data). + * + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @param number $id + * + * @return FS_Plugin|false + */ + function get_addon( $id ) { + $this->_logger->entrance(); + + $addons = $this->get_addons(); + + if ( is_array( $addons ) ) { + foreach ( $addons as $addon ) { + if ( $id == $addon->id ) { + return $addon; + } + } + } + + return false; + } + + /** + * Get add-on by slug (from local data). + * + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @param string $slug + * + * @return FS_Plugin|false + */ + function get_addon_by_slug( $slug ) { + $this->_logger->entrance(); + + $addons = $this->get_addons(); + + if ( is_array( $addons ) ) { + foreach ( $addons as $addon ) { + if ( $slug == $addon->slug ) { + return $addon; + } + } + } + + return false; + } + + #region Plans & Licensing ------------------------------------------------------------------ + + /** + * Check if running premium plugin code. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.5 + * + * @return bool + */ + function is_premium() { + return $this->_plugin->is_premium; + } + + /** + * Get site's plan ID. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.2 + * + * @return number + */ + function get_plan_id() { + return $this->_site->plan->id; + } + + /** + * Get site's plan title. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.2 + * + * @return string + */ + function get_plan_title() { + return $this->_site->plan->title; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @return FS_Plugin_Plan + */ + function get_plan() { + return is_object( $this->_site->plan ) ? $this->_site->plan : false; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.3 + * + * @return bool + */ + function is_trial() { + $this->_logger->entrance(); + + if ( ! $this->is_registered() ) { + return false; + } + + return $this->_site->is_trial(); + } + + /** + * Check if currently in a trial with payment method (credit card or paypal). + * + * @author Vova Feldman (@svovaf) + * @since 1.1.7 + * + * @return bool + */ + function is_paid_trial() { + $this->_logger->entrance(); + + if ( ! $this->is_trial() ) { + return false; + } + + return $this->has_active_license() && ( $this->_site->trial_plan_id == $this->_license->plan_id ); + } + + /** + * Check if trial already utilized. + * + * @since 1.0.9 + * + * @return bool + */ + function is_trial_utilized() { + $this->_logger->entrance(); + + if ( ! $this->is_registered() ) { + return false; + } + + return $this->_site->is_trial_utilized(); + } + + /** + * Get trial plan information (if in trial). + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @return bool|FS_Plugin_Plan + */ + function get_trial_plan() { + $this->_logger->entrance(); + + if ( ! $this->is_trial() ) { + return false; + } + + return $this->_storage->trial_plan; + } + + /** + * Check if the user has an activated and valid paid license on current plugin's install. + * + * @since 1.0.9 + * + * @return bool + */ + function is_paying() { + $this->_logger->entrance(); + + if ( ! $this->is_registered() ) { + return false; + } + + if ( ! $this->has_paid_plan() ) { + return false; + } + + return ( + ! $this->is_trial() && + 'free' !== $this->_site->plan->name && + $this->has_features_enabled_license() + ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + * + * @return bool + */ + function is_free_plan() { + if ( ! $this->is_registered() ) { + return true; + } + + if ( ! $this->has_paid_plan() ) { + return true; + } + + return ( + 'free' === $this->_site->plan->name || + ! $this->has_features_enabled_license() + ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.5 + * + * @return bool + */ + function _has_premium_license() { + $this->_logger->entrance(); + + $premium_license = $this->_get_available_premium_license(); + + return ( false !== $premium_license ); + } + + /** + * Check if user has any licenses associated with the plugin (including expired or blocking). + * + * @author Vova Feldman (@svovaf) + * @since 1.1.7.3 + * + * @return bool + */ + private function has_any_license() { + return is_array( $this->_licenses ) && ( 0 < count( $this->_licenses ) ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.5 + * + * @return FS_Plugin_License + */ + function _get_available_premium_license() { + $this->_logger->entrance(); + + if ( ! $this->has_paid_plan() ) { + return false; + } + + if ( is_array( $this->_licenses ) ) { + foreach ( $this->_licenses as $license ) { + if ( ! $license->is_utilized() && $license->is_features_enabled() ) { + return $license; + } + } + } + + return false; + } + + /** + * Sync local plugin plans with remote server. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.5 + * + * @return FS_Plugin_Plan[]|object + */ + function _sync_plans() { + $plans = $this->_fetch_plugin_plans(); + if ( ! $this->is_api_error( $plans ) ) { + $this->_plans = $plans; + $this->_store_plans(); + } + + $this->do_action( 'after_plans_sync', $plans ); + + return $this->_plans; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.5 + * + * @param number $id + * + * @return FS_Plugin_Plan + */ + function _get_plan_by_id( $id ) { + $this->_logger->entrance(); + + if ( ! is_array( $this->_plans ) || 0 === count( $this->_plans ) ) { + $this->_sync_plans(); + } + + foreach ( $this->_plans as $plan ) { + if ( $id == $plan->id ) { + return $plan; + } + } + + return false; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.8.1 + * + * @param string $name + * + * @return FS_Plugin_Plan|false + */ + private function get_plan_by_name( $name ) { + $this->_logger->entrance(); + + if ( ! is_array( $this->_plans ) || 0 === count( $this->_plans ) ) { + $this->_sync_plans(); + } + + foreach ( $this->_plans as $plan ) { + if ( $name == $plan->name ) { + return $plan; + } + } + + return false; + } + + /** + * Sync local plugin plans with remote server. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @return FS_Plugin_License[]|object + */ + function _sync_licenses() { + $licenses = $this->_fetch_licenses(); + if ( ! $this->is_api_error( $licenses ) ) { + $this->_licenses = $licenses; + $this->_store_licenses(); + } + + // Update current license. + if ( is_object( $this->_license ) ) { + $this->_license = $this->_get_license_by_id( $this->_license->id ); + } + + return $this->_licenses; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.5 + * + * @param number $id + * + * @return FS_Plugin_License + */ + function _get_license_by_id( $id ) { + $this->_logger->entrance(); + + if ( ! is_numeric( $id ) ) { + return false; + } + + if ( ! is_array( $this->_licenses ) || 0 === count( $this->_licenses ) ) { + $this->_sync_licenses(); + } + + foreach ( $this->_licenses as $license ) { + if ( $id == $license->id ) { + return $license; + } + } + + return false; + } + + /** + * Sync site's license with user licenses. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @param FS_Plugin_License|null $new_license + */ + function _update_site_license( $new_license ) { + $this->_logger->entrance(); + + $this->_license = $new_license; + + if ( ! is_object( $new_license ) ) { + $this->_site->license_id = null; + $this->_sync_site_subscription( null ); + + return; + } + + $this->_site->license_id = $this->_license->id; + + if ( ! is_array( $this->_licenses ) ) { + $this->_licenses = array(); + } + + $is_license_found = false; + for ( $i = 0, $len = count( $this->_licenses ); $i < $len; $i ++ ) { + if ( $new_license->id == $this->_licenses[ $i ]->id ) { + $this->_licenses[ $i ] = $new_license; + + $is_license_found = true; + break; + } + } + + // If new license just append. + if ( ! $is_license_found ) { + $this->_licenses[] = $new_license; + } + + $this->_sync_site_subscription( $new_license ); + } + + /** + * Sync site's subscription. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @param FS_Plugin_License|null $license + * + * @return bool|\FS_Subscription + */ + private function _sync_site_subscription( $license ) { + if ( ! is_object( $license ) ) { + unset( $this->_storage->subscription ); + + return false; + } + + // Load subscription details if not lifetime. + $subscription = $license->is_lifetime() ? + false : + $this->_fetch_site_license_subscription(); + + if ( is_object( $subscription ) && ! isset( $subscription->error ) ) { + $this->_storage->subscription = $subscription; + } else { + unset( $this->_storage->subscription ); + } + + return $subscription; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @return bool|\FS_Plugin_License + */ + function _get_license() { + return $this->_license; + } + + /** + * @return bool|\FS_Subscription + */ + function _get_subscription() { + return isset( $this->_storage->subscription ) ? + $this->_storage->subscription : + false; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.2 + * + * @param string $plan Plan name + * @param bool $exact If true, looks for exact plan. If false, also check "higher" plans. + * + * @return bool + */ + function is_plan( $plan, $exact = false ) { + $this->_logger->entrance(); + + if ( ! $this->is_registered() ) { + return false; + } + + $plan = strtolower( $plan ); + + if ( $this->_site->plan->name === $plan ) // Exact plan. + { + return true; + } else if ( $exact ) // Required exact, but plans are different. + { + return false; + } + + $current_plan_order = - 1; + $required_plan_order = - 1; + for ( $i = 0, $len = count( $this->_plans ); $i < $len; $i ++ ) { + if ( $plan === $this->_plans[ $i ]->name ) { + $required_plan_order = $i; + } else if ( $this->_site->plan->name === $this->_plans[ $i ]->name ) { + $current_plan_order = $i; + } + } + + return ( $current_plan_order > $required_plan_order ); + } + + /** + * Check if plan based on trial. If not in trial mode, should return false. + * + * @since 1.0.9 + * + * @param string $plan Plan name + * @param bool $exact If true, looks for exact plan. If false, also check "higher" plans. + * + * @return bool + */ + function is_trial_plan( $plan, $exact = false ) { + $this->_logger->entrance(); + + if ( ! $this->is_registered() ) { + return false; + } + + if ( ! $this->is_trial() ) { + return false; + } + + if ( ! isset( $this->_storage->trial_plan ) ) { + // Store trial plan information. + $this->_enrich_site_trial_plan( true ); + } + + if ( $this->_storage->trial_plan->name === $plan ) // Exact plan. + { + return true; + } else if ( $exact ) // Required exact, but plans are different. + { + return false; + } + + $current_plan_order = - 1; + $required_plan_order = - 1; + for ( $i = 0, $len = count( $this->_plans ); $i < $len; $i ++ ) { + if ( $plan === $this->_plans[ $i ]->name ) { + $required_plan_order = $i; + } else if ( $this->_storage->trial_plan->name === $this->_plans[ $i ]->name ) { + $current_plan_order = $i; + } + } + + return ( $current_plan_order > $required_plan_order ); + } + + /** + * Check if plugin has any paid plans. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + * + * @return bool + */ + function has_paid_plan() { + return $this->_has_paid_plans || FS_Plan_Manager::instance()->has_paid_plan( $this->_plans ); + } + + /** + * Check if plugin has any plan with a trail. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @return bool + */ + function has_trial_plan() { + if ( ! $this->is_registered() ) { + return false; + } + + return $this->_storage->get( 'has_trial_plan', false ); + } + + /** + * Check if plugin has any free plan, or is it premium only. + * + * Note: If no plans configured, assume plugin is free. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + * + * @return bool + */ + function has_free_plan() { + return FS_Plan_Manager::instance()->has_free_plan( $this->_plans ); + } + + #region URL Generators + + /** + * Alias to pricing_url(). + * + * @author Vova Feldman (@svovaf) + * @since 1.0.2 + * + * @uses pricing_url() + * + * @param string $period Billing cycle + * @param bool $is_trial + * + * @return string + */ + function get_upgrade_url( $period = WP_FS__PERIOD_ANNUALLY, $is_trial = false ) { + return $this->pricing_url( $period, $is_trial ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @uses get_upgrade_url() + * + * @return string + */ + function get_trial_url() { + return $this->get_upgrade_url( WP_FS__PERIOD_ANNUALLY, true ); + } + + /** + * Plugin's pricing URL. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + * + * @param string $billing_cycle Billing cycle + * + * @param bool $is_trial + * + * @return string + */ + function pricing_url( $billing_cycle = WP_FS__PERIOD_ANNUALLY, $is_trial = false ) { + $this->_logger->entrance(); + + $params = array( + 'billing_cycle' => $billing_cycle + ); + + if ( $is_trial ) { + $params['trial'] = 'true'; + } + + return $this->_get_admin_page_url( 'pricing', $params ); + } + + /** + * Checkout page URL. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @param string $billing_cycle Billing cycle + * @param bool $is_trial + * @param array $extra (optional) Extra parameters, override other query params. + * + * @return string + */ + function checkout_url( + $billing_cycle = WP_FS__PERIOD_ANNUALLY, + $is_trial = false, + $extra = array() + ) { + $this->_logger->entrance(); + + $params = array( + 'checkout' => 'true', + 'billing_cycle' => $billing_cycle, + ); + + if ( $is_trial ) { + $params['trial'] = 'true'; + } + + /** + * Params in extra override other params. + */ + $params = array_merge( $params, $extra ); + + return $this->_get_admin_page_url( 'pricing', $params ); + } + + /** + * Add-on checkout URL. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.7 + * + * @param number $addon_id + * @param number $pricing_id + * @param string $billing_cycle + * @param bool $is_trial + * + * @return string + */ + function addon_checkout_url( + $addon_id, + $pricing_id, + $billing_cycle = WP_FS__PERIOD_ANNUALLY, + $is_trial = false + ) { + return $this->checkout_url( $billing_cycle, $is_trial, array( + 'plugin_id' => $addon_id, + 'pricing_id' => $pricing_id, + ) ); + } + + #endregion + + #endregion ------------------------------------------------------------------ + + /** + * Check if plugin has any add-ons. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.5 + * + * @since 1.1.7.3 Base logic only on the parameter provided by the developer in the init function. + * + * @return bool + */ + function has_addons() { + $this->_logger->entrance(); + + return $this->_has_addons; + } + + /** + * Check if plugin can work in anonymous mode. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @return bool + */ + function enable_anonymous() { + return $this->_enable_anonymous; + } + + /** + * Check if feature supported with current site's plan. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.1 + * + * @todo IMPLEMENT + * + * @param number $feature_id + * + * @throws Exception + */ + function is_feature_supported( $feature_id ) { + throw new Exception( 'not implemented' ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.1 + * + * @return bool Is running in SSL/HTTPS + */ + function is_ssl() { + return WP_FS__IS_HTTPS; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @return bool Is running in AJAX call. + * + * @link http://wordpress.stackexchange.com/questions/70676/how-to-check-if-i-am-in-admin-ajax + */ + function is_ajax() { + return ( defined( 'DOING_AJAX' ) && DOING_AJAX ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.7 + * + * @return bool + */ + function is_cron() { + return ( defined( 'DOING_CRON' ) && DOING_CRON ); + } + + /** + * Check if a real user is visiting the admin dashboard. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.7 + * + * @return bool + */ + function is_user_in_admin() { + return is_admin() && ! $this->is_ajax() && ! $this->is_cron(); + } + + /** + * Check if running in HTTPS and if site's plan matching the specified plan. + * + * @param string $plan + * @param bool $exact + * + * @return bool + */ + function is_ssl_and_plan( $plan, $exact = false ) { + return ( $this->is_ssl() && $this->is_plan( $plan, $exact ) ); + } + + /** + * Construct plugin's settings page URL. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + * + * @param string $page + * @param array $params + * + * @return string + */ + function _get_admin_page_url( $page = '', $params = array() ) { + if ( ! $this->_menu->is_top_level() ) { + $parent_slug = $this->_menu->get_parent_slug(); + $menu_file = ( false !== strpos( $parent_slug, '.php' ) ) ? + $parent_slug : + 'admin.php'; + + return add_query_arg( array_merge( $params, array( + 'page' => $this->_menu->get_slug( $page ), + ) ), admin_url( $menu_file, 'admin' ) ); + } + + if ( $this->_menu->is_cpt() ) { + if ( empty( $page ) && $this->is_activation_mode() ) { + return add_query_arg( array_merge( $params, array( + 'page' => $this->_menu->get_slug() + ) ), admin_url( 'admin.php', 'admin' ) ); + } else { + if ( ! empty( $page ) ) { + $params['page'] = $this->_menu->get_slug( $page ); + } + + return add_query_arg( $params, admin_url( $this->_menu->get_raw_slug(), 'admin' ) ); + } + } else { + return add_query_arg( array_merge( $params, array( + 'page' => $this->_menu->get_slug( $page ), + ) ), admin_url( 'admin.php', 'admin' ) ); + } + } + + + /** + * Plugin's account URL. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + * + * @param bool|string $action + * @param array $params + * + * @param bool $add_action_nonce + * + * @return string + */ + function get_account_url( $action = false, $params = array(), $add_action_nonce = true ) { + if ( is_string( $action ) ) { + $params['fs_action'] = $action; + } + + self::require_pluggable_essentials(); + + return ( $add_action_nonce && is_string( $action ) ) ? + wp_nonce_url( $this->_get_admin_page_url( 'account', $params ), $action ) : + $this->_get_admin_page_url( 'account', $params ); + } + + /** + * Plugin's account URL. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + * + * @param bool|string $topic + * @param bool|string $message + * + * @return string + */ + function contact_url( $topic = false, $message = false ) { + $params = array(); + if ( is_string( $topic ) ) { + $params['topic'] = $topic; + } + if ( is_string( $message ) ) { + $params['message'] = $message; + } + + if ( $this->is_addon() ) { + $params['addon_id'] = $this->get_id(); + + return $this->get_parent_instance()->_get_admin_page_url( 'contact', $params ); + } else { + return $this->_get_admin_page_url( 'contact', $params ); + } + } + + /** + * Add-on direct info URL. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.0 + * + * @param string $slug + * + * @return string + */ + function addon_url( $slug ) { + return $this->_get_admin_page_url( 'addons', array( + 'slug' => $slug + ) ); + } + + /* Logger + ------------------------------------------------------------------------------------------------------------------*/ + /** + * @param string $id + * @param bool $prefix_slug + * + * @return FS_Logger + */ + function get_logger( $id = '', $prefix_slug = true ) { + return FS_Logger::get_logger( ( $prefix_slug ? $this->_slug : '' ) . ( ( ! $prefix_slug || empty( $id ) ) ? '' : '_' ) . $id ); + } + + /** + * @param $id + * @param bool $load_options + * @param bool $prefix_slug + * + * @return FS_Option_Manager + */ + function get_options_manager( $id, $load_options = false, $prefix_slug = true ) { + return FS_Option_Manager::get_manager( ( $prefix_slug ? $this->_slug : '' ) . ( ( ! $prefix_slug || empty( $id ) ) ? '' : '_' ) . $id, $load_options ); + } + + /* Security + ------------------------------------------------------------------------------------------------------------------*/ + private function _encrypt( $str ) { + if ( is_null( $str ) ) { + return null; + } + + return base64_encode( $str ); + } + + private function _decrypt( $str ) { + if ( is_null( $str ) ) { + return null; + } + + return base64_decode( $str ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.5 + * + * @param FS_Entity $entity + * + * @return FS_Entity Return an encrypted clone entity. + */ + private function _encrypt_entity( FS_Entity $entity ) { + $clone = clone $entity; + $props = get_object_vars( $entity ); + + foreach ( $props as $key => $val ) { + $clone->{$key} = $this->_encrypt( $val ); + } + + return $clone; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.5 + * + * @param FS_Entity $entity + * + * @return FS_Entity Return an decrypted clone entity. + */ + private function _decrypt_entity( FS_Entity $entity ) { + $clone = clone $entity; + $props = get_object_vars( $entity ); + + foreach ( $props as $key => $val ) { + $clone->{$key} = $this->_decrypt( $val ); + } + + return $clone; + } + + /** + * Tries to activate account based on POST params. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.2 + */ + function _activate_account() { + if ( $this->is_registered() ) { + // Already activated. + return; + } + + self::_clean_admin_content_section(); + + if ( fs_request_is_action( 'activate' ) && fs_request_is_post() ) { +// check_admin_referer( 'activate_' . $this->_plugin->public_key ); + + // Verify matching plugin details. + if ( $this->_plugin->id != fs_request_get( 'plugin_id' ) || $this->_slug != fs_request_get( 'plugin_slug' ) ) { + return; + } + + $user = new FS_User(); + $user->id = fs_request_get( 'user_id' ); + $user->public_key = fs_request_get( 'user_public_key' ); + $user->secret_key = fs_request_get( 'user_secret_key' ); + $user->email = fs_request_get( 'user_email' ); + $user->first = fs_request_get( 'user_first' ); + $user->last = fs_request_get( 'user_last' ); + $user->is_verified = fs_request_get_bool( 'user_is_verified' ); + + $site = new FS_Site(); + $site->id = fs_request_get( 'install_id' ); + $site->public_key = fs_request_get( 'install_public_key' ); + $site->secret_key = fs_request_get( 'install_secret_key' ); + $site->plan->id = fs_request_get( 'plan_id' ); + $site->plan->title = fs_request_get( 'plan_title' ); + $site->plan->name = fs_request_get( 'plan_name' ); + + $plans = array(); + $plans_data = json_decode( urldecode( fs_request_get( 'plans' ) ) ); + foreach ( $plans_data as $p ) { + $plans[] = new FS_Plugin_Plan( $p ); + } + + $this->_set_account( $user, $site, $plans ); + + // Reload the page with the keys. + if ( fs_redirect( $this->_get_admin_page_url() ) ) { + exit(); + } + } + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + * + * @param string $email + * + * @return FS_User|bool + */ + static function _get_user_by_email( $email ) { + self::$_static_logger->entrance(); + + $email = trim( strtolower( $email ) ); + $users = self::get_all_users(); + if ( is_array( $users ) ) { + foreach ( $users as $u ) { + if ( $email === trim( strtolower( $u->email ) ) ) { + return $u; + } + } + } + + return false; + } + + #region Account (Loading, Updates & Activation) ------------------------------------------------------------------ + + /*** + * Load account information (user + site). + * + * @author Vova Feldman (@svovaf) + * @since 1.0.1 + */ + private function _load_account() { + $this->_logger->entrance(); + + $this->do_action( 'before_account_load' ); + + $sites = self::get_all_sites(); + $users = self::get_all_users(); + $plans = self::get_all_plans(); + $licenses = self::get_all_licenses(); + + if ( $this->_logger->is_on() && is_admin() ) { + $this->_logger->log( 'sites = ' . var_export( $sites, true ) ); + $this->_logger->log( 'users = ' . var_export( $users, true ) ); + $this->_logger->log( 'plans = ' . var_export( $plans, true ) ); + $this->_logger->log( 'licenses = ' . var_export( $licenses, true ) ); + } + + $site = isset( $sites[ $this->_slug ] ) ? $sites[ $this->_slug ] : false; + + if ( is_object( $site ) && + is_numeric( $site->id ) && + is_numeric( $site->user_id ) && + is_object( $site->plan ) + ) { + // Load site. + $this->_site = clone $site; + $this->_site->plan = $this->_decrypt_entity( $this->_site->plan ); + + // Load relevant user. + $this->_user = clone $users[ $this->_site->user_id ]; + + // Load plans. + $this->_plans = $plans[ $this->_slug ]; + if ( ! is_array( $this->_plans ) || empty( $this->_plans ) ) { + $this->_sync_plans( true ); + } else { + for ( $i = 0, $len = count( $this->_plans ); $i < $len; $i ++ ) { + if ( $this->_plans[ $i ] instanceof FS_Plugin_Plan ) { + $this->_plans[ $i ] = $this->_decrypt_entity( $this->_plans[ $i ] ); + } else { + unset( $this->_plans[ $i ] ); + } + } + } + + // Load licenses. + $this->_licenses = array(); + if ( is_array( $licenses ) && + isset( $licenses[ $this->_slug ] ) && + isset( $licenses[ $this->_slug ][ $this->_user->id ] ) + ) { + $this->_licenses = $licenses[ $this->_slug ][ $this->_user->id ]; + } + + $this->_license = $this->_get_license_by_id( $this->_site->license_id ); + + if ( $this->_site->version != $this->get_plugin_version() ) { + // If stored install version is different than current installed plugin version, + // then update plugin version event. + $this->update_plugin_version_event(); + } + } + + $this->_register_account_hooks(); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.1 + * + * @param FS_User $user + * @param FS_Site $site + * @param bool|array $plans + */ + private function _set_account( FS_User $user, FS_Site $site, $plans = false ) { + $site->slug = $this->_slug; + $site->user_id = $user->id; + + $this->_site = $site; + $this->_user = $user; + if ( false !== $plans ) { + $this->_plans = $plans; + } + + $this->send_install_update(); + + $this->_store_account(); + + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.7.4 + * + * @param array $override_with + * + * @return array + */ + function get_opt_in_params( $override_with = array() ) { + $this->_logger->entrance(); + + $current_user = self::_get_current_wp_user(); + + $params = array( + 'user_firstname' => $current_user->user_firstname, + 'user_lastname' => $current_user->user_lastname, + 'user_nickname' => $current_user->user_nicename, + 'user_email' => $current_user->user_email, + 'user_ip' => WP_FS__REMOTE_ADDR, + 'plugin_slug' => $this->_slug, + 'plugin_id' => $this->get_id(), + 'plugin_public_key' => $this->get_public_key(), + 'plugin_version' => $this->get_plugin_version(), + 'return_url' => wp_nonce_url( $this->_get_admin_page_url( + '', + array( 'fs_action' => $this->_slug . '_activate_new' ) + ), $this->_slug . '_activate_new' ), + 'account_url' => wp_nonce_url( $this->_get_admin_page_url( + 'account', + array( 'fs_action' => 'sync_user' ) + ), 'sync_user' ), + 'site_uid' => $this->get_anonymous_id(), + 'site_url' => get_site_url(), + 'site_name' => get_bloginfo( 'name' ), + 'platform_version' => get_bloginfo( 'version' ), + 'php_version' => phpversion(), + 'language' => get_bloginfo( 'language' ), + 'charset' => get_bloginfo( 'charset' ), + ); + + if ( WP_FS__SKIP_EMAIL_ACTIVATION && $this->has_secret_key() ) { + // Even though rand() is known for its security issues, + // the timestamp adds another layer of protection. + // It would be very hard for an attacker to get the secret key form here. + // Plus, this should never run in production since the secret should never + // be included in the production version. + $params['ts'] = WP_FS__SCRIPT_START_TIME; + $params['salt'] = md5( uniqid( rand() ) ); + $params['secure'] = md5( + $params['ts'] . + $params['salt'] . + $this->get_secret_key() + ); + } + + return array_merge( $params, $override_with ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.7.4 + * + * @param string|bool $email + * @param string|bool $first + * @param string|bool $last + * + * @return bool Is successful opt-in (or set to pending). + */ + function opt_in( $email = false, $first = false, $last = false ) { + $this->_logger->entrance(); + + if ( false === $email ) { + $current_user = self::_get_current_wp_user(); + $email = $current_user->user_email; + } + + $fs_user = Freemius::_get_user_by_email( $email ); + if ( is_object( $fs_user ) && ! $this->is_pending_activation() ) { + $this->install_with_current_user( false ); + + return true; + } + + $user_info = array(); + if ( ! empty( $email ) ) { + $user_info['user_email'] = $email; + } + if ( ! empty( $first ) ) { + $user_info['user_firstname'] = $first; + } + if ( ! empty( $last ) ) { + $user_info['user_lastname'] = $last; + } + + $params = $this->get_opt_in_params( $user_info ); + $params['format'] = 'json'; + + $url = WP_FS__ADDRESS . '/action/service/user/install/'; + if ( isset( $_COOKIE['XDEBUG_SESSION'] ) ) { + $url = add_query_arg( 'XDEBUG_SESSION', 'PHPSTORM', $url ); + } + + $response = wp_remote_post( $url, array( + 'method' => 'POST', + 'body' => $params, + 'timeout' => 15, + ) ); + + if ( $response instanceof WP_Error ) { + if ( 'https://' === substr( $url, 0, 8 ) && + isset( $response->errors ) && + isset( $response->errors['http_request_failed'] ) && + false !== strpos( $response->errors['http_request_failed'][0], 'sslv3 alert handshake' ) + ) { + // Failed due to old version of cURL or Open SSL (SSLv3 is not supported by CloudFlare). + $url = 'http://' . substr( $url, 8 ); + + $response = wp_remote_post( $url, array( + 'method' => 'POST', + 'body' => $params, + 'timeout' => 15, + ) ); + } + + if ( $response instanceof WP_Error ) { + return false; + } + } + + if ( is_wp_error( $response ) ) { + return false; + } + + $decoded = @json_decode( $response['body'] ); + + if ( empty( $decoded ) ) { + return false; + } + + if ( isset( $decoded->error ) ) { + return false; + } else if ( isset( $decoded->pending_activation ) && $decoded->pending_activation ) { + // Pending activation, add message. + $this->set_pending_confirmation( false, false ); + + return true; + } else if ( isset( $decoded->install_secret_key ) ) { + $this->install_with_new_user( + $decoded->user_id, + $decoded->user_public_key, + $decoded->user_secret_key, + $decoded->install_id, + $decoded->install_public_key, + $decoded->install_secret_key, + false + ); + + return true; + } + + return false; + } + + /** + * Set user and site identities. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @param FS_User $user + * @param FS_Site $site + * @param bool $redirect + * + * @return bool False if account already set. + */ + function setup_account( FS_User $user, FS_Site $site, $redirect = true ) { + $this->_user = $user; + $this->_site = $site; + + $this->_sync_plans(); + + $this->_enrich_site_plan( false ); + + $this->_set_account( $user, $site ); + + if ( $this->is_trial() ) { + // Store trial plan information. + $this->_enrich_site_trial_plan( true ); + } + + // If Freemius was OFF before, turn it on. + $this->turn_on(); + + $this->do_action( 'after_account_connection', $user, $site ); + + if ( is_numeric( $site->license_id ) ) { + $this->_license = $this->_get_license_by_id( $site->license_id ); + } + + if ( $this->is_pending_activation() ) { + // Remove pending activation sticky notice (if still exist). + $this->_admin_notices->remove_sticky( 'activation_pending' ); + + // Remove plugin from pending activation mode. + unset( $this->_storage->is_pending_activation ); + + if ( ! $this->is_paying() ) { + $this->_admin_notices->add_sticky( + sprintf( __fs( 'plugin-x-activation-message', $this->_slug ), '<b>' . $this->get_plugin_name() . '</b>' ), + 'activation_complete' + ); + } + } + + if ( $this->is_paying() && ! $this->is_premium() ) { + $this->_admin_notices->add_sticky( + sprintf( + __fs( 'activation-with-plan-x-message', $this->_slug ), + $this->_site->plan->title + ) . ' ' . $this->_get_latest_download_link( sprintf( + __fs( 'download-latest-x-version', $this->_slug ), + $this->_site->plan->title + ) ), + 'plan_upgraded', + __fs( 'yee-haw', $this->_slug ) . '!' + ); + } + + $plugin_id = fs_request_get( 'plugin_id', false ); + + // Store activation time ONLY for plugins (not add-ons). + if ( ! is_numeric( $plugin_id ) || ( $plugin_id == $this->_plugin->id ) ) { + $this->_storage->activation_timestamp = WP_FS__SCRIPT_START_TIME; + } + + if ( is_numeric( $plugin_id ) ) { + if ( $plugin_id != $this->_plugin->id ) { + // Add-on was installed - sync license right after install. + if ( $redirect && fs_redirect( fs_nonce_url( $this->_get_admin_page_url( + 'account', + array( + 'fs_action' => $this->_slug . '_sync_license', + 'plugin_id' => $plugin_id + ) + ), $this->_slug . '_sync_license' ) ) + ) { + exit(); + } + + } + } else { + // Reload the page with the keys. + if ( $redirect && fs_redirect( $this->get_after_activation_url( 'after_connect_url' ) ) ) { + exit(); + } + } + } + + /** + * Install plugin with new user information after approval. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + */ + function _install_with_new_user() { + $this->_logger->entrance(); + + if ( $this->is_registered() ) { + return; + } + + if ( fs_request_is_action( $this->_slug . '_activate_new' ) ) { +// check_admin_referer( $this->_slug . '_activate_new' ); + + $this->_admin_notices->remove_sticky( 'connect_account' ); + + if ( fs_request_has( 'user_secret_key' ) ) { + $this->install_with_new_user( + fs_request_get( 'user_id' ), + fs_request_get( 'user_public_key' ), + fs_request_get( 'user_secret_key' ), + fs_request_get( 'install_id' ), + fs_request_get( 'install_public_key' ), + fs_request_get( 'install_secret_key' ) + ); + } else if ( fs_request_has( 'pending_activation' ) ) { + $this->set_pending_confirmation( fs_request_get( 'user_email' ), true ); + } + } + } + + /** + * Install plugin with new user. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.7.4 + * + * @param number $user_id + * @param string $user_public_key + * @param string $user_secret_key + * @param number $install_id + * @param string $install_public_key + * @param string $install_secret_key + * @param bool $redirect + */ + private function install_with_new_user( + $user_id, + $user_public_key, + $user_secret_key, + $install_id, + $install_public_key, + $install_secret_key, + $redirect = true + ) { + $user = new FS_User(); + $user->id = $user_id; + $user->public_key = $user_public_key; + $user->secret_key = $user_secret_key; + + $this->_user = $user; + $user_result = $this->get_api_user_scope()->get(); + $user = new FS_User( $user_result ); + $this->_user = $user; + + $site = new FS_Site(); + $site->id = $install_id; + $site->public_key = $install_public_key; + $site->secret_key = $install_secret_key; + + $this->_site = $site; + $site_result = $this->get_api_site_scope()->get(); + $site = new FS_Site( $site_result ); + $this->_site = $site; + + $this->setup_account( $this->_user, $this->_site, $redirect ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.7.4 + * + * @param bool $email + * @param bool $redirect + */ + private function set_pending_confirmation( $email = false, $redirect = true ) { + // Install must be activated via email since + // user with the same email already exist. + $this->_storage->is_pending_activation = true; + $this->_add_pending_activation_notice( $email ); + + // Reload the page with with pending activation message. + if ( $redirect && fs_redirect( $this->get_after_activation_url( 'after_pending_connect_url' ) ) ) { + exit(); + } + } + + /** + * Install plugin with current logged WP user info. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + */ + function _install_with_current_user() { + $this->_logger->entrance(); + + if ( $this->is_registered() ) { + return; + } + + if ( fs_request_is_action( $this->_slug . '_activate_existing' ) && fs_request_is_post() ) { +// check_admin_referer( 'activate_existing_' . $this->_plugin->public_key ); + + $this->install_with_current_user(); + } + } + + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.7.4 + * + * @param bool $redirect + */ + private function install_with_current_user( $redirect = true ) { + $this->_admin_notices->remove_sticky( 'connect_account' ); + + // Get current logged WP user. + $current_user = self::_get_current_wp_user(); + + // Find the relevant FS user by the email. + $user = self::_get_user_by_email( $current_user->user_email ); + + // We have to set the user before getting user scope API handler. + $this->_user = $user; + + // Install the plugin. + $install = $this->get_api_user_scope()->call( + "/plugins/{$this->get_id()}/installs.json", + 'post', + $this->get_install_data_for_api( array( + 'uid' => $this->get_anonymous_id(), + ), false, false ) + ); + + if ( isset( $install->error ) ) { + $this->_admin_notices->add( + sprintf( __fs( 'could-not-activate-x', $this->_slug ), $this->get_plugin_name() ) . ' ' . + __fs( 'contact-us-with-error-message', $this->_slug ) . ' ' . '<b>' . $install->error->message . '</b>', + __fs( 'oops', $this->_slug ) . '...', + 'error' + ); + + return; + } + + $site = new FS_Site( $install ); + $this->_site = $site; +// $this->_enrich_site_plan( false ); + +// $this->_set_account( $user, $site ); +// $this->_sync_plans(); + + $this->setup_account( $this->_user, $this->_site, $redirect ); + } + + /** + * Tries to activate add-on account based on parent plugin info. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @param Freemius $parent_fs + */ + private function _activate_addon_account( Freemius $parent_fs ) { + if ( $this->is_registered() ) { + // Already activated. + return; + } + + // Activate add-on with parent plugin credentials. + $addon_install = $parent_fs->get_api_site_scope()->call( + "/addons/{$this->_plugin->id}/installs.json", + 'post', + $this->get_install_data_for_api( array( + 'uid' => $this->get_anonymous_id(), + ), false, false ) + ); + + if ( isset( $addon_install->error ) ) { + $this->_admin_notices->add( + sprintf( __fs( 'could-not-activate-x', $this->_slug ), $this->get_plugin_name() ) . ' ' . + __fs( 'contact-us-with-error-message', $this->_slug ) . ' ' . '<b>' . $addon_install->error->message . '</b>', + __fs( 'oops', $this->_slug ) . '...', + 'error' + ); + + return; + } + + // First of all, set site info - otherwise we won't + // be able to invoke API calls. + $this->_site = new FS_Site( $addon_install ); + + // Sync add-on plans. + $this->_sync_plans(); + + // Get site's current plan. + $this->_site->plan = $this->_get_plan_by_id( $this->_site->plan->id ); + + // Get user information based on parent's plugin. + $user = $parent_fs->get_user(); + + $this->_set_account( $user, $this->_site ); + + // Sync licenses. + $this->_sync_licenses(); + + // Try to activate premium license. + $this->_activate_license( true ); + } + + #endregion ------------------------------------------------------------------ + + #region Admin Menu Items ------------------------------------------------------------------ + + private $_menu_items = array(); + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + * + * @return string + */ + function get_menu_slug() { + return $this->_menu->get_slug(); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + */ + function _prepare_admin_menu() { +// if ( ! $this->is_on() ) { +// return; +// } + + if ( ! $this->has_api_connectivity() && ! $this->enable_anonymous() ) { + $this->_menu->remove_menu_item(); + } else { + $this->add_submenu_items(); + $this->add_menu_action(); + } + } + + /** + * Admin dashboard menu items modifications. + * + * NOTE: admin_menu action executed before admin_init. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + * + */ + private function add_menu_action() { + if ( $this->is_activation_mode() ) { + $this->override_plugin_menu_with_activation(); + } else { + // If not registered try to install user. + if ( ! $this->is_registered() && + fs_request_is_action( $this->_slug . '_activate_new' ) + ) { + $this->_install_with_new_user(); + } + } + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.1 + * + * @return string + */ + function _redirect_on_clicked_menu_link() { + $this->_logger->entrance(); + + $page = strtolower( isset( $_REQUEST['page'] ) ? $_REQUEST['page'] : '' ); + + $this->_logger->log( 'page = ' . $page ); + + foreach ( $this->_menu_items as $priority => $items ) { + foreach ( $items as $item ) { + if ( isset( $item['url'] ) ) { + if ( $page === strtolower( $item['menu_slug'] ) ) { + $this->_logger->log( 'Redirecting to ' . $item['url'] ); + + fs_redirect( $item['url'] ); + } + } + } + } + } + + /** + * Remove plugin's all admin menu items & pages, and replace with activation page. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.1 + */ + private function override_plugin_menu_with_activation() { + $this->_logger->entrance(); + + $hook = false; + + if ( $this->_menu->is_top_level() ) { + $hook = $this->_menu->override_menu_item( array( &$this, '_connect_page_render' ) ); + + if ( false === $hook ) { + // Create new menu item just for the opt-in. + $hook = add_menu_page( + $this->get_plugin_name(), + $this->get_plugin_name(), + 'manage_options', + $this->_menu->get_slug(), + array( &$this, '_connect_page_render' ) + ); + } + } else { + $menus = array( $this->_menu->get_parent_slug() ); + + if ( $this->_menu->is_override_exact() ) { + // Make sure the current page is matching the activation page. + $activation_url = strtolower( $this->get_activation_url() ); + $request_url = strtolower( $_SERVER['REQUEST_URI'] ); + + if ( parse_url( $activation_url, PHP_URL_PATH ) !== parse_url( $request_url, PHP_URL_PATH ) ) { + // Different path - DO NOT OVERRIDE PAGE. + return; + } + + $activation_url_params = array(); + parse_str( parse_url( $activation_url, PHP_URL_QUERY ), $activation_url_params ); + + $request_url_params = array(); + parse_str( parse_url( $request_url, PHP_URL_QUERY ), $request_url_params ); + + + foreach ( $activation_url_params as $key => $val ) { + if ( ! isset( $request_url_params[ $key ] ) || $val != $request_url_params[ $key ] ) { + // Not matching query string - DO NOT OVERRIDE PAGE. + return; + } + } + } + + foreach ( $menus as $parent_slug ) { + $hook = $this->_menu->override_submenu_action( + $parent_slug, + $this->_menu->get_raw_slug(), + array( &$this, '_connect_page_render' ) + ); + + if ( false !== $hook ) { + // Found plugin's submenu item. + break; + } + } + } + + if ( $this->_menu->is_activation_page() ) { + // Clean admin page from distracting content. + self::_clean_admin_content_section(); + } + + if ( false !== $hook ) { + if ( fs_request_is_action( $this->_slug . '_activate_existing' ) ) { + add_action( "load-$hook", array( &$this, '_install_with_current_user' ) ); + } else if ( fs_request_is_action( $this->_slug . '_activate_new' ) ) { + add_action( "load-$hook", array( &$this, '_install_with_new_user' ) ); + } + } + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.0 + * + * @return string + */ + private function get_top_level_menu_slug() { + return ( $this->is_addon() ? + $this->get_parent_instance()->_menu->get_top_level_menu_slug() : + $this->_menu->get_top_level_menu_slug() ); + } + + /** + * Add default Freemius menu items. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.0 + */ + private function add_submenu_items() { + $this->_logger->entrance(); + + $this->do_action( 'before_admin_menu_init' ); + + if ( ! $this->is_addon() ) { + if ( ! $this->is_activation_mode() ) { + if ( $this->is_registered() ) { + // Add user account page. + $this->add_submenu_item( + __fs( 'account', $this->_slug ), + array( &$this, '_account_page_render' ), + $this->get_plugin_name() . ' – ' . __fs( 'account', $this->_slug ), + 'manage_options', + 'account', + array( &$this, '_account_page_load' ), + WP_FS__DEFAULT_PRIORITY, + $this->_menu->is_submenu_item_visible( 'account' ) + ); + } + + // Add contact page. + $this->add_submenu_item( + __fs( 'contact-us', $this->_slug ), + array( &$this, '_contact_page_render' ), + $this->get_plugin_name() . ' – ' . __fs( 'contact-us', $this->_slug ), + 'manage_options', + 'contact', + 'Freemius::_clean_admin_content_section', + WP_FS__DEFAULT_PRIORITY, + $this->_menu->is_submenu_item_visible( 'contact' ) + ); + + if ( $this->has_addons() ) { + $this->add_submenu_item( + __fs( 'add-ons', $this->_slug ), + array( &$this, '_addons_page_render' ), + $this->get_plugin_name() . ' – ' . __fs( 'add-ons', $this->_slug ), + 'manage_options', + 'addons', + array( &$this, '_addons_page_load' ), + WP_FS__LOWEST_PRIORITY - 1, + $this->_menu->is_submenu_item_visible( 'addons' ) + ); + } + + $show_pricing = ( $this->has_paid_plan() && $this->_menu->is_submenu_item_visible( 'pricing' ) ); + // If user don't have paid plans, add pricing page + // to support add-ons checkout but don't add the submenu item. + // || (isset( $_GET['page'] ) && $this->_menu->get_slug( 'pricing' ) == $_GET['page']); + + // Add upgrade/pricing page. + $this->add_submenu_item( + ( $this->is_paying() ? __fs( 'pricing', $this->_slug ) : __fs( 'upgrade', $this->_slug ) . ' ➤' ), + array( &$this, '_pricing_page_render' ), + $this->get_plugin_name() . ' – ' . __fs( 'pricing', $this->_slug ), + 'manage_options', + 'pricing', + 'Freemius::_clean_admin_content_section', + WP_FS__LOWEST_PRIORITY, + $show_pricing + ); + } + } + + + if ( 0 < count( $this->_menu_items ) ) { + if ( ! $this->_menu->is_top_level() ) { + fs_enqueue_local_style( 'fs_common', '/admin/common.css' ); + + // Append submenu items right after the plugin's submenu item. + $this->order_sub_submenu_items(); + } else { + // Append submenu items. + $this->embed_submenu_items(); + } + } + } + + /** + * Moved the actual submenu item additions to a separated function, + * in order to support sub-submenu items when the plugin's settings + * only have a submenu and not top-level menu item. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.4 + */ + private function embed_submenu_items() { + $item_template = $this->_menu->is_top_level() ? + '<span class="fs-submenu-item">%s</span>' : + '<span class="fs-submenu-item fs-sub">%s</span>'; + + ksort( $this->_menu_items ); + + foreach ( $this->_menu_items as $priority => $items ) { + foreach ( $items as $item ) { + if ( ! isset( $item['url'] ) ) { + $hook = add_submenu_page( + $item['show_submenu'] ? + $this->get_top_level_menu_slug() : + null, + $item['page_title'], + sprintf( $item_template, $item['menu_title'] ), + $item['capability'], + $item['menu_slug'], + $item['render_function'] + ); + + if ( false !== $item['before_render_function'] ) { + add_action( "load-$hook", $item['before_render_function'] ); + } + } else { + add_submenu_page( + $this->get_top_level_menu_slug(), + $item['page_title'], + sprintf( $item_template, $item['menu_title'] ), + $item['capability'], + $item['menu_slug'], + array( $this, '' ) + ); + } + } + } + } + + /** + * Re-order the submenu items so all Freemius added new submenu items + * are added right after the plugin's settings submenu item. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.4 + */ + private function order_sub_submenu_items() { + global $submenu; + + $top_level_menu = &$submenu[ $this->_menu->get_top_level_menu_slug() ]; + + $all_submenu_items_after = array(); + + $found_submenu_item = false; + + foreach ( $top_level_menu as $submenu_id => $meta ) { + if ( $found_submenu_item ) { + // Remove all submenu items after the plugin's submenu item. + $all_submenu_items_after[] = $meta; + unset( $top_level_menu[ $submenu_id ] ); + } + + if ( $this->_menu->get_raw_slug() === $meta[2] ) { + // Found the submenu item, put all below. + $found_submenu_item = true; + continue; + } + } + + // Embed all plugin's new submenu items. + $this->embed_submenu_items(); + + // Start with specially high number to make sure it's appended. + $i = max( 10000, max( array_keys( $top_level_menu ) ) + 1 ); + foreach ( $all_submenu_items_after as $meta ) { + $top_level_menu[ $i ] = $meta; + $i ++; + } + + // Sort submenu items. + ksort( $top_level_menu ); + } + + /** + * Displays the Support Forum link when enabled. + * + * Can be filtered like so: + * + * function _fs_show_support_menu( $is_visible, $menu_id ) { + * if ( 'support' === $menu_id ) { + * return _fs->is_registered(); + * } + * return $is_visible; + * } + * _fs()->add_filter('is_submenu_visible', '_fs_show_support_menu', 10, 2); + * + */ + function _add_default_submenu_items() { + if ( ! $this->is_on() ) { + return; + } + + if ( ! $this->is_activation_mode() ) { + if ( $this->_menu->is_submenu_item_visible( 'support' ) ) { + $this->add_submenu_link_item( + $this->apply_filters( 'support_forum_submenu', __fs( 'support-forum', $this->_slug ) ), + $this->apply_filters( 'support_forum_url', 'https://wordpress.org/support/plugin/' . $this->_slug ), + 'wp-support-forum', + 'read', + 50 + ); + } + } + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.1 + * + * @param string $menu_title + * @param callable $render_function + * @param bool|string $page_title + * @param string $capability + * @param bool|string $menu_slug + * @param bool|callable $before_render_function + * @param int $priority + * @param bool $show_submenu + */ + function add_submenu_item( + $menu_title, + $render_function, + $page_title = false, + $capability = 'manage_options', + $menu_slug = false, + $before_render_function = false, + $priority = WP_FS__DEFAULT_PRIORITY, + $show_submenu = true + ) { + $this->_logger->entrance( 'Title = ' . $menu_title ); + + if ( $this->is_addon() ) { + $parent_fs = $this->get_parent_instance(); + + if ( is_object( $parent_fs ) ) { + $parent_fs->add_submenu_item( + $menu_title, + $render_function, + $page_title, + $capability, + $menu_slug, + $before_render_function, + $priority, + $show_submenu + ); + + return; + } + } + + if ( ! isset( $this->_menu_items[ $priority ] ) ) { + $this->_menu_items[ $priority ] = array(); + } + + $this->_menu_items[ $priority ][] = array( + 'page_title' => is_string( $page_title ) ? $page_title : $menu_title, + 'menu_title' => $menu_title, + 'capability' => $capability, + 'menu_slug' => $this->_menu->get_slug( is_string( $menu_slug ) ? $menu_slug : strtolower( $menu_title ) ), + 'render_function' => $render_function, + 'before_render_function' => $before_render_function, + 'show_submenu' => $show_submenu, + ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.1 + * + * @param string $menu_title + * @param string $url + * @param bool $menu_slug + * @param string $capability + * @param int $priority + * + */ + function add_submenu_link_item( + $menu_title, + $url, + $menu_slug = false, + $capability = 'read', + $priority = WP_FS__DEFAULT_PRIORITY + ) { + $this->_logger->entrance( 'Title = ' . $menu_title . '; Url = ' . $url ); + + if ( $this->is_addon() ) { + $parent_fs = $this->get_parent_instance(); + + if ( is_object( $parent_fs ) ) { + $parent_fs->add_submenu_link_item( + $menu_title, + $url, + $menu_slug, + $capability, + $priority + ); + + return; + } + } + + if ( ! isset( $this->_menu_items[ $priority ] ) ) { + $this->_menu_items[ $priority ] = array(); + } + + $this->_menu_items[ $priority ][] = array( + 'menu_title' => $menu_title, + 'capability' => $capability, + 'menu_slug' => $this->_menu->get_slug( is_string( $menu_slug ) ? $menu_slug : strtolower( $menu_title ) ), + 'url' => $url, + 'page_title' => $menu_title, + 'render_function' => 'fs_dummy', + 'before_render_function' => '', + ); + } + + #endregion ------------------------------------------------------------------ + + /* Actions / Hooks / Filters + ------------------------------------------------------------------------------------------------------------------*/ + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.7 + * + * @param string $tag + * + * @return string + */ + private function get_action_tag( $tag ) { + return 'fs_' . $tag . '_' . $this->_slug; + } + + /** + * Do action, specific for the current context plugin. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.1 + * + * @param string $tag The name of the action to be executed. + * @param mixed $arg,... Optional. Additional arguments which are passed on to the + * functions hooked to the action. Default empty. + * + * @uses do_action() + */ + function do_action( $tag, $arg = '' ) { + $this->_logger->entrance( $tag ); + + $args = func_get_args(); + + call_user_func_array( 'do_action', array_merge( + array( $this->get_action_tag( $tag ) ), + array_slice( $args, 1 ) ) + ); + } + + /** + * Add action, specific for the current context plugin. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.1 + * + * @param string $tag + * @param callable $function_to_add + * @param int $priority + * @param int $accepted_args + * + * @uses add_action() + */ + function add_action( $tag, $function_to_add, $priority = WP_FS__DEFAULT_PRIORITY, $accepted_args = 1 ) { + $this->_logger->entrance( $tag ); + + add_action( $this->get_action_tag( $tag ), $function_to_add, $priority, $accepted_args ); + } + + /** + * Apply filter, specific for the current context plugin. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @param string $tag The name of the filter hook. + * @param mixed $value The value on which the filters hooked to `$tag` are applied on. + * + * @return mixed The filtered value after all hooked functions are applied to it. + * + * @uses apply_filters() + */ + function apply_filters( $tag, $value ) { + $this->_logger->entrance( $tag ); + + $args = func_get_args(); + array_unshift( $args, $this->_slug ); + + return call_user_func_array( 'fs_apply_filter', $args ); + } + + /** + * Add filter, specific for the current context plugin. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @param string $tag + * @param callable $function_to_add + * @param int $priority + * @param int $accepted_args + * + * @uses add_filter() + */ + function add_filter( $tag, $function_to_add, $priority = WP_FS__DEFAULT_PRIORITY, $accepted_args = 1 ) { + $this->_logger->entrance( $tag ); + + add_filter( $this->get_action_tag( $tag ), $function_to_add, $priority, $accepted_args ); + } + + /** + * Check if has filter. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.4 + * + * @param string $tag + * @param callable|bool $function_to_check Optional. The callback to check for. Default false. + * + * @return false|int + * + * @uses has_filter() + */ + function has_filter( $tag, $function_to_check = false ) { + $this->_logger->entrance( $tag ); + + return has_filter( $this->get_action_tag( $tag ), $function_to_check ); + } + + /** + * Override default i18n text phrases. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.6 + * + * @param string[] string $key_value + * + * @uses fs_override_i18n() + */ + function override_i18n( $key_value ) { + fs_override_i18n( $key_value, $this->_slug ); + } + + /* Account Page + ------------------------------------------------------------------------------------------------------------------*/ + /** + * Update site information. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.1 + * + * @param bool $store Flush to Database if true. + */ + private function _store_site( $store = true ) { + $this->_logger->entrance(); + + $encrypted_site = clone $this->_site; + $encrypted_site->plan = $this->_encrypt_entity( $this->_site->plan ); + + $sites = self::get_all_sites(); + $sites[ $this->_slug ] = $encrypted_site; + self::$_accounts->set_option( 'sites', $sites, $store ); + } + + /** + * Update plugin's plans information. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.2 + * + * @param bool $store Flush to Database if true. + */ + private function _store_plans( $store = true ) { + $this->_logger->entrance(); + + $plans = self::get_all_plans(); + + // Copy plans. + $encrypted_plans = array(); + for ( $i = 0, $len = count( $this->_plans ); $i < $len; $i ++ ) { + $encrypted_plans[] = $this->_encrypt_entity( $this->_plans[ $i ] ); + } + + $plans[ $this->_slug ] = $encrypted_plans; + self::$_accounts->set_option( 'plans', $plans, $store ); + } + + /** + * Update user's plugin licenses. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.5 + * + * @param bool $store + * @param string|bool $plugin_slug + * @param FS_Plugin_License[] $licenses + */ + private function _store_licenses( $store = true, $plugin_slug = false, $licenses = array() ) { + $this->_logger->entrance(); + + $all_licenses = self::get_all_licenses(); + + if ( ! is_string( $plugin_slug ) ) { + $plugin_slug = $this->_slug; + $licenses = $this->_licenses; + } + + if ( ! isset( $all_licenses[ $plugin_slug ] ) ) { + $all_licenses[ $plugin_slug ] = array(); + } + + $all_licenses[ $plugin_slug ][ $this->_user->id ] = $licenses; + + self::$_accounts->set_option( 'licenses', $all_licenses, $store ); + } + + /** + * Update user information. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.1 + * + * @param bool $store Flush to Database if true. + */ + private function _store_user( $store = true ) { + $this->_logger->entrance(); + + $users = self::get_all_users(); + $users[ $this->_user->id ] = $this->_user; + self::$_accounts->set_option( 'users', $users, $store ); + } + + /** + * Update new updates information. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + * + * @param FS_Plugin_Tag|null $update + * @param bool $store Flush to Database if true. + * @param bool|number $plugin_id + */ + private function _store_update( $update, $store = true, $plugin_id = false ) { + $this->_logger->entrance(); + + if ( $update instanceof FS_Plugin_Tag ) { + $update->updated = time(); + } + + if ( ! is_numeric( $plugin_id ) ) { + $plugin_id = $this->_plugin->id; + } + + $updates = self::get_all_updates(); + $updates[ $plugin_id ] = $update; + self::$_accounts->set_option( 'updates', $updates, $store ); + } + + /** + * Update new updates information. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @param FS_Plugin[] $plugin_addons + * @param bool $store Flush to Database if true. + */ + private function _store_addons( $plugin_addons, $store = true ) { + $this->_logger->entrance(); + + $addons = self::get_all_addons(); + $addons[ $this->_plugin->id ] = $plugin_addons; + self::$_accounts->set_option( 'addons', $addons, $store ); + } + + /** + * Delete plugin's associated add-ons. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.8 + * + * @param bool $store + * + * @return bool + */ + private function _delete_account_addons( $store = true ) { + $all_addons = self::get_all_account_addons(); + + if ( ! isset( $all_addons[ $this->_plugin->id ] ) ) { + return false; + } + + unset( $all_addons[ $this->_plugin->id ] ); + + self::$_accounts->set_option( 'account_addons', $all_addons, $store ); + + return true; + } + + /** + * Update account add-ons list. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @param FS_Plugin[] $addons + * @param bool $store Flush to Database if true. + */ + private function _store_account_addons( $addons, $store = true ) { + $this->_logger->entrance(); + + $all_addons = self::get_all_account_addons(); + $all_addons[ $this->_plugin->id ] = $addons; + self::$_accounts->set_option( 'account_addons', $all_addons, $store ); + } + + /** + * Store account params in the Database. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.1 + */ + private function _store_account() { + $this->_logger->entrance(); + + $this->_store_site( false ); + $this->_store_user( false ); + $this->_store_plans( false ); + $this->_store_licenses( false ); + + self::$_accounts->store(); + } + + /** + * Sync user's information. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.3 + * @uses FS_Api + */ + private function _handle_account_user_sync() { + $this->_logger->entrance(); + + $api = $this->get_api_user_scope(); + + // Get user's information. + $user = $api->get( '/', true ); + + if ( isset( $user->id ) ) { + $this->_user->first = $user->first; + $this->_user->last = $user->last; + $this->_user->email = $user->email; + + $is_menu_item_account_visible = $this->_menu->is_submenu_item_visible( 'account' ); + + if ( $user->is_verified && + ( ! isset( $this->_user->is_verified ) || false === $this->_user->is_verified ) + ) { + $this->_user->is_verified = true; + + $this->do_action( 'account_email_verified', $user->email ); + + $this->_admin_notices->add( + __fs( 'email-verified-message', $this->_slug ), + __fs( 'right-on', $this->_slug ) . '!', + 'success', + // Make admin sticky if account menu item is invisible, + // since the page will be auto redirected to the plugin's + // main settings page, and the non-sticky message + // will disappear. + ! $is_menu_item_account_visible, + false, + 'email_verified' + ); + } + + // Flush user details to DB. + $this->_store_user(); + + $this->do_action( 'after_account_user_sync', $user ); + + /** + * If account menu item is hidden, redirect to plugin's main settings page. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.6 + * + * @link https://github.com/Freemius/wordpress-sdk/issues/6 + */ + if ( ! $is_menu_item_account_visible ) { + if ( fs_redirect( $this->_get_admin_page_url() ) ) { + exit(); + } + } + } + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.5 + * @uses FS_Api + * + * @param bool $flush + * + * @return object|\FS_Site + */ + private function _fetch_site( $flush = false ) { + $this->_logger->entrance(); + $api = $this->get_api_site_scope(); + + $site = $api->get( '/', $flush ); + + if ( ! isset( $site->error ) ) { + $site = new FS_Site( $site ); + $site->slug = $this->_slug; + $site->version = $this->get_plugin_version(); + } + + return $site; + } + + /** + * @param bool $store + * + * @return FS_Plugin_Plan|object|false + */ + private function _enrich_site_plan( $store = true ) { + // Try to load plan from local cache. + $plan = $this->_get_plan_by_id( $this->_site->plan->id ); + + if ( false === $plan ) { + $plan = $this->_fetch_site_plan(); + } + + if ( $plan instanceof FS_Plugin_Plan ) { + $this->_update_plan( $plan, $store ); + } + + return $plan; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * @uses FS_Api + * + * @param bool $store + * + * @return FS_Plugin_Plan|object|false + */ + private function _enrich_site_trial_plan( $store = true ) { + // Try to load plan from local cache. + $trial_plan = $this->_get_plan_by_id( $this->_site->trial_plan_id ); + + if ( false === $trial_plan ) { + $trial_plan = $this->_fetch_site_plan( $this->_site->trial_plan_id ); + } + + if ( $trial_plan instanceof FS_Plugin_Plan ) { + $this->_storage->store( 'trial_plan', $trial_plan, $store ); + } + + return $trial_plan; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * @uses FS_Api + * + * @param number|bool $license_id + * + * @return FS_Subscription|object|bool + */ + private function _fetch_site_license_subscription( $license_id = false ) { + $this->_logger->entrance(); + $api = $this->get_api_site_scope(); + + if ( ! is_numeric( $license_id ) ) { + $license_id = $this->_license->id; + } + + $result = $api->get( "/licenses/{$license_id}/subscriptions.json", true ); + + return ! isset( $result->error ) ? + ( ( is_array( $result->subscriptions ) && 0 < count( $result->subscriptions ) ) ? + new FS_Subscription( $result->subscriptions[0] ) : + false + ) : + $result; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + * @uses FS_Api + * + * @param number|bool $plan_id + * + * @return FS_Plugin_Plan|object + */ + private function _fetch_site_plan( $plan_id = false ) { + $this->_logger->entrance(); + $api = $this->get_api_site_scope(); + + if ( ! is_numeric( $plan_id ) ) { + $plan_id = $this->_site->plan->id; + } + + $plan = $api->get( "/plans/{$plan_id}.json", true ); + + return ! isset( $plan->error ) ? new FS_Plugin_Plan( $plan ) : $plan; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.5 + * @uses FS_Api + * + * @return FS_Plugin_Plan[]|object + */ + private function _fetch_plugin_plans() { + $this->_logger->entrance(); + $api = $this->get_api_site_scope(); + + $result = $api->get( '/plans.json', true ); + + if ( ! $this->is_api_error( $result ) ) { + for ( $i = 0, $len = count( $result->plans ); $i < $len; $i ++ ) { + $result->plans[ $i ] = new FS_Plugin_Plan( $result->plans[ $i ] ); + } + + $result = $result->plans; + } + + return $result; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.5 + * @uses FS_Api + * + * @param number|bool $plugin_id + * + * @return FS_Plugin_License[]|object + */ + private function _fetch_licenses( $plugin_id = false ) { + $this->_logger->entrance(); + + $api = $this->get_api_user_scope(); + + if ( ! is_numeric( $plugin_id ) ) { + $plugin_id = $this->_plugin->id; + } + + $result = $api->get( "/plugins/{$plugin_id}/licenses.json", true ); + + if ( ! isset( $result->error ) ) { + for ( $i = 0, $len = count( $result->licenses ); $i < $len; $i ++ ) { + $result->licenses[ $i ] = new FS_Plugin_License( $result->licenses[ $i ] ); + } + + $result = $result->licenses; + } + + return $result; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + * + * @param FS_Plugin_Plan $plan + * @param bool $store + */ + private function _update_plan( $plan, $store = false ) { + $this->_logger->entrance(); + + $this->_site->plan = $plan; + $this->_store_site( $store ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.5 + * + * @param FS_Plugin_License[] $licenses + * @param string|bool $plugin_slug + */ + private function _update_licenses( $licenses, $plugin_slug = false ) { + $this->_logger->entrance(); + + if ( is_array( $licenses ) ) { + for ( $i = 0, $len = count( $licenses ); $i < $len; $i ++ ) { + $licenses[ $i ]->updated = time(); + } + } + + if ( ! is_string( $plugin_slug ) ) { + $this->_licenses = $licenses; + } + + $this->_store_licenses( true, $plugin_slug, $licenses ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + * + * @param bool|number $plugin_id + * @param bool $flush Since 1.1.7.3 + * + * @return object|false New plugin tag info if exist. + */ + private function _fetch_newer_version( $plugin_id = false, $flush = true ) { + $latest_tag = $this->_fetch_latest_version( $plugin_id, $flush ); + + if ( ! is_object( $latest_tag ) ) { + return false; + } + + // Check if version is actually newer. + $has_new_version = + // If it's an non-installed add-on then always return latest. + ( $this->_is_addon_id( $plugin_id ) && ! $this->is_addon_activated( $plugin_id ) ) || + // Compare versions. + version_compare( $this->get_plugin_version(), $latest_tag->version, '<' ); + + $this->_logger->departure( $has_new_version ? 'Found newer plugin version ' . $latest_tag->version : 'No new version' ); + + return $has_new_version ? $latest_tag : false; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.5 + * + * @param bool|number $plugin_id + * @param bool $flush Since 1.1.7.3 + * + * @return bool|FS_Plugin_Tag + */ + function get_update( $plugin_id = false, $flush = true ) { + $this->_logger->entrance(); + + if ( ! is_numeric( $plugin_id ) ) { + $plugin_id = $this->_plugin->id; + } + + $this->_check_updates( true, $plugin_id, $flush ); + $updates = $this->get_all_updates(); + + return isset( $updates[ $plugin_id ] ) && is_object( $updates[ $plugin_id ] ) ? $updates[ $plugin_id ] : false; + } + + /** + * Check if site assigned with active license. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + */ + function has_active_license() { + return ( + is_object( $this->_license ) && + is_numeric( $this->_license->id ) && + ! $this->_license->is_expired() + ); + } + + /** + * Check if site assigned with license with enabled features. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @return bool + */ + function has_features_enabled_license() { + return ( + is_object( $this->_license ) && + is_numeric( $this->_license->id ) && + $this->_license->is_features_enabled() + ); + } + + /** + * Check if user is a trial or have feature enabled license. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.7 + * + * @return bool + */ + function can_use_premium_code() { + return $this->is_trial() || $this->has_features_enabled_license(); + } + + /** + * Sync site's plan. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.3 + * + * @uses FS_Api + * + * @param bool $background Hints the method if it's a background sync. If false, it means that was initiated by + * the admin. + */ + private function _sync_license( $background = false ) { + $this->_logger->entrance(); + + $plugin_id = fs_request_get( 'plugin_id', $this->get_id() ); + + $is_addon_sync = ( ! $this->_plugin->is_addon() && $plugin_id != $this->get_id() ); + + if ( $is_addon_sync ) { + $this->_sync_addon_license( $plugin_id, $background ); + } else { + $this->_sync_plugin_license( $background ); + } + + $this->do_action( 'after_account_plan_sync', $this->_site->plan->name ); + } + + /** + * Sync plugin's add-on license. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * @uses FS_Api + * + * @param number $addon_id + * @param bool $background + */ + private function _sync_addon_license( $addon_id, $background ) { + $this->_logger->entrance(); + + if ( $this->is_addon_activated( $addon_id ) ) { + // If already installed, use add-on sync. + $fs_addon = self::get_instance_by_id( $addon_id ); + $fs_addon->_sync_license( $background ); + + return; + } + + // Validate add-on exists. + $addon = $this->get_addon( $addon_id ); + + if ( ! is_object( $addon ) ) { + return; + } + + // Add add-on into account add-ons. + $account_addons = $this->get_account_addons(); + if ( ! is_array( $account_addons ) ) { + $account_addons = array(); + } + $account_addons[] = $addon->id; + $account_addons = array_unique( $account_addons ); + $this->_store_account_addons( $account_addons ); + + // Load add-on licenses. + $licenses = $this->_fetch_licenses( $addon->id ); + + // Sync add-on licenses. + if ( ! isset( $licenses->error ) ) { + $this->_update_licenses( $licenses, $addon->slug ); + + if ( ! $this->is_addon_installed( $addon->slug ) && FS_License_Manager::has_premium_license( $licenses ) ) { + $plans_result = $this->get_api_site_or_plugin_scope()->get( "/addons/{$addon_id}/plans.json" ); + + if ( ! isset( $plans_result->error ) ) { + $plans = array(); + foreach ( $plans_result->plans as $plan ) { + $plans[] = new FS_Plugin_Plan( $plan ); + } + + $this->_admin_notices->add_sticky( + FS_Plan_Manager::instance()->has_free_plan( $plans ) ? + sprintf( + __fs( 'addon-successfully-upgraded-message', $this->_slug ), + $addon->title + ) . ' ' . $this->_get_latest_download_link( + __fs( 'download-latest-version', $this->_slug ), + $addon_id + ) + : + sprintf( + __fs( 'addon-successfully-purchased-message', $this->_slug ), + $addon->title + ) . ' ' . $this->_get_latest_download_link( + __fs( 'download-latest-version', $this->_slug ), + $addon_id + ), + 'addon_plan_upgraded_' . $addon->slug, + __fs( 'yee-haw', $this->_slug ) . '!' + ); + } + } + } + } + + /** + * Sync site's plugin plan. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * @uses FS_Api + * + * @param bool $background Hints the method if it's a background sync. If false, it means that was initiated by + * the admin. + */ + private function _sync_plugin_license( $background = false ) { + $this->_logger->entrance(); + + // Sync site info. + $site = $this->send_install_update( array(), true ); + + $plan_change = 'none'; + + if ( $this->is_api_error( $site ) ) { + // Show API messages only if not background sync or if paying customer. + if ( ! $background || $this->is_paying() ) { + // Try to ping API to see if not blocked. + if ( ! FS_Api::test() ) { + /** + * Failed to ping API - blocked! + * + * @author Vova Feldman (@svovaf) + * @since 1.1.6 Only show message related to one of the Freemius powered plugins. Once it will be resolved it will fix the issue for all plugins anyways. There's no point to scare users with multiple error messages. + */ + $api = $this->get_api_site_scope(); + + if ( ! self::$_global_admin_notices->has_sticky( 'api_blocked' ) ) { + self::$_global_admin_notices->add( + sprintf( + __fs( 'server-blocking-access', $this->_slug ), + $this->get_plugin_name(), + '<a href="' . $api->get_url() . '" target="_blank">' . $api->get_url() . '</a>' + ) . '<br> ' . __fs( 'server-error-message', $this->_slug ) . var_export( $site->error, true ), + __fs( 'oops', $this->_slug ) . '...', + 'error', + $background, + false, + 'api_blocked' + ); + } + } else { + // Authentication params are broken. + $this->_admin_notices->add( + __fs( 'wrong-authentication-param-message', $this->_slug ), + __fs( 'oops', $this->_slug ) . '...', + 'error' + ); + } + } + + // No reason to continue with license sync while there are API issues. + return; + } + + // Remove sticky API connectivity message. + self::$_global_admin_notices->remove_sticky( 'api_blocked' ); + + $site = new FS_Site( $site ); + + // Sync plans. + $this->_sync_plans(); + + if ( ! $this->has_paid_plan() ) { + $this->_site = $site; + $this->_enrich_site_plan( true ); + $this->_store_site(); + } else { + // Sync licenses. + $this->_sync_licenses(); + + // Check if plan / license changed. + if ( ! FS_Entity::equals( $site->plan, $this->_site->plan ) || + // Check if trial started. + $site->trial_plan_id != $this->_site->trial_plan_id || + $site->trial_ends != $this->_site->trial_ends || + // Check if license changed. + $site->license_id != $this->_site->license_id + ) { + if ( $site->is_trial() && ( ! $this->_site->is_trial() || $site->trial_ends != $this->_site->trial_ends ) ) { + // New trial started. + $this->_site = $site; + $plan_change = 'trial_started'; + + // Store trial plan information. + $this->_enrich_site_trial_plan( true ); + + // For trial with subscription use-case. + $new_license = is_null( $site->license_id ) ? null : $this->_get_license_by_id( $site->license_id ); + + if ( is_object( $new_license ) && ! $new_license->is_expired() ) { + $this->_site = $site; + $this->_update_site_license( $new_license ); + $this->_store_licenses(); + $this->_enrich_site_plan( true ); + + $this->_sync_site_subscription( $this->_license ); + } + } else if ( $this->_site->is_trial() && ! $site->is_trial() && ! is_numeric( $site->license_id ) ) { + // Was in trial, but now trial expired and no license ID. + // New trial started. + $this->_site = $site; + $plan_change = 'trial_expired'; + + // Clear trial plan information. + $this->_storage->trial_plan = null; + + } else { + $is_free = $this->is_free_plan(); + + // Make sure license exist and not expired. + $new_license = is_null( $site->license_id ) ? null : $this->_get_license_by_id( $site->license_id ); + + if ( $is_free && ( ( ! is_object( $new_license ) || $new_license->is_expired() ) ) ) { + // The license is expired, so ignore upgrade method. + } else { + // License changed. + $this->_site = $site; + $this->_update_site_license( $new_license ); + $this->_store_licenses(); + $this->_enrich_site_plan( true ); + + $plan_change = $is_free ? + 'upgraded' : + ( is_object( $new_license ) ? + 'changed' : + 'downgraded' ); + } + } + + // Store updated site info. + $this->_store_site(); + } else { + if ( is_object( $this->_license ) && $this->_license->is_expired() ) { + if ( ! $this->has_features_enabled_license() ) { + $this->_deactivate_license(); + $plan_change = 'downgraded'; + } else { + $plan_change = 'expired'; + } + } + + if ( is_numeric( $site->license_id ) && is_object( $this->_license ) ) { + $this->_sync_site_subscription( $this->_license ); + } + } + } + + if ( $this->has_paid_plan() ) { + switch ( $plan_change ) { + case 'none': + if ( ! $background && is_admin() ) { + $plan = $this->is_trial() ? + $this->_storage->trial_plan : + $this->_site->plan; + + $this->_admin_notices->add( + sprintf( + __fs( 'plan-did-not-change-message', $this->_slug ) . ' ' . + sprintf( + '<a href="%s">%s</a>', + $this->contact_url( + 'bug', + sprintf( __fs( 'plan-did-not-change-email-message', $this->_slug ), + strtoupper( $plan->name ) + ) + ), + __fs( 'contact-us-here', $this->_slug ) + ), + '<i>' . $plan->title . ( $this->is_trial() ? ' ' . __fs( 'trial', $this->_slug ) : '' ) . '</i>' + ), + __fs( 'hmm', $this->_slug ) . '...', + 'error' + ); + } + break; + case 'upgraded': + $this->_admin_notices->add_sticky( + sprintf( + __fs( 'plan-upgraded-message', $this->_slug ), + '<i>' . $this->get_plugin_name() . '</i>' + ) . ( $this->is_premium() ? '' : ' ' . $this->_get_latest_download_link( sprintf( + __fs( 'download-latest-x-version', $this->_slug ), + $this->_site->plan->title + ) ) + ), + 'plan_upgraded', + __fs( 'yee-haw', $this->_slug ) . '!' + ); + + $this->_admin_notices->remove_sticky( array( + 'trial_started', + 'trial_promotion', + 'trial_expired', + 'activation_complete', + ) ); + break; + case 'changed': + $this->_admin_notices->add_sticky( + sprintf( + __fs( 'plan-changed-to-x-message', $this->_slug ), + $this->_site->plan->title + ), + 'plan_changed' + ); + + $this->_admin_notices->remove_sticky( array( + 'trial_started', + 'trial_promotion', + 'trial_expired', + 'activation_complete', + ) ); + break; + case 'downgraded': + $this->_admin_notices->add_sticky( + sprintf( __fs( 'license-expired-blocking-message', $this->_slug ) ), + 'license_expired', + __fs( 'hmm', $this->_slug ) . '...' + ); + $this->_admin_notices->remove_sticky( 'plan_upgraded' ); + break; + case 'expired': + $this->_admin_notices->add_sticky( + sprintf( __fs( 'license-expired-non-blocking-message', $this->_slug ), $this->_site->plan->title ), + 'license_expired', + __fs( 'hmm', $this->_slug ) . '...' + ); + $this->_admin_notices->remove_sticky( 'plan_upgraded' ); + break; + case 'trial_started': + $this->_admin_notices->add_sticky( + sprintf( + __fs( 'trial-started-message', $this->_slug ), + '<i>' . $this->get_plugin_name() . '</i>' + ) . ( $this->is_premium() ? '' : ' ' . $this->_get_latest_download_link( sprintf( + __fs( 'download-latest-x-version', $this->_slug ), + $this->_storage->trial_plan->title + ) ) ), + 'trial_started', + __fs( 'yee-haw', $this->_slug ) . '!' + ); + + $this->_admin_notices->remove_sticky( array( + 'trial_promotion', + ) ); + break; + case 'trial_expired': + $this->_admin_notices->add_sticky( + __fs( 'trial-expired-message', $this->_slug ), + 'trial_expired', + __fs( 'hmm', $this->_slug ) . '...' + ); + $this->_admin_notices->remove_sticky( array( + 'trial_started', + 'trial_promotion', + 'plan_upgraded', + ) ); + break; + } + } + + if ( 'none' !== $plan_change ) { + $this->do_action( 'after_license_change', $plan_change, $this->_site->plan ); + } + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.5 + * + * @param bool $background + */ + protected function _activate_license( $background = false ) { + $this->_logger->entrance(); + + $license_id = fs_request_get( 'license_id' ); + + if ( FS_Plugin_License::is_valid_id( $license_id ) && $license_id == $this->_site->license_id ) { + // License is already activated. + return; + } + + $premium_license = FS_Plugin_License::is_valid_id( $license_id ) ? + $this->_get_license_by_id( $license_id ) : + $this->_get_available_premium_license(); + + if ( ! is_object( $premium_license ) ) { + return; + } + + $api = $this->get_api_site_scope(); + $license = $api->call( "/licenses/{$premium_license->id}.json", 'put' ); + + if ( $this->is_api_error( $license ) ) { + if ( ! $background ) { + $this->_admin_notices->add( + __fs( 'license-activation-failed-message', $this->_slug ) . '<br> ' . + __fs( 'server-error-message', $this->_slug ) . ' ' . var_export( $license, true ), + __fs( 'hmm', $this->_slug ) . '...', + 'error' + ); + } + + return; + } + + $premium_license = new FS_Plugin_License( $license ); + + // Updated site plan. + $site = $this->get_api_site_scope()->get( '/', true ); + if ( ! $this->is_api_error( $site ) ) { + $this->_site = new FS_Site( $site ); + } + $this->_update_site_license( $premium_license ); + $this->_enrich_site_plan( false ); + + $this->_store_account(); + + if ( ! $background ) { + $this->_admin_notices->add_sticky( + __fs( 'license-activated-message', $this->_slug ) . + ( $this->is_premium() ? '' : ' ' . $this->_get_latest_download_link( sprintf( + __fs( 'download-latest-x-version', $this->_slug ), + $this->_site->plan->title + ) ) ), + 'license_activated', + __fs( 'yee-haw', $this->_slug ) . '!' + ); + } + + $this->_admin_notices->remove_sticky( array( + 'trial_promotion', + 'license_expired', + ) ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.5 + * + * @param bool $show_notice + */ + protected function _deactivate_license( $show_notice = true ) { + $this->_logger->entrance(); + + if ( ! is_object( $this->_license ) ) { + $this->_admin_notices->add( + sprintf( __fs( 'no-active-license-message', $this->_slug ), $this->_site->plan->title ), + __fs( 'hmm', $this->_slug ) . '...' + ); + + return; + } + + $api = $this->get_api_site_scope(); + $license = $api->call( "/licenses/{$this->_site->license_id}.json", 'delete' ); + + if ( isset( $license->error ) ) { + $this->_admin_notices->add( + __fs( 'license-deactivation-failed-message', $this->_slug ) . '<br> ' . + __fs( 'server-error-message', $this->_slug ) . ' ' . var_export( $license->error, true ), + __fs( 'hmm', $this->_slug ) . '...', + 'error' + ); + + return; + } + + // Update license cache. + for ( $i = 0, $len = count( $this->_licenses ); $i < $len; $i ++ ) { + if ( $license->id == $this->_licenses[ $i ]->id ) { + $this->_licenses[ $i ] = new FS_Plugin_License( $license ); + } + } + + // Updated site plan to default. + $this->_sync_plans(); + $this->_site->plan->id = $this->_plans[0]->id; + // Unlink license from site. + $this->_update_site_license( null ); + $this->_enrich_site_plan( false ); + + $this->_store_account(); + + if ( $show_notice ) { + $this->_admin_notices->add( + sprintf( __fs( 'license-deactivation-message', $this->_slug ), $this->_site->plan->title ), + __fs( 'ok', $this->_slug ) + ); + } + + $this->_admin_notices->remove_sticky( array( + 'plan_upgraded', + 'license_activated', + ) ); + } + + /** + * Site plan downgrade. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + * + * @uses FS_Api + */ + private function _downgrade_site() { + $this->_logger->entrance(); + + $api = $this->get_api_site_scope(); + $site = $api->call( 'downgrade.json', 'put' ); + + $plan_downgraded = false; + $plan = false; + if ( ! isset( $site->error ) ) { + $prev_plan_id = $this->_site->plan->id; + + // Update new site plan id. + $this->_site->plan->id = $site->plan_id; + + $plan = $this->_enrich_site_plan(); + $subscription = $this->_sync_site_subscription( $this->_license ); + + // Plan downgraded if plan was changed or subscription was cancelled. + $plan_downgraded = ( $plan instanceof FS_Plugin_Plan && $prev_plan_id != $plan->id ) || + ( is_object( $subscription ) && ! isset( $subscription->error ) && ! $subscription->is_active() ); + } else { + // handle different error cases. + + } + + if ( $plan_downgraded ) { + // Remove previous sticky message about upgrade (if exist). + $this->_admin_notices->remove_sticky( 'plan_upgraded' ); + + $this->_admin_notices->add( + sprintf( __fs( 'plan-x-downgraded-message', $this->_slug ), + $plan->title, + human_time_diff( time(), strtotime( $this->_license->expiration ) ) + ) + ); + + // Store site updates. + $this->_store_site(); + } else { + $this->_admin_notices->add( + __fs( 'plan-downgraded-failure-message', $this->_slug ), + __fs( 'oops', $this->_slug ) . '...', + 'error' + ); + } + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.8.1 + * + * @param bool|string $plan_name + * + * @return bool If trial was successfully started. + */ + function start_trial($plan_name = false) { + $this->_logger->entrance(); + + if ( $this->is_trial() ) { + // Already in trial mode. + $this->_admin_notices->add( + __fs( 'in-trial-mode', $this->_slug ), + __fs( 'oops', $this->_slug ) . '...', + 'error' + ); + + return false; + } + + if ( $this->_site->is_trial_utilized() ) { + // Trial was already utilized. + $this->_admin_notices->add( + __fs( 'trial-utilized', $this->_slug ), + __fs( 'oops', $this->_slug ) . '...', + 'error' + ); + + return false; + } + + if ( false !== $plan_name ) { + $plan = $this->get_plan_by_name( $plan_name ); + + if ( false === $plan ) { + // Plan doesn't exist. + $this->_admin_notices->add( + sprintf( __fs( 'trial-plan-x-not-exist', $this->_slug ), $plan_name ), + __fs( 'oops', $this->_slug ) . '...', + 'error' + ); + + return false; + } + + if ( ! $plan->has_trial() ) { + // Plan doesn't exist. + $this->_admin_notices->add( + sprintf( __fs( 'plan-x-no-trial', $this->_slug ), $plan_name ), + __fs( 'oops', $this->_slug ) . '...', + 'error' + ); + + return false; + } + } else { + if ( ! $this->has_trial_plan() ) { + // None of the plans have a trial. + $this->_admin_notices->add( + __fs( 'no-trials', $this->_slug ), + __fs( 'oops', $this->_slug ) . '...', + 'error' + ); + + return false; + } + + $plans_with_trial = FS_Plan_Manager::instance()->get_trial_plans( $this->_plans ); + + $plan = $plans_with_trial[0]; + } + + $api = $this->get_api_site_scope(); + $plan = $api->call( "plans/{$plan->id}/trials.json", 'post' ); + + if ( $this->is_api_error( $plan ) ) { + // Some API error while trying to start the trial. + $this->_admin_notices->add( + __fs( 'unexpected-api-error', $this->_slug ) . ' ' . var_export( $plan, true ), + __fs( 'oops', $this->_slug ) . '...', + 'error' + ); + + return false; + } + + // Sync license. + $this->_sync_license(); + + return $this->is_trial(); + } + + /** + * Cancel site trial. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @uses FS_Api + */ + private function _cancel_trial() { + $this->_logger->entrance(); + + if ( ! $this->is_trial() ) { + $this->_admin_notices->add( + __fs( 'trial-cancel-no-trial-message', $this->_slug ), + __fs( 'oops', $this->_slug ) . '...', + 'error' + ); + + return; + } + + $api = $this->get_api_site_scope(); + $site = $api->call( 'trials.json', 'delete' ); + + $trial_cancelled = false; + + if ( ! $this->is_api_error( $site ) ) { + $prev_trial_ends = $this->_site->trial_ends; + + if ( $this->is_paid_trial() ) { + $this->_license->expiration = $site->trial_ends; + $this->_license->is_cancelled = true; + $this->_update_site_license( $this->_license ); + $this->_store_licenses(); + + // Clear subscription reference. + $this->_sync_site_subscription( null ); + } + + // Update site info. + $this->_site = new FS_Site( $site ); + $this->_enrich_site_plan(); + + $trial_cancelled = ( $prev_trial_ends != $site->trial_ends ); + } else { + // handle different error cases. + + } + + if ( $trial_cancelled ) { + // Remove previous sticky messages about upgrade or trial (if exist). + $this->_admin_notices->remove_sticky( array( + 'trial_started', + 'trial_promotion', + 'plan_upgraded', + ) ); + + // Store site updates. + $this->_store_site(); + + // Clear trial plan information. + unset( $this->_storage->trial_plan ); + + if ( ! $this->is_addon() || + ! $this->deactivate_premium_only_addon_without_license( true ) + ) { + $this->_admin_notices->add( + sprintf( __fs( 'trial-cancel-message', $this->_slug ), $this->_storage->trial_plan->title ) + ); + } + } else { + $this->_admin_notices->add( + __fs( 'trial-cancel-failure-message', $this->_slug ), + __fs( 'oops', $this->_slug ) . '...', + 'error' + ); + } + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @param bool|number $plugin_id + * + * @return bool + */ + private function _is_addon_id( $plugin_id ) { + return is_numeric( $plugin_id ) && ( $this->get_id() != $plugin_id ); + } + + /** + * Check if user eligible to download premium version updates. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @return bool + */ + private function _can_download_premium() { + return $this->has_active_license() || + ( $this->is_trial() && ! $this->get_trial_plan()->is_free() ); + } + + /** + * + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @param bool|number $addon_id + * @param string $type "json" or "zip" + * + * @return string + */ + private function _get_latest_version_endpoint( $addon_id = false, $type = 'json' ) { + + $is_addon = $this->_is_addon_id( $addon_id ); + + $is_premium = null; + if ( ! $is_addon ) { + $is_premium = $this->_can_download_premium(); + } else if ( $this->is_addon_activated( $addon_id ) ) { + $is_premium = self::get_instance_by_id( $addon_id )->_can_download_premium(); + } + + return // If add-on, then append add-on ID. + ( $is_addon ? "/addons/$addon_id" : '' ) . + '/updates/latest.' . $type . + // If add-on and not yet activated, try to fetch based on server licensing. + ( is_bool( $is_premium ) ? '?is_premium=' . json_encode( $is_premium ) : '' ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + * + * @param bool|number $addon_id + * @param bool $flush Since 1.1.7.3 + * + * @return object|false Plugin latest tag info. + */ + function _fetch_latest_version( $addon_id = false, $flush = true ) { + $this->_logger->entrance(); + + /** + * @since 1.1.7.3 Check for plugin updates from Freemius only if opted-in. + * @since 1.1.7.4 Also check updates for add-ons. + */ + if ( ! $this->is_registered() && + ! $this->_is_addon_id( $addon_id ) + ) { + return false; + } + + $tag = $this->get_api_site_or_plugin_scope()->get( + $this->_get_latest_version_endpoint( $addon_id, 'json' ), + $flush + ); + + $latest_version = ( is_object( $tag ) && isset( $tag->version ) ) ? $tag->version : 'couldn\'t get'; + + $this->_logger->departure( 'Latest version ' . $latest_version ); + + return ( is_object( $tag ) && isset( $tag->version ) ) ? $tag : false; + } + + #region Download Plugin ------------------------------------------------------------------ + + /** + * Download latest plugin version, based on plan. + * The download will be fetched via the API first. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + * + * @param bool|number $plugin_id + * + * @uses FS_Api + * + * @deprecated + */ + private function _download_latest( $plugin_id = false ) { + $this->_logger->entrance(); + + $is_addon = $this->_is_addon_id( $plugin_id ); + + $is_premium = $this->_can_download_premium(); + + $latest = $this->get_api_site_scope()->call( + $this->_get_latest_version_endpoint( $plugin_id, 'zip' ) + ); + + $slug = $this->_slug; + if ( $is_addon ) { + $addon = $this->get_addon( $plugin_id ); + $slug = is_object( $addon ) ? $addon->slug : 'addon'; + } + + if ( ! is_object( $latest ) ) { + header( "Content-Type: application/zip" ); + header( "Content-Disposition: attachment; filename={$slug}" . ( ! $is_addon && $is_premium ? '-premium' : '' ) . ".zip" ); + header( "Content-Length: " . strlen( $latest ) ); + echo $latest; + + exit(); + } + } + + /** + * Download latest plugin version, based on plan. + * + * Not like _download_latest(), this will redirect the page + * to secure download url to prevent dual download (from FS to WP server, + * and then from WP server to the client / browser). + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @param bool|number $plugin_id + * + * @uses FS_Api + * @uses wp_redirect() + */ + private function _download_latest_directly( $plugin_id = false ) { + $this->_logger->entrance(); + + wp_redirect( $this->_get_latest_download_api_url( $plugin_id ) ); + } + + /** + * Get latest plugin FS API download URL. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @param bool|number $plugin_id + * + * @return string + */ + private function _get_latest_download_api_url( $plugin_id = false ) { + $this->_logger->entrance(); + + return $this->get_api_site_scope()->get_signed_url( + $this->_get_latest_version_endpoint( $plugin_id, 'zip' ) + ); + } + + /** + * Get latest plugin download link. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @param string $label + * @param bool|number $plugin_id + * + * @return string + */ + private function _get_latest_download_link( $label, $plugin_id = false ) { + return sprintf( + '<a target="_blank" href="%s">%s</a>', + $this->_get_latest_download_local_url( $plugin_id ), + $label + ); + } + + /** + * Get latest plugin download local URL. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @param bool|number $plugin_id + * + * @return string + */ + function _get_latest_download_local_url( $plugin_id = false ) { + // Add timestamp to protect from caching. + $params = array( 'ts' => WP_FS__SCRIPT_START_TIME ); + + if ( ! empty( $plugin_id ) ) { + $params['plugin_id'] = $plugin_id; + } + + return $this->get_account_url( 'download_latest', $params ); + } + + #endregion Download Plugin ------------------------------------------------------------------ + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + * + * @uses FS_Api + * + * @param bool $background Hints the method if it's a background updates check. If false, it means that + * was initiated by the admin. + * @param bool|number $plugin_id + * @param bool $flush Since 1.1.7.3 + */ + private function _check_updates( $background = false, $plugin_id = false, $flush = true ) { + $this->_logger->entrance(); + + // Check if there's a newer version for download. + $new_version = $this->_fetch_newer_version( $plugin_id, $flush ); + + $update = null; + if ( is_object( $new_version ) ) { + $update = new FS_Plugin_Tag( $new_version ); + + if ( ! $background ) { + $this->_admin_notices->add( + sprintf( + __fs( 'version-x-released', $this->_slug ) . ' ' . __fs( 'please-download-x', $this->_slug ), + $update->version, + sprintf( + '<a href="%s" target="_blank">%s</a>', + $this->get_account_url( 'download_latest' ), + sprintf( __fs( 'latest-x-version', $this->_slug ), $this->_site->plan->title ) + ) + ), + __fs( 'new', $this->_slug ) . '!' + ); + } + } else if ( false === $new_version && ! $background ) { + $this->_admin_notices->add( + __fs( 'you-have-latest', $this->_slug ), + __fs( 'you-are-good', $this->_slug ) + ); + } + + $this->_store_update( $update, true, $plugin_id ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + * + * @param bool $flush Since 1.1.7.3 by default add 24 hour cache. + * + * @return FS_Plugin[] + * + * @uses FS_Api + */ + private function _sync_addons( $flush = false ) { + $this->_logger->entrance(); + + $result = $this->get_api_site_or_plugin_scope()->get( '/addons.json?enriched=true', $flush ); + + $addons = array(); + if ( ! $this->is_api_error( $result ) ) { + for ( $i = 0, $len = count( $result->plugins ); $i < $len; $i ++ ) { + $addons[ $i ] = new FS_Plugin( $result->plugins[ $i ] ); + } + + $this->_store_addons( $addons, true ); + } + + return $addons; + } + + /** + * Handle user email update. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.3 + * @uses FS_Api + * + * @param string $new_email + * + * @return object + */ + private function _update_email( $new_email ) { + $this->_logger->entrance(); + + + $api = $this->get_api_user_scope(); + $user = $api->call( "?plugin_id={$this->_plugin->id}&fields=id,email,is_verified", 'put', array( + 'email' => $new_email, + 'after_email_confirm_url' => $this->_get_admin_page_url( + 'account', + array( 'fs_action' => 'sync_user' ) + ), + ) ); + + if ( ! isset( $user->error ) ) { + $this->_user->email = $user->email; + $this->_user->is_verified = $user->is_verified; + $this->_store_user(); + } else { + // handle different error cases. + + } + + return $user; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.1 + * + * @param mixed $result + * + * @return bool Is API result contains an error. + */ + private function is_api_error( $result ) { + return ( is_object( $result ) && isset( $result->error ) ) || + is_string( $result ); + } + + /** + * Start install ownership change. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.1 + * @uses FS_Api + * + * @param string $candidate_email + * + * @return bool Is ownership change successfully initiated. + */ + private function init_change_owner( $candidate_email ) { + $this->_logger->entrance(); + + $api = $this->get_api_site_scope(); + $result = $api->call( "/users/{$this->_user->id}.json", 'put', array( + 'email' => $candidate_email, + 'after_confirm_url' => $this->_get_admin_page_url( + 'account', + array( 'fs_action' => 'change_owner' ) + ), + ) ); + + return ! $this->is_api_error( $result ); + } + + /** + * Handle install ownership change. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.1 + * @uses FS_Api + * + * @return bool Was ownership change successfully complete. + */ + private function complete_change_owner() { + $this->_logger->entrance(); + + $site_result = $this->get_api_site_scope( true )->get(); + $site = new FS_Site( $site_result ); + $this->_site = $site; + + $user = new FS_User(); + $user->id = fs_request_get( 'user_id' ); + + // Validate install's user and given user. + if ( $user->id != $this->_site->user_id ) { + return false; + } + + $user->public_key = fs_request_get( 'user_public_key' ); + $user->secret_key = fs_request_get( 'user_secret_key' ); + + // Fetch new user information. + $this->_user = $user; + $user_result = $this->get_api_user_scope( true )->get(); + $user = new FS_User( $user_result ); + $this->_user = $user; + + $this->_set_account( $user, $site ); + + return true; + } + + /** + * Handle user name update. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * @uses FS_Api + * + * @return object + */ + private function update_user_name() { + $this->_logger->entrance(); + $name = fs_request_get( 'fs_user_name_' . $this->_slug, '' ); + + $api = $this->get_api_user_scope(); + $user = $api->call( "?plugin_id={$this->_plugin->id}&fields=id,first,last", 'put', array( + 'name' => $name, + ) ); + + if ( ! isset( $user->error ) ) { + $this->_user->first = $user->first; + $this->_user->last = $user->last; + $this->_store_user(); + } else { + // handle different error cases. + + } + + return $user; + } + + /** + * Verify user email. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.3 + * @uses FS_Api + */ + private function verify_email() { + $this->_handle_account_user_sync(); + + if ( $this->_user->is_verified() ) { + return; + } + + $api = $this->get_api_site_scope(); + $result = $api->call( "/users/{$this->_user->id}/verify.json", 'put', array( + 'after_email_confirm_url' => $this->_get_admin_page_url( + 'account', + array( 'fs_action' => 'sync_user' ) + ) + ) ); + + if ( ! isset( $result->error ) ) { + $this->_admin_notices->add( sprintf( + __fs( 'verification-email-sent-message', $this->_slug ), + sprintf( '<a href="mailto:%1s">%2s</a>', esc_url( $this->_user->email ), $this->_user->email ) + ) ); + } else { + // handle different error cases. + + } + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.2 + * + * @return string + */ + private function get_activation_url() { + return $this->apply_filters( 'connect_url', $this->_get_admin_page_url() ); + } + + /** + * Get the URL of the page that should be loaded after the user connect or skip in the opt-in screen. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.3 + * + * @param string $filter Filter name. + * + * @return string + */ + private function get_after_activation_url( $filter ) { + $first_time_path = $this->_menu->get_first_time_path(); + + return $this->apply_filters( + $filter, + empty( $first_time_path ) ? + $this->_get_admin_page_url() : + $first_time_path + ); + } + + /** + * Handle account page updates / edits / actions. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.2 + * + */ + private function _handle_account_edits() { + if ( ! current_user_can( 'activate_plugins' ) ) { + return; + } + + $plugin_id = fs_request_get( 'plugin_id', $this->get_id() ); + $action = fs_get_action(); + + switch ( $action ) { + case 'delete_account': + check_admin_referer( $action ); + + if ( $plugin_id == $this->get_id() ) { + $this->delete_account_event(); + + // Clear user and site. + $this->_site = null; + $this->_user = null; + + if ( fs_redirect( $this->get_activation_url() ) ) { + exit(); + } + } else { + if ( $this->is_addon_activated( $plugin_id ) ) { + $fs_addon = self::get_instance_by_id( $plugin_id ); + $fs_addon->delete_account_event(); + + if ( fs_redirect( $this->_get_admin_page_url( 'account' ) ) ) { + exit(); + } + } + } + + return; + + case 'downgrade_account': + check_admin_referer( $action ); + $this->_downgrade_site(); + + return; + + case 'activate_license': + check_admin_referer( $action ); + + if ( $plugin_id == $this->get_id() ) { + $this->_activate_license(); + } else { + if ( $this->is_addon_activated( $plugin_id ) ) { + $fs_addon = self::get_instance_by_id( $plugin_id ); + $fs_addon->_activate_license(); + } + } + + return; + + case 'deactivate_license': + check_admin_referer( $action ); + + if ( $plugin_id == $this->get_id() ) { + $this->_deactivate_license(); + } else { + if ( $this->is_addon_activated( $plugin_id ) ) { + $fs_addon = self::get_instance_by_id( $plugin_id ); + $fs_addon->_deactivate_license(); + } + } + + return; + + case 'check_updates': + check_admin_referer( $action ); + $this->_check_updates(); + + return; + + case 'change_owner': + $state = fs_request_get( 'state', 'init' ); + switch ( $state ) { + case 'init': + $candidate_email = fs_request_get( 'candidate_email', '' ); + + if ( $this->init_change_owner( $candidate_email ) ) { + $this->_admin_notices->add( sprintf( __fs( 'change-owner-request-sent-x', $this->_slug ), '<b>' . $this->_user->email . '</b>' ) ); + } + break; + case 'owner_confirmed': + $candidate_email = fs_request_get( 'candidate_email', '' ); + + $this->_admin_notices->add( sprintf( __fs( 'change-owner-request_owner-confirmed', $this->_slug ), '<b>' . $candidate_email . '</b>' ) ); + break; + case 'candidate_confirmed': + if ( $this->complete_change_owner() ) { + $this->_admin_notices->add_sticky( + sprintf( __fs( 'change-owner-request_candidate-confirmed', $this->_slug ), '<b>' . $this->_user->email . '</b>' ), + 'ownership_changed', + __fs( 'congrats', $this->_slug ) . '!' + ); + } else { + // @todo Handle failed ownership change message. + } + break; + } + + return; + + case 'update_email': + check_admin_referer( 'update_email' ); + + $new_email = fs_request_get( 'fs_email_' . $this->_slug, '' ); + $result = $this->_update_email( $new_email ); + + if ( isset( $result->error ) ) { + switch ( $result->error->code ) { + case 'user_exist': + $this->_admin_notices->add( + __fs( 'user-exist-message', $this->_slug ) . ' ' . + sprintf( __fs( 'user-exist-message_ownership', $this->_slug ), '<b>' . $new_email . '</b>' ) . + sprintf( + '<a style="margin-left: 10px;" href="%s"><button class="button button-primary">%s ➜</button></a>', + $this->get_account_url( 'change_owner', array( + 'state' => 'init', + 'candidate_email' => $new_email + ) ), + __fs( 'change-ownership', $this->_slug ) + ), + __fs( 'oops', $this->_slug ) . '...', + 'error' + ); + break; + } + } else { + $this->_admin_notices->add( __fs( 'email-updated-message', $this->_slug ) ); + } + + return; + + case 'update_user_name': + check_admin_referer( 'update_user_name' ); + + $result = $this->update_user_name(); + + if ( isset( $result->error ) ) { + $this->_admin_notices->add( + __fs( 'name-update-failed-message', $this->_slug ), + __fs( 'oops', $this->_slug ) . '...', + 'error' + ); + } else { + $this->_admin_notices->add( __fs( 'name-updated-message', $this->_slug ) ); + } + + return; + + #region Actions that might be called from external links (e.g. email) + + case 'cancel_trial': + if ( $plugin_id == $this->get_id() ) { + $this->_cancel_trial(); + } else { + if ( $this->is_addon_activated( $plugin_id ) ) { + $fs_addon = self::get_instance_by_id( $plugin_id ); + $fs_addon->_cancel_trial(); + } + } + + return; + + case 'verify_email': + $this->verify_email(); + + return; + + case 'sync_user': + $this->_handle_account_user_sync(); + + return; + + case $this->_slug . '_sync_license': + $this->_sync_license(); + + return; + + case 'download_latest': + $this->_download_latest_directly( $plugin_id ); + + return; + + #endregion + } + + if ( WP_FS__IS_POST_REQUEST ) { + $properties = array( 'site_secret_key', 'site_id', 'site_public_key' ); + foreach ( $properties as $p ) { + if ( 'update_' . $p === $action ) { + check_admin_referer( $action ); + + $this->_logger->log( $action ); + + $site_property = substr( $p, strlen( 'site_' ) ); + $site_property_value = fs_request_get( 'fs_' . $p . '_' . $this->_slug, '' ); + $this->get_site()->{$site_property} = $site_property_value; + + // Store account after modification. + $this->_store_site(); + + $this->do_action( 'account_property_edit', 'site', $site_property, $site_property_value ); + + $this->_admin_notices->add( sprintf( + __fs( 'x-updated', $this->_slug ), + '<b>' . str_replace( '_', ' ', $p ) . '</b>' ) ); + + return; + } + } + } + } + + /** + * Account page resources load. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + */ + function _account_page_load() { + $this->_logger->entrance(); + + $this->_logger->info( var_export( $_REQUEST, true ) ); + + fs_enqueue_local_style( 'fs_account', '/admin/account.css' ); + + if ( $this->has_addons() ) { + wp_enqueue_script( 'plugin-install' ); + add_thickbox(); + + function fs_addons_body_class( $classes ) { + $classes .= ' plugins-php'; + + return $classes; + } + + add_filter( 'admin_body_class', 'fs_addons_body_class' ); + } + + if ( $this->has_paid_plan() && + ! $this->has_any_license() && + ! $this->is_sync_executed() + ) { + /** + * If no licenses found and no sync job was executed during the last 24 hours, + * just execute the sync job right away (blocking execution). + * + * @since 1.1.7.3 + */ + $this->run_manual_sync(); + } + + $this->_handle_account_edits(); + + $this->do_action( 'account_page_load_before_departure' ); + } + + /** + * Render account page. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.0 + */ + function _account_page_render() { + $this->_logger->entrance(); + + $vars = array( 'slug' => $this->_slug ); + fs_require_once_template( 'account.php', $vars ); + } + + /** + * Render account connect page. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + */ + function _connect_page_render() { + $this->_logger->entrance(); + + $vars = array( 'slug' => $this->_slug ); + fs_require_once_template( 'connect.php', $vars ); + } + + /** + * Load required resources before add-ons page render. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + */ + function _addons_page_load() { + $this->_logger->entrance(); + + fs_enqueue_local_style( 'fs_addons', '/admin/add-ons.css' ); + + wp_enqueue_script( 'plugin-install' ); + add_thickbox(); + + function fs_addons_body_class( $classes ) { + $classes .= ' plugins-php'; + + return $classes; + } + + add_filter( 'admin_body_class', 'fs_addons_body_class' ); + + if ( ! $this->is_registered() && $this->is_org_repo_compliant() ) { + $this->_admin_notices->add( + sprintf( __fs( 'addons-info-external-message', $this->_slug ), '<b>' . $this->get_plugin_name() . '</b>' ), + __fs( 'heads-up', $this->_slug ), + 'update-nag' + ); + } + } + + /** + * Render add-ons page. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + */ + function _addons_page_render() { + $this->_logger->entrance(); + + $vars = array( 'slug' => $this->_slug ); + fs_require_once_template( 'add-ons.php', $vars ); + } + + /* Pricing & Upgrade + ------------------------------------------------------------------------------------------------------------------*/ + /** + * Render pricing page. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.0 + */ + function _pricing_page_render() { + $this->_logger->entrance(); + + $vars = array( 'slug' => $this->_slug ); + + if ( 'true' === fs_request_get( 'checkout', false ) ) { + fs_require_once_template( 'checkout.php', $vars ); + } else { + fs_require_once_template( 'pricing.php', $vars ); + } + } + + #region Contact Us ------------------------------------------------------------------ + + /** + * Render contact-us page. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.3 + */ + function _contact_page_render() { + $this->_logger->entrance(); + + $vars = array( 'slug' => $this->_slug ); + fs_require_once_template( 'contact.php', $vars ); + } + + #endregion ------------------------------------------------------------------ + + /** + * Hide all admin notices to prevent distractions. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.3 + * + * @uses remove_all_actions() + */ + private static function _hide_admin_notices() { + remove_all_actions( 'admin_notices' ); + remove_all_actions( 'network_admin_notices' ); + remove_all_actions( 'all_admin_notices' ); + remove_all_actions( 'user_admin_notices' ); + } + + static function _clean_admin_content_section_hook() { + self::_hide_admin_notices(); + + // Hide footer. + echo '<style>#wpfooter { display: none !important; }</style>'; + } + + /** + * Attach to admin_head hook to hide all admin notices. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.3 + */ + static function _clean_admin_content_section() { + add_action( 'admin_head', 'Freemius::_clean_admin_content_section_hook' ); + } + + /* CSS & JavaScript + ------------------------------------------------------------------------------------------------------------------*/ + /* function _enqueue_script($handle, $src) { + $url = plugins_url( substr( WP_FS__DIR_JS, strlen( $this->_plugin_dir_path ) ) . '/assets/js/' . $src ); + + $this->_logger->entrance( 'script = ' . $url ); + + wp_enqueue_script( $handle, $url ); + }*/ + + /* SDK + ------------------------------------------------------------------------------------------------------------------*/ + private $_user_api; + + /** + * + * @author Vova Feldman (@svovaf) + * @since 1.0.2 + * + * @param bool $flush + * + * @return FS_Api + */ + function get_api_user_scope( $flush = false ) { + if ( ! isset( $this->_user_api ) || $flush ) { + $this->_user_api = FS_Api::instance( + $this->_slug, + 'user', + $this->_user->id, + $this->_user->public_key, + ! $this->is_live(), + $this->_user->secret_key + ); + } + + return $this->_user_api; + } + + private $_site_api; + + /** + * + * @author Vova Feldman (@svovaf) + * @since 1.0.2 + * + * @param bool $flush + * + * @return FS_Api + */ + function get_api_site_scope( $flush = false ) { + if ( ! isset( $this->_site_api ) || $flush ) { + $this->_site_api = FS_Api::instance( + $this->_slug, + 'install', + $this->_site->id, + $this->_site->public_key, + ! $this->is_live(), + $this->_site->secret_key + ); + } + + return $this->_site_api; + } + + private $_plugin_api; + + /** + * Get plugin public API scope. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + * + * @return FS_Api + */ + function get_api_plugin_scope() { + if ( ! isset( $this->_plugin_api ) ) { + $this->_plugin_api = FS_Api::instance( + $this->_slug, + 'plugin', + $this->_plugin->id, + $this->_plugin->public_key, + ! $this->is_live() + ); + } + + return $this->_plugin_api; + } + + /** + * Get site API scope object (fallback to public plugin scope when not registered). + * + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + * + * @return FS_Api + */ + function get_api_site_or_plugin_scope() { + return $this->is_registered() ? + $this->get_api_site_scope() : + $this->get_api_plugin_scope(); + } + + /** + * Show trial promotional notice (if any trial exist). + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @param $plans + */ + function _check_for_trial_plans( $plans ) { + $this->_storage->has_trial_plan = FS_Plan_Manager::instance()->has_trial_plan( $plans ); + } + + /** + * Show trial promotional notice (if any trial exist). + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + */ + function _add_trial_notice() { + // Check if trial already utilized. + if ( $this->_site->is_trial_utilized() ) { + return; + } + + // Check if already paying. + if ( $this->is_paying() ) { + return; + } + + // Check if trial message is already shown. + if ( $this->_admin_notices->has_sticky( 'trial_promotion' ) ) { + return; + } + + $trial_plans = FS_Plan_Manager::instance()->get_trial_plans( $this->_plans ); + $trial_plans_count = count( $trial_plans ); + + // Check if any of the plans contains trial. + if ( 0 === $trial_plans_count ) { + return; + } + + /** + * @var FS_Plugin_Plan $paid_plan + */ + $paid_plan = $trial_plans[0]; + $require_subscription = $paid_plan->is_require_subscription; + $upgrade_url = $this->get_trial_url(); + $cc_string = $require_subscription ? + sprintf( __fs( 'no-commitment-for-x-days', $this->_slug ), $paid_plan->trial_period ) : + __fs( 'no-cc-required', $this->_slug ) . '!'; + + + $total_paid_plans = count( $this->_plans ) - ( FS_Plan_Manager::instance()->has_free_plan( $this->_plans ) ? 1 : 0 ); + + if ( $total_paid_plans === $trial_plans_count ) { + // All paid plans have trials. + $message = sprintf( + __fs( 'hey', $this->_slug ) . '! ' . __fs( 'trial-x-promotion-message', $this->_slug ), + sprintf( '<b>%s</b>', $this->get_plugin_name() ), + strtolower( __fs( 'awesome', $this->_slug ) ), + $paid_plan->trial_period + ); + } else { + $plans_string = ''; + for ( $i = 0; $i < $trial_plans_count; $i ++ ) { + $plans_string .= sprintf( '<a href="%s">%s</a>', $upgrade_url, $trial_plans[ $i ]->title ); + + if ( $i < $trial_plans_count - 2 ) { + $plans_string .= ', '; + } else if ( $i == $trial_plans_count - 2 ) { + $plans_string .= ' and '; + } + } + + // Not all paid plans have trials. + $message = sprintf( + __fs( 'hey', $this->_slug ) . '! ' . __fs( 'trial-x-promotion-message', $this->_slug ), + sprintf( '<b>%s</b>', $this->get_plugin_name() ), + $plans_string, + $paid_plan->trial_period + ); + } + + $message .= ' ' . $cc_string; + + // Add start trial button. + $message .= ' ' . sprintf( + '<a style="margin-left: 10px; vertical-align: super;" href="%s"><button class="button button-primary">%s ➜</button></a>', + $upgrade_url, + __fs( 'start-free-trial', $this->_slug ) + ); + + $this->_admin_notices->add_sticky( + $this->apply_filters( 'trial_promotion_message', $message ), + 'trial_promotion', + '', + 'promotion' + ); + + $this->_storage->trial_promotion_shown = WP_FS__SCRIPT_START_TIME; + } + + /* Action Links + ------------------------------------------------------------------------------------------------------------------*/ + private $_action_links_hooked = false; + private $_action_links = array(); + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.0 + * + * @return bool + */ + private function is_plugin_action_links_hooked() { + $this->_logger->entrance( json_encode( $this->_action_links_hooked ) ); + + return $this->_action_links_hooked; + } + + /** + * Hook to plugin action links filter. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.0 + */ + private function hook_plugin_action_links() { + $this->_logger->entrance(); + + $this->_action_links_hooked = true; + + $this->_logger->log( 'Adding action links hooks.' ); + + // Add action link to settings page. + add_filter( 'plugin_action_links_' . $this->_plugin_basename, array( + &$this, + '_modify_plugin_action_links_hook' + ), WP_FS__DEFAULT_PRIORITY, 2 ); + add_filter( 'network_admin_plugin_action_links_' . $this->_plugin_basename, array( + &$this, + '_modify_plugin_action_links_hook' + ), WP_FS__DEFAULT_PRIORITY, 2 ); + } + + /** + * Add plugin action link. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.0 + * + * @param $label + * @param $url + * @param bool $external + * @param int $priority + * @param bool $key + */ + function add_plugin_action_link( $label, $url, $external = false, $priority = WP_FS__DEFAULT_PRIORITY, $key = false ) { + $this->_logger->entrance(); + + if ( ! isset( $this->_action_links[ $priority ] ) ) { + $this->_action_links[ $priority ] = array(); + } + + if ( false === $key ) { + $key = preg_replace( "/[^A-Za-z0-9 ]/", '', strtolower( $label ) ); + } + + $this->_action_links[ $priority ][] = array( + 'label' => $label, + 'href' => $url, + 'key' => $key, + 'external' => $external + ); + } + + /** + * Adds Upgrade and Add-Ons links to the main Plugins page link actions collection. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.0 + */ + function _add_upgrade_action_link() { + $this->_logger->entrance(); + + if ( $this->is_registered() ) { + if ( ! $this->is_paying() && $this->has_paid_plan() ) { + $this->add_plugin_action_link( + __fs( 'upgrade', $this->_slug ), + $this->get_upgrade_url(), + false, + 7, + 'upgrade' + ); + } + + if ( $this->has_addons() ) { + $this->add_plugin_action_link( + __fs( 'add-ons', $this->_slug ), + $this->_get_admin_page_url( 'addons' ), + false, + 9, + 'addons' + ); + } + } + } + + /** + * Get the URL of the page that should be loaded right after the plugin activation. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.7.4 + * + * @return string + */ + function get_after_plugin_activation_redirect_url() { + $url = false; + $plugin_fs = false; + + if ( ! $this->is_addon() ) { + $first_time_path = $this->_menu->get_first_time_path(); + $plugin_fs = $this; + $url = $plugin_fs->is_activation_mode() ? + $plugin_fs->get_activation_url() : + ( empty( $first_time_path ) ? + $this->_get_admin_page_url() : + $first_time_path ); + } else { + if ( $this->is_parent_plugin_installed() ) { + $plugin_fs = self::get_parent_instance(); + } + + if ( is_object( $plugin_fs ) ) { + if ( ! $plugin_fs->is_registered() ) { + // Forward to parent plugin connect when parent not registered. + $url = $plugin_fs->get_activation_url(); + } else { + // Forward to account page. + $url = $plugin_fs->_get_admin_page_url( 'account' ); + } + } + } + + return $url; + } + + /** + * Forward page to activation page. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.3 + */ + function _redirect_on_activation_hook() { + $url = $this->get_after_plugin_activation_redirect_url(); + + if ( is_string( $url ) ) { + fs_redirect( $url ); + exit(); + } + } + + /** + * Modify plugin's page action links collection. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.0 + * + * @param array $links + * @param $file + * + * @return array + */ + function _modify_plugin_action_links_hook( $links, $file ) { + $this->_logger->entrance(); + + $passed_deactivate = false; + $deactivate_link = ''; + $before_deactivate = array(); + $after_deactivate = array(); + foreach ( $links as $key => $link ) { + if ( 'deactivate' === $key ) { + $deactivate_link = $link; + $passed_deactivate = true; + continue; + } + + if ( ! $passed_deactivate ) { + $before_deactivate[ $key ] = $link; + } else { + $after_deactivate[ $key ] = $link; + } + } + + ksort( $this->_action_links ); + + foreach ( $this->_action_links as $new_links ) { + foreach ( $new_links as $link ) { + $before_deactivate[ $link['key'] ] = '<a href="' . $link['href'] . '"' . ( $link['external'] ? ' target="_blank"' : '' ) . '>' . $link['label'] . '</a>'; + } + } + + if ( ! empty( $deactivate_link ) ) { + if ( ! $this->is_paying_or_trial() || $this->is_premium() ) { + /* + * This HTML element is used to identify the correct plugin when attaching an event to its Deactivate link. + * + * If user is paying or in trial and have the free version installed, + * assume that the deactivation is for the upgrade process, so this is not needed. + */ + $deactivate_link .= '<i class="fs-slug" data-slug="' . $this->_slug . '"></i>'; + } + + // Append deactivation link. + $before_deactivate['deactivate'] = $deactivate_link; + } + + return array_merge( $before_deactivate, $after_deactivate ); + } + + /** + * Adds admin message. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + * + * @param string $message + * @param string $title + * @param string $type + */ + function add_admin_message( $message, $title = '', $type = 'success' ) { + $this->_admin_notices->add( $message, $title, $type ); + } + + /** + * Adds sticky admin message. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.0 + * + * @param string $message + * @param string $id + * @param string $title + * @param string $type + */ + function add_sticky_admin_message( $message, $id, $title = '', $type = 'success' ) { + $this->_admin_notices->add_sticky( $message, $id, $title, $type ); + } + + /* Plugin Auto-Updates (@since 1.0.4) + ------------------------------------------------------------------------------------------------------------------*/ + /** + * @var string[] + */ + private static $_auto_updated_plugins; + + /** + * @todo TEST IF IT WORKS!!! + * + * Include plugins for automatic updates based on stored settings. + * + * @see http://wordpress.stackexchange.com/questions/131394/how-do-i-exclude-plugins-from-getting-automatically-updated/131404#131404 + * + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + * + * @param bool $update Whether to update (not used for plugins) + * @param object $item The plugin's info + * + * @return bool + */ + static function _include_plugins_in_auto_update( $update, $item ) { + // Before version 3.8.2 the $item was the file name of the plugin, + // while in 3.8.2 statistics were added (https://core.trac.wordpress.org/changeset/27905). + $by_slug = ( (int) str_replace( '.', '', get_bloginfo( 'version' ) ) >= 382 ); + + if ( ! isset( self::$_auto_updated_plugins ) ) { + $plugins = self::$_accounts->get_option( 'plugins', array() ); + + $identifiers = array(); + foreach ( $plugins as $p ) { + /** + * @var FS_Plugin $p + */ + if ( isset( $p->auto_update ) && $p->auto_update ) { + $identifiers[] = ( $by_slug ? $p->slug : plugin_basename( $p->file ) ); + } + } + + self::$_auto_updated_plugins = $identifiers; + } + + if ( in_array( $by_slug ? $item->slug : $item, self::$_auto_updated_plugins ) ) { + return true; + } + + // Pass update decision to next filters + return $update; + } + + #region Versioning ------------------------------------------------------------------ + + /** + * Check if Freemius in SDK upgrade mode. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @return bool + */ + function is_sdk_upgrade_mode() { + return isset( $this->_storage->sdk_upgrade_mode ) ? + $this->_storage->sdk_upgrade_mode : + false; + } + + /** + * Turn SDK upgrade mode off. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @return bool + */ + function set_sdk_upgrade_complete() { + $this->_storage->sdk_upgrade_mode = false; + } + + /** + * Check if plugin upgrade mode. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @return bool + */ + function is_plugin_upgrade_mode() { + return isset( $this->_storage->plugin_upgrade_mode ) ? + $this->_storage->plugin_upgrade_mode : + false; + } + + /** + * Turn plugin upgrade mode off. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @return bool + */ + function set_plugin_upgrade_complete() { + $this->_storage->plugin_upgrade_mode = false; + } + + #endregion ------------------------------------------------------------------ + + #region Permissions ------------------------------------------------------------------ + + /** + * Check if specific permission requested. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.6 + * + * @param string $permission + * + * @return bool + */ + function is_permission_requested( $permission ) { + return isset( $this->_permissions[ $permission ] ) && ( true === $this->_permissions[ $permission ] ); + } + + #endregion Permissions ------------------------------------------------------------------ + + #region Marketing ------------------------------------------------------------------ + + /** + * Check if current user purchased any other plugins before. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @return bool + */ + function has_purchased_before() { + // TODO: Implement has_purchased_before() method. + } + + /** + * Check if current user classified as an agency. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @return bool + */ + function is_agency() { + // TODO: Implement is_agency() method. + } + + /** + * Check if current user classified as a developer. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @return bool + */ + function is_developer() { + // TODO: Implement is_developer() method. + } + + /** + * Check if current user classified as a business. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @return bool + */ + function is_business() { + // TODO: Implement is_business() method. + } + + #endregion ------------------------------------------------------------------ } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/includes/class-fs-api.php b/wp-content/plugins/nextgen-gallery/freemius/includes/class-fs-api.php index d2a8a08ba001938a4691dbfc9f48802533963583..79bd2bf06fcca5208735a4e08bc43cc6f732dec4 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/includes/class-fs-api.php +++ b/wp-content/plugins/nextgen-gallery/freemius/includes/class-fs-api.php @@ -1,455 +1,455 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.4 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - /** - * Class FS_Api - * - * Wraps Freemius API SDK to handle: - * 1. Clock sync. - * 2. Fallback to HTTP when HTTPS fails. - * 3. Adds caching layer to GET requests. - * 4. Adds consistency for failed requests by using last cached version. - */ - class FS_Api { - /** - * @var FS_Api[] - */ - private static $_instances = array(); - - /** - * @var FS_Option_Manager Freemius options, options-manager. - */ - private static $_options; - - /** - * @var FS_Cache_Manager API Caching layer - */ - private static $_cache; - - /** - * @var int Clock diff in seconds between current server to API server. - */ - private static $_clock_diff; - - /** - * @var Freemius_Api - */ - private $_api; - - /** - * @var string - */ - private $_slug; - - /** - * @var FS_Logger - * @since 1.0.4 - */ - private $_logger; - - /** - * @param string $slug - * @param string $scope 'app', 'developer', 'user' or 'install'. - * @param number $id Element's id. - * @param string $public_key Public key. - * @param bool $is_sandbox - * @param bool|string $secret_key Element's secret key. - * - * @return FS_Api - */ - static function instance( $slug, $scope, $id, $public_key, $is_sandbox, $secret_key = false ) { - $identifier = md5( $slug . $scope . $id . $public_key . ( is_string( $secret_key ) ? $secret_key : '' ) . json_encode( $is_sandbox ) ); - - if ( ! isset( self::$_instances[ $identifier ] ) ) { - self::_init(); - - self::$_instances[ $identifier ] = new FS_Api( $slug, $scope, $id, $public_key, $secret_key, $is_sandbox ); - } - - return self::$_instances[ $identifier ]; - } - - private static function _init() { - if ( isset( self::$_options ) ) { - return; - } - - if ( ! class_exists( 'Freemius_Api' ) ) { - require_once( WP_FS__DIR_SDK . '/Freemius.php' ); - } - - self::$_options = FS_Option_Manager::get_manager( WP_FS__OPTIONS_OPTION_NAME, true ); - self::$_cache = FS_Cache_Manager::get_manager( WP_FS__API_CACHE_OPTION_NAME ); - - self::$_clock_diff = self::$_options->get_option( 'api_clock_diff', 0 ); - Freemius_Api::SetClockDiff( self::$_clock_diff ); - - if ( self::$_options->get_option( 'api_force_http', false ) ) { - Freemius_Api::SetHttp(); - } - } - - /** - * @param string $slug - * @param string $scope 'app', 'developer', 'user' or 'install'. - * @param number $id Element's id. - * @param string $public_key Public key. - * @param bool|string $secret_key Element's secret key. - * @param bool $is_sandbox - */ - private function __construct( $slug, $scope, $id, $public_key, $secret_key, $is_sandbox ) { - $this->_api = new Freemius_Api( $scope, $id, $public_key, $secret_key, $is_sandbox ); - - $this->_slug = $slug; - $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $slug . '_api', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); - } - - /** - * Find clock diff between server and API server, and store the diff locally. - * - * @param bool|int $diff - * - * @return bool|int False if clock diff didn't change, otherwise returns the clock diff in seconds. - */ - private function _sync_clock_diff( $diff = false ) { - $this->_logger->entrance(); - - // Sync clock and store. - $new_clock_diff = ( false === $diff ) ? - Freemius_Api::FindClockDiff() : - $diff; - - if ( $new_clock_diff === self::$_clock_diff ) { - return false; - } - - self::$_clock_diff = $new_clock_diff; - - // Update API clock's diff. - Freemius_Api::SetClockDiff( self::$_clock_diff ); - - // Store new clock diff in storage. - self::$_options->set_option( 'api_clock_diff', self::$_clock_diff, true ); - - return $new_clock_diff; - } - - /** - * Override API call to enable retry with servers' clock auto sync method. - * - * @param string $path - * @param string $method - * @param array $params - * @param bool $retry Is in retry or first call attempt. - * - * @return array|mixed|string|void - */ - private function _call( $path, $method = 'GET', $params = array(), $retry = false ) { - $this->_logger->entrance( $method . ':' . $path ); - - if ( self::is_temporary_down() ) { - $result = $this->get_temporary_unavailable_error(); - } else { - $result = $this->_api->Api( $path, $method, $params ); - - if ( null !== $result && - isset( $result->error ) && - isset( $result->error->code ) && - 'request_expired' === $result->error->code - ) { - if ( ! $retry ) { - $diff = isset( $result->error->timestamp ) ? - ( time() - strtotime( $result->error->timestamp ) ) : - false; - - // Try to sync clock diff. - if ( false !== $this->_sync_clock_diff( $diff ) ) { - // Retry call with new synced clock. - return $this->_call( $path, $method, $params, true ); - } - } - } - } - - if ( null !== $result && isset( $result->error ) && isset( $result->error->message ) ) { - // Log API errors. - $this->_logger->error( $result->error->message ); - } - - return $result; - } - - /** - * Override API call to wrap it in servers' clock sync method. - * - * @param string $path - * @param string $method - * @param array $params - * - * @return array|mixed|string|void - * @throws Freemius_Exception - */ - function call( $path, $method = 'GET', $params = array() ) { - return $this->_call( $path, $method, $params ); - } - - /** - * Get API request URL signed via query string. - * - * @param string $path - * - * @return string - */ - function get_signed_url( $path ) { - return $this->_api->GetSignedUrl( $path ); - } - - /** - * @param string $path - * @param bool $flush - * @param int $expiration (optional) Time until expiration in seconds from now, defaults to 24 hours - * - * @return stdClass|mixed - */ - function get( $path = '/', $flush = false, $expiration = WP_FS__TIME_24_HOURS_IN_SEC ) { - $this->_logger->entrance( $path ); - - $cache_key = $this->get_cache_key( $path ); - - // Always flush during development. - if ( WP_FS__DEV_MODE || $this->_api->IsSandbox() ) { - $flush = true; - } - - $cached_result = self::$_cache->get( $cache_key ); - - if ( $flush || ! self::$_cache->has_valid( $cache_key ) ) { - $result = $this->call( $path ); - - if ( ! is_object( $result ) || isset( $result->error ) ) { - // Api returned an error. - if ( is_object( $cached_result ) && - ! isset( $cached_result ) - ) { - // If there was an error during a newer data fetch, - // fallback to older data version. - $result = $cached_result; - } else { - // If no older data version, return result without - // caching the error. - return $result; - } - } - - self::$_cache->set( $cache_key, $result, $expiration ); - - $cached_result = $result; - } - - return $cached_result; - } - - private function get_cache_key( $path, $method = 'GET', $params = array() ) { - $canonized = $this->_api->CanonizePath( $path ); -// $exploded = explode('/', $canonized); -// return $method . '_' . array_pop($exploded) . '_' . md5($canonized . json_encode($params)); - return $method . ':' . $canonized . ( ! empty( $params ) ? '#' . md5( json_encode( $params ) ) : '' ); - } - - /** - * Test API connectivity. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 If fails, try to fallback to HTTP. - * @since 1.1.6 Added a 5-min caching mechanism, to prevent from overloading the server if the API if - * temporary down. - * - * @return bool True if successful connectivity to the API. - */ - static function test() { - self::_init(); - - $cache_key = 'ping_test'; - - $test = self::$_cache->get_valid( $cache_key, null ); - - if ( is_null( $test ) ) { - $test = Freemius_Api::Test(); - - if ( false === $test && Freemius_Api::IsHttps() ) { - // Fallback to HTTP, since HTTPS fails. - Freemius_Api::SetHttp(); - - self::$_options->set_option( 'api_force_http', true, true ); - - $test = Freemius_Api::Test(); - - if ( false === $test ) { - /** - * API connectivity test fail also in HTTP request, therefore, - * fallback to HTTPS to keep connection secure. - * - * @since 1.1.6 - */ - self::$_options->set_option( 'api_force_http', false, true ); - } - } - - self::$_cache->set( $cache_key, $test, WP_FS__TIME_5_MIN_IN_SEC ); - } - - return $test; - } - - /** - * Check if API is temporary down. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.6 - * - * @return bool - */ - static function is_temporary_down() { - self::_init(); - - $test = self::$_cache->get_valid( 'ping_test', null ); - - return ( false === $test ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.6 - * - * @return object - */ - private function get_temporary_unavailable_error() { - return (object) array( - 'error' => array( - 'type' => 'TemporaryUnavailable', - 'message' => 'API is temporary unavailable, please retry in ' . ( self::$_cache->get_record_expiration( 'ping_test' ) - WP_FS__SCRIPT_START_TIME ) . ' sec.', - 'code' => 'temporary_unavailable', - 'http' => 503 - ) - ); - } - - /** - * Ping API for connectivity test, and return result object. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @param null|string $unique_anonymous_id - * @param array $params - * - * @return object - */ - function ping( $unique_anonymous_id = null, $params = array() ) { - $this->_logger->entrance(); - - if ( self::is_temporary_down() ) { - return $this->get_temporary_unavailable_error(); - } - - $pong = is_null( $unique_anonymous_id ) ? - Freemius_Api::Ping() : - $this->_call( 'ping.json?' . http_build_query( array_merge( - array( 'uid' => $unique_anonymous_id ), - $params - ) ) ); - - if ( $this->is_valid_ping( $pong ) ) { - return $pong; - } - - if ( self::should_try_with_http( $pong ) ) { - // Fallback to HTTP, since HTTPS fails. - Freemius_Api::SetHttp(); - - self::$_options->set_option( 'api_force_http', true, true ); - - $pong = is_null( $unique_anonymous_id ) ? - Freemius_Api::Ping() : - $this->_call( 'ping.json?' . http_build_query( array_merge( - array( 'uid' => $unique_anonymous_id ), - $params - ) ) ); - - if ( ! $this->is_valid_ping( $pong ) ) { - self::$_options->set_option( 'api_force_http', false, true ); - } - } - - return $pong; - } - - /** - * Check if based on the API result we should try - * to re-run the same request with HTTP instead of HTTPS. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.6 - * - * @param $result - * - * @return bool - */ - private static function should_try_with_http( $result ) { - if ( ! Freemius_Api::IsHttps() ) { - return false; - } - - return ( ! is_object( $result ) || - ! isset( $result->error ) || - ! isset( $result->error->code ) || - ! in_array( $result->error->code, array( - 'curl_missing', - 'cloudflare_ddos_protection', - 'maintenance_mode', - 'squid_cache_block', - 'too_many_requests', - ) ) ); - - } - - /** - * Check if valid ping request result. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.1 - * - * @param mixed $pong - * - * @return bool - */ - function is_valid_ping( $pong ) { - return Freemius_Api::Test( $pong ); - } - - function get_url( $path = '' ) { - return Freemius_Api::GetUrl( $path, $this->_api->IsSandbox() ); - } - - /** - * Clear API cache. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - */ - static function clear_cache() { - self::_init(); - - self::$_cache = FS_Cache_Manager::get_manager( WP_FS__API_CACHE_OPTION_NAME ); - self::$_cache->clear( true ); - } +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.4 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + /** + * Class FS_Api + * + * Wraps Freemius API SDK to handle: + * 1. Clock sync. + * 2. Fallback to HTTP when HTTPS fails. + * 3. Adds caching layer to GET requests. + * 4. Adds consistency for failed requests by using last cached version. + */ + class FS_Api { + /** + * @var FS_Api[] + */ + private static $_instances = array(); + + /** + * @var FS_Option_Manager Freemius options, options-manager. + */ + private static $_options; + + /** + * @var FS_Cache_Manager API Caching layer + */ + private static $_cache; + + /** + * @var int Clock diff in seconds between current server to API server. + */ + private static $_clock_diff; + + /** + * @var Freemius_Api + */ + private $_api; + + /** + * @var string + */ + private $_slug; + + /** + * @var FS_Logger + * @since 1.0.4 + */ + private $_logger; + + /** + * @param string $slug + * @param string $scope 'app', 'developer', 'user' or 'install'. + * @param number $id Element's id. + * @param string $public_key Public key. + * @param bool $is_sandbox + * @param bool|string $secret_key Element's secret key. + * + * @return FS_Api + */ + static function instance( $slug, $scope, $id, $public_key, $is_sandbox, $secret_key = false ) { + $identifier = md5( $slug . $scope . $id . $public_key . ( is_string( $secret_key ) ? $secret_key : '' ) . json_encode( $is_sandbox ) ); + + if ( ! isset( self::$_instances[ $identifier ] ) ) { + self::_init(); + + self::$_instances[ $identifier ] = new FS_Api( $slug, $scope, $id, $public_key, $secret_key, $is_sandbox ); + } + + return self::$_instances[ $identifier ]; + } + + private static function _init() { + if ( isset( self::$_options ) ) { + return; + } + + if ( ! class_exists( 'Freemius_Api' ) ) { + require_once( WP_FS__DIR_SDK . '/Freemius.php' ); + } + + self::$_options = FS_Option_Manager::get_manager( WP_FS__OPTIONS_OPTION_NAME, true ); + self::$_cache = FS_Cache_Manager::get_manager( WP_FS__API_CACHE_OPTION_NAME ); + + self::$_clock_diff = self::$_options->get_option( 'api_clock_diff', 0 ); + Freemius_Api::SetClockDiff( self::$_clock_diff ); + + if ( self::$_options->get_option( 'api_force_http', false ) ) { + Freemius_Api::SetHttp(); + } + } + + /** + * @param string $slug + * @param string $scope 'app', 'developer', 'user' or 'install'. + * @param number $id Element's id. + * @param string $public_key Public key. + * @param bool|string $secret_key Element's secret key. + * @param bool $is_sandbox + */ + private function __construct( $slug, $scope, $id, $public_key, $secret_key, $is_sandbox ) { + $this->_api = new Freemius_Api( $scope, $id, $public_key, $secret_key, $is_sandbox ); + + $this->_slug = $slug; + $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $slug . '_api', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); + } + + /** + * Find clock diff between server and API server, and store the diff locally. + * + * @param bool|int $diff + * + * @return bool|int False if clock diff didn't change, otherwise returns the clock diff in seconds. + */ + private function _sync_clock_diff( $diff = false ) { + $this->_logger->entrance(); + + // Sync clock and store. + $new_clock_diff = ( false === $diff ) ? + Freemius_Api::FindClockDiff() : + $diff; + + if ( $new_clock_diff === self::$_clock_diff ) { + return false; + } + + self::$_clock_diff = $new_clock_diff; + + // Update API clock's diff. + Freemius_Api::SetClockDiff( self::$_clock_diff ); + + // Store new clock diff in storage. + self::$_options->set_option( 'api_clock_diff', self::$_clock_diff, true ); + + return $new_clock_diff; + } + + /** + * Override API call to enable retry with servers' clock auto sync method. + * + * @param string $path + * @param string $method + * @param array $params + * @param bool $retry Is in retry or first call attempt. + * + * @return array|mixed|string|void + */ + private function _call( $path, $method = 'GET', $params = array(), $retry = false ) { + $this->_logger->entrance( $method . ':' . $path ); + + if ( self::is_temporary_down() ) { + $result = $this->get_temporary_unavailable_error(); + } else { + $result = $this->_api->Api( $path, $method, $params ); + + if ( null !== $result && + isset( $result->error ) && + isset( $result->error->code ) && + 'request_expired' === $result->error->code + ) { + if ( ! $retry ) { + $diff = isset( $result->error->timestamp ) ? + ( time() - strtotime( $result->error->timestamp ) ) : + false; + + // Try to sync clock diff. + if ( false !== $this->_sync_clock_diff( $diff ) ) { + // Retry call with new synced clock. + return $this->_call( $path, $method, $params, true ); + } + } + } + } + + if ( null !== $result && isset( $result->error ) && isset( $result->error->message ) ) { + // Log API errors. + $this->_logger->error( $result->error->message ); + } + + return $result; + } + + /** + * Override API call to wrap it in servers' clock sync method. + * + * @param string $path + * @param string $method + * @param array $params + * + * @return array|mixed|string|void + * @throws Freemius_Exception + */ + function call( $path, $method = 'GET', $params = array() ) { + return $this->_call( $path, $method, $params ); + } + + /** + * Get API request URL signed via query string. + * + * @param string $path + * + * @return string + */ + function get_signed_url( $path ) { + return $this->_api->GetSignedUrl( $path ); + } + + /** + * @param string $path + * @param bool $flush + * @param int $expiration (optional) Time until expiration in seconds from now, defaults to 24 hours + * + * @return stdClass|mixed + */ + function get( $path = '/', $flush = false, $expiration = WP_FS__TIME_24_HOURS_IN_SEC ) { + $this->_logger->entrance( $path ); + + $cache_key = $this->get_cache_key( $path ); + + // Always flush during development. + if ( WP_FS__DEV_MODE || $this->_api->IsSandbox() ) { + $flush = true; + } + + $cached_result = self::$_cache->get( $cache_key ); + + if ( $flush || ! self::$_cache->has_valid( $cache_key ) ) { + $result = $this->call( $path ); + + if ( ! is_object( $result ) || isset( $result->error ) ) { + // Api returned an error. + if ( is_object( $cached_result ) && + ! isset( $cached_result ) + ) { + // If there was an error during a newer data fetch, + // fallback to older data version. + $result = $cached_result; + } else { + // If no older data version, return result without + // caching the error. + return $result; + } + } + + self::$_cache->set( $cache_key, $result, $expiration ); + + $cached_result = $result; + } + + return $cached_result; + } + + private function get_cache_key( $path, $method = 'GET', $params = array() ) { + $canonized = $this->_api->CanonizePath( $path ); +// $exploded = explode('/', $canonized); +// return $method . '_' . array_pop($exploded) . '_' . md5($canonized . json_encode($params)); + return $method . ':' . $canonized . ( ! empty( $params ) ? '#' . md5( json_encode( $params ) ) : '' ); + } + + /** + * Test API connectivity. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 If fails, try to fallback to HTTP. + * @since 1.1.6 Added a 5-min caching mechanism, to prevent from overloading the server if the API if + * temporary down. + * + * @return bool True if successful connectivity to the API. + */ + static function test() { + self::_init(); + + $cache_key = 'ping_test'; + + $test = self::$_cache->get_valid( $cache_key, null ); + + if ( is_null( $test ) ) { + $test = Freemius_Api::Test(); + + if ( false === $test && Freemius_Api::IsHttps() ) { + // Fallback to HTTP, since HTTPS fails. + Freemius_Api::SetHttp(); + + self::$_options->set_option( 'api_force_http', true, true ); + + $test = Freemius_Api::Test(); + + if ( false === $test ) { + /** + * API connectivity test fail also in HTTP request, therefore, + * fallback to HTTPS to keep connection secure. + * + * @since 1.1.6 + */ + self::$_options->set_option( 'api_force_http', false, true ); + } + } + + self::$_cache->set( $cache_key, $test, WP_FS__TIME_5_MIN_IN_SEC ); + } + + return $test; + } + + /** + * Check if API is temporary down. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.6 + * + * @return bool + */ + static function is_temporary_down() { + self::_init(); + + $test = self::$_cache->get_valid( 'ping_test', null ); + + return ( false === $test ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.6 + * + * @return object + */ + private function get_temporary_unavailable_error() { + return (object) array( + 'error' => array( + 'type' => 'TemporaryUnavailable', + 'message' => 'API is temporary unavailable, please retry in ' . ( self::$_cache->get_record_expiration( 'ping_test' ) - WP_FS__SCRIPT_START_TIME ) . ' sec.', + 'code' => 'temporary_unavailable', + 'http' => 503 + ) + ); + } + + /** + * Ping API for connectivity test, and return result object. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @param null|string $unique_anonymous_id + * @param array $params + * + * @return object + */ + function ping( $unique_anonymous_id = null, $params = array() ) { + $this->_logger->entrance(); + + if ( self::is_temporary_down() ) { + return $this->get_temporary_unavailable_error(); + } + + $pong = is_null( $unique_anonymous_id ) ? + Freemius_Api::Ping() : + $this->_call( 'ping.json?' . http_build_query( array_merge( + array( 'uid' => $unique_anonymous_id ), + $params + ) ) ); + + if ( $this->is_valid_ping( $pong ) ) { + return $pong; + } + + if ( self::should_try_with_http( $pong ) ) { + // Fallback to HTTP, since HTTPS fails. + Freemius_Api::SetHttp(); + + self::$_options->set_option( 'api_force_http', true, true ); + + $pong = is_null( $unique_anonymous_id ) ? + Freemius_Api::Ping() : + $this->_call( 'ping.json?' . http_build_query( array_merge( + array( 'uid' => $unique_anonymous_id ), + $params + ) ) ); + + if ( ! $this->is_valid_ping( $pong ) ) { + self::$_options->set_option( 'api_force_http', false, true ); + } + } + + return $pong; + } + + /** + * Check if based on the API result we should try + * to re-run the same request with HTTP instead of HTTPS. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.6 + * + * @param $result + * + * @return bool + */ + private static function should_try_with_http( $result ) { + if ( ! Freemius_Api::IsHttps() ) { + return false; + } + + return ( ! is_object( $result ) || + ! isset( $result->error ) || + ! isset( $result->error->code ) || + ! in_array( $result->error->code, array( + 'curl_missing', + 'cloudflare_ddos_protection', + 'maintenance_mode', + 'squid_cache_block', + 'too_many_requests', + ) ) ); + + } + + /** + * Check if valid ping request result. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.1 + * + * @param mixed $pong + * + * @return bool + */ + function is_valid_ping( $pong ) { + return Freemius_Api::Test( $pong ); + } + + function get_url( $path = '' ) { + return Freemius_Api::GetUrl( $path, $this->_api->IsSandbox() ); + } + + /** + * Clear API cache. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + */ + static function clear_cache() { + self::_init(); + + self::$_cache = FS_Cache_Manager::get_manager( WP_FS__API_CACHE_OPTION_NAME ); + self::$_cache->clear( true ); + } } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/includes/class-fs-logger.php b/wp-content/plugins/nextgen-gallery/freemius/includes/class-fs-logger.php index 6f5fc76ac11a7af8c10669027c13878f25216ae0..420676122b5408285cf17a387a50f51585f00bde 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/includes/class-fs-logger.php +++ b/wp-content/plugins/nextgen-gallery/freemius/includes/class-fs-logger.php @@ -1,179 +1,179 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.3 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - class FS_Logger { - private $_id; - private $_on = false; - private $_echo = false; - private $_file_start = 0; - - private static $LOGGERS = array(); - private static $LOG = array(); - private static $CNT = 0; - private static $_HOOKED_FOOTER = false; - - private function __construct( $id, $on = false, $echo = false ) { - $this->_id = $id; - - $bt = debug_backtrace(); - $caller = $bt[2]; - - $this->_file_start = strpos( $caller['file'], 'plugins' ) + strlen( 'plugins/' ); - - if ( $on ) { - $this->on(); - } - if ( $echo ) { - $this->echo_on(); - } - } - - /** - * @param string $id - * @param bool $on - * @param bool $echo - * - * @return FS_Logger - */ - public static function get_logger( $id, $on = false, $echo = false ) { - $id = strtolower( $id ); - - if ( ! isset( self::$LOGGERS[ $id ] ) ) { - self::$LOGGERS[ $id ] = new FS_Logger( $id, $on, $echo ); - } - - return self::$LOGGERS[ $id ]; - } - - private static function _hook_footer() { - if ( self::$_HOOKED_FOOTER ) { - return; - } - - if ( is_admin() ) { - add_action( 'admin_footer', 'FS_Logger::dump', 100 ); - } else { - add_action( 'wp_footer', 'FS_Logger::dump', 100 ); - } - } - - function is_on() { - return $this->_on; - } - - function on() { - $this->_on = true; - - self::_hook_footer(); - } - - function echo_on() { - $this->on(); - - $this->_echo = true; - } - - function is_echo_on() { - return $this->_echo; - } - - function get_id() { - return $this->_id; - } - - function get_file() { - return $this->_file_start; - } - - private function _log( &$message, $type = 'log', $wrapper ) { - if ( ! $this->is_on() ) { - return; - } - - $bt = debug_backtrace(); - $depth = $wrapper ? 3 : 2; - while ( $depth < count( $bt ) - 1 && 'eval' === $bt[ $depth ]['function'] ) { - $depth ++; - } - - $caller = $bt[ $depth ]; - - $log = array_merge( $caller, array( - 'cnt' => self::$CNT ++, - 'logger' => $this, - 'timestamp' => microtime(true), - 'type' => $type, - 'msg' => $message, - ) ); - - self::$LOG[] = $log; - - if ( $this->is_echo_on() ) { - echo self::format_html( $log ) . "\n"; - } - } - - function log( $message, $wrapper = false ) { - $this->_log( $message, 'log', $wrapper ); - } - - function info( $message, $wrapper = false ) { - $this->_log( $message, 'info', $wrapper ); - } - - function warn( $message, $wrapper = false ) { - $this->_log( $message, 'warn', $wrapper ); - } - - function error( $message, $wrapper = false ) { - $this->_log( $message, 'error', $wrapper ); - } - - function entrance( $message = '', $wrapper = false ) { - $msg = 'Entrance' . ( empty( $message ) ? '' : ' > ' ) . $message; - - $this->_log( $msg, 'log', $wrapper ); - } - - function departure( $message = '', $wrapper = false ) { - $msg = 'Departure' . ( empty( $message ) ? '' : ' > ' ) . $message; - - $this->_log( $msg, 'log', $wrapper ); - } - - private static function format( $log, $show_type = true ) { - return '[' . str_pad( $log['cnt'], strlen( self::$CNT ), '0', STR_PAD_LEFT ) . '] [' . $log['logger']->_id . '] ' . ( $show_type ? '[' . $log['type'] . ']' : '' ) . $log['function'] . ' >> ' . $log['msg'] . ( isset( $log['file'] ) ? ' (' . substr( $log['file'], $log['logger']->_file_start ) . ' ' . $log['line'] . ') ' : '' ) . ' [' . $log['timestamp'] . ']'; - } - - private static function format_html( $log ) { - return '<div style="font-size: 11px; padding: 3px; background: #ccc; margin-bottom: 3px;">[' . $log['cnt'] . '] [' . $log['logger']->_id . '] [' . $log['type'] . '] <b><code style="color: blue;">' . $log['function'] . '</code> >> <b style="color: darkorange;">' . $log['msg'] . '</b></b>' . ( isset( $log['file'] ) ? ' (' . substr( $log['file'], $log['logger']->_file_start ) . ' ' . $log['line'] . ')' : '' ) . ' [' . $log['timestamp'] . ']</div>'; - } - - static function dump() { - ?> - <!-- BEGIN: Freemius PHP Console Log --> - <script type="text/javascript"> - <?php - foreach (self::$LOG as $log) - { - echo 'console.' . $log['type'] . '(' . json_encode(self::format($log, false)) . ')' . "\n"; - } - ?> - </script> - <!-- END: Freemius PHP Console Log --> - <?php - } - - static function get_log() { - return self::$LOG; - } +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.3 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + class FS_Logger { + private $_id; + private $_on = false; + private $_echo = false; + private $_file_start = 0; + + private static $LOGGERS = array(); + private static $LOG = array(); + private static $CNT = 0; + private static $_HOOKED_FOOTER = false; + + private function __construct( $id, $on = false, $echo = false ) { + $this->_id = $id; + + $bt = debug_backtrace(); + $caller = $bt[2]; + + $this->_file_start = strpos( $caller['file'], 'plugins' ) + strlen( 'plugins/' ); + + if ( $on ) { + $this->on(); + } + if ( $echo ) { + $this->echo_on(); + } + } + + /** + * @param string $id + * @param bool $on + * @param bool $echo + * + * @return FS_Logger + */ + public static function get_logger( $id, $on = false, $echo = false ) { + $id = strtolower( $id ); + + if ( ! isset( self::$LOGGERS[ $id ] ) ) { + self::$LOGGERS[ $id ] = new FS_Logger( $id, $on, $echo ); + } + + return self::$LOGGERS[ $id ]; + } + + private static function _hook_footer() { + if ( self::$_HOOKED_FOOTER ) { + return; + } + + if ( is_admin() ) { + add_action( 'admin_footer', 'FS_Logger::dump', 100 ); + } else { + add_action( 'wp_footer', 'FS_Logger::dump', 100 ); + } + } + + function is_on() { + return $this->_on; + } + + function on() { + $this->_on = true; + + self::_hook_footer(); + } + + function echo_on() { + $this->on(); + + $this->_echo = true; + } + + function is_echo_on() { + return $this->_echo; + } + + function get_id() { + return $this->_id; + } + + function get_file() { + return $this->_file_start; + } + + private function _log( &$message, $type = 'log', $wrapper ) { + if ( ! $this->is_on() ) { + return; + } + + $bt = debug_backtrace(); + $depth = $wrapper ? 3 : 2; + while ( $depth < count( $bt ) - 1 && 'eval' === $bt[ $depth ]['function'] ) { + $depth ++; + } + + $caller = $bt[ $depth ]; + + $log = array_merge( $caller, array( + 'cnt' => self::$CNT ++, + 'logger' => $this, + 'timestamp' => microtime(true), + 'type' => $type, + 'msg' => $message, + ) ); + + self::$LOG[] = $log; + + if ( $this->is_echo_on() ) { + echo self::format_html( $log ) . "\n"; + } + } + + function log( $message, $wrapper = false ) { + $this->_log( $message, 'log', $wrapper ); + } + + function info( $message, $wrapper = false ) { + $this->_log( $message, 'info', $wrapper ); + } + + function warn( $message, $wrapper = false ) { + $this->_log( $message, 'warn', $wrapper ); + } + + function error( $message, $wrapper = false ) { + $this->_log( $message, 'error', $wrapper ); + } + + function entrance( $message = '', $wrapper = false ) { + $msg = 'Entrance' . ( empty( $message ) ? '' : ' > ' ) . $message; + + $this->_log( $msg, 'log', $wrapper ); + } + + function departure( $message = '', $wrapper = false ) { + $msg = 'Departure' . ( empty( $message ) ? '' : ' > ' ) . $message; + + $this->_log( $msg, 'log', $wrapper ); + } + + private static function format( $log, $show_type = true ) { + return '[' . str_pad( $log['cnt'], strlen( self::$CNT ), '0', STR_PAD_LEFT ) . '] [' . $log['logger']->_id . '] ' . ( $show_type ? '[' . $log['type'] . ']' : '' ) . $log['function'] . ' >> ' . $log['msg'] . ( isset( $log['file'] ) ? ' (' . substr( $log['file'], $log['logger']->_file_start ) . ' ' . $log['line'] . ') ' : '' ) . ' [' . $log['timestamp'] . ']'; + } + + private static function format_html( $log ) { + return '<div style="font-size: 11px; padding: 3px; background: #ccc; margin-bottom: 3px;">[' . $log['cnt'] . '] [' . $log['logger']->_id . '] [' . $log['type'] . '] <b><code style="color: blue;">' . $log['function'] . '</code> >> <b style="color: darkorange;">' . $log['msg'] . '</b></b>' . ( isset( $log['file'] ) ? ' (' . substr( $log['file'], $log['logger']->_file_start ) . ' ' . $log['line'] . ')' : '' ) . ' [' . $log['timestamp'] . ']</div>'; + } + + static function dump() { + ?> + <!-- BEGIN: Freemius PHP Console Log --> + <script type="text/javascript"> + <?php + foreach (self::$LOG as $log) + { + echo 'console.' . $log['type'] . '(' . json_encode(self::format($log, false)) . ')' . "\n"; + } + ?> + </script> + <!-- END: Freemius PHP Console Log --> + <?php + } + + static function get_log() { + return self::$LOG; + } } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/includes/class-fs-plugin-updater.php b/wp-content/plugins/nextgen-gallery/freemius/includes/class-fs-plugin-updater.php index 15fc787205094b44cf17f038c422efd6758aa7f6..830db3662dd219f2007c4c1374ee860c815772e8 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/includes/class-fs-plugin-updater.php +++ b/wp-content/plugins/nextgen-gallery/freemius/includes/class-fs-plugin-updater.php @@ -1,334 +1,334 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.4 - * - * @link https://github.com/easydigitaldownloads/EDD-License-handler/blob/master/EDD_SL_Plugin_Updater.php - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - // Uncomment this line for testing. -// set_site_transient( 'update_plugins', null ); - - class FS_Plugin_Updater { - - /** - * @var Freemius - * @since 1.0.4 - */ - private $_fs; - /** - * @var FS_Logger - * @since 1.0.4 - */ - private $_logger; - /** - * @var object - * @since 1.1.8.1 - */ - private $_update_details; - - function __construct( Freemius $freemius ) { - $this->_fs = $freemius; - - $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $freemius->get_slug() . '_updater', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); - - $this->_filters(); - } - - /** - * Initiate required filters. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - */ - private function _filters() { - // Override request for plugin information - add_filter( 'plugins_api', array( &$this, 'plugins_api_filter' ), 10, 3 ); - - // WP 3.0+ - add_filter( 'pre_set_site_transient_update_plugins', array( - &$this, - 'pre_set_site_transient_update_plugins_filter' - ) ); - - if ( ! $this->_fs->has_active_license() ) { - /** - * If user has the premium plugin's code but do NOT have an active license, - * encourage him to upgrade by showing that there's a new release, but instead - * of showing an update link, show upgrade link to the pricing page. - * - * @since 1.1.6 - * - */ - // WP 2.9+ - add_action( "after_plugin_row_{$this->_fs->get_plugin_basename()}", array( - &$this, - 'catch_plugin_update_row' - ), 9 ); - add_action( "after_plugin_row_{$this->_fs->get_plugin_basename()}", array( - &$this, - 'edit_and_echo_plugin_update_row' - ), 11, 2 ); - } - - if ( ! WP_FS__IS_PRODUCTION_MODE ) { - add_filter( 'http_request_host_is_external', array( - $this, - 'http_request_host_is_external_filter' - ), 10, 3 ); - } - } - - /** - * Capture plugin update row by turning output buffering. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.6 - */ - function catch_plugin_update_row() { - ob_start(); - } - - /** - * Overrides default update message format with "renew your license" message. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.6 - */ - function edit_and_echo_plugin_update_row( $file, $plugin_data ) { - $plugin_update_row = ob_get_clean(); - - $current = get_site_transient( 'update_plugins' ); - if ( ! isset( $current->response[ $file ] ) ) { - echo $plugin_update_row; - - return false; - } - - $r = $current->response[ $file ]; - - $plugin_update_row = preg_replace( - '/(\<div.+>)(.+)(\<a.+\<a.+)\<\/div\>/is', - '$1 $2 ' . sprintf( - __fs( 'renew-license-now' ), - '<a href="' . $this->_fs->pricing_url() . '">', '</a>', - $r->new_version ) . - '$4', - $plugin_update_row - ); - - echo $plugin_update_row; - } - - /** - * Since WP version 3.6, a new security feature was added that denies access to repository with a local ip. - * During development mode we want to be able updating plugin versions via our localhost repository. This - * filter white-list all domains including "api.freemius". - * - * @link http://www.emanueletessore.com/wordpress-download-failed-valid-url-provided/ - * - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - * - * @param bool $allow - * @param string $host - * @param string $url - * - * @return bool - */ - function http_request_host_is_external_filter( $allow, $host, $url ) { - return ( false !== strpos( $host, 'freemius' ) ) ? true : $allow; - } - - /** - * Check for Updates at the defined API endpoint and modify the update array. - * - * This function dives into the update api just when WordPress creates its update array, - * then adds a custom API call and injects the custom plugin data retrieved from the API. - * It is reassembled from parts of the native WordPress plugin update code. - * See wp-includes/update.php line 121 for the original wp_update_plugins() function. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - * - * @uses FS_Api - * - * @param stdClass $transient_data Update array build by WordPress. - * - * @return array Modified update array with custom plugin data. - */ - function pre_set_site_transient_update_plugins_filter( $transient_data ) { - $this->_logger->entrance(); - - if ( empty( $transient_data ) || - defined( 'WP_FS__UNINSTALL_MODE' ) - ) { - return $transient_data; - } - - if ( ! isset( $this->_update_details ) ) { - // Get plugin's newest update. - $new_version = $this->_fs->get_update( false, false ); - - $this->_update_details = false; - - if ( is_object( $new_version ) ) { - $this->_logger->log( 'Found newer plugin version ' . $new_version->version ); - - $plugin_details = new stdClass(); - $plugin_details->slug = $this->_fs->get_slug(); - $plugin_details->new_version = $new_version->version; - $plugin_details->url = WP_FS__ADDRESS; - $plugin_details->package = $new_version->url; - $plugin_details->plugin = $this->_fs->get_plugin_basename(); - - /** - * Cache plugin details locally since set_site_transient( 'update_plugins' ) - * called multiple times and the non wp.org plugins are filtered after the - * call to .org. - * - * @since 1.1.8.1 - */ - $this->_update_details = $plugin_details; - } - } - - if ( is_object( $this->_update_details ) ) { - // Add plugin to transient data. - $transient_data->response[ $this->_fs->get_plugin_basename() ] = $this->_update_details; - } - - return $transient_data; - } - - /** - * Try to fetch plugin's info from .org repository. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.5 - * - * @param string $action - * @param object $args - * - * @return bool|mixed - */ - static function _fetch_plugin_info_from_repository( $action, $args ) { - $url = $http_url = 'http://api.wordpress.org/plugins/info/1.0/'; - if ( $ssl = wp_http_supports( array( 'ssl' ) ) ) { - $url = set_url_scheme( $url, 'https' ); - } - - $args = array( - 'timeout' => 15, - 'body' => array( - 'action' => $action, - 'request' => serialize( $args ) - ) - ); - - $request = wp_remote_post( $url, $args ); - - if ( is_wp_error( $request ) ) { - return false; - } - - $res = maybe_unserialize( wp_remote_retrieve_body( $request ) ); - - if ( ! is_object( $res ) && ! is_array( $res ) ) { - return false; - } - - return $res; - } - - /** - * Updates information on the "View version x.x details" page with custom data. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - * - * @uses FS_Api - * - * @param object $data - * @param string $action - * @param mixed $args - * - * @return object - */ - function plugins_api_filter( $data, $action = '', $args = null ) { - $this->_logger->entrance(); - - if ( ( 'plugin_information' !== $action ) || - ! isset( $args->slug ) - ) { - return $data; - } - - $addon = false; - $is_addon = false; - - if ( $this->_fs->get_slug() !== $args->slug ) { - $addon = $this->_fs->get_addon_by_slug( $args->slug ); - - if ( ! is_object( $addon ) ) { - return $data; - } - - $is_addon = true; - } - - $plugin_in_repo = false; - if ( ! $is_addon ) { - // Try to fetch info from .org repository. - $data = self::_fetch_plugin_info_from_repository( $action, $args ); - - $plugin_in_repo = ( false !== $data ); - } - - if ( ! $plugin_in_repo ) { - $data = $args; - - // Fetch as much as possible info from local files. - $plugin_local_data = $this->_fs->get_plugin_data(); - $data->name = $plugin_local_data['Name']; - $data->author = $plugin_local_data['Author']; - $data->sections = array( - 'description' => 'Upgrade ' . $plugin_local_data['Name'] . ' to latest.', - ); - - // @todo Store extra plugin info on Freemius or parse readme.txt markup. - /*$info = $this->_fs->get_api_site_scope()->call('/information.json'); - -if ( !isset($info->error) ) { - $data = $info; -}*/ - } - - // Get plugin's newest update. - $new_version = $this->_fs->_fetch_latest_version( $is_addon ? $addon->id : false ); - - if ( $is_addon ) { - $data->name = $addon->title . ' ' . __fs( 'addon', $this->_fs->get_slug() ); - $data->slug = $addon->slug; - $data->url = WP_FS__ADDRESS; - $data->package = $new_version->url; - } - - if ( ! $plugin_in_repo ) { - $data->last_updated = ! is_null( $new_version->updated ) ? $new_version->updated : $new_version->created; - $data->requires = $new_version->requires_platform_version; - $data->tested = $new_version->tested_up_to_version; - } - - $data->version = $new_version->version; - $data->download_link = $new_version->url; - - return $data; - } +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.4 + * + * @link https://github.com/easydigitaldownloads/EDD-License-handler/blob/master/EDD_SL_Plugin_Updater.php + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + // Uncomment this line for testing. +// set_site_transient( 'update_plugins', null ); + + class FS_Plugin_Updater { + + /** + * @var Freemius + * @since 1.0.4 + */ + private $_fs; + /** + * @var FS_Logger + * @since 1.0.4 + */ + private $_logger; + /** + * @var object + * @since 1.1.8.1 + */ + private $_update_details; + + function __construct( Freemius $freemius ) { + $this->_fs = $freemius; + + $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $freemius->get_slug() . '_updater', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); + + $this->_filters(); + } + + /** + * Initiate required filters. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + */ + private function _filters() { + // Override request for plugin information + add_filter( 'plugins_api', array( &$this, 'plugins_api_filter' ), 10, 3 ); + + // WP 3.0+ + add_filter( 'pre_set_site_transient_update_plugins', array( + &$this, + 'pre_set_site_transient_update_plugins_filter' + ) ); + + if ( ! $this->_fs->has_active_license() ) { + /** + * If user has the premium plugin's code but do NOT have an active license, + * encourage him to upgrade by showing that there's a new release, but instead + * of showing an update link, show upgrade link to the pricing page. + * + * @since 1.1.6 + * + */ + // WP 2.9+ + add_action( "after_plugin_row_{$this->_fs->get_plugin_basename()}", array( + &$this, + 'catch_plugin_update_row' + ), 9 ); + add_action( "after_plugin_row_{$this->_fs->get_plugin_basename()}", array( + &$this, + 'edit_and_echo_plugin_update_row' + ), 11, 2 ); + } + + if ( ! WP_FS__IS_PRODUCTION_MODE ) { + add_filter( 'http_request_host_is_external', array( + $this, + 'http_request_host_is_external_filter' + ), 10, 3 ); + } + } + + /** + * Capture plugin update row by turning output buffering. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.6 + */ + function catch_plugin_update_row() { + ob_start(); + } + + /** + * Overrides default update message format with "renew your license" message. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.6 + */ + function edit_and_echo_plugin_update_row( $file, $plugin_data ) { + $plugin_update_row = ob_get_clean(); + + $current = get_site_transient( 'update_plugins' ); + if ( ! isset( $current->response[ $file ] ) ) { + echo $plugin_update_row; + + return false; + } + + $r = $current->response[ $file ]; + + $plugin_update_row = preg_replace( + '/(\<div.+>)(.+)(\<a.+\<a.+)\<\/div\>/is', + '$1 $2 ' . sprintf( + __fs( 'renew-license-now' ), + '<a href="' . $this->_fs->pricing_url() . '">', '</a>', + $r->new_version ) . + '$4', + $plugin_update_row + ); + + echo $plugin_update_row; + } + + /** + * Since WP version 3.6, a new security feature was added that denies access to repository with a local ip. + * During development mode we want to be able updating plugin versions via our localhost repository. This + * filter white-list all domains including "api.freemius". + * + * @link http://www.emanueletessore.com/wordpress-download-failed-valid-url-provided/ + * + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + * + * @param bool $allow + * @param string $host + * @param string $url + * + * @return bool + */ + function http_request_host_is_external_filter( $allow, $host, $url ) { + return ( false !== strpos( $host, 'freemius' ) ) ? true : $allow; + } + + /** + * Check for Updates at the defined API endpoint and modify the update array. + * + * This function dives into the update api just when WordPress creates its update array, + * then adds a custom API call and injects the custom plugin data retrieved from the API. + * It is reassembled from parts of the native WordPress plugin update code. + * See wp-includes/update.php line 121 for the original wp_update_plugins() function. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + * + * @uses FS_Api + * + * @param stdClass $transient_data Update array build by WordPress. + * + * @return array Modified update array with custom plugin data. + */ + function pre_set_site_transient_update_plugins_filter( $transient_data ) { + $this->_logger->entrance(); + + if ( empty( $transient_data ) || + defined( 'WP_FS__UNINSTALL_MODE' ) + ) { + return $transient_data; + } + + if ( ! isset( $this->_update_details ) ) { + // Get plugin's newest update. + $new_version = $this->_fs->get_update( false, false ); + + $this->_update_details = false; + + if ( is_object( $new_version ) ) { + $this->_logger->log( 'Found newer plugin version ' . $new_version->version ); + + $plugin_details = new stdClass(); + $plugin_details->slug = $this->_fs->get_slug(); + $plugin_details->new_version = $new_version->version; + $plugin_details->url = WP_FS__ADDRESS; + $plugin_details->package = $new_version->url; + $plugin_details->plugin = $this->_fs->get_plugin_basename(); + + /** + * Cache plugin details locally since set_site_transient( 'update_plugins' ) + * called multiple times and the non wp.org plugins are filtered after the + * call to .org. + * + * @since 1.1.8.1 + */ + $this->_update_details = $plugin_details; + } + } + + if ( is_object( $this->_update_details ) ) { + // Add plugin to transient data. + $transient_data->response[ $this->_fs->get_plugin_basename() ] = $this->_update_details; + } + + return $transient_data; + } + + /** + * Try to fetch plugin's info from .org repository. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.5 + * + * @param string $action + * @param object $args + * + * @return bool|mixed + */ + static function _fetch_plugin_info_from_repository( $action, $args ) { + $url = $http_url = 'http://api.wordpress.org/plugins/info/1.0/'; + if ( $ssl = wp_http_supports( array( 'ssl' ) ) ) { + $url = set_url_scheme( $url, 'https' ); + } + + $args = array( + 'timeout' => 15, + 'body' => array( + 'action' => $action, + 'request' => serialize( $args ) + ) + ); + + $request = wp_remote_post( $url, $args ); + + if ( is_wp_error( $request ) ) { + return false; + } + + $res = maybe_unserialize( wp_remote_retrieve_body( $request ) ); + + if ( ! is_object( $res ) && ! is_array( $res ) ) { + return false; + } + + return $res; + } + + /** + * Updates information on the "View version x.x details" page with custom data. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + * + * @uses FS_Api + * + * @param object $data + * @param string $action + * @param mixed $args + * + * @return object + */ + function plugins_api_filter( $data, $action = '', $args = null ) { + $this->_logger->entrance(); + + if ( ( 'plugin_information' !== $action ) || + ! isset( $args->slug ) + ) { + return $data; + } + + $addon = false; + $is_addon = false; + + if ( $this->_fs->get_slug() !== $args->slug ) { + $addon = $this->_fs->get_addon_by_slug( $args->slug ); + + if ( ! is_object( $addon ) ) { + return $data; + } + + $is_addon = true; + } + + $plugin_in_repo = false; + if ( ! $is_addon ) { + // Try to fetch info from .org repository. + $data = self::_fetch_plugin_info_from_repository( $action, $args ); + + $plugin_in_repo = ( false !== $data ); + } + + if ( ! $plugin_in_repo ) { + $data = $args; + + // Fetch as much as possible info from local files. + $plugin_local_data = $this->_fs->get_plugin_data(); + $data->name = $plugin_local_data['Name']; + $data->author = $plugin_local_data['Author']; + $data->sections = array( + 'description' => 'Upgrade ' . $plugin_local_data['Name'] . ' to latest.', + ); + + // @todo Store extra plugin info on Freemius or parse readme.txt markup. + /*$info = $this->_fs->get_api_site_scope()->call('/information.json'); + +if ( !isset($info->error) ) { + $data = $info; +}*/ + } + + // Get plugin's newest update. + $new_version = $this->_fs->_fetch_latest_version( $is_addon ? $addon->id : false ); + + if ( $is_addon ) { + $data->name = $addon->title . ' ' . __fs( 'addon', $this->_fs->get_slug() ); + $data->slug = $addon->slug; + $data->url = WP_FS__ADDRESS; + $data->package = $new_version->url; + } + + if ( ! $plugin_in_repo ) { + $data->last_updated = ! is_null( $new_version->updated ) ? $new_version->updated : $new_version->created; + $data->requires = $new_version->requires_platform_version; + $data->tested = $new_version->tested_up_to_version; + } + + $data->version = $new_version->version; + $data->download_link = $new_version->url; + + return $data; + } } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/includes/debug/class-fs-debug-bar-panel.php b/wp-content/plugins/nextgen-gallery/freemius/includes/debug/class-fs-debug-bar-panel.php index 1c3259bdf52b015ae679b3928dc2e1b75b228822..af0c6cb27c01503d53da226a641723ba23efe828 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/includes/debug/class-fs-debug-bar-panel.php +++ b/wp-content/plugins/nextgen-gallery/freemius/includes/debug/class-fs-debug-bar-panel.php @@ -1,64 +1,64 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.1.7.3 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - /** - * Extends Debug Bar plugin by adding a panel to show all Freemius API requests. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.7.3 - * - * Class Freemius_Debug_Bar_Panel - */ - class Freemius_Debug_Bar_Panel extends Debug_Bar_Panel { - function init() { - $this->title( 'Freemius' ); - } - - static function requests_count() { - if ( class_exists( 'Freemius_Api' ) ) { - $logger = Freemius_Api::GetLogger(); - } else { - $logger = array(); - } - - return number_format( count( $logger ) ); - } - - static function total_time() { - if ( class_exists( 'Freemius_Api' ) ) { - $logger = Freemius_Api::GetLogger(); - } else { - $logger = array(); - } - - $total_time = .0; - foreach ( $logger as $l ) { - $total_time += $l['total']; - } - - return number_format( 100 * $total_time, 2 ) . ' ' . __fs( 'ms' ); - } - - function render() { - ?> - <div id='debug-bar-php'> - <?php fs_require_template( '/debug/api-calls.php' ) ?> - <br> - <?php fs_require_template( '/debug/scheduled-crons.php' ) ?> - <br> - <?php fs_require_template( '/debug/plugins-themes-sync.php' ) ?> - <br> - <?php fs_require_template( '/debug/logger.php' ) ?> - </div> - <?php - } - } +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.1.7.3 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + /** + * Extends Debug Bar plugin by adding a panel to show all Freemius API requests. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.7.3 + * + * Class Freemius_Debug_Bar_Panel + */ + class Freemius_Debug_Bar_Panel extends Debug_Bar_Panel { + function init() { + $this->title( 'Freemius' ); + } + + static function requests_count() { + if ( class_exists( 'Freemius_Api' ) ) { + $logger = Freemius_Api::GetLogger(); + } else { + $logger = array(); + } + + return number_format( count( $logger ) ); + } + + static function total_time() { + if ( class_exists( 'Freemius_Api' ) ) { + $logger = Freemius_Api::GetLogger(); + } else { + $logger = array(); + } + + $total_time = .0; + foreach ( $logger as $l ) { + $total_time += $l['total']; + } + + return number_format( 100 * $total_time, 2 ) . ' ' . __fs( 'ms' ); + } + + function render() { + ?> + <div id='debug-bar-php'> + <?php fs_require_template( '/debug/api-calls.php' ) ?> + <br> + <?php fs_require_template( '/debug/scheduled-crons.php' ) ?> + <br> + <?php fs_require_template( '/debug/plugins-themes-sync.php' ) ?> + <br> + <?php fs_require_template( '/debug/logger.php' ) ?> + </div> + <?php + } + } diff --git a/wp-content/plugins/nextgen-gallery/freemius/includes/debug/debug-bar-start.php b/wp-content/plugins/nextgen-gallery/freemius/includes/debug/debug-bar-start.php index 852dfd7ceaa1a1b701807714fe66db262aeb61a4..9ae7b2adad347dcee6880bac337606b07a1d6c9c 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/includes/debug/debug-bar-start.php +++ b/wp-content/plugins/nextgen-gallery/freemius/includes/debug/debug-bar-start.php @@ -1,52 +1,52 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.1.7.3 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - if ( ! WP_FS__DEBUG_SDK ) { - return; - } - - /** - * Initialize Freemius custom debug panels. - * - * @param array $panels Debug bar panels objects - * - * @return array Debug bar panels with your custom panels - */ - function fs_custom_panels_init( $panels ) { - if ( class_exists( 'Debug_Bar_Panel' ) ) { - if ( FS_API__LOGGER_ON ) { - require_once dirname( __FILE__ ) . '/class-fs-debug-bar-panel.php'; - $panels[] = new Freemius_Debug_Bar_Panel(); - } - } - - return $panels; - } - - function fs_custom_status_init( $statuses ) { - if ( class_exists( 'Debug_Bar_Panel' ) ) { - if ( FS_API__LOGGER_ON ) { - require_once dirname( __FILE__ ) . '/class-fs-debug-bar-panel.php'; - $statuses[] = array( - 'fs_api_requests', - __fs( 'Freemius API' ), - Freemius_Debug_Bar_Panel::requests_count() . ' ' . __fs( 'Requests' ) . - ' (' . Freemius_Debug_Bar_Panel::total_time() . ')' - ); - } - } - - return $statuses; - } - - add_filter( 'debug_bar_panels', 'fs_custom_panels_init' ); +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.1.7.3 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + if ( ! WP_FS__DEBUG_SDK ) { + return; + } + + /** + * Initialize Freemius custom debug panels. + * + * @param array $panels Debug bar panels objects + * + * @return array Debug bar panels with your custom panels + */ + function fs_custom_panels_init( $panels ) { + if ( class_exists( 'Debug_Bar_Panel' ) ) { + if ( FS_API__LOGGER_ON ) { + require_once dirname( __FILE__ ) . '/class-fs-debug-bar-panel.php'; + $panels[] = new Freemius_Debug_Bar_Panel(); + } + } + + return $panels; + } + + function fs_custom_status_init( $statuses ) { + if ( class_exists( 'Debug_Bar_Panel' ) ) { + if ( FS_API__LOGGER_ON ) { + require_once dirname( __FILE__ ) . '/class-fs-debug-bar-panel.php'; + $statuses[] = array( + 'fs_api_requests', + __fs( 'Freemius API' ), + Freemius_Debug_Bar_Panel::requests_count() . ' ' . __fs( 'Requests' ) . + ' (' . Freemius_Debug_Bar_Panel::total_time() . ')' + ); + } + } + + return $statuses; + } + + add_filter( 'debug_bar_panels', 'fs_custom_panels_init' ); add_filter( 'debug_bar_statuses', 'fs_custom_status_init' ); \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/includes/entities/class-fs-plugin-license.php b/wp-content/plugins/nextgen-gallery/freemius/includes/entities/class-fs-plugin-license.php index 655605f34b52cfb70596cc1060260ad9faf28cb8..8fd5f378761806500c0f094fcb0586317d4b15cf 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/includes/entities/class-fs-plugin-license.php +++ b/wp-content/plugins/nextgen-gallery/freemius/includes/entities/class-fs-plugin-license.php @@ -1,172 +1,172 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.5 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - class FS_Plugin_License extends FS_Entity { - - #region Properties - - /** - * @var number - */ - public $plugin_id; - /** - * @var number - */ - public $user_id; - /** - * @var number - */ - public $plan_id; - /** - * @var number - */ - public $pricing_id; - /** - * @var int|null - */ - public $quota; - /** - * @var int - */ - public $activated; - /** - * @var int - */ - public $activated_local; - /** - * @var string - */ - public $expiration; - /** - * @var bool $is_free_localhost Defaults to true. If true, allow unlimited localhost installs with the same - * license. - */ - public $is_free_localhost; - /** - * @var bool $is_block_features Defaults to true. If false, don't block features after license expiry - only - * block updates and support. - */ - public $is_block_features; - /** - * @var bool - */ - public $is_cancelled; - - #endregion Properties - - /** - * @param stdClass|bool $license - */ - function __construct( $license = false ) { - parent::__construct( $license ); - } - - static function get_type() { - return 'license'; - } - - /** - * Check how many site activations left. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.5 - * - * @return int - */ - function left() { - if ( $this->is_expired() ) { - return 0; - } - - return ( $this->quota - $this->activated - ( $this->is_free_localhost ? 0 : $this->activated_local ) ); - } - - /** - * Check if single site license. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.8.1 - * - * @return bool - */ - function is_single_site() { - return ( is_numeric( $this->quota ) && 1 == $this->quota ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.5 - * - * @return bool - */ - function is_expired() { - return ! $this->is_lifetime() && ( strtotime( $this->expiration ) < WP_FS__SCRIPT_START_TIME ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @return bool - */ - function is_lifetime() { - return is_null( $this->expiration ); - } - - /** - * Check if license is fully utilized. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @param bool $is_localhost - * - * @return bool - */ - function is_utilized( $is_localhost = null ) { - if ( is_null( $is_localhost ) ) { - $is_localhost = WP_FS__IS_LOCALHOST_FOR_SERVER; - } - - return ! ( $this->is_free_localhost && $is_localhost ) && - ( $this->quota <= $this->activated + ( $this->is_free_localhost ? 0 : $this->activated_local ) ); - } - - /** - * Check if license's plan features are enabled. - * - * - Either if plan not expired - * - If expired, based on the configuration to block features or not. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @return bool - */ - function is_features_enabled() { - return ( ! $this->is_block_features || ! $this->is_expired() ); - } - - /** - * Subscription considered to be new without any payments - * if the license expires in less than 24 hours - * from the license creation. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @return bool - */ - function is_first_payment_pending() { - return ( WP_FS__TIME_24_HOURS_IN_SEC >= strtotime( $this->expiration ) - strtotime( $this->created ) ); - } +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.5 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + class FS_Plugin_License extends FS_Entity { + + #region Properties + + /** + * @var number + */ + public $plugin_id; + /** + * @var number + */ + public $user_id; + /** + * @var number + */ + public $plan_id; + /** + * @var number + */ + public $pricing_id; + /** + * @var int|null + */ + public $quota; + /** + * @var int + */ + public $activated; + /** + * @var int + */ + public $activated_local; + /** + * @var string + */ + public $expiration; + /** + * @var bool $is_free_localhost Defaults to true. If true, allow unlimited localhost installs with the same + * license. + */ + public $is_free_localhost; + /** + * @var bool $is_block_features Defaults to true. If false, don't block features after license expiry - only + * block updates and support. + */ + public $is_block_features; + /** + * @var bool + */ + public $is_cancelled; + + #endregion Properties + + /** + * @param stdClass|bool $license + */ + function __construct( $license = false ) { + parent::__construct( $license ); + } + + static function get_type() { + return 'license'; + } + + /** + * Check how many site activations left. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.5 + * + * @return int + */ + function left() { + if ( $this->is_expired() ) { + return 0; + } + + return ( $this->quota - $this->activated - ( $this->is_free_localhost ? 0 : $this->activated_local ) ); + } + + /** + * Check if single site license. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.8.1 + * + * @return bool + */ + function is_single_site() { + return ( is_numeric( $this->quota ) && 1 == $this->quota ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.5 + * + * @return bool + */ + function is_expired() { + return ! $this->is_lifetime() && ( strtotime( $this->expiration ) < WP_FS__SCRIPT_START_TIME ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @return bool + */ + function is_lifetime() { + return is_null( $this->expiration ); + } + + /** + * Check if license is fully utilized. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @param bool $is_localhost + * + * @return bool + */ + function is_utilized( $is_localhost = null ) { + if ( is_null( $is_localhost ) ) { + $is_localhost = WP_FS__IS_LOCALHOST_FOR_SERVER; + } + + return ! ( $this->is_free_localhost && $is_localhost ) && + ( $this->quota <= $this->activated + ( $this->is_free_localhost ? 0 : $this->activated_local ) ); + } + + /** + * Check if license's plan features are enabled. + * + * - Either if plan not expired + * - If expired, based on the configuration to block features or not. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @return bool + */ + function is_features_enabled() { + return ( ! $this->is_block_features || ! $this->is_expired() ); + } + + /** + * Subscription considered to be new without any payments + * if the license expires in less than 24 hours + * from the license creation. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @return bool + */ + function is_first_payment_pending() { + return ( WP_FS__TIME_24_HOURS_IN_SEC >= strtotime( $this->expiration ) - strtotime( $this->created ) ); + } } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/includes/entities/class-fs-plugin-plan.php b/wp-content/plugins/nextgen-gallery/freemius/includes/entities/class-fs-plugin-plan.php index 1df50eb2af7650ac323215800d0c4f4301cb1d01..90378b4fc7018db770db603e8368aa460d7fa7ac 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/includes/entities/class-fs-plugin-plan.php +++ b/wp-content/plugins/nextgen-gallery/freemius/includes/entities/class-fs-plugin-plan.php @@ -1,124 +1,124 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.5 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - class FS_Plugin_Plan extends FS_Entity { - - #region Properties - - /** - * @var number - */ - public $plugin_id; - /** - * @var string - */ - public $name; - /** - * @var string - */ - public $title; - /** - * @var string - */ - public $description; - /** - * @var bool Defaults to true. If true, allow unlimited localhost installs with the same license. - */ - public $is_free_localhost; - /** - * @var bool Defaults to true. If false, don't block features after license expiry - only block updates and - * support. - */ - public $is_block_features; - /** - * @var int - */ - public $license_type; - /** - * @var bool - */ - public $is_https_support; - /** - * @var int Trial days. - */ - public $trial_period; - /** - * @var string If true, require payment for trial. - */ - public $is_require_subscription; - /** - * @var string Knowledge Base URL. - */ - public $support_kb; - /** - * @var string Support Forum URL. - */ - public $support_forum; - /** - * @var string Support email address. - */ - public $support_email; - /** - * @var string Support phone. - */ - public $support_phone; - /** - * @var string Support skype username. - */ - public $support_skype; - /** - * @var bool Is personal success manager supported with the plan. - */ - public $is_success_manager; - /** - * @var bool Is featured plan. - */ - public $is_featured; - - #endregion Properties - - /** - * @param object|bool $plan - */ - function __construct( $plan = false ) { - parent::__construct( $plan ); - - if ( is_object( $plan ) ) { - $this->name = strtolower( $plan->name ); - } - } - - static function get_type() { - return 'plan'; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @return bool - */ - function is_free() { - return ( 'free' === $this->name ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @return bool - */ - function has_trial() { - return ! $this->is_free() && - is_numeric( $this->trial_period ) && ( $this->trial_period > 0 ); - } +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.5 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + class FS_Plugin_Plan extends FS_Entity { + + #region Properties + + /** + * @var number + */ + public $plugin_id; + /** + * @var string + */ + public $name; + /** + * @var string + */ + public $title; + /** + * @var string + */ + public $description; + /** + * @var bool Defaults to true. If true, allow unlimited localhost installs with the same license. + */ + public $is_free_localhost; + /** + * @var bool Defaults to true. If false, don't block features after license expiry - only block updates and + * support. + */ + public $is_block_features; + /** + * @var int + */ + public $license_type; + /** + * @var bool + */ + public $is_https_support; + /** + * @var int Trial days. + */ + public $trial_period; + /** + * @var string If true, require payment for trial. + */ + public $is_require_subscription; + /** + * @var string Knowledge Base URL. + */ + public $support_kb; + /** + * @var string Support Forum URL. + */ + public $support_forum; + /** + * @var string Support email address. + */ + public $support_email; + /** + * @var string Support phone. + */ + public $support_phone; + /** + * @var string Support skype username. + */ + public $support_skype; + /** + * @var bool Is personal success manager supported with the plan. + */ + public $is_success_manager; + /** + * @var bool Is featured plan. + */ + public $is_featured; + + #endregion Properties + + /** + * @param object|bool $plan + */ + function __construct( $plan = false ) { + parent::__construct( $plan ); + + if ( is_object( $plan ) ) { + $this->name = strtolower( $plan->name ); + } + } + + static function get_type() { + return 'plan'; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @return bool + */ + function is_free() { + return ( 'free' === $this->name ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @return bool + */ + function has_trial() { + return ! $this->is_free() && + is_numeric( $this->trial_period ) && ( $this->trial_period > 0 ); + } } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/includes/entities/class-fs-pricing.php b/wp-content/plugins/nextgen-gallery/freemius/includes/entities/class-fs-pricing.php index fb70b5aef08c78d8b2d5cf39d2b72f4f93fedb33..2962f6d436e892a5e856e893e3549d54acee5b4c 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/includes/entities/class-fs-pricing.php +++ b/wp-content/plugins/nextgen-gallery/freemius/includes/entities/class-fs-pricing.php @@ -1,141 +1,141 @@ -<?php - /** - * @package Freemius for EDD Add-On - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.0 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - class FS_Pricing extends FS_Entity { - - #region Properties - - /** - * @var number - */ - public $plan_id; - /** - * @var int - */ - public $licenses; - /** - * @var null|float - */ - public $monthly_price; - /** - * @var null|float - */ - public $annual_price; - /** - * @var null|float - */ - public $lifetime_price; - - #endregion Properties - - /** - * @param object|bool $pricing - */ - function __construct( $pricing = false ) { - parent::__construct( $pricing ); - } - - static function get_type() { - return 'pricing'; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.8 - * - * @return bool - */ - function has_monthly() { - return ( is_numeric( $this->monthly_price ) && $this->monthly_price > 0 ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.8 - * - * @return bool - */ - function has_annual() { - return ( is_numeric( $this->annual_price ) && $this->annual_price > 0 ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.8 - * - * @return bool - */ - function has_lifetime() { - return ( is_numeric( $this->lifetime_price ) && $this->lifetime_price > 0 ); - } - - /** - * Check if unlimited licenses pricing. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.8 - * - * @return bool - */ - function is_unlimited() { - return is_null( $this->licenses ); - } - - - /** - * Check if pricing has more than one billing cycle. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.8 - * - * @return bool - */ - function is_multi_cycle() { - $cycles = 0; - if ( $this->has_monthly() ) { - $cycles ++; - } - if ( $this->has_annual() ) { - $cycles ++; - } - if ( $this->has_lifetime() ) { - $cycles ++; - } - - return $cycles > 1; - } - - /** - * Get annual over monthly discount. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.8 - * - * @return int - */ - function annual_discount_percentage() { - return floor( $this->annual_savings() / ( $this->monthly_price * 12 * ( $this->is_unlimited() ? 1 : $this->licenses ) ) * 100 ); - } - - /** - * Get annual over monthly savings. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.8 - * - * @return float - */ - function annual_savings() { - return ( $this->monthly_price * 12 - $this->annual_price ) * ( $this->is_unlimited() ? 1 : $this->licenses ); - } - +<?php + /** + * @package Freemius for EDD Add-On + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.0 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + class FS_Pricing extends FS_Entity { + + #region Properties + + /** + * @var number + */ + public $plan_id; + /** + * @var int + */ + public $licenses; + /** + * @var null|float + */ + public $monthly_price; + /** + * @var null|float + */ + public $annual_price; + /** + * @var null|float + */ + public $lifetime_price; + + #endregion Properties + + /** + * @param object|bool $pricing + */ + function __construct( $pricing = false ) { + parent::__construct( $pricing ); + } + + static function get_type() { + return 'pricing'; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.8 + * + * @return bool + */ + function has_monthly() { + return ( is_numeric( $this->monthly_price ) && $this->monthly_price > 0 ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.8 + * + * @return bool + */ + function has_annual() { + return ( is_numeric( $this->annual_price ) && $this->annual_price > 0 ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.8 + * + * @return bool + */ + function has_lifetime() { + return ( is_numeric( $this->lifetime_price ) && $this->lifetime_price > 0 ); + } + + /** + * Check if unlimited licenses pricing. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.8 + * + * @return bool + */ + function is_unlimited() { + return is_null( $this->licenses ); + } + + + /** + * Check if pricing has more than one billing cycle. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.8 + * + * @return bool + */ + function is_multi_cycle() { + $cycles = 0; + if ( $this->has_monthly() ) { + $cycles ++; + } + if ( $this->has_annual() ) { + $cycles ++; + } + if ( $this->has_lifetime() ) { + $cycles ++; + } + + return $cycles > 1; + } + + /** + * Get annual over monthly discount. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.8 + * + * @return int + */ + function annual_discount_percentage() { + return floor( $this->annual_savings() / ( $this->monthly_price * 12 * ( $this->is_unlimited() ? 1 : $this->licenses ) ) * 100 ); + } + + /** + * Get annual over monthly savings. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.8 + * + * @return float + */ + function annual_savings() { + return ( $this->monthly_price * 12 - $this->annual_price ) * ( $this->is_unlimited() ? 1 : $this->licenses ); + } + } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/includes/entities/class-fs-site.php b/wp-content/plugins/nextgen-gallery/freemius/includes/entities/class-fs-site.php index 1c9393bdf325c139078ae34642079a4b39b429eb..37215699468d084f6cf4fb4b98c56446b6718126 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/includes/entities/class-fs-site.php +++ b/wp-content/plugins/nextgen-gallery/freemius/includes/entities/class-fs-site.php @@ -1,127 +1,127 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.3 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - class FS_Site extends FS_Scope_Entity { - /** - * @var string - */ - public $slug; - /** - * @var number - */ - public $site_id; - /** - * @var number - */ - public $plugin_id; - /** - * @var number - */ - public $user_id; - /** - * @var string - */ - public $title; - /** - * @var string - */ - public $url; - /** - * @var string - */ - public $version; - /** - * @var string E.g. en-GB - */ - public $language; - /** - * @var string E.g. UTF-8 - */ - public $charset; - /** - * @var string Platform version (e.g WordPress version). - */ - public $platform_version; - /** - * @var string Programming language version (e.g PHP version). - */ - public $programming_language_version; - /** - * @var FS_Plugin_Plan $plan - */ - public $plan; - /** - * @var number|null - */ - public $license_id; - /** - * @var number|null - */ - public $trial_plan_id; - /** - * @var string|null - */ - public $trial_ends; - /** - * @since 1.0.9 - * - * @var bool - */ - public $is_premium = false; - - /** - * @param stdClass|bool $site - */ - function __construct( $site = false ) { - $this->plan = new FS_Plugin_Plan(); - - parent::__construct( $site ); - - if ( is_object( $site ) ) { - $this->plan->id = $site->plan_id; - } - } - - static function get_type() { - return 'install'; - } - - function is_localhost() { - // The server has no way to verify if localhost unless localhost appears in domain. - return WP_FS__IS_LOCALHOST_FOR_SERVER; -// return (substr($_SERVER['REMOTE_ADDR'], 0, 4) == '127.' || $_SERVER['REMOTE_ADDR'] == '::1'); - } - - /** - * Check if site in trial. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @return bool - */ - function is_trial() { - return is_numeric( $this->trial_plan_id ) && ( strtotime( $this->trial_ends ) > WP_FS__SCRIPT_START_TIME ); - } - - /** - * Check if user already utilized the trial with the current install. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @return bool - */ - function is_trial_utilized() { - return is_numeric( $this->trial_plan_id ); - } +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.3 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + class FS_Site extends FS_Scope_Entity { + /** + * @var string + */ + public $slug; + /** + * @var number + */ + public $site_id; + /** + * @var number + */ + public $plugin_id; + /** + * @var number + */ + public $user_id; + /** + * @var string + */ + public $title; + /** + * @var string + */ + public $url; + /** + * @var string + */ + public $version; + /** + * @var string E.g. en-GB + */ + public $language; + /** + * @var string E.g. UTF-8 + */ + public $charset; + /** + * @var string Platform version (e.g WordPress version). + */ + public $platform_version; + /** + * @var string Programming language version (e.g PHP version). + */ + public $programming_language_version; + /** + * @var FS_Plugin_Plan $plan + */ + public $plan; + /** + * @var number|null + */ + public $license_id; + /** + * @var number|null + */ + public $trial_plan_id; + /** + * @var string|null + */ + public $trial_ends; + /** + * @since 1.0.9 + * + * @var bool + */ + public $is_premium = false; + + /** + * @param stdClass|bool $site + */ + function __construct( $site = false ) { + $this->plan = new FS_Plugin_Plan(); + + parent::__construct( $site ); + + if ( is_object( $site ) ) { + $this->plan->id = $site->plan_id; + } + } + + static function get_type() { + return 'install'; + } + + function is_localhost() { + // The server has no way to verify if localhost unless localhost appears in domain. + return WP_FS__IS_LOCALHOST_FOR_SERVER; +// return (substr($_SERVER['REMOTE_ADDR'], 0, 4) == '127.' || $_SERVER['REMOTE_ADDR'] == '::1'); + } + + /** + * Check if site in trial. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @return bool + */ + function is_trial() { + return is_numeric( $this->trial_plan_id ) && ( strtotime( $this->trial_ends ) > WP_FS__SCRIPT_START_TIME ); + } + + /** + * Check if user already utilized the trial with the current install. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @return bool + */ + function is_trial_utilized() { + return is_numeric( $this->trial_plan_id ); + } } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/includes/entities/class-fs-subscription.php b/wp-content/plugins/nextgen-gallery/freemius/includes/entities/class-fs-subscription.php index 0041df0e94b42bff0eeacaf624a75643cdc3b647..b18634c5e6a7485add66ecce19c185df095622ec 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/includes/entities/class-fs-subscription.php +++ b/wp-content/plugins/nextgen-gallery/freemius/includes/entities/class-fs-subscription.php @@ -1,125 +1,125 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.9 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - class FS_Subscription extends FS_Entity { - - #region Properties - - /** - * @var number - */ - public $user_id; - /** - * @var number - */ - public $install_id; - /** - * @var number - */ - public $plan_id; - /** - * @var number - */ - public $license_id; - /** - * @var float - */ - public $total_gross; - /** - * @var float - */ - public $amount_per_cycle; - /** - * @var int # of months - */ - public $billing_cycle; - /** - * @var float - */ - public $outstanding_balance; - /** - * @var int - */ - public $failed_payments; - /** - * @var string - */ - public $gateway; - /** - * @var string - */ - public $external_id; - /** - * @var string|null - */ - public $trial_ends; - /** - * @var string|null Datetime of the next payment, or null if cancelled - */ - public $next_payment; - /** - * @var string|null - */ - public $vat_id; - /** - * @var string Two characters country code - */ - public $country_code; - - #endregion Properties - - /** - * @param object|bool $subscription - */ - function __construct( $subscription = false ) { - parent::__construct( $subscription ); - } - - static function get_type() { - return 'subscription'; - } - - /** - * Check if subscription is active. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @return bool - */ - function is_active() { - return ! empty( $this->next_payment ) && - ( strtotime( $this->next_payment ) > WP_FS__SCRIPT_START_TIME ); - } - - /** - * Subscription considered to be new without any payments - * if the next payment should be made within less than 24 hours - * from the subscription creation. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @return bool - */ - function is_first_payment_pending() { - return ( WP_FS__TIME_24_HOURS_IN_SEC >= strtotime( $this->next_payment ) - strtotime( $this->created ) ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.7 - */ - function has_trial() { - return ! is_null( $this->trial_ends ); - } +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.9 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + class FS_Subscription extends FS_Entity { + + #region Properties + + /** + * @var number + */ + public $user_id; + /** + * @var number + */ + public $install_id; + /** + * @var number + */ + public $plan_id; + /** + * @var number + */ + public $license_id; + /** + * @var float + */ + public $total_gross; + /** + * @var float + */ + public $amount_per_cycle; + /** + * @var int # of months + */ + public $billing_cycle; + /** + * @var float + */ + public $outstanding_balance; + /** + * @var int + */ + public $failed_payments; + /** + * @var string + */ + public $gateway; + /** + * @var string + */ + public $external_id; + /** + * @var string|null + */ + public $trial_ends; + /** + * @var string|null Datetime of the next payment, or null if cancelled + */ + public $next_payment; + /** + * @var string|null + */ + public $vat_id; + /** + * @var string Two characters country code + */ + public $country_code; + + #endregion Properties + + /** + * @param object|bool $subscription + */ + function __construct( $subscription = false ) { + parent::__construct( $subscription ); + } + + static function get_type() { + return 'subscription'; + } + + /** + * Check if subscription is active. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @return bool + */ + function is_active() { + return ! empty( $this->next_payment ) && + ( strtotime( $this->next_payment ) > WP_FS__SCRIPT_START_TIME ); + } + + /** + * Subscription considered to be new without any payments + * if the next payment should be made within less than 24 hours + * from the subscription creation. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @return bool + */ + function is_first_payment_pending() { + return ( WP_FS__TIME_24_HOURS_IN_SEC >= strtotime( $this->next_payment ) - strtotime( $this->created ) ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.7 + */ + function has_trial() { + return ! is_null( $this->trial_ends ); + } } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/includes/fs-core-functions.php b/wp-content/plugins/nextgen-gallery/freemius/includes/fs-core-functions.php index 8eee70ba344496de60abfb2cada749c90557e460..49fdc5f652a8a62c68cb058d948e04e528471912 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/includes/fs-core-functions.php +++ b/wp-content/plugins/nextgen-gallery/freemius/includes/fs-core-functions.php @@ -1,441 +1,441 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.3 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - global $fs_core_logger; - - $fs_core_logger = FS_Logger::get_logger( WP_FS__SLUG . '_core', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); - - if ( ! function_exists( 'fs_dummy' ) ) { - function fs_dummy() { - } - } - - /* Url. - --------------------------------------------------------------------------------------------*/ - function fs_get_url_daily_cache_killer() { - return date( '\YY\Mm\Dd' ); - } - - /* Templates / Views. - --------------------------------------------------------------------------------------------*/ - if ( ! function_exists( 'fs_get_template_path' ) ) { - function fs_get_template_path( $path ) { - return WP_FS__DIR_TEMPLATES . '/' . trim( $path, '/' ); - } - - function fs_include_template( $path, &$params = null ) { - $VARS = &$params; - include( fs_get_template_path( $path ) ); - } - - function fs_include_once_template( $path, &$params = null ) { - $VARS = &$params; - include_once( fs_get_template_path( $path ) ); - } - - function fs_require_template( $path, &$params = null ) { - $VARS = &$params; - require( fs_get_template_path( $path ) ); - } - - function fs_require_once_template( $path, &$params = null ) { - $VARS = &$params; - require_once( fs_get_template_path( $path ) ); - } - - function fs_get_template( $path, &$params = null ) { - ob_start(); - - $VARS = &$params; - require_once( fs_get_template_path( $path ) ); - - return ob_get_clean(); - } - } - - /* Scripts and styles including. - --------------------------------------------------------------------------------------------*/ - function fs_enqueue_local_style( $handle, $path, $deps = array(), $ver = false, $media = 'all' ) { - global $fs_core_logger; - if ( $fs_core_logger->is_on() ) { - $fs_core_logger->info( 'handle = ' . $handle . '; path = ' . $path . ';' ); - $fs_core_logger->info( 'plugin_basename = ' . plugins_url( WP_FS__DIR_CSS . trim( $path, '/' ) ) ); - $fs_core_logger->info( 'plugins_url = ' . plugins_url( plugin_basename( WP_FS__DIR_CSS . '/' . trim( $path, '/' ) ) ) ); - } - - wp_enqueue_style( $handle, plugins_url( plugin_basename( WP_FS__DIR_CSS . '/' . trim( $path, '/' ) ) ), $deps, $ver, $media ); - } - - function fs_enqueue_local_script( $handle, $path, $deps = array(), $ver = false, $in_footer = 'all' ) { - global $fs_core_logger; - if ( $fs_core_logger->is_on() ) { - $fs_core_logger->info( 'handle = ' . $handle . '; path = ' . $path . ';' ); - $fs_core_logger->info( 'plugin_basename = ' . plugins_url( WP_FS__DIR_JS . trim( $path, '/' ) ) ); - $fs_core_logger->info( 'plugins_url = ' . plugins_url( plugin_basename( WP_FS__DIR_JS . '/' . trim( $path, '/' ) ) ) ); - } - - wp_enqueue_script( $handle, plugins_url( plugin_basename( WP_FS__DIR_JS . '/' . trim( $path, '/' ) ) ), $deps, $ver, $in_footer ); - } - - function fs_img_url( $path, $img_dir = WP_FS__DIR_IMG ) { - return plugins_url( plugin_basename( $img_dir . '/' . trim( $path, '/' ) ) ); - } - - /* Request handlers. - --------------------------------------------------------------------------------------------*/ - /** - * @param string $key - * @param mixed $def - * - * @return mixed - */ - function fs_request_get( $key, $def = false ) { - return isset( $_REQUEST[ $key ] ) ? $_REQUEST[ $key ] : $def; - } - - function fs_request_has( $key ) { - return isset( $_REQUEST[ $key ] ); - } - - function fs_request_get_bool( $key, $def = false ) { - return ( isset( $_REQUEST[ $key ] ) && ( 1 == $_REQUEST[ $key ] || 'true' === strtolower( $_REQUEST[ $key ] ) ) ) ? true : $def; - } - - function fs_request_is_post() { - return ( 'post' === strtolower( $_SERVER['REQUEST_METHOD'] ) ); - } - - function fs_request_is_get() { - return ( 'get' === strtolower( $_SERVER['REQUEST_METHOD'] ) ); - } - - function fs_get_action( $action_key = 'action' ) { - if ( ! empty( $_REQUEST[ $action_key ] ) ) { - return strtolower( $_REQUEST[ $action_key ] ); - } - - if ( 'action' == $action_key ) { - $action_key = 'fs_action'; - - if ( ! empty( $_REQUEST[ $action_key ] ) ) { - return strtolower( $_REQUEST[ $action_key ] ); - } - } - - return false; - } - - function fs_request_is_action( $action, $action_key = 'action' ) { - return ( strtolower( $action ) === fs_get_action( $action_key ) ); - } - - function fs_is_plugin_page( $menu_slug ) { - return ( is_admin() && $_REQUEST['page'] === $menu_slug ); - } - - /* Core UI. - --------------------------------------------------------------------------------------------*/ - /** - * @param string $slug - * @param string $page - * @param string $action - * @param string $title - * @param array $params - * @param bool $is_primary - * @param string|bool $icon_class Optional class for an icon (since 1.1.7). - * @param string|bool $confirmation Optional confirmation message before submit (since 1.1.7). - * @param string $method Since 1.1.7 - * - * @uses fs_ui_get_action_button() - */ - function fs_ui_action_button( - $slug, - $page, - $action, - $title, - $params = array(), - $is_primary = true, - $icon_class = false, - $confirmation = false, - $method = 'GET' - ) { - echo fs_ui_get_action_button( - $slug, - $page, - $action, - $title, - $params, - $is_primary, - $icon_class, - $confirmation, - $method - ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.7 - * - * @param string $slug - * @param string $page - * @param string $action - * @param string $title - * @param array $params - * @param bool $is_primary - * @param string|bool $icon_class Optional class for an icon. - * @param string|bool $confirmation Optional confirmation message before submit. - * @param string $method - * - * @return string - */ - function fs_ui_get_action_button( - $slug, - $page, - $action, - $title, - $params = array(), - $is_primary = true, - $icon_class = false, - $confirmation = false, - $method = 'GET' - ) { - // Prepend icon (if set). - $title = ( is_string( $icon_class ) ? '<i class="' . $icon_class . '"></i> ' : '' ) . $title; - - if ( is_string( $confirmation ) ) { - return sprintf( '<form action="%s" method="%s"><input type="hidden" name="fs_action" value="%s">%s<a href="#" class="%s" onclick="if (confirm(\'%s\')) this.parentNode.submit(); return false;">%s</a></form>', - freemius( $slug )->_get_admin_page_url( $page, $params ), - $method, - $action, - wp_nonce_field( $action, '_wpnonce', true, false ), - 'button' . ( $is_primary ? ' button-primary' : '' ), - $confirmation, - $title - ); - } else if ( 'GET' !== strtoupper( $method ) ) { - return sprintf( '<form action="%s" method="%s"><input type="hidden" name="fs_action" value="%s">%s<a href="#" class="%s" onclick="this.parentNode.submit(); return false;">%s</a></form>', - freemius( $slug )->_get_admin_page_url( $page, $params ), - $method, - $action, - wp_nonce_field( $action, '_wpnonce', true, false ), - 'button' . ( $is_primary ? ' button-primary' : '' ), - $title - ); - } else { - return sprintf( '<a href="%s" class="%s">%s</a></form>', - wp_nonce_url( freemius( $slug )->_get_admin_page_url( $page, array_merge( $params, array( 'fs_action' => $action ) ) ), $action ), - 'button' . ( $is_primary ? ' button-primary' : '' ), - $title - ); - } - } - - function fs_ui_action_link( $slug, $page, $action, $title, $params = array() ) { - ?><a class="" - href="<?php echo wp_nonce_url( freemius( $slug )->_get_admin_page_url( $page, array_merge( $params, array( 'fs_action' => $action ) ) ), $action ) ?>"><?php echo $title ?></a><?php - } - - /*function fs_error_handler($errno, $errstr, $errfile, $errline) - { - if (false === strpos($errfile, 'freemius/')) - { - // @todo Dump Freemius errors to local log. - } - -// switch ($errno) { -// case E_USER_ERROR: -// break; -// case E_WARNING: -// case E_USER_WARNING: -// break; -// case E_NOTICE: -// case E_USER_NOTICE: -// break; -// default: -// break; -// } - } - - set_error_handler('fs_error_handler');*/ - - function fs_nonce_url( $actionurl, $action = - 1, $name = '_wpnonce' ) { -// $actionurl = str_replace( '&', '&', $actionurl ); - return add_query_arg( $name, wp_create_nonce( $action ), $actionurl ); - } - - if ( ! function_exists( 'fs_starts_with' ) ) { - /** - * Check if string starts with. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.3 - * - * @param string $haystack - * @param string $needle - * - * @return bool - */ - function fs_starts_with( $haystack, $needle ) { - $length = strlen( $needle ); - - return ( substr( $haystack, 0, $length ) === $needle ); - } - } - - #region Url Canonization ------------------------------------------------------------------ - - if ( ! function_exists( 'fs_canonize_url' ) ) { - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.3 - * - * @param string $url - * @param bool $omit_host - * @param array $ignore_params - * - * @return string - */ - function fs_canonize_url( $url, $omit_host = false, $ignore_params = array() ) { - $parsed_url = parse_url( strtolower( $url ) ); - -// if ( ! isset( $parsed_url['host'] ) ) { -// return $url; -// } - - $canonical = ( ( $omit_host || ! isset( $parsed_url['host'] ) ) ? '' : $parsed_url['host'] ) . $parsed_url['path']; - - if ( isset( $parsed_url['query'] ) ) { - parse_str( $parsed_url['query'], $queryString ); - $canonical .= '?' . fs_canonize_query_string( $queryString, $ignore_params ); - } - - return $canonical; - } - } - - if ( ! function_exists( 'fs_canonize_query_string' ) ) { - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.3 - * - * @param array $params - * @param array $ignore_params - * @param bool $params_prefix - * - * @return string - */ - function fs_canonize_query_string( array $params, array &$ignore_params, $params_prefix = false ) { - if ( ! is_array( $params ) || 0 === count( $params ) ) { - return ''; - } - - // Urlencode both keys and values - $keys = fs_urlencode_rfc3986( array_keys( $params ) ); - $values = fs_urlencode_rfc3986( array_values( $params ) ); - $params = array_combine( $keys, $values ); - - // Parameters are sorted by name, using lexicographical byte value ordering. - // Ref: Spec: 9.1.1 (1) - uksort( $params, 'strcmp' ); - - $pairs = array(); - foreach ( $params as $parameter => $value ) { - $lower_param = strtolower( $parameter ); - - // Skip ignore params. - if ( in_array( $lower_param, $ignore_params ) || ( false !== $params_prefix && startsWith( $lower_param, $params_prefix ) ) ) { - continue; - } - - if ( is_array( $value ) ) { - // If two or more parameters share the same name, they are sorted by their value - // Ref: Spec: 9.1.1 (1) - natsort( $value ); - foreach ( $value as $duplicate_value ) { - $pairs[] = $lower_param . '=' . $duplicate_value; - } - } else { - $pairs[] = $lower_param . '=' . $value; - } - } - - if ( 0 === count( $pairs ) ) { - return ''; - } - - return implode( "&", $pairs ); - } - } - - if ( ! function_exists( 'fs_urlencode_rfc3986' ) ) { - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.3 - * - * @param string|string[] $input - * - * @return array|mixed|string - */ - function fs_urlencode_rfc3986( $input ) { - if ( is_array( $input ) ) { - return array_map( 'fs_urlencode_rfc3986', $input ); - } else if ( is_scalar( $input ) ) { - return str_replace( '+', ' ', str_replace( '%7E', '~', rawurlencode( $input ) ) ); - } - - return ''; - } - } - - #endregion Url Canonization ------------------------------------------------------------------ - - function fs_download_image( $from, $to ) { - $ch = curl_init( $from ); - $fp = fopen( fs_normalize_path( $to ), 'wb' ); - curl_setopt( $ch, CURLOPT_FILE, $fp ); - curl_setopt( $ch, CURLOPT_HEADER, 0 ); - curl_exec( $ch ); - curl_close( $ch ); - fclose( $fp ); - } - - /* General Utilities - --------------------------------------------------------------------------------------------*/ - - /** - * Sorts an array by the value of the priority key. - * - * @author Daniel Iser (@danieliser) - * @since 1.1.7 - * - * @param $a - * @param $b - * - * @return int - */ - function fs_sort_by_priority( $a, $b ) { - - // If b has a priority and a does not, b wins. - if ( ! isset( $a['priority'] ) && isset( $b['priority'] ) ) { - return 1; - } // If b has a priority and a does not, b wins. - elseif ( isset( $a['priority'] ) && ! isset( $b['priority'] ) ) { - return - 1; - } // If neither has a priority or both priorities are equal its a tie. - elseif ( ( ! isset( $a['priority'] ) && ! isset( $b['priority'] ) ) || $a['priority'] === $b['priority'] ) { - return 0; - } - - // If both have priority return the winner. - return ( $a['priority'] < $b['priority'] ) ? - 1 : 1; - } - +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.3 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + global $fs_core_logger; + + $fs_core_logger = FS_Logger::get_logger( WP_FS__SLUG . '_core', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); + + if ( ! function_exists( 'fs_dummy' ) ) { + function fs_dummy() { + } + } + + /* Url. + --------------------------------------------------------------------------------------------*/ + function fs_get_url_daily_cache_killer() { + return date( '\YY\Mm\Dd' ); + } + + /* Templates / Views. + --------------------------------------------------------------------------------------------*/ + if ( ! function_exists( 'fs_get_template_path' ) ) { + function fs_get_template_path( $path ) { + return WP_FS__DIR_TEMPLATES . '/' . trim( $path, '/' ); + } + + function fs_include_template( $path, &$params = null ) { + $VARS = &$params; + include( fs_get_template_path( $path ) ); + } + + function fs_include_once_template( $path, &$params = null ) { + $VARS = &$params; + include_once( fs_get_template_path( $path ) ); + } + + function fs_require_template( $path, &$params = null ) { + $VARS = &$params; + require( fs_get_template_path( $path ) ); + } + + function fs_require_once_template( $path, &$params = null ) { + $VARS = &$params; + require_once( fs_get_template_path( $path ) ); + } + + function fs_get_template( $path, &$params = null ) { + ob_start(); + + $VARS = &$params; + require_once( fs_get_template_path( $path ) ); + + return ob_get_clean(); + } + } + + /* Scripts and styles including. + --------------------------------------------------------------------------------------------*/ + function fs_enqueue_local_style( $handle, $path, $deps = array(), $ver = false, $media = 'all' ) { + global $fs_core_logger; + if ( $fs_core_logger->is_on() ) { + $fs_core_logger->info( 'handle = ' . $handle . '; path = ' . $path . ';' ); + $fs_core_logger->info( 'plugin_basename = ' . plugins_url( WP_FS__DIR_CSS . trim( $path, '/' ) ) ); + $fs_core_logger->info( 'plugins_url = ' . plugins_url( plugin_basename( WP_FS__DIR_CSS . '/' . trim( $path, '/' ) ) ) ); + } + + wp_enqueue_style( $handle, plugins_url( plugin_basename( WP_FS__DIR_CSS . '/' . trim( $path, '/' ) ) ), $deps, $ver, $media ); + } + + function fs_enqueue_local_script( $handle, $path, $deps = array(), $ver = false, $in_footer = 'all' ) { + global $fs_core_logger; + if ( $fs_core_logger->is_on() ) { + $fs_core_logger->info( 'handle = ' . $handle . '; path = ' . $path . ';' ); + $fs_core_logger->info( 'plugin_basename = ' . plugins_url( WP_FS__DIR_JS . trim( $path, '/' ) ) ); + $fs_core_logger->info( 'plugins_url = ' . plugins_url( plugin_basename( WP_FS__DIR_JS . '/' . trim( $path, '/' ) ) ) ); + } + + wp_enqueue_script( $handle, plugins_url( plugin_basename( WP_FS__DIR_JS . '/' . trim( $path, '/' ) ) ), $deps, $ver, $in_footer ); + } + + function fs_img_url( $path, $img_dir = WP_FS__DIR_IMG ) { + return plugins_url( plugin_basename( $img_dir . '/' . trim( $path, '/' ) ) ); + } + + /* Request handlers. + --------------------------------------------------------------------------------------------*/ + /** + * @param string $key + * @param mixed $def + * + * @return mixed + */ + function fs_request_get( $key, $def = false ) { + return isset( $_REQUEST[ $key ] ) ? $_REQUEST[ $key ] : $def; + } + + function fs_request_has( $key ) { + return isset( $_REQUEST[ $key ] ); + } + + function fs_request_get_bool( $key, $def = false ) { + return ( isset( $_REQUEST[ $key ] ) && ( 1 == $_REQUEST[ $key ] || 'true' === strtolower( $_REQUEST[ $key ] ) ) ) ? true : $def; + } + + function fs_request_is_post() { + return ( 'post' === strtolower( $_SERVER['REQUEST_METHOD'] ) ); + } + + function fs_request_is_get() { + return ( 'get' === strtolower( $_SERVER['REQUEST_METHOD'] ) ); + } + + function fs_get_action( $action_key = 'action' ) { + if ( ! empty( $_REQUEST[ $action_key ] ) ) { + return strtolower( $_REQUEST[ $action_key ] ); + } + + if ( 'action' == $action_key ) { + $action_key = 'fs_action'; + + if ( ! empty( $_REQUEST[ $action_key ] ) ) { + return strtolower( $_REQUEST[ $action_key ] ); + } + } + + return false; + } + + function fs_request_is_action( $action, $action_key = 'action' ) { + return ( strtolower( $action ) === fs_get_action( $action_key ) ); + } + + function fs_is_plugin_page( $menu_slug ) { + return ( is_admin() && $_REQUEST['page'] === $menu_slug ); + } + + /* Core UI. + --------------------------------------------------------------------------------------------*/ + /** + * @param string $slug + * @param string $page + * @param string $action + * @param string $title + * @param array $params + * @param bool $is_primary + * @param string|bool $icon_class Optional class for an icon (since 1.1.7). + * @param string|bool $confirmation Optional confirmation message before submit (since 1.1.7). + * @param string $method Since 1.1.7 + * + * @uses fs_ui_get_action_button() + */ + function fs_ui_action_button( + $slug, + $page, + $action, + $title, + $params = array(), + $is_primary = true, + $icon_class = false, + $confirmation = false, + $method = 'GET' + ) { + echo fs_ui_get_action_button( + $slug, + $page, + $action, + $title, + $params, + $is_primary, + $icon_class, + $confirmation, + $method + ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.7 + * + * @param string $slug + * @param string $page + * @param string $action + * @param string $title + * @param array $params + * @param bool $is_primary + * @param string|bool $icon_class Optional class for an icon. + * @param string|bool $confirmation Optional confirmation message before submit. + * @param string $method + * + * @return string + */ + function fs_ui_get_action_button( + $slug, + $page, + $action, + $title, + $params = array(), + $is_primary = true, + $icon_class = false, + $confirmation = false, + $method = 'GET' + ) { + // Prepend icon (if set). + $title = ( is_string( $icon_class ) ? '<i class="' . $icon_class . '"></i> ' : '' ) . $title; + + if ( is_string( $confirmation ) ) { + return sprintf( '<form action="%s" method="%s"><input type="hidden" name="fs_action" value="%s">%s<a href="#" class="%s" onclick="if (confirm(\'%s\')) this.parentNode.submit(); return false;">%s</a></form>', + freemius( $slug )->_get_admin_page_url( $page, $params ), + $method, + $action, + wp_nonce_field( $action, '_wpnonce', true, false ), + 'button' . ( $is_primary ? ' button-primary' : '' ), + $confirmation, + $title + ); + } else if ( 'GET' !== strtoupper( $method ) ) { + return sprintf( '<form action="%s" method="%s"><input type="hidden" name="fs_action" value="%s">%s<a href="#" class="%s" onclick="this.parentNode.submit(); return false;">%s</a></form>', + freemius( $slug )->_get_admin_page_url( $page, $params ), + $method, + $action, + wp_nonce_field( $action, '_wpnonce', true, false ), + 'button' . ( $is_primary ? ' button-primary' : '' ), + $title + ); + } else { + return sprintf( '<a href="%s" class="%s">%s</a></form>', + wp_nonce_url( freemius( $slug )->_get_admin_page_url( $page, array_merge( $params, array( 'fs_action' => $action ) ) ), $action ), + 'button' . ( $is_primary ? ' button-primary' : '' ), + $title + ); + } + } + + function fs_ui_action_link( $slug, $page, $action, $title, $params = array() ) { + ?><a class="" + href="<?php echo wp_nonce_url( freemius( $slug )->_get_admin_page_url( $page, array_merge( $params, array( 'fs_action' => $action ) ) ), $action ) ?>"><?php echo $title ?></a><?php + } + + /*function fs_error_handler($errno, $errstr, $errfile, $errline) + { + if (false === strpos($errfile, 'freemius/')) + { + // @todo Dump Freemius errors to local log. + } + +// switch ($errno) { +// case E_USER_ERROR: +// break; +// case E_WARNING: +// case E_USER_WARNING: +// break; +// case E_NOTICE: +// case E_USER_NOTICE: +// break; +// default: +// break; +// } + } + + set_error_handler('fs_error_handler');*/ + + function fs_nonce_url( $actionurl, $action = - 1, $name = '_wpnonce' ) { +// $actionurl = str_replace( '&', '&', $actionurl ); + return add_query_arg( $name, wp_create_nonce( $action ), $actionurl ); + } + + if ( ! function_exists( 'fs_starts_with' ) ) { + /** + * Check if string starts with. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.3 + * + * @param string $haystack + * @param string $needle + * + * @return bool + */ + function fs_starts_with( $haystack, $needle ) { + $length = strlen( $needle ); + + return ( substr( $haystack, 0, $length ) === $needle ); + } + } + + #region Url Canonization ------------------------------------------------------------------ + + if ( ! function_exists( 'fs_canonize_url' ) ) { + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.3 + * + * @param string $url + * @param bool $omit_host + * @param array $ignore_params + * + * @return string + */ + function fs_canonize_url( $url, $omit_host = false, $ignore_params = array() ) { + $parsed_url = parse_url( strtolower( $url ) ); + +// if ( ! isset( $parsed_url['host'] ) ) { +// return $url; +// } + + $canonical = ( ( $omit_host || ! isset( $parsed_url['host'] ) ) ? '' : $parsed_url['host'] ) . $parsed_url['path']; + + if ( isset( $parsed_url['query'] ) ) { + parse_str( $parsed_url['query'], $queryString ); + $canonical .= '?' . fs_canonize_query_string( $queryString, $ignore_params ); + } + + return $canonical; + } + } + + if ( ! function_exists( 'fs_canonize_query_string' ) ) { + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.3 + * + * @param array $params + * @param array $ignore_params + * @param bool $params_prefix + * + * @return string + */ + function fs_canonize_query_string( array $params, array &$ignore_params, $params_prefix = false ) { + if ( ! is_array( $params ) || 0 === count( $params ) ) { + return ''; + } + + // Urlencode both keys and values + $keys = fs_urlencode_rfc3986( array_keys( $params ) ); + $values = fs_urlencode_rfc3986( array_values( $params ) ); + $params = array_combine( $keys, $values ); + + // Parameters are sorted by name, using lexicographical byte value ordering. + // Ref: Spec: 9.1.1 (1) + uksort( $params, 'strcmp' ); + + $pairs = array(); + foreach ( $params as $parameter => $value ) { + $lower_param = strtolower( $parameter ); + + // Skip ignore params. + if ( in_array( $lower_param, $ignore_params ) || ( false !== $params_prefix && startsWith( $lower_param, $params_prefix ) ) ) { + continue; + } + + if ( is_array( $value ) ) { + // If two or more parameters share the same name, they are sorted by their value + // Ref: Spec: 9.1.1 (1) + natsort( $value ); + foreach ( $value as $duplicate_value ) { + $pairs[] = $lower_param . '=' . $duplicate_value; + } + } else { + $pairs[] = $lower_param . '=' . $value; + } + } + + if ( 0 === count( $pairs ) ) { + return ''; + } + + return implode( "&", $pairs ); + } + } + + if ( ! function_exists( 'fs_urlencode_rfc3986' ) ) { + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.3 + * + * @param string|string[] $input + * + * @return array|mixed|string + */ + function fs_urlencode_rfc3986( $input ) { + if ( is_array( $input ) ) { + return array_map( 'fs_urlencode_rfc3986', $input ); + } else if ( is_scalar( $input ) ) { + return str_replace( '+', ' ', str_replace( '%7E', '~', rawurlencode( $input ) ) ); + } + + return ''; + } + } + + #endregion Url Canonization ------------------------------------------------------------------ + + function fs_download_image( $from, $to ) { + $ch = curl_init( $from ); + $fp = fopen( fs_normalize_path( $to ), 'wb' ); + curl_setopt( $ch, CURLOPT_FILE, $fp ); + curl_setopt( $ch, CURLOPT_HEADER, 0 ); + curl_exec( $ch ); + curl_close( $ch ); + fclose( $fp ); + } + + /* General Utilities + --------------------------------------------------------------------------------------------*/ + + /** + * Sorts an array by the value of the priority key. + * + * @author Daniel Iser (@danieliser) + * @since 1.1.7 + * + * @param $a + * @param $b + * + * @return int + */ + function fs_sort_by_priority( $a, $b ) { + + // If b has a priority and a does not, b wins. + if ( ! isset( $a['priority'] ) && isset( $b['priority'] ) ) { + return 1; + } // If b has a priority and a does not, b wins. + elseif ( isset( $a['priority'] ) && ! isset( $b['priority'] ) ) { + return - 1; + } // If neither has a priority or both priorities are equal its a tie. + elseif ( ( ! isset( $a['priority'] ) && ! isset( $b['priority'] ) ) || $a['priority'] === $b['priority'] ) { + return 0; + } + + // If both have priority return the winner. + return ( $a['priority'] < $b['priority'] ) ? - 1 : 1; + } + diff --git a/wp-content/plugins/nextgen-gallery/freemius/includes/fs-essential-functions.php b/wp-content/plugins/nextgen-gallery/freemius/includes/fs-essential-functions.php index 64a53087927564a5076b596ae7a843e4965d38e6..38eb8d598d672b1009b1a7142cafd674437f567d 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/includes/fs-essential-functions.php +++ b/wp-content/plugins/nextgen-gallery/freemius/includes/fs-essential-functions.php @@ -1,412 +1,412 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.1.5 - */ - - if ( ! function_exists( 'fs_normalize_path' ) ) { - if ( function_exists( 'wp_normalize_path' ) ) { - /** - * Normalize a filesystem path. - * - * Replaces backslashes with forward slashes for Windows systems, and ensures - * no duplicate slashes exist. - * - * @param string $path Path to normalize. - * - * @return string Normalized path. - */ - function fs_normalize_path( $path ) { - return wp_normalize_path( $path ); - } - } else { - function fs_normalize_path( $path ) { - $path = str_replace( '\\', '/', $path ); - $path = preg_replace( '|/+|', '/', $path ); - - return $path; - } - } - } - - #region Core Redirect (copied from BuddyPress) ----------------------------------------- - - if ( ! function_exists( 'fs_redirect' ) ) { - /** - * Redirects to another page, with a workaround for the IIS Set-Cookie bug. - * - * @link http://support.microsoft.com/kb/q176113/ - * @since 1.5.1 - * @uses apply_filters() Calls 'wp_redirect' hook on $location and $status. - * - * @param string $location The path to redirect to - * @param int $status Status code to use - * - * @return bool False if $location is not set - */ - function fs_redirect( $location, $status = 302 ) { - global $is_IIS; - - if ( headers_sent() ) { - return false; - } - - if ( ! $location ) // allows the wp_redirect filter to cancel a redirect - { - return false; - } - - $location = fs_sanitize_redirect( $location ); - - if ( $is_IIS ) { - header( "Refresh: 0;url=$location" ); - } else { - if ( php_sapi_name() != 'cgi-fcgi' ) { - status_header( $status ); - } // This causes problems on IIS and some FastCGI setups - header( "Location: $location" ); - } - - return true; - } - - if ( ! function_exists( 'fs_sanitize_redirect' ) ) { - /** - * Sanitizes a URL for use in a redirect. - * - * @since 2.3 - * - * @param string $location - * - * @return string redirect-sanitized URL - */ - function fs_sanitize_redirect( $location ) { - $location = preg_replace( '|[^a-z0-9-~+_.?#=&;,/:%!]|i', '', $location ); - $location = fs_kses_no_null( $location ); - - // remove %0d and %0a from location - $strip = array( '%0d', '%0a' ); - $found = true; - while ( $found ) { - $found = false; - foreach ( (array) $strip as $val ) { - while ( strpos( $location, $val ) !== false ) { - $found = true; - $location = str_replace( $val, '', $location ); - } - } - } - - return $location; - } - } - - if ( ! function_exists( 'fs_kses_no_null' ) ) { - /** - * Removes any NULL characters in $string. - * - * @since 1.0.0 - * - * @param string $string - * - * @return string - */ - function fs_kses_no_null( $string ) { - $string = preg_replace( '/\0+/', '', $string ); - $string = preg_replace( '/(\\\\0)+/', '', $string ); - - return $string; - } - } - } - - #endregion Core Redirect (copied from BuddyPress) ----------------------------------------- - - if ( ! function_exists( '__fs' ) ) { - global $fs_text_overrides; - - if ( ! isset( $fs_text_overrides ) ) { - $fs_text_overrides = array(); - } - - /** - * Retrieve a translated text by key. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.4 - * - * @param string $key - * @param string $slug - * - * @return string - * - * @global $fs_text , $fs_text_overrides - */ - function __fs( $key, $slug = 'freemius' ) { - global $fs_text, $fs_text_overrides; - - if ( ! isset( $fs_text ) ) { - require_once( ( defined( 'WP_FS__DIR_INCLUDES' ) ? WP_FS__DIR_INCLUDES : dirname( __FILE__ ) ) . '/i18n.php' ); - } - - if ( isset( $fs_text_overrides[ $slug ] ) ) { - if ( isset( $fs_text_overrides[ $slug ][ $key ] ) ) { - return $fs_text_overrides[ $slug ][ $key ]; - } - - $lower_key = strtolower( $key ); - if ( isset( $fs_text_overrides[ $slug ][ $lower_key ] ) ) { - return $fs_text_overrides[ $slug ][ $lower_key ]; - } - } - - return isset( $fs_text[ $key ] ) ? - $fs_text[ $key ] : - $key; - } - - /** - * Display a translated text by key. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.4 - * - * @param string $key - * @param string $slug - */ - function _efs( $key, $slug = 'freemius' ) { - echo __fs( $key, $slug ); - } - - /** - * Override default i18n text phrases. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.6 - * - * @param string[] $key_value - * @param string $slug - * - * @global $fs_text_overrides - */ - function fs_override_i18n( array $key_value, $slug = 'freemius' ) { - global $fs_text_overrides; - - if ( ! isset( $fs_text_overrides[ $slug ] ) ) { - $fs_text_overrides[ $slug ] = array(); - } - - foreach ( $key_value as $key => $value ) { - $fs_text_overrides[ $slug ][ $key ] = $value; - } - } - } - - if ( ! function_exists( 'fs_get_ip' ) ) { - /** - * Get client IP. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.2 - * - * @return string|null - */ - function fs_get_ip() { - $fields = array( - 'HTTP_CF_CONNECTING_IP', - 'HTTP_CLIENT_IP', - 'HTTP_X_FORWARDED_FOR', - 'HTTP_X_FORWARDED', - 'HTTP_FORWARDED_FOR', - 'HTTP_FORWARDED', - 'REMOTE_ADDR', - ); - - foreach ( $fields as $ip_field ) { - if ( ! empty( $_SERVER[ $ip_field ] ) ) { - return $_SERVER[ $ip_field ]; - } - } - - return null; - } - } - - /** - * Leverage backtrace to find caller plugin main file path. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @return string - */ - function fs_find_caller_plugin_file() { - /** - * All the code below will be executed once on activation. - * If the user changes the main plugin's file name, the file_exists() - * will catch it. - */ - if ( ! function_exists( 'get_plugins' ) ) { - require_once( ABSPATH . 'wp-admin/includes/plugin.php' ); - } - - $all_plugins = get_plugins(); - $all_plugins_paths = array(); - - // Get active plugin's main files real full names (might be symlinks). - foreach ( $all_plugins as $relative_path => &$data ) { - $all_plugins_paths[] = fs_normalize_path( realpath( WP_PLUGIN_DIR . '/' . $relative_path ) ); - } - - $plugin_file = null; - for ( $i = 1, $bt = debug_backtrace(), $len = count( $bt ); $i < $len; $i ++ ) { - if ( in_array( fs_normalize_path( $bt[ $i ]['file'] ), $all_plugins_paths ) ) { - $plugin_file = $bt[ $i ]['file']; - break; - } - } - - if ( is_null( $plugin_file ) ) { - // Throw an error to the developer in case of some edge case dev environment. - wp_die( __fs( 'failed-finding-main-path' ), __fs( 'error' ), array( 'back_link' => true ) ); - } - - return $plugin_file; - } - - require_once dirname( __FILE__ ) . '/supplements/fs-essential-functions-1.1.7.1.php'; - - /** - * Update SDK newest version reference. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.6 - * - * @param string $sdk_relative_path - * @param string|bool $plugin_file - * - * @global $fs_active_plugins - */ - function fs_update_sdk_newest_version( $sdk_relative_path, $plugin_file = false ) { - global $fs_active_plugins; - - if ( ! is_string( $plugin_file ) ) { - $plugin_file = plugin_basename( fs_find_caller_plugin_file() ); - } - - $fs_active_plugins->newest = (object) array( - 'plugin_path' => $plugin_file, - 'sdk_path' => $sdk_relative_path, - 'version' => $fs_active_plugins->plugins[ $sdk_relative_path ]->version, - 'in_activation' => ! is_plugin_active( $plugin_file ), - 'timestamp' => time(), - ); - - // Update DB with latest SDK version and path. - update_option( 'fs_active_plugins', $fs_active_plugins ); - } - - /** - * Reorder the plugins load order so the plugin with the newest Freemius SDK is loaded first. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.6 - * - * @return bool Was plugin order changed. Return false if plugin was loaded first anyways. - * - * @global $fs_active_plugins - */ - function fs_newest_sdk_plugin_first() { - global $fs_active_plugins; - - /** - * @todo Multi-site network activated plugin are always loaded prior to site plugins so if there's a a plugin activated in the network mode that has an older version of the SDK of another plugin which is site activated that has new SDK version, the fs-essential-functions.php will be loaded from the older SDK. Same thing about MU plugins (loaded even before network activated plugins). - * - * @link https://github.com/Freemius/wordpress-sdk/issues/26 - */ -// $active_sitewide_plugins = get_site_option( 'active_sitewide_plugins' ); - - $active_plugins = get_option( 'active_plugins' ); - $newest_sdk_plugin_key = array_search( $fs_active_plugins->newest->plugin_path, $active_plugins ); - if ( 0 == $newest_sdk_plugin_key ) { - // if it's 0 it's the first plugin already, no need to continue - return false; - } - - array_splice( $active_plugins, $newest_sdk_plugin_key, 1 ); - array_unshift( $active_plugins, $fs_active_plugins->newest->plugin_path ); - update_option( 'active_plugins', $active_plugins ); - - return true; - } - - /** - * Go over all Freemius SDKs in the system and find and "remember" - * the newest SDK which is associated with an active plugin. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.6 - * - * @global $fs_active_plugins - */ - function fs_fallback_to_newest_active_sdk() { - global $fs_active_plugins; - - $newest_sdk_data = null; - $newest_sdk_path = null; - - foreach ( $fs_active_plugins->plugins as $sdk_relative_path => $data ) { - if ( is_null( $newest_sdk_data ) || version_compare( $data->version, $newest_sdk_data->version, '>' ) - ) { - // If plugin inactive or SDK starter file doesn't exist, remove SDK reference. - if ( ! is_plugin_active( $data->plugin_path ) || - ! file_exists( fs_normalize_path( WP_PLUGIN_DIR . '/' . $sdk_relative_path . '/start.php' ) ) - ) { - unset( $fs_active_plugins->plugins[ $sdk_relative_path ] ); - - // No need to store the data since it will be stored in fs_update_sdk_newest_version() - // or explicitly with update_option(). - } else { - $newest_sdk_data = $data; - $newest_sdk_path = $sdk_relative_path; - } - } - } - - if ( is_null( $newest_sdk_data ) ) { - // Couldn't find any SDK reference. - $fs_active_plugins = new stdClass(); - update_option( 'fs_active_plugins', $fs_active_plugins ); - } else { - fs_update_sdk_newest_version( $newest_sdk_path, $newest_sdk_data->plugin_path ); - } - } - - #region Actions / Filters ----------------------------------------- - - /** - * Apply filter for specific plugin. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @param string $slug Plugin slug - * @param string $tag The name of the filter hook. - * @param mixed $value The value on which the filters hooked to `$tag` are applied on. - * - * @return mixed The filtered value after all hooked functions are applied to it. - * - * @uses apply_filters() - */ - function fs_apply_filter( $slug, $tag, $value ) { - $args = func_get_args(); - - return call_user_func_array( 'apply_filters', array_merge( - array( 'fs_' . $tag . '_' . $slug ), - array_slice( $args, 2 ) ) - ); - } - +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.1.5 + */ + + if ( ! function_exists( 'fs_normalize_path' ) ) { + if ( function_exists( 'wp_normalize_path' ) ) { + /** + * Normalize a filesystem path. + * + * Replaces backslashes with forward slashes for Windows systems, and ensures + * no duplicate slashes exist. + * + * @param string $path Path to normalize. + * + * @return string Normalized path. + */ + function fs_normalize_path( $path ) { + return wp_normalize_path( $path ); + } + } else { + function fs_normalize_path( $path ) { + $path = str_replace( '\\', '/', $path ); + $path = preg_replace( '|/+|', '/', $path ); + + return $path; + } + } + } + + #region Core Redirect (copied from BuddyPress) ----------------------------------------- + + if ( ! function_exists( 'fs_redirect' ) ) { + /** + * Redirects to another page, with a workaround for the IIS Set-Cookie bug. + * + * @link http://support.microsoft.com/kb/q176113/ + * @since 1.5.1 + * @uses apply_filters() Calls 'wp_redirect' hook on $location and $status. + * + * @param string $location The path to redirect to + * @param int $status Status code to use + * + * @return bool False if $location is not set + */ + function fs_redirect( $location, $status = 302 ) { + global $is_IIS; + + if ( headers_sent() ) { + return false; + } + + if ( ! $location ) // allows the wp_redirect filter to cancel a redirect + { + return false; + } + + $location = fs_sanitize_redirect( $location ); + + if ( $is_IIS ) { + header( "Refresh: 0;url=$location" ); + } else { + if ( php_sapi_name() != 'cgi-fcgi' ) { + status_header( $status ); + } // This causes problems on IIS and some FastCGI setups + header( "Location: $location" ); + } + + return true; + } + + if ( ! function_exists( 'fs_sanitize_redirect' ) ) { + /** + * Sanitizes a URL for use in a redirect. + * + * @since 2.3 + * + * @param string $location + * + * @return string redirect-sanitized URL + */ + function fs_sanitize_redirect( $location ) { + $location = preg_replace( '|[^a-z0-9-~+_.?#=&;,/:%!]|i', '', $location ); + $location = fs_kses_no_null( $location ); + + // remove %0d and %0a from location + $strip = array( '%0d', '%0a' ); + $found = true; + while ( $found ) { + $found = false; + foreach ( (array) $strip as $val ) { + while ( strpos( $location, $val ) !== false ) { + $found = true; + $location = str_replace( $val, '', $location ); + } + } + } + + return $location; + } + } + + if ( ! function_exists( 'fs_kses_no_null' ) ) { + /** + * Removes any NULL characters in $string. + * + * @since 1.0.0 + * + * @param string $string + * + * @return string + */ + function fs_kses_no_null( $string ) { + $string = preg_replace( '/\0+/', '', $string ); + $string = preg_replace( '/(\\\\0)+/', '', $string ); + + return $string; + } + } + } + + #endregion Core Redirect (copied from BuddyPress) ----------------------------------------- + + if ( ! function_exists( '__fs' ) ) { + global $fs_text_overrides; + + if ( ! isset( $fs_text_overrides ) ) { + $fs_text_overrides = array(); + } + + /** + * Retrieve a translated text by key. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.4 + * + * @param string $key + * @param string $slug + * + * @return string + * + * @global $fs_text , $fs_text_overrides + */ + function __fs( $key, $slug = 'freemius' ) { + global $fs_text, $fs_text_overrides; + + if ( ! isset( $fs_text ) ) { + require_once( ( defined( 'WP_FS__DIR_INCLUDES' ) ? WP_FS__DIR_INCLUDES : dirname( __FILE__ ) ) . '/i18n.php' ); + } + + if ( isset( $fs_text_overrides[ $slug ] ) ) { + if ( isset( $fs_text_overrides[ $slug ][ $key ] ) ) { + return $fs_text_overrides[ $slug ][ $key ]; + } + + $lower_key = strtolower( $key ); + if ( isset( $fs_text_overrides[ $slug ][ $lower_key ] ) ) { + return $fs_text_overrides[ $slug ][ $lower_key ]; + } + } + + return isset( $fs_text[ $key ] ) ? + $fs_text[ $key ] : + $key; + } + + /** + * Display a translated text by key. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.4 + * + * @param string $key + * @param string $slug + */ + function _efs( $key, $slug = 'freemius' ) { + echo __fs( $key, $slug ); + } + + /** + * Override default i18n text phrases. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.6 + * + * @param string[] $key_value + * @param string $slug + * + * @global $fs_text_overrides + */ + function fs_override_i18n( array $key_value, $slug = 'freemius' ) { + global $fs_text_overrides; + + if ( ! isset( $fs_text_overrides[ $slug ] ) ) { + $fs_text_overrides[ $slug ] = array(); + } + + foreach ( $key_value as $key => $value ) { + $fs_text_overrides[ $slug ][ $key ] = $value; + } + } + } + + if ( ! function_exists( 'fs_get_ip' ) ) { + /** + * Get client IP. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.2 + * + * @return string|null + */ + function fs_get_ip() { + $fields = array( + 'HTTP_CF_CONNECTING_IP', + 'HTTP_CLIENT_IP', + 'HTTP_X_FORWARDED_FOR', + 'HTTP_X_FORWARDED', + 'HTTP_FORWARDED_FOR', + 'HTTP_FORWARDED', + 'REMOTE_ADDR', + ); + + foreach ( $fields as $ip_field ) { + if ( ! empty( $_SERVER[ $ip_field ] ) ) { + return $_SERVER[ $ip_field ]; + } + } + + return null; + } + } + + /** + * Leverage backtrace to find caller plugin main file path. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @return string + */ + function fs_find_caller_plugin_file() { + /** + * All the code below will be executed once on activation. + * If the user changes the main plugin's file name, the file_exists() + * will catch it. + */ + if ( ! function_exists( 'get_plugins' ) ) { + require_once( ABSPATH . 'wp-admin/includes/plugin.php' ); + } + + $all_plugins = get_plugins(); + $all_plugins_paths = array(); + + // Get active plugin's main files real full names (might be symlinks). + foreach ( $all_plugins as $relative_path => &$data ) { + $all_plugins_paths[] = fs_normalize_path( realpath( WP_PLUGIN_DIR . '/' . $relative_path ) ); + } + + $plugin_file = null; + for ( $i = 1, $bt = debug_backtrace(), $len = count( $bt ); $i < $len; $i ++ ) { + if ( in_array( fs_normalize_path( $bt[ $i ]['file'] ), $all_plugins_paths ) ) { + $plugin_file = $bt[ $i ]['file']; + break; + } + } + + if ( is_null( $plugin_file ) ) { + // Throw an error to the developer in case of some edge case dev environment. + wp_die( __fs( 'failed-finding-main-path' ), __fs( 'error' ), array( 'back_link' => true ) ); + } + + return $plugin_file; + } + + require_once dirname( __FILE__ ) . '/supplements/fs-essential-functions-1.1.7.1.php'; + + /** + * Update SDK newest version reference. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.6 + * + * @param string $sdk_relative_path + * @param string|bool $plugin_file + * + * @global $fs_active_plugins + */ + function fs_update_sdk_newest_version( $sdk_relative_path, $plugin_file = false ) { + global $fs_active_plugins; + + if ( ! is_string( $plugin_file ) ) { + $plugin_file = plugin_basename( fs_find_caller_plugin_file() ); + } + + $fs_active_plugins->newest = (object) array( + 'plugin_path' => $plugin_file, + 'sdk_path' => $sdk_relative_path, + 'version' => $fs_active_plugins->plugins[ $sdk_relative_path ]->version, + 'in_activation' => ! is_plugin_active( $plugin_file ), + 'timestamp' => time(), + ); + + // Update DB with latest SDK version and path. + update_option( 'fs_active_plugins', $fs_active_plugins ); + } + + /** + * Reorder the plugins load order so the plugin with the newest Freemius SDK is loaded first. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.6 + * + * @return bool Was plugin order changed. Return false if plugin was loaded first anyways. + * + * @global $fs_active_plugins + */ + function fs_newest_sdk_plugin_first() { + global $fs_active_plugins; + + /** + * @todo Multi-site network activated plugin are always loaded prior to site plugins so if there's a a plugin activated in the network mode that has an older version of the SDK of another plugin which is site activated that has new SDK version, the fs-essential-functions.php will be loaded from the older SDK. Same thing about MU plugins (loaded even before network activated plugins). + * + * @link https://github.com/Freemius/wordpress-sdk/issues/26 + */ +// $active_sitewide_plugins = get_site_option( 'active_sitewide_plugins' ); + + $active_plugins = get_option( 'active_plugins' ); + $newest_sdk_plugin_key = array_search( $fs_active_plugins->newest->plugin_path, $active_plugins ); + if ( 0 == $newest_sdk_plugin_key ) { + // if it's 0 it's the first plugin already, no need to continue + return false; + } + + array_splice( $active_plugins, $newest_sdk_plugin_key, 1 ); + array_unshift( $active_plugins, $fs_active_plugins->newest->plugin_path ); + update_option( 'active_plugins', $active_plugins ); + + return true; + } + + /** + * Go over all Freemius SDKs in the system and find and "remember" + * the newest SDK which is associated with an active plugin. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.6 + * + * @global $fs_active_plugins + */ + function fs_fallback_to_newest_active_sdk() { + global $fs_active_plugins; + + $newest_sdk_data = null; + $newest_sdk_path = null; + + foreach ( $fs_active_plugins->plugins as $sdk_relative_path => $data ) { + if ( is_null( $newest_sdk_data ) || version_compare( $data->version, $newest_sdk_data->version, '>' ) + ) { + // If plugin inactive or SDK starter file doesn't exist, remove SDK reference. + if ( ! is_plugin_active( $data->plugin_path ) || + ! file_exists( fs_normalize_path( WP_PLUGIN_DIR . '/' . $sdk_relative_path . '/start.php' ) ) + ) { + unset( $fs_active_plugins->plugins[ $sdk_relative_path ] ); + + // No need to store the data since it will be stored in fs_update_sdk_newest_version() + // or explicitly with update_option(). + } else { + $newest_sdk_data = $data; + $newest_sdk_path = $sdk_relative_path; + } + } + } + + if ( is_null( $newest_sdk_data ) ) { + // Couldn't find any SDK reference. + $fs_active_plugins = new stdClass(); + update_option( 'fs_active_plugins', $fs_active_plugins ); + } else { + fs_update_sdk_newest_version( $newest_sdk_path, $newest_sdk_data->plugin_path ); + } + } + + #region Actions / Filters ----------------------------------------- + + /** + * Apply filter for specific plugin. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @param string $slug Plugin slug + * @param string $tag The name of the filter hook. + * @param mixed $value The value on which the filters hooked to `$tag` are applied on. + * + * @return mixed The filtered value after all hooked functions are applied to it. + * + * @uses apply_filters() + */ + function fs_apply_filter( $slug, $tag, $value ) { + $args = func_get_args(); + + return call_user_func_array( 'apply_filters', array_merge( + array( 'fs_' . $tag . '_' . $slug ), + array_slice( $args, 2 ) ) + ); + } + #endregion Actions / Filters ----------------------------------------- \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/includes/fs-plugin-info-dialog.php b/wp-content/plugins/nextgen-gallery/freemius/includes/fs-plugin-info-dialog.php index 2280144a0bda359a9d4f41b1df82f0813540af96..caacfb794784f79262efeda0501d2ede6593bb56 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/includes/fs-plugin-info-dialog.php +++ b/wp-content/plugins/nextgen-gallery/freemius/includes/fs-plugin-info-dialog.php @@ -1,936 +1,936 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.6 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - /** - * Class FS_Plugin_Info_Dialog - * - * @author Vova Feldman (@svovaf) - * @since 1.1.7 - */ - class FS_Plugin_Info_Dialog { - /** - * @since 1.1.7 - * - * @var FS_Logger - */ - private $_logger; - - /** - * @since 1.1.7 - * - * @var Freemius - */ - private $_fs; - - function __construct( Freemius $fs ) { - $this->_fs = $fs; - - $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $fs->get_slug() . '_info', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); - - // Remove default plugin information action. - remove_all_actions( 'install_plugins_pre_plugin-information' ); - - // Override action with custom plugins function for add-ons. - add_action( 'install_plugins_pre_plugin-information', array( &$this, 'install_plugin_information' ) ); - - // Override request for plugin information for Add-ons. - add_filter( - 'fs_plugins_api', - array( &$this, '_get_addon_info_filter' ), - WP_FS__DEFAULT_PRIORITY, 3 ); - } - - /** - * Generate add-on plugin information. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @param array $data - * @param string $action - * @param object|null $args - * - * @return array|null - */ - function _get_addon_info_filter( $data, $action = '', $args = null ) { - $this->_logger->entrance(); - - $parent_plugin_id = fs_request_get( 'parent_plugin_id', false ); - - if ( $this->_fs->get_id() != $parent_plugin_id || - ( 'plugin_information' !== $action ) || - ! isset( $args->slug ) - ) { - return $data; - } - - // Find add-on by slug. - $addons = $this->_fs->get_addons(); - $selected_addon = false; - foreach ( $addons as $addon ) { - if ( $addon->slug == $args->slug ) { - $selected_addon = $addon; - break; - } - } - - if ( false === $selected_addon ) { - return $data; - } - - if ( ! isset( $selected_addon->info ) ) { - // Setup some default info. - $selected_addon->info = new stdClass(); - $selected_addon->info->selling_point_0 = 'Selling Point 1'; - $selected_addon->info->selling_point_1 = 'Selling Point 2'; - $selected_addon->info->selling_point_2 = 'Selling Point 3'; - $selected_addon->info->description = '<p>Tell your users all about your add-on</p>'; - } - - fs_enqueue_local_style( 'fs_addons', '/admin/add-ons.css' ); - - $data = $args; - - $is_free = true; - - // Load add-on pricing. - $has_pricing = false; - $has_features = false; - $plans = false; - $plans_result = $this->_fs->get_api_site_or_plugin_scope()->get( "/addons/{$selected_addon->id}/plans.json" ); - if ( ! isset( $plans_result->error ) ) { - $plans = $plans_result->plans; - if ( is_array( $plans ) ) { - for ( $i = 0, $len = count( $plans ); $i < $len; $i ++ ) { - $plans[ $i ] = new FS_Plugin_Plan( $plans[ $i ] ); - $plan = $plans[ $i ]; - - $pricing_result = $this->_fs->get_api_site_or_plugin_scope()->get( "/addons/{$selected_addon->id}/plans/{$plan->id}/pricing.json" ); - if ( ! isset( $pricing_result->error ) ) { - // Update plan's pricing. - $plan->pricing = $pricing_result->pricing; - - if ( is_array( $plan->pricing ) && ! empty( $plan->pricing ) ) { - $is_free = false; - - foreach ( $plan->pricing as &$pricing ) { - $pricing = new FS_Pricing( $pricing ); - } - } - - $has_pricing = true; - } - - $features_result = $this->_fs->get_api_site_or_plugin_scope()->get( "/addons/{$selected_addon->id}/plans/{$plan->id}/features.json" ); - if ( ! isset( $features_result->error ) && - is_array( $features_result->features ) && - 0 < count( $features_result->features ) - ) { - // Update plan's pricing. - $plan->features = $features_result->features; - - $has_features = true; - } - } - } - } - - // Fetch latest version from Freemius. - $latest = $this->_fs->_fetch_latest_version( $selected_addon->id ); - - if ( ! $is_free ) { - // If paid add-on, then it's not on wordpress.org - $is_wordpress_org = false; - } else { - // If no versions found, then assume it's a .org plugin. - $is_wordpress_org = ( false === $latest ); - } - - if ( $is_wordpress_org ) { - $repo_data = FS_Plugin_Updater::_fetch_plugin_info_from_repository( - 'plugin_information', (object) array( - 'slug' => $selected_addon->slug, - 'is_ssl' => is_ssl(), - 'fields' => array( - 'banners' => true, - 'reviews' => true, - 'downloaded' => false, - 'active_installs' => true - ) - ) ); - - if ( ! empty( $repo_data ) ) { - $data = $repo_data; - $data->wp_org_missing = false; - } else { - // Couldn't find plugin on .org. - $is_wordpress_org = false; - - // Plugin is missing, not on Freemius nor WP.org. - $data->wp_org_missing = true; - } - } - - if ( ! $is_wordpress_org ) { - $data->checkout_link = $this->_fs->checkout_url(); - $data->fs_missing = ( false === $latest ); - - if ( $is_free ) { - $data->download_link = $this->_fs->_get_latest_download_local_url( $selected_addon->id ); - } - } - - if ( ! $is_wordpress_org ) { -// Fetch as much as possible info from local files. - $plugin_local_data = $this->_fs->get_plugin_data(); - $data->name = $selected_addon->title; - $data->author = $plugin_local_data['Author']; - $view_vars = array( 'plugin' => $selected_addon ); - $data->sections = array( - 'description' => fs_get_template( '/plugin-info/description.php', $view_vars ), - ); - - if ( ! empty( $selected_addon->info->banner_url ) ) { - $data->banners = array( - 'low' => $selected_addon->info->banner_url, - ); - } - - if ( ! empty( $selected_addon->info->screenshots ) ) { - $view_vars = array( - 'screenshots' => $selected_addon->info->screenshots, - 'plugin' => $selected_addon, - ); - $data->sections['screenshots'] = fs_get_template( '/plugin-info/screenshots.php', $view_vars ); - } - - if ( is_object( $latest ) ) { - $data->version = $latest->version; - $data->last_updated = ! is_null( $latest->updated ) ? $latest->updated : $latest->created; - $data->requires = $latest->requires_platform_version; - $data->tested = $latest->tested_up_to_version; - } else { - // Add dummy version. - $data->version = '1.0.0'; - - // Add message to developer to deploy the plugin through Freemius. - } - } - - if ( $has_pricing ) { - // Add plans to data. - $data->plans = $plans; - - if ( $has_features ) { - $view_vars = array( - 'plans' => $plans, - 'plugin' => $selected_addon, - ); - $data->sections['features'] = fs_get_template( '/plugin-info/features.php', $view_vars ); - } - } - - $data->is_paid = ! $is_free; - $data->external = ! $is_wordpress_org; - - return $data; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.7 - * - * @param FS_Plugin_Plan $plan - * - * @return string - */ - private function get_billing_cycle( FS_Plugin_Plan $plan ) { - $billing_cycle = null; - - if ( 1 === count( $plan->pricing ) && 1 == $plan->pricing[0]->licenses ) { - $pricing = $plan->pricing[0]; - if ( isset( $pricing->annual_price ) ) { - $billing_cycle = 'annual'; - } else if ( isset( $pricing->monthly_price ) ) { - $billing_cycle = 'monthly'; - } else if ( isset( $pricing->lifetime_price ) ) { - $billing_cycle = 'lifetime'; - } - } else { - foreach ( $plan->pricing as $pricing ) { - if ( isset( $pricing->annual_price ) ) { - $billing_cycle = 'annual'; - } else if ( isset( $pricing->monthly_price ) ) { - $billing_cycle = 'monthly'; - } else if ( isset( $pricing->lifetime_price ) ) { - $billing_cycle = 'lifetime'; - } - - if ( ! is_null( $billing_cycle ) ) { - break; - } - } - } - - return $billing_cycle; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.7 - * - * @param FS_Plugin_Plan $plan - * @param FS_Pricing $pricing - * - * @return float|null|string - */ - private function get_price_tag( FS_Plugin_Plan $plan, FS_Pricing $pricing ) { - $price_tag = ''; - if ( isset( $pricing->annual_price ) ) { - $price_tag = $pricing->annual_price . ( $plan->is_block_features ? ' / year' : '' ); - } else if ( isset( $pricing->monthly_price ) ) { - $price_tag = $pricing->monthly_price . ' / mo'; - } else if ( isset( $pricing->lifetime_price ) ) { - $price_tag = $pricing->lifetime_price; - } - - return '$' . $price_tag; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.7 - * - * @param object $api - * @param FS_Plugin_Plan|null $plan - * - * @return string - */ - private function get_plugin_cta( $api, $plan = null ) { - if ( ( current_user_can( 'install_plugins' ) || current_user_can( 'update_plugins' ) ) ) { - - if ( ! empty( $api->checkout_link ) && isset( $api->plans ) && 0 < is_array( $api->plans ) ) { - if ( is_null( $plan ) ) { - $plan = $api->plans[0]; - } - - return ' <a class="button button-primary right" href="' . $this->_fs->addon_checkout_url( - $plan->plugin_id, - $plan->pricing[0]->id, - $this->get_billing_cycle( $plan ), - $plan->has_trial() - ) . '" target="_parent">' . - ( ! $plan->has_trial() ? - __fs( 'purchase', $api->slug ) : - sprintf( __fs( 'start-free-x', $api->slug ), $this->get_trial_period( $plan ) ) - ) . - '</a>'; - - // @todo Add Cart concept. -// echo ' <a class="button right" href="' . $status['url'] . '" target="_parent">' . __( 'Add to Cart' ) . '</a>'; - - } else if ( ! empty( $api->download_link ) ) { - $status = install_plugin_install_status( $api ); - - - // Hosted on WordPress.org. - switch ( $status['status'] ) { - case 'install': - if ( $api->external && - $this->_fs->is_org_repo_compliant() || - ! $this->_fs->is_premium() - ) { - /** - * Add-on hosted on Freemius, not yet installed, and core - * plugin is wordpress.org compliant. Therefore, require a download - * since installing external plugins is not allowed by the wp.org guidelines. - */ - return ' <a class="button button-primary right" href="' . esc_url( $api->download_link ) . '" target="_blank">' . __fs( 'download-latest', $api->slug ) . '</a>'; - } else { - if ( $status['url'] ) { - return '<a class="button button-primary right" href="' . $status['url'] . '" target="_parent">' . __( 'Install Now' ) . '</a>'; - } - } - break; - case 'update_available': - if ( $status['url'] ) { - return '<a class="button button-primary right" href="' . $status['url'] . '" target="_parent">' . __( 'Install Update Now' ) . '</a>'; - } - break; - case 'newer_installed': - return '<a class="button button-primary right disabled">' . sprintf( __( 'Newer Version (%s) Installed' ), $status['version'] ) . '</a>'; - break; - case 'latest_installed': - return '<a class="button button-primary right disabled">' . __( 'Latest Version Installed' ) . '</a>'; - break; - } - - } - } - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.7 - * - * @param FS_Plugin_Plan $plan - * - * @return string - */ - private function get_trial_period( $plan ) { - $trial_period = (int) $plan->trial_period; - - switch ( $trial_period ) { - case 30: - return 'month'; - case 60: - return '2 months'; - default: - return "{$plan->trial_period} days"; - } - } - - /** - * Display plugin information in dialog box form. - * - * Based on core install_plugin_information() function. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - */ - function install_plugin_information() { - global $tab; - - if ( empty( $_REQUEST['plugin'] ) ) { - return; - } - - $args = array( - 'slug' => wp_unslash( $_REQUEST['plugin'] ), - 'is_ssl' => is_ssl(), - 'fields' => array( - 'banners' => true, - 'reviews' => true, - 'downloaded' => false, - 'active_installs' => true - ) - ); - - if ( is_array( $args ) ) { - $args = (object) $args; - } - - if ( ! isset( $args->per_page ) ) { - $args->per_page = 24; - } - - if ( ! isset( $args->locale ) ) { - $args->locale = get_locale(); - } - - $api = apply_filters( 'fs_plugins_api', false, 'plugin_information', $args ); - - if ( is_wp_error( $api ) ) { - wp_die( $api ); - } - - $plugins_allowedtags = array( - 'a' => array( - 'href' => array(), - 'title' => array(), - 'target' => array(), - // Add image style for screenshots. - 'class' => array() - ), - 'style' => array(), - 'abbr' => array( 'title' => array() ), - 'acronym' => array( 'title' => array() ), - 'code' => array(), - 'pre' => array(), - 'em' => array(), - 'strong' => array(), - 'div' => array( 'class' => array() ), - 'span' => array( 'class' => array() ), - 'p' => array(), - 'ul' => array(), - 'ol' => array(), - 'li' => array( 'class' => array() ), - 'i' => array( 'class' => array() ), - 'h1' => array(), - 'h2' => array(), - 'h3' => array(), - 'h4' => array(), - 'h5' => array(), - 'h6' => array(), - 'img' => array( 'src' => array(), 'class' => array(), 'alt' => array() ), -// 'table' => array(), -// 'td' => array(), -// 'tr' => array(), -// 'th' => array(), -// 'thead' => array(), -// 'tbody' => array(), - ); - - $plugins_section_titles = array( - 'description' => _x( 'Description', 'Plugin installer section title' ), - 'installation' => _x( 'Installation', 'Plugin installer section title' ), - 'faq' => _x( 'FAQ', 'Plugin installer section title' ), - 'screenshots' => _x( 'Screenshots', 'Plugin installer section title' ), - 'changelog' => _x( 'Changelog', 'Plugin installer section title' ), - 'reviews' => _x( 'Reviews', 'Plugin installer section title' ), - 'other_notes' => _x( 'Other Notes', 'Plugin installer section title' ), - ); - - // Sanitize HTML -// foreach ( (array) $api->sections as $section_name => $content ) { -// $api->sections[$section_name] = wp_kses( $content, $plugins_allowedtags ); -// } - - foreach ( array( 'version', 'author', 'requires', 'tested', 'homepage', 'downloaded', 'slug' ) as $key ) { - if ( isset( $api->$key ) ) { - $api->$key = wp_kses( $api->$key, $plugins_allowedtags ); - } - } - - // Add after $api->slug is ready. - $plugins_section_titles['features'] = __fs( 'features-and-pricing', $api->slug ); - - $_tab = esc_attr( $tab ); - - $section = isset( $_REQUEST['section'] ) ? wp_unslash( $_REQUEST['section'] ) : 'description'; // Default to the Description tab, Do not translate, API returns English. - if ( empty( $section ) || ! isset( $api->sections[ $section ] ) ) { - $section_titles = array_keys( (array) $api->sections ); - $section = array_shift( $section_titles ); - } - - iframe_header( __( 'Plugin Install' ) ); - - $_with_banner = ''; - -// var_dump($api->banners); - if ( ! empty( $api->banners ) && ( ! empty( $api->banners['low'] ) || ! empty( $api->banners['high'] ) ) ) { - $_with_banner = 'with-banner'; - $low = empty( $api->banners['low'] ) ? $api->banners['high'] : $api->banners['low']; - $high = empty( $api->banners['high'] ) ? $api->banners['low'] : $api->banners['high']; - ?> - <style type="text/css"> - #plugin-information-title.with-banner - { - background-image: url( <?php echo esc_url( $low ); ?> ); - } - - @media only screen and ( -webkit-min-device-pixel-ratio: 1.5 ) - { - #plugin-information-title.with-banner - { - background-image: url( <?php echo esc_url( $high ); ?> ); - } - } - </style> - <?php - } - - echo '<div id="plugin-information-scrollable">'; - echo "<div id='{$_tab}-title' class='{$_with_banner}'><div class='vignette'></div><h2>{$api->name}</h2></div>"; - echo "<div id='{$_tab}-tabs' class='{$_with_banner}'>\n"; - - foreach ( (array) $api->sections as $section_name => $content ) { - if ( 'reviews' === $section_name && ( empty( $api->ratings ) || 0 === array_sum( (array) $api->ratings ) ) ) { - continue; - } - - if ( isset( $plugins_section_titles[ $section_name ] ) ) { - $title = $plugins_section_titles[ $section_name ]; - } else { - $title = ucwords( str_replace( '_', ' ', $section_name ) ); - } - - $class = ( $section_name === $section ) ? ' class="current"' : ''; - $href = add_query_arg( array( 'tab' => $tab, 'section' => $section_name ) ); - $href = esc_url( $href ); - $san_section = esc_attr( $section_name ); - echo "\t<a name='$san_section' href='$href' $class>$title</a>\n"; - } - - echo "</div>\n"; - - ?> - <div id="<?php echo $_tab; ?>-content" class='<?php echo $_with_banner; ?>'> - <div class="fyi"> - <?php if ( $api->is_paid ) : ?> - <?php if ( isset( $api->plans ) ) : ?> - <div class="plugin-information-pricing"> - <?php foreach ( $api->plans as $plan ) : ?> - <?php - /** - * @var FS_Plugin_Plan $plan - */ - ?> - <?php $first_pricing = $plan->pricing[0] ?> - <?php $is_multi_cycle = $first_pricing->is_multi_cycle() ?> - <div class="fs-plan<?php if ( ! $is_multi_cycle ) { - echo ' fs-single-cycle'; - } ?>" data-plan-id="<?php echo $plan->id ?>"> - <h3 data-plan="<?php echo $plan->id ?>"><?php printf( __fs( 'x-plan', $api->slug ), $plan->title ) ?></h3> - <?php $has_annual = $first_pricing->has_annual() ?> - <?php $has_monthly = $first_pricing->has_monthly() ?> - <div class="nav-tab-wrapper"> - <?php $billing_cycles = array( 'monthly', 'annual', 'lifetime' ) ?> - <?php $i = 0; - foreach ( $billing_cycles as $cycle ) : ?> - <?php $prop = "{$cycle}_price"; - if ( isset( $first_pricing->{$prop} ) ) : ?> - <?php $is_featured = ( 'annual' === $cycle && $is_multi_cycle ) ?> - <?php - $prices = array(); - foreach ( $plan->pricing as $pricing ) { - if ( isset( $pricing->{$prop} ) ) { - $prices[] = array( - 'id' => $pricing->id, - 'licenses' => $pricing->licenses, - 'price' => $pricing->{$prop} - ); - } - } - ?> - <a class="nav-tab" data-billing-cycle="<?php echo $cycle ?>" - data-pricing="<?php esc_attr_e( json_encode( $prices ) ) ?>"> - <?php if ( $is_featured ) : ?> - <label>★ <?php _efs( 'best', $api->slug ) ?> ★</label> - <?php endif ?> - <?php _efs( $cycle, $api->slug ) ?> - </a> - <?php endif ?> - <?php $i ++; endforeach ?> - <?php wp_enqueue_script( 'jquery' ) ?> - <script type="text/javascript"> - (function ($, undef) { - var - _formatBillingFrequency = function (cycle) { - switch (cycle) { - case 'monthly': - return '<?php printf(__fs('billed-x', $api->slug), __fs('monthly', $api->slug)) ?>'; - case 'annual': - return '<?php printf(__fs('billed-x', $api->slug), __fs('annually', $api->slug)) ?>'; - case 'lifetime': - return '<?php printf(__fs('billed-x', $api->slug), __fs('once', $api->slug)) ?>'; - } - }, - _formatLicensesTitle = function (pricing) { - switch (pricing.licenses) { - case 1: - return '<?php _efs( 'license-single-site', $api->slug ) ?>'; - case null: - return '<?php _efs( 'license-unlimited', $api->slug ) ?>'; - default: - return '<?php _efs( 'license-x-sites', $api->slug ) ?>'.replace('%s', pricing.licenses); - } - }, - _formatPrice = function (pricing, cycle, multipleLicenses) { - if (undef === multipleLicenses) - multipleLicenses = true; - - var priceCycle; - switch (cycle) { - case 'monthly': - priceCycle = ' / <?php _efs('mo', $api->slug) ?>'; - break; - case 'lifetime': - priceCycle = ''; - break; - case 'annual': - default: - priceCycle = ' / <?php _efs('year', $api->slug) ?>'; - break; - } - - if (!multipleLicenses && 1 == pricing.licenses) { - return '$' + pricing.price + priceCycle; - } - - return _formatLicensesTitle(pricing) + ' - <var class="fs-price">$' + pricing.price + priceCycle + '</var>'; - }, - _checkoutUrl = function (plan, pricing, cycle) { - return '<?php echo esc_url_raw(remove_query_arg('billing_cycle', add_query_arg(array('plugin_id' => $plan->plugin_id), $api->checkout_link))) ?>' + - '&plan_id=' + plan + - '&pricing_id=' + pricing + - '&billing_cycle=' + cycle<?php if ($plan->has_trial()) { echo " + '&trial=true'"; }?>; - }, - _updateCtaUrl = function (plan, pricing, cycle) { - $('.plugin-information-pricing .button, #plugin-information-footer .button').attr('href', _checkoutUrl(plan, pricing, cycle)); - }; - - $(document).ready(function () { - var $plan = $('.plugin-information-pricing .fs-plan[data-plan-id=<?php echo $plan->id ?>]'); - $plan.find('input[type=radio]').live('click', function () { - _updateCtaUrl( - $plan.attr('data-plan-id'), - $(this).val(), - $plan.find('.nav-tab-active').attr('data-billing-cycle') - ); - - $plan.find('.fs-trial-terms .fs-price').html( - $(this).parents('label').find('.fs-price').html() - ); - }); - - $plan.find('.nav-tab').click(function () { - if ($(this).hasClass('nav-tab-active')) - return; - - var $this = $(this), - billingCycle = $this.attr('data-billing-cycle'), - pricing = JSON.parse($this.attr('data-pricing')), - $pricesList = $this.parents('.fs-plan').find('.fs-pricing-body .fs-licenses'), - html = ''; - - // Un-select previously selected tab. - $plan.find('.nav-tab').removeClass('nav-tab-active'); - - // Select current tab. - $this.addClass('nav-tab-active'); - - // Render licenses prices. - if (1 == pricing.length) { - html = '<li><label><?php _efs( 'price', $api->slug ) ?>: ' + _formatPrice(pricing[0], billingCycle, false) + '</label></li>'; - } else { - for (var i = 0; i < pricing.length; i++) { - html += '<li><label><input name="pricing-<?php echo $plan->id ?>" type="radio" value="' + pricing[i].id + '">' + _formatPrice(pricing[i], billingCycle) + '</label></li>'; - } - } - $pricesList.html(html); - - if (1 < pricing.length) { - // Select first license option. - $pricesList.find('li:first input').click(); - } - else { - _updateCtaUrl( - $plan.attr('data-plan-id'), - pricing[0].id, - billingCycle - ); - } - - // Update billing frequency. - $plan.find('.fs-billing-frequency').html(_formatBillingFrequency(billingCycle)); - - if ('annual' === billingCycle) { - $plan.find('.fs-annual-discount').show(); - } else { - $plan.find('.fs-annual-discount').hide(); - } - }); - - <?php if ( $has_annual ) : ?> - // Select annual by default. - $plan.find('.nav-tab[data-billing-cycle=annual]').click(); - <?php else : ?> - // Select first tab. - $plan.find('.nav-tab:first').click(); - <?php endif ?> - }); - }(jQuery)); - </script> - </div> - <div class="fs-pricing-body"> - <span class="fs-billing-frequency"></span> - <?php $annual_discount = ( $has_annual && $has_monthly ) ? $plan->pricing[0]->annual_discount_percentage() : 0 ?> - <?php if ( $annual_discount > 0 ) : ?> - <span - class="fs-annual-discount"><?php printf( __fs( 'save-x', $api->slug ), $annual_discount . '%' ) ?></span> - <?php endif ?> - <ul class="fs-licenses"> - </ul> - <?php echo $this->get_plugin_cta( $api, $plan ) ?> - <div style="clear:both"></div> - <?php if ( $plan->has_trial() ) : ?> - <?php $trial_period = $this->get_trial_period( $plan ) ?> - <ul class="fs-trial-terms"> - <li> - <i class="dashicons dashicons-yes"></i><?php printf( __fs( 'no-commitment-x', $api->slug ), $trial_period ) ?> - </li> - <li> - <i class="dashicons dashicons-yes"></i><?php printf( __fs( 'after-x-pay-as-little-y', $api->slug ), $trial_period, '<var class="fs-price">' . $this->get_price_tag( $plan, $plan->pricing[0] ) . '</var>' ) ?> - </li> - </ul> - <?php endif ?> - </div> - </div> - </div> - <?php endforeach ?> - <?php endif ?> - <?php endif ?> - <div> - <h3><?php _efs( 'details', $api->slug ) ?></h3> - <ul> - <?php if ( ! empty( $api->version ) ) { ?> - <li><strong><?php _e( 'Version:' ); ?></strong> <?php echo $api->version; ?></li> - <?php - } - if ( ! empty( $api->author ) ) { - ?> - <li> - <strong><?php _e( 'Author:' ); ?></strong> <?php echo links_add_target( $api->author, '_blank' ); ?> - </li> - <?php - } - if ( ! empty( $api->last_updated ) ) { - ?> - <li><strong><?php _e( 'Last Updated:' ); ?></strong> <span - title="<?php echo $api->last_updated; ?>"> - <?php printf( __( '%s ago' ), human_time_diff( strtotime( $api->last_updated ) ) ); ?> - </span></li> - <?php - } - if ( ! empty( $api->requires ) ) { - ?> - <li> - <strong><?php _e( 'Requires WordPress Version:' ); ?></strong> <?php printf( __( '%s or higher' ), $api->requires ); ?> - </li> - <?php - } - if ( ! empty( $api->tested ) ) { - ?> - <li><strong><?php _e( 'Compatible up to:' ); ?></strong> <?php echo $api->tested; ?> - </li> - <?php - } - if ( ! empty( $api->downloaded ) ) { - ?> - <li> - <strong><?php _e( 'Downloaded:' ); ?></strong> <?php printf( _n( '%s time', '%s times', $api->downloaded ), number_format_i18n( $api->downloaded ) ); ?> - </li> - <?php - } - if ( ! empty( $api->slug ) && empty( $api->external ) ) { - ?> - <li><a target="_blank" - href="https://wordpress.org/plugins/<?php echo $api->slug; ?>/"><?php _e( 'WordPress.org Plugin Page »' ); ?></a> - </li> - <?php - } - if ( ! empty( $api->homepage ) ) { - ?> - <li><a target="_blank" - href="<?php echo esc_url( $api->homepage ); ?>"><?php _e( 'Plugin Homepage »' ); ?></a> - </li> - <?php - } - if ( ! empty( $api->donate_link ) && empty( $api->contributors ) ) { - ?> - <li><a target="_blank" - href="<?php echo esc_url( $api->donate_link ); ?>"><?php _e( 'Donate to this plugin »' ); ?></a> - </li> - <?php } ?> - </ul> - </div> - <?php if ( ! empty( $api->rating ) ) { ?> - <h3><?php _e( 'Average Rating' ); ?></h3> - <?php wp_star_rating( array( - 'rating' => $api->rating, - 'type' => 'percent', - 'number' => $api->num_ratings - ) ); ?> - <small><?php printf( _n( '(based on %s rating)', '(based on %s ratings)', $api->num_ratings ), number_format_i18n( $api->num_ratings ) ); ?></small> - <?php - } - - if ( ! empty( $api->ratings ) && array_sum( (array) $api->ratings ) > 0 ) { - foreach ( $api->ratings as $key => $ratecount ) { - // Avoid div-by-zero. - $_rating = $api->num_ratings ? ( $ratecount / $api->num_ratings ) : 0; - ?> - <div class="counter-container"> - <span class="counter-label"><a - href="https://wordpress.org/support/view/plugin-reviews/<?php echo $api->slug; ?>?filter=<?php echo $key; ?>" - target="_blank" - title="<?php echo esc_attr( sprintf( _n( 'Click to see reviews that provided a rating of %d star', 'Click to see reviews that provided a rating of %d stars', $key ), $key ) ); ?>"><?php printf( _n( '%d star', '%d stars', $key ), $key ); ?></a></span> - <span class="counter-back"> - <span class="counter-bar" style="width: <?php echo 92 * $_rating; ?>px;"></span> - </span> - <span class="counter-count"><?php echo number_format_i18n( $ratecount ); ?></span> - </div> - <?php - } - } - if ( ! empty( $api->contributors ) ) { - ?> - <h3><?php _e( 'Contributors' ); ?></h3> - <ul class="contributors"> - <?php - foreach ( (array) $api->contributors as $contrib_username => $contrib_profile ) { - if ( empty( $contrib_username ) && empty( $contrib_profile ) ) { - continue; - } - if ( empty( $contrib_username ) ) { - $contrib_username = preg_replace( '/^.+\/(.+)\/?$/', '\1', $contrib_profile ); - } - $contrib_username = sanitize_user( $contrib_username ); - if ( empty( $contrib_profile ) ) { - echo "<li><img src='https://wordpress.org/grav-redirect.php?user={$contrib_username}&s=36' width='18' height='18' />{$contrib_username}</li>"; - } else { - echo "<li><a href='{$contrib_profile}' target='_blank'><img src='https://wordpress.org/grav-redirect.php?user={$contrib_username}&s=36' width='18' height='18' />{$contrib_username}</a></li>"; - } - } - ?> - </ul> - <?php if ( ! empty( $api->donate_link ) ) { ?> - <a target="_blank" - href="<?php echo esc_url( $api->donate_link ); ?>"><?php _e( 'Donate to this plugin »' ); ?></a> - <?php } ?> - <?php } ?> - </div> - <div id="section-holder" class="wrap"> - <?php - if ( ! empty( $api->tested ) && version_compare( substr( $GLOBALS['wp_version'], 0, strlen( $api->tested ) ), $api->tested, '>' ) ) { - echo '<div class="notice notice-warning"><p>' . '<strong>' . __( 'Warning:' ) . '</strong> ' . __( 'This plugin has not been tested with your current version of WordPress.' ) . '</p></div>'; - } else if ( ! empty( $api->requires ) && version_compare( substr( $GLOBALS['wp_version'], 0, strlen( $api->requires ) ), $api->requires, '<' ) ) { - echo '<div class="notice notice-warning"><p>' . '<strong>' . __( 'Warning:' ) . '</strong> ' . __( 'This plugin has not been marked as compatible with your version of WordPress.' ) . '</p></div>'; - } - - foreach ( (array) $api->sections as $section_name => $content ) { - $content = links_add_base_url( $content, 'https://wordpress.org/plugins/' . $api->slug . '/' ); - $content = links_add_target( $content, '_blank' ); - - $san_section = esc_attr( $section_name ); - - $display = ( $section_name === $section ) ? 'block' : 'none'; - - if ( 'description' === $section_name && - ( ( ! $api->external && $api->wp_org_missing ) || - ( $api->external && $api->fs_missing ) ) - ) { - $missing_notice = array( - 'type' => 'error', - 'id' => md5( microtime() ), - 'message' => __fs( ( $api->is_paid ? 'paid-addon-not-deployed' : 'free-addon-not-deployed' ), $api->slug ), - ); - fs_require_template( 'admin-notice.php', $missing_notice ); - } - echo "\t<div id='section-{$san_section}' class='section' style='display: {$display};'>\n"; - echo $content; - echo "\t</div>\n"; - } - echo "</div>\n"; - echo "</div>\n"; - echo "</div>\n"; // #plugin-information-scrollable - echo "<div id='$tab-footer'>\n"; - - echo $this->get_plugin_cta( $api ); - - echo "</div>\n"; - - iframe_footer(); - exit; -} - } +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.6 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + /** + * Class FS_Plugin_Info_Dialog + * + * @author Vova Feldman (@svovaf) + * @since 1.1.7 + */ + class FS_Plugin_Info_Dialog { + /** + * @since 1.1.7 + * + * @var FS_Logger + */ + private $_logger; + + /** + * @since 1.1.7 + * + * @var Freemius + */ + private $_fs; + + function __construct( Freemius $fs ) { + $this->_fs = $fs; + + $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $fs->get_slug() . '_info', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); + + // Remove default plugin information action. + remove_all_actions( 'install_plugins_pre_plugin-information' ); + + // Override action with custom plugins function for add-ons. + add_action( 'install_plugins_pre_plugin-information', array( &$this, 'install_plugin_information' ) ); + + // Override request for plugin information for Add-ons. + add_filter( + 'fs_plugins_api', + array( &$this, '_get_addon_info_filter' ), + WP_FS__DEFAULT_PRIORITY, 3 ); + } + + /** + * Generate add-on plugin information. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @param array $data + * @param string $action + * @param object|null $args + * + * @return array|null + */ + function _get_addon_info_filter( $data, $action = '', $args = null ) { + $this->_logger->entrance(); + + $parent_plugin_id = fs_request_get( 'parent_plugin_id', false ); + + if ( $this->_fs->get_id() != $parent_plugin_id || + ( 'plugin_information' !== $action ) || + ! isset( $args->slug ) + ) { + return $data; + } + + // Find add-on by slug. + $addons = $this->_fs->get_addons(); + $selected_addon = false; + foreach ( $addons as $addon ) { + if ( $addon->slug == $args->slug ) { + $selected_addon = $addon; + break; + } + } + + if ( false === $selected_addon ) { + return $data; + } + + if ( ! isset( $selected_addon->info ) ) { + // Setup some default info. + $selected_addon->info = new stdClass(); + $selected_addon->info->selling_point_0 = 'Selling Point 1'; + $selected_addon->info->selling_point_1 = 'Selling Point 2'; + $selected_addon->info->selling_point_2 = 'Selling Point 3'; + $selected_addon->info->description = '<p>Tell your users all about your add-on</p>'; + } + + fs_enqueue_local_style( 'fs_addons', '/admin/add-ons.css' ); + + $data = $args; + + $is_free = true; + + // Load add-on pricing. + $has_pricing = false; + $has_features = false; + $plans = false; + $plans_result = $this->_fs->get_api_site_or_plugin_scope()->get( "/addons/{$selected_addon->id}/plans.json" ); + if ( ! isset( $plans_result->error ) ) { + $plans = $plans_result->plans; + if ( is_array( $plans ) ) { + for ( $i = 0, $len = count( $plans ); $i < $len; $i ++ ) { + $plans[ $i ] = new FS_Plugin_Plan( $plans[ $i ] ); + $plan = $plans[ $i ]; + + $pricing_result = $this->_fs->get_api_site_or_plugin_scope()->get( "/addons/{$selected_addon->id}/plans/{$plan->id}/pricing.json" ); + if ( ! isset( $pricing_result->error ) ) { + // Update plan's pricing. + $plan->pricing = $pricing_result->pricing; + + if ( is_array( $plan->pricing ) && ! empty( $plan->pricing ) ) { + $is_free = false; + + foreach ( $plan->pricing as &$pricing ) { + $pricing = new FS_Pricing( $pricing ); + } + } + + $has_pricing = true; + } + + $features_result = $this->_fs->get_api_site_or_plugin_scope()->get( "/addons/{$selected_addon->id}/plans/{$plan->id}/features.json" ); + if ( ! isset( $features_result->error ) && + is_array( $features_result->features ) && + 0 < count( $features_result->features ) + ) { + // Update plan's pricing. + $plan->features = $features_result->features; + + $has_features = true; + } + } + } + } + + // Fetch latest version from Freemius. + $latest = $this->_fs->_fetch_latest_version( $selected_addon->id ); + + if ( ! $is_free ) { + // If paid add-on, then it's not on wordpress.org + $is_wordpress_org = false; + } else { + // If no versions found, then assume it's a .org plugin. + $is_wordpress_org = ( false === $latest ); + } + + if ( $is_wordpress_org ) { + $repo_data = FS_Plugin_Updater::_fetch_plugin_info_from_repository( + 'plugin_information', (object) array( + 'slug' => $selected_addon->slug, + 'is_ssl' => is_ssl(), + 'fields' => array( + 'banners' => true, + 'reviews' => true, + 'downloaded' => false, + 'active_installs' => true + ) + ) ); + + if ( ! empty( $repo_data ) ) { + $data = $repo_data; + $data->wp_org_missing = false; + } else { + // Couldn't find plugin on .org. + $is_wordpress_org = false; + + // Plugin is missing, not on Freemius nor WP.org. + $data->wp_org_missing = true; + } + } + + if ( ! $is_wordpress_org ) { + $data->checkout_link = $this->_fs->checkout_url(); + $data->fs_missing = ( false === $latest ); + + if ( $is_free ) { + $data->download_link = $this->_fs->_get_latest_download_local_url( $selected_addon->id ); + } + } + + if ( ! $is_wordpress_org ) { +// Fetch as much as possible info from local files. + $plugin_local_data = $this->_fs->get_plugin_data(); + $data->name = $selected_addon->title; + $data->author = $plugin_local_data['Author']; + $view_vars = array( 'plugin' => $selected_addon ); + $data->sections = array( + 'description' => fs_get_template( '/plugin-info/description.php', $view_vars ), + ); + + if ( ! empty( $selected_addon->info->banner_url ) ) { + $data->banners = array( + 'low' => $selected_addon->info->banner_url, + ); + } + + if ( ! empty( $selected_addon->info->screenshots ) ) { + $view_vars = array( + 'screenshots' => $selected_addon->info->screenshots, + 'plugin' => $selected_addon, + ); + $data->sections['screenshots'] = fs_get_template( '/plugin-info/screenshots.php', $view_vars ); + } + + if ( is_object( $latest ) ) { + $data->version = $latest->version; + $data->last_updated = ! is_null( $latest->updated ) ? $latest->updated : $latest->created; + $data->requires = $latest->requires_platform_version; + $data->tested = $latest->tested_up_to_version; + } else { + // Add dummy version. + $data->version = '1.0.0'; + + // Add message to developer to deploy the plugin through Freemius. + } + } + + if ( $has_pricing ) { + // Add plans to data. + $data->plans = $plans; + + if ( $has_features ) { + $view_vars = array( + 'plans' => $plans, + 'plugin' => $selected_addon, + ); + $data->sections['features'] = fs_get_template( '/plugin-info/features.php', $view_vars ); + } + } + + $data->is_paid = ! $is_free; + $data->external = ! $is_wordpress_org; + + return $data; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.7 + * + * @param FS_Plugin_Plan $plan + * + * @return string + */ + private function get_billing_cycle( FS_Plugin_Plan $plan ) { + $billing_cycle = null; + + if ( 1 === count( $plan->pricing ) && 1 == $plan->pricing[0]->licenses ) { + $pricing = $plan->pricing[0]; + if ( isset( $pricing->annual_price ) ) { + $billing_cycle = 'annual'; + } else if ( isset( $pricing->monthly_price ) ) { + $billing_cycle = 'monthly'; + } else if ( isset( $pricing->lifetime_price ) ) { + $billing_cycle = 'lifetime'; + } + } else { + foreach ( $plan->pricing as $pricing ) { + if ( isset( $pricing->annual_price ) ) { + $billing_cycle = 'annual'; + } else if ( isset( $pricing->monthly_price ) ) { + $billing_cycle = 'monthly'; + } else if ( isset( $pricing->lifetime_price ) ) { + $billing_cycle = 'lifetime'; + } + + if ( ! is_null( $billing_cycle ) ) { + break; + } + } + } + + return $billing_cycle; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.7 + * + * @param FS_Plugin_Plan $plan + * @param FS_Pricing $pricing + * + * @return float|null|string + */ + private function get_price_tag( FS_Plugin_Plan $plan, FS_Pricing $pricing ) { + $price_tag = ''; + if ( isset( $pricing->annual_price ) ) { + $price_tag = $pricing->annual_price . ( $plan->is_block_features ? ' / year' : '' ); + } else if ( isset( $pricing->monthly_price ) ) { + $price_tag = $pricing->monthly_price . ' / mo'; + } else if ( isset( $pricing->lifetime_price ) ) { + $price_tag = $pricing->lifetime_price; + } + + return '$' . $price_tag; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.7 + * + * @param object $api + * @param FS_Plugin_Plan|null $plan + * + * @return string + */ + private function get_plugin_cta( $api, $plan = null ) { + if ( ( current_user_can( 'install_plugins' ) || current_user_can( 'update_plugins' ) ) ) { + + if ( ! empty( $api->checkout_link ) && isset( $api->plans ) && 0 < is_array( $api->plans ) ) { + if ( is_null( $plan ) ) { + $plan = $api->plans[0]; + } + + return ' <a class="button button-primary right" href="' . $this->_fs->addon_checkout_url( + $plan->plugin_id, + $plan->pricing[0]->id, + $this->get_billing_cycle( $plan ), + $plan->has_trial() + ) . '" target="_parent">' . + ( ! $plan->has_trial() ? + __fs( 'purchase', $api->slug ) : + sprintf( __fs( 'start-free-x', $api->slug ), $this->get_trial_period( $plan ) ) + ) . + '</a>'; + + // @todo Add Cart concept. +// echo ' <a class="button right" href="' . $status['url'] . '" target="_parent">' . __( 'Add to Cart' ) . '</a>'; + + } else if ( ! empty( $api->download_link ) ) { + $status = install_plugin_install_status( $api ); + + + // Hosted on WordPress.org. + switch ( $status['status'] ) { + case 'install': + if ( $api->external && + $this->_fs->is_org_repo_compliant() || + ! $this->_fs->is_premium() + ) { + /** + * Add-on hosted on Freemius, not yet installed, and core + * plugin is wordpress.org compliant. Therefore, require a download + * since installing external plugins is not allowed by the wp.org guidelines. + */ + return ' <a class="button button-primary right" href="' . esc_url( $api->download_link ) . '" target="_blank">' . __fs( 'download-latest', $api->slug ) . '</a>'; + } else { + if ( $status['url'] ) { + return '<a class="button button-primary right" href="' . $status['url'] . '" target="_parent">' . __( 'Install Now' ) . '</a>'; + } + } + break; + case 'update_available': + if ( $status['url'] ) { + return '<a class="button button-primary right" href="' . $status['url'] . '" target="_parent">' . __( 'Install Update Now' ) . '</a>'; + } + break; + case 'newer_installed': + return '<a class="button button-primary right disabled">' . sprintf( __( 'Newer Version (%s) Installed' ), $status['version'] ) . '</a>'; + break; + case 'latest_installed': + return '<a class="button button-primary right disabled">' . __( 'Latest Version Installed' ) . '</a>'; + break; + } + + } + } + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.7 + * + * @param FS_Plugin_Plan $plan + * + * @return string + */ + private function get_trial_period( $plan ) { + $trial_period = (int) $plan->trial_period; + + switch ( $trial_period ) { + case 30: + return 'month'; + case 60: + return '2 months'; + default: + return "{$plan->trial_period} days"; + } + } + + /** + * Display plugin information in dialog box form. + * + * Based on core install_plugin_information() function. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + */ + function install_plugin_information() { + global $tab; + + if ( empty( $_REQUEST['plugin'] ) ) { + return; + } + + $args = array( + 'slug' => wp_unslash( $_REQUEST['plugin'] ), + 'is_ssl' => is_ssl(), + 'fields' => array( + 'banners' => true, + 'reviews' => true, + 'downloaded' => false, + 'active_installs' => true + ) + ); + + if ( is_array( $args ) ) { + $args = (object) $args; + } + + if ( ! isset( $args->per_page ) ) { + $args->per_page = 24; + } + + if ( ! isset( $args->locale ) ) { + $args->locale = get_locale(); + } + + $api = apply_filters( 'fs_plugins_api', false, 'plugin_information', $args ); + + if ( is_wp_error( $api ) ) { + wp_die( $api ); + } + + $plugins_allowedtags = array( + 'a' => array( + 'href' => array(), + 'title' => array(), + 'target' => array(), + // Add image style for screenshots. + 'class' => array() + ), + 'style' => array(), + 'abbr' => array( 'title' => array() ), + 'acronym' => array( 'title' => array() ), + 'code' => array(), + 'pre' => array(), + 'em' => array(), + 'strong' => array(), + 'div' => array( 'class' => array() ), + 'span' => array( 'class' => array() ), + 'p' => array(), + 'ul' => array(), + 'ol' => array(), + 'li' => array( 'class' => array() ), + 'i' => array( 'class' => array() ), + 'h1' => array(), + 'h2' => array(), + 'h3' => array(), + 'h4' => array(), + 'h5' => array(), + 'h6' => array(), + 'img' => array( 'src' => array(), 'class' => array(), 'alt' => array() ), +// 'table' => array(), +// 'td' => array(), +// 'tr' => array(), +// 'th' => array(), +// 'thead' => array(), +// 'tbody' => array(), + ); + + $plugins_section_titles = array( + 'description' => _x( 'Description', 'Plugin installer section title' ), + 'installation' => _x( 'Installation', 'Plugin installer section title' ), + 'faq' => _x( 'FAQ', 'Plugin installer section title' ), + 'screenshots' => _x( 'Screenshots', 'Plugin installer section title' ), + 'changelog' => _x( 'Changelog', 'Plugin installer section title' ), + 'reviews' => _x( 'Reviews', 'Plugin installer section title' ), + 'other_notes' => _x( 'Other Notes', 'Plugin installer section title' ), + ); + + // Sanitize HTML +// foreach ( (array) $api->sections as $section_name => $content ) { +// $api->sections[$section_name] = wp_kses( $content, $plugins_allowedtags ); +// } + + foreach ( array( 'version', 'author', 'requires', 'tested', 'homepage', 'downloaded', 'slug' ) as $key ) { + if ( isset( $api->$key ) ) { + $api->$key = wp_kses( $api->$key, $plugins_allowedtags ); + } + } + + // Add after $api->slug is ready. + $plugins_section_titles['features'] = __fs( 'features-and-pricing', $api->slug ); + + $_tab = esc_attr( $tab ); + + $section = isset( $_REQUEST['section'] ) ? wp_unslash( $_REQUEST['section'] ) : 'description'; // Default to the Description tab, Do not translate, API returns English. + if ( empty( $section ) || ! isset( $api->sections[ $section ] ) ) { + $section_titles = array_keys( (array) $api->sections ); + $section = array_shift( $section_titles ); + } + + iframe_header( __( 'Plugin Install' ) ); + + $_with_banner = ''; + +// var_dump($api->banners); + if ( ! empty( $api->banners ) && ( ! empty( $api->banners['low'] ) || ! empty( $api->banners['high'] ) ) ) { + $_with_banner = 'with-banner'; + $low = empty( $api->banners['low'] ) ? $api->banners['high'] : $api->banners['low']; + $high = empty( $api->banners['high'] ) ? $api->banners['low'] : $api->banners['high']; + ?> + <style type="text/css"> + #plugin-information-title.with-banner + { + background-image: url( <?php echo esc_url( $low ); ?> ); + } + + @media only screen and ( -webkit-min-device-pixel-ratio: 1.5 ) + { + #plugin-information-title.with-banner + { + background-image: url( <?php echo esc_url( $high ); ?> ); + } + } + </style> + <?php + } + + echo '<div id="plugin-information-scrollable">'; + echo "<div id='{$_tab}-title' class='{$_with_banner}'><div class='vignette'></div><h2>{$api->name}</h2></div>"; + echo "<div id='{$_tab}-tabs' class='{$_with_banner}'>\n"; + + foreach ( (array) $api->sections as $section_name => $content ) { + if ( 'reviews' === $section_name && ( empty( $api->ratings ) || 0 === array_sum( (array) $api->ratings ) ) ) { + continue; + } + + if ( isset( $plugins_section_titles[ $section_name ] ) ) { + $title = $plugins_section_titles[ $section_name ]; + } else { + $title = ucwords( str_replace( '_', ' ', $section_name ) ); + } + + $class = ( $section_name === $section ) ? ' class="current"' : ''; + $href = add_query_arg( array( 'tab' => $tab, 'section' => $section_name ) ); + $href = esc_url( $href ); + $san_section = esc_attr( $section_name ); + echo "\t<a name='$san_section' href='$href' $class>$title</a>\n"; + } + + echo "</div>\n"; + + ?> + <div id="<?php echo $_tab; ?>-content" class='<?php echo $_with_banner; ?>'> + <div class="fyi"> + <?php if ( $api->is_paid ) : ?> + <?php if ( isset( $api->plans ) ) : ?> + <div class="plugin-information-pricing"> + <?php foreach ( $api->plans as $plan ) : ?> + <?php + /** + * @var FS_Plugin_Plan $plan + */ + ?> + <?php $first_pricing = $plan->pricing[0] ?> + <?php $is_multi_cycle = $first_pricing->is_multi_cycle() ?> + <div class="fs-plan<?php if ( ! $is_multi_cycle ) { + echo ' fs-single-cycle'; + } ?>" data-plan-id="<?php echo $plan->id ?>"> + <h3 data-plan="<?php echo $plan->id ?>"><?php printf( __fs( 'x-plan', $api->slug ), $plan->title ) ?></h3> + <?php $has_annual = $first_pricing->has_annual() ?> + <?php $has_monthly = $first_pricing->has_monthly() ?> + <div class="nav-tab-wrapper"> + <?php $billing_cycles = array( 'monthly', 'annual', 'lifetime' ) ?> + <?php $i = 0; + foreach ( $billing_cycles as $cycle ) : ?> + <?php $prop = "{$cycle}_price"; + if ( isset( $first_pricing->{$prop} ) ) : ?> + <?php $is_featured = ( 'annual' === $cycle && $is_multi_cycle ) ?> + <?php + $prices = array(); + foreach ( $plan->pricing as $pricing ) { + if ( isset( $pricing->{$prop} ) ) { + $prices[] = array( + 'id' => $pricing->id, + 'licenses' => $pricing->licenses, + 'price' => $pricing->{$prop} + ); + } + } + ?> + <a class="nav-tab" data-billing-cycle="<?php echo $cycle ?>" + data-pricing="<?php esc_attr_e( json_encode( $prices ) ) ?>"> + <?php if ( $is_featured ) : ?> + <label>★ <?php _efs( 'best', $api->slug ) ?> ★</label> + <?php endif ?> + <?php _efs( $cycle, $api->slug ) ?> + </a> + <?php endif ?> + <?php $i ++; endforeach ?> + <?php wp_enqueue_script( 'jquery' ) ?> + <script type="text/javascript"> + (function ($, undef) { + var + _formatBillingFrequency = function (cycle) { + switch (cycle) { + case 'monthly': + return '<?php printf(__fs('billed-x', $api->slug), __fs('monthly', $api->slug)) ?>'; + case 'annual': + return '<?php printf(__fs('billed-x', $api->slug), __fs('annually', $api->slug)) ?>'; + case 'lifetime': + return '<?php printf(__fs('billed-x', $api->slug), __fs('once', $api->slug)) ?>'; + } + }, + _formatLicensesTitle = function (pricing) { + switch (pricing.licenses) { + case 1: + return '<?php _efs( 'license-single-site', $api->slug ) ?>'; + case null: + return '<?php _efs( 'license-unlimited', $api->slug ) ?>'; + default: + return '<?php _efs( 'license-x-sites', $api->slug ) ?>'.replace('%s', pricing.licenses); + } + }, + _formatPrice = function (pricing, cycle, multipleLicenses) { + if (undef === multipleLicenses) + multipleLicenses = true; + + var priceCycle; + switch (cycle) { + case 'monthly': + priceCycle = ' / <?php _efs('mo', $api->slug) ?>'; + break; + case 'lifetime': + priceCycle = ''; + break; + case 'annual': + default: + priceCycle = ' / <?php _efs('year', $api->slug) ?>'; + break; + } + + if (!multipleLicenses && 1 == pricing.licenses) { + return '$' + pricing.price + priceCycle; + } + + return _formatLicensesTitle(pricing) + ' - <var class="fs-price">$' + pricing.price + priceCycle + '</var>'; + }, + _checkoutUrl = function (plan, pricing, cycle) { + return '<?php echo esc_url_raw(remove_query_arg('billing_cycle', add_query_arg(array('plugin_id' => $plan->plugin_id), $api->checkout_link))) ?>' + + '&plan_id=' + plan + + '&pricing_id=' + pricing + + '&billing_cycle=' + cycle<?php if ($plan->has_trial()) { echo " + '&trial=true'"; }?>; + }, + _updateCtaUrl = function (plan, pricing, cycle) { + $('.plugin-information-pricing .button, #plugin-information-footer .button').attr('href', _checkoutUrl(plan, pricing, cycle)); + }; + + $(document).ready(function () { + var $plan = $('.plugin-information-pricing .fs-plan[data-plan-id=<?php echo $plan->id ?>]'); + $plan.find('input[type=radio]').live('click', function () { + _updateCtaUrl( + $plan.attr('data-plan-id'), + $(this).val(), + $plan.find('.nav-tab-active').attr('data-billing-cycle') + ); + + $plan.find('.fs-trial-terms .fs-price').html( + $(this).parents('label').find('.fs-price').html() + ); + }); + + $plan.find('.nav-tab').click(function () { + if ($(this).hasClass('nav-tab-active')) + return; + + var $this = $(this), + billingCycle = $this.attr('data-billing-cycle'), + pricing = JSON.parse($this.attr('data-pricing')), + $pricesList = $this.parents('.fs-plan').find('.fs-pricing-body .fs-licenses'), + html = ''; + + // Un-select previously selected tab. + $plan.find('.nav-tab').removeClass('nav-tab-active'); + + // Select current tab. + $this.addClass('nav-tab-active'); + + // Render licenses prices. + if (1 == pricing.length) { + html = '<li><label><?php _efs( 'price', $api->slug ) ?>: ' + _formatPrice(pricing[0], billingCycle, false) + '</label></li>'; + } else { + for (var i = 0; i < pricing.length; i++) { + html += '<li><label><input name="pricing-<?php echo $plan->id ?>" type="radio" value="' + pricing[i].id + '">' + _formatPrice(pricing[i], billingCycle) + '</label></li>'; + } + } + $pricesList.html(html); + + if (1 < pricing.length) { + // Select first license option. + $pricesList.find('li:first input').click(); + } + else { + _updateCtaUrl( + $plan.attr('data-plan-id'), + pricing[0].id, + billingCycle + ); + } + + // Update billing frequency. + $plan.find('.fs-billing-frequency').html(_formatBillingFrequency(billingCycle)); + + if ('annual' === billingCycle) { + $plan.find('.fs-annual-discount').show(); + } else { + $plan.find('.fs-annual-discount').hide(); + } + }); + + <?php if ( $has_annual ) : ?> + // Select annual by default. + $plan.find('.nav-tab[data-billing-cycle=annual]').click(); + <?php else : ?> + // Select first tab. + $plan.find('.nav-tab:first').click(); + <?php endif ?> + }); + }(jQuery)); + </script> + </div> + <div class="fs-pricing-body"> + <span class="fs-billing-frequency"></span> + <?php $annual_discount = ( $has_annual && $has_monthly ) ? $plan->pricing[0]->annual_discount_percentage() : 0 ?> + <?php if ( $annual_discount > 0 ) : ?> + <span + class="fs-annual-discount"><?php printf( __fs( 'save-x', $api->slug ), $annual_discount . '%' ) ?></span> + <?php endif ?> + <ul class="fs-licenses"> + </ul> + <?php echo $this->get_plugin_cta( $api, $plan ) ?> + <div style="clear:both"></div> + <?php if ( $plan->has_trial() ) : ?> + <?php $trial_period = $this->get_trial_period( $plan ) ?> + <ul class="fs-trial-terms"> + <li> + <i class="dashicons dashicons-yes"></i><?php printf( __fs( 'no-commitment-x', $api->slug ), $trial_period ) ?> + </li> + <li> + <i class="dashicons dashicons-yes"></i><?php printf( __fs( 'after-x-pay-as-little-y', $api->slug ), $trial_period, '<var class="fs-price">' . $this->get_price_tag( $plan, $plan->pricing[0] ) . '</var>' ) ?> + </li> + </ul> + <?php endif ?> + </div> + </div> + </div> + <?php endforeach ?> + <?php endif ?> + <?php endif ?> + <div> + <h3><?php _efs( 'details', $api->slug ) ?></h3> + <ul> + <?php if ( ! empty( $api->version ) ) { ?> + <li><strong><?php _e( 'Version:' ); ?></strong> <?php echo $api->version; ?></li> + <?php + } + if ( ! empty( $api->author ) ) { + ?> + <li> + <strong><?php _e( 'Author:' ); ?></strong> <?php echo links_add_target( $api->author, '_blank' ); ?> + </li> + <?php + } + if ( ! empty( $api->last_updated ) ) { + ?> + <li><strong><?php _e( 'Last Updated:' ); ?></strong> <span + title="<?php echo $api->last_updated; ?>"> + <?php printf( __( '%s ago' ), human_time_diff( strtotime( $api->last_updated ) ) ); ?> + </span></li> + <?php + } + if ( ! empty( $api->requires ) ) { + ?> + <li> + <strong><?php _e( 'Requires WordPress Version:' ); ?></strong> <?php printf( __( '%s or higher' ), $api->requires ); ?> + </li> + <?php + } + if ( ! empty( $api->tested ) ) { + ?> + <li><strong><?php _e( 'Compatible up to:' ); ?></strong> <?php echo $api->tested; ?> + </li> + <?php + } + if ( ! empty( $api->downloaded ) ) { + ?> + <li> + <strong><?php _e( 'Downloaded:' ); ?></strong> <?php printf( _n( '%s time', '%s times', $api->downloaded ), number_format_i18n( $api->downloaded ) ); ?> + </li> + <?php + } + if ( ! empty( $api->slug ) && empty( $api->external ) ) { + ?> + <li><a target="_blank" + href="https://wordpress.org/plugins/<?php echo $api->slug; ?>/"><?php _e( 'WordPress.org Plugin Page »' ); ?></a> + </li> + <?php + } + if ( ! empty( $api->homepage ) ) { + ?> + <li><a target="_blank" + href="<?php echo esc_url( $api->homepage ); ?>"><?php _e( 'Plugin Homepage »' ); ?></a> + </li> + <?php + } + if ( ! empty( $api->donate_link ) && empty( $api->contributors ) ) { + ?> + <li><a target="_blank" + href="<?php echo esc_url( $api->donate_link ); ?>"><?php _e( 'Donate to this plugin »' ); ?></a> + </li> + <?php } ?> + </ul> + </div> + <?php if ( ! empty( $api->rating ) ) { ?> + <h3><?php _e( 'Average Rating' ); ?></h3> + <?php wp_star_rating( array( + 'rating' => $api->rating, + 'type' => 'percent', + 'number' => $api->num_ratings + ) ); ?> + <small><?php printf( _n( '(based on %s rating)', '(based on %s ratings)', $api->num_ratings ), number_format_i18n( $api->num_ratings ) ); ?></small> + <?php + } + + if ( ! empty( $api->ratings ) && array_sum( (array) $api->ratings ) > 0 ) { + foreach ( $api->ratings as $key => $ratecount ) { + // Avoid div-by-zero. + $_rating = $api->num_ratings ? ( $ratecount / $api->num_ratings ) : 0; + ?> + <div class="counter-container"> + <span class="counter-label"><a + href="https://wordpress.org/support/view/plugin-reviews/<?php echo $api->slug; ?>?filter=<?php echo $key; ?>" + target="_blank" + title="<?php echo esc_attr( sprintf( _n( 'Click to see reviews that provided a rating of %d star', 'Click to see reviews that provided a rating of %d stars', $key ), $key ) ); ?>"><?php printf( _n( '%d star', '%d stars', $key ), $key ); ?></a></span> + <span class="counter-back"> + <span class="counter-bar" style="width: <?php echo 92 * $_rating; ?>px;"></span> + </span> + <span class="counter-count"><?php echo number_format_i18n( $ratecount ); ?></span> + </div> + <?php + } + } + if ( ! empty( $api->contributors ) ) { + ?> + <h3><?php _e( 'Contributors' ); ?></h3> + <ul class="contributors"> + <?php + foreach ( (array) $api->contributors as $contrib_username => $contrib_profile ) { + if ( empty( $contrib_username ) && empty( $contrib_profile ) ) { + continue; + } + if ( empty( $contrib_username ) ) { + $contrib_username = preg_replace( '/^.+\/(.+)\/?$/', '\1', $contrib_profile ); + } + $contrib_username = sanitize_user( $contrib_username ); + if ( empty( $contrib_profile ) ) { + echo "<li><img src='https://wordpress.org/grav-redirect.php?user={$contrib_username}&s=36' width='18' height='18' />{$contrib_username}</li>"; + } else { + echo "<li><a href='{$contrib_profile}' target='_blank'><img src='https://wordpress.org/grav-redirect.php?user={$contrib_username}&s=36' width='18' height='18' />{$contrib_username}</a></li>"; + } + } + ?> + </ul> + <?php if ( ! empty( $api->donate_link ) ) { ?> + <a target="_blank" + href="<?php echo esc_url( $api->donate_link ); ?>"><?php _e( 'Donate to this plugin »' ); ?></a> + <?php } ?> + <?php } ?> + </div> + <div id="section-holder" class="wrap"> + <?php + if ( ! empty( $api->tested ) && version_compare( substr( $GLOBALS['wp_version'], 0, strlen( $api->tested ) ), $api->tested, '>' ) ) { + echo '<div class="notice notice-warning"><p>' . '<strong>' . __( 'Warning:' ) . '</strong> ' . __( 'This plugin has not been tested with your current version of WordPress.' ) . '</p></div>'; + } else if ( ! empty( $api->requires ) && version_compare( substr( $GLOBALS['wp_version'], 0, strlen( $api->requires ) ), $api->requires, '<' ) ) { + echo '<div class="notice notice-warning"><p>' . '<strong>' . __( 'Warning:' ) . '</strong> ' . __( 'This plugin has not been marked as compatible with your version of WordPress.' ) . '</p></div>'; + } + + foreach ( (array) $api->sections as $section_name => $content ) { + $content = links_add_base_url( $content, 'https://wordpress.org/plugins/' . $api->slug . '/' ); + $content = links_add_target( $content, '_blank' ); + + $san_section = esc_attr( $section_name ); + + $display = ( $section_name === $section ) ? 'block' : 'none'; + + if ( 'description' === $section_name && + ( ( ! $api->external && $api->wp_org_missing ) || + ( $api->external && $api->fs_missing ) ) + ) { + $missing_notice = array( + 'type' => 'error', + 'id' => md5( microtime() ), + 'message' => __fs( ( $api->is_paid ? 'paid-addon-not-deployed' : 'free-addon-not-deployed' ), $api->slug ), + ); + fs_require_template( 'admin-notice.php', $missing_notice ); + } + echo "\t<div id='section-{$san_section}' class='section' style='display: {$display};'>\n"; + echo $content; + echo "\t</div>\n"; + } + echo "</div>\n"; + echo "</div>\n"; + echo "</div>\n"; // #plugin-information-scrollable + echo "<div id='$tab-footer'>\n"; + + echo $this->get_plugin_cta( $api ); + + echo "</div>\n"; + + iframe_footer(); + exit; +} + } diff --git a/wp-content/plugins/nextgen-gallery/freemius/includes/i18n.php b/wp-content/plugins/nextgen-gallery/freemius/includes/i18n.php index 704e9ff873539d13d4ef1a5e7c997ace696a6f44..32ea23dce406b94ef96af0e4d1bb6b3dc86132cb 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/includes/i18n.php +++ b/wp-content/plugins/nextgen-gallery/freemius/includes/i18n.php @@ -1,352 +1,352 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.1.4 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - /** - * All strings can now be overridden. - * - * For example, if we want to override: - * 'you-are-step-away' => 'You are just one step away - %s', - * - * We can use the filter: - * fs_override_i18n( array( - * 'opt-in-connect' => __( "Yes - I'm in!", '{your-text_domain}' ), - * 'skip' => __( 'Not today', '{your-text_domain}' ), - * ), '{plugin_slug}' ); - * - * Or with the Freemius instance: - * - * my_freemius->override_i18n( array( - * 'opt-in-connect' => __( "Yes - I'm in!", '{your-text_domain}' ), - * 'skip' => __( 'Not today', '{your-text_domain}' ), - * ); - */ - global $fs_text; - - $fs_text = array( - 'account' => __( 'Account', 'freemius' ), - 'addon' => __( 'Add On', 'freemius' ), - 'contact-us' => __( 'Contact Us', 'freemius' ), - 'change-ownership' => __( 'Change Ownership', 'freemius' ), - 'support' => __( 'Support', 'freemius' ), - 'support-forum' => __( 'Support Forum', 'freemius' ), - 'add-ons' => __( 'Add Ons', 'freemius' ), - 'upgrade' => _x( 'Upgrade', 'verb', 'freemius' ), - 'awesome' => __( 'Awesome', 'freemius' ), - 'pricing' => _x( 'Pricing', 'noun', 'freemius' ), - 'price' => _x( 'Price', 'noun', 'freemius' ), - 'unlimited-updates' => __( 'Unlimited Updates', 'freemius' ), - 'downgrade' => _x( 'Downgrade', 'verb', 'freemius' ), - 'cancel-trial' => __( 'Cancel Trial', 'freemius' ), - 'free-trial' => __( 'Free Trial', 'freemius' ), - 'start-free-x' => __( 'Start my free %s', 'freemius' ), - 'no-commitment-x' => __( 'No commitment for %s - cancel anytime', 'freemius' ), - 'after-x-pay-as-little-y' => __( 'After your free %s, pay as little as %s', 'freemius' ), - 'details' => __( 'Details', 'freemius' ), - 'account-details' => __( 'Account Details', 'freemius' ), - 'delete' => _x( 'Delete', 'verb', 'freemius' ), - 'delete-account' => __( 'Delete Account', 'freemius' ), - 'dismiss' => _x( 'Dismiss', 'as close a window', 'freemius' ), - 'plan' => _x( 'Plan', 'as product pricing plan', 'freemius' ), - 'change-plan' => __( 'Change Plan', 'freemius' ), - 'download-x-version' => _x( 'Download %s Version', 'as download professional version', 'freemius' ), - 'download-x-version-now' => _x( 'Download %s version now', 'as download professional version now', 'freemius' ), - 'download-latest' => _x( 'Download Latest', 'as download latest version', 'freemius' ), - 'you-have-x-license' => _x( 'You have a %s license.', 'E.g. you have a professional license.', 'freemius' ), - 'new' => __( 'New', 'freemius' ), - 'free' => __( 'Free', 'freemius' ), - 'trial' => _x( 'Trial', 'as trial plan', 'freemius' ), - 'purchase' => _x( 'Purchase', 'verb', 'freemius' ), - 'purchase-license' => __( 'Purchase License', 'freemius' ), - 'buy' => _x( 'Buy', 'verb', 'freemius' ), - 'buy-license' => __( 'Buy License', 'freemius' ), - 'license-single-site' => __( 'Single Site License', 'freemius' ), - 'license-unlimited' => __( 'Unlimited Licenses', 'freemius' ), - 'license-x-sites' => __( 'Up to %s Sites', 'freemius' ), - 'renew-license-now' => __( '%sRenew your license now%s to access version %s features and support.', 'freemius' ), - 'x-plan' => _x( '%s Plan', 'e.g. Professional Plan', 'freemius' ), - 'you-are-step-away' => __( 'You are just one step away - %s', 'freemius' ), - 'activate-x-now' => _x( 'Complete "%s" Activation Now', '%s - plugin name. As complete "Jetpack" activation now', 'freemius' ), - 'few-plugin-tweaks' => __( 'We made a few tweaks to the plugin, %s', 'freemius' ), - 'optin-x-now' => __( 'Opt-in to make "%s" Better!', 'freemius' ), - 'error' => __( 'Error', 'freemius' ), - 'failed-finding-main-path' => __( 'Freemius SDK couldn\'t find the plugin\'s main file. Please contact sdk@freemius.com with the current error.', 'freemius' ), - #region Account - - 'expiration' => _x( 'Expiration', 'as expiration date', 'freemius' ), - 'license' => _x( 'License', 'as software license', 'freemius' ), - 'not-verified' => __( 'not verified', 'freemius' ), - 'verify-email' => __( 'Verify Email', 'freemius' ), - 'expires-in' => _x( 'Expires in %s', 'e.g. expires in 2 months', 'freemius' ), - 'renews-in' => _x( 'Auto renews in %s', 'e.g. auto renews in 2 months', 'freemius' ), - 'no-expiration' => __( 'No expiration', 'freemius' ), - 'expired' => __( 'Expired', 'freemius' ), - 'cancelled' => __( 'Cancelled', 'freemius' ), - 'in-x' => _x( 'In %s', 'e.g. In 2 hours', 'freemius' ), - 'x-ago' => _x( '%s ago', 'e.g. 2 min ago', 'freemius' ), - 'version' => _x( 'Version', 'as plugin version', 'freemius' ), - 'name' => __( 'Name', 'freemius' ), - 'email' => __( 'Email', 'freemius' ), - 'verified' => __( 'Verified', 'freemius' ), - 'plugin' => __( 'Plugin', 'freemius' ), - 'plugins' => __( 'Plugins', 'freemius' ), - 'themes' => __( 'Themes', 'freemius' ), - 'path' => _x( 'Path', 'as file/folder path', 'freemius' ), - 'title' => __( 'Title', 'freemius' ), - 'free-version' => __( 'Free version', 'freemius' ), - 'premium-version' => __( 'Premium version', 'freemius' ), - 'slug' => _x( 'Slug', 'as WP plugin slug', 'freemius' ), - 'id' => __( 'ID', 'freemius' ), - 'users' => __( 'Users', 'freemius' ), - 'plugin-installs' => __( 'Plugin Installs', 'freemius' ), - 'sites' => _x( 'Sites', 'like websites', 'freemius' ), - 'user-id' => __( 'User ID', 'freemius' ), - 'site-id' => __( 'Site ID', 'freemius' ), - 'public-key' => __( 'Public Key', 'freemius' ), - 'secret-key' => __( 'Secret Key', 'freemius' ), - 'no-secret' => _x( 'No Secret', 'as secret encryption key missing', 'freemius' ), - 'no-id' => __( 'No ID', 'freemius' ), - 'sync-license' => _x( 'Sync License', 'as synchronize license', 'freemius' ), - 'sync' => _x( 'Sync', 'as synchronize', 'freemius' ), - 'deactivate-license' => __( 'Deactivate License', 'freemius' ), - 'activate' => __( 'Activate', 'freemius' ), - 'deactivate' => __( 'Deactivate', 'freemius' ), - 'skip-deactivate' => __( 'Skip & Deactivate', 'freemius' ), - 'no-deactivate' => __( 'No - just deactivate', 'freemius' ), - 'yes-do-your-thing' => __( 'Yes - do your thing', 'freemius' ), - 'active' => _x( 'Active', 'active mode', 'freemius' ), - 'is-active' => _x( 'Is Active', 'is active mode?', 'freemius' ), - 'install-now' => __( 'Install Now', 'freemius' ), - 'install-update-now' => __( 'Install Update Now', 'freemius' ), - 'more-information-about-x' => __( 'More information about %s', 'freemius' ), - 'localhost' => __( 'Localhost', 'freemius' ), - 'activate-x-plan' => _x( 'Activate %s Plan', 'as activate Professional plan', 'freemius' ), - 'x-left' => _x( '%s left', 'as 5 licenses left', 'freemius' ), - 'last-license' => __( 'Last license', 'freemius' ), - 'what-is-your-x' => __( 'What is your %s?', 'freemius' ), - 'activate-this-addon' => __( 'Activate this add-on', 'freemius' ), - 'deactivate-license-confirm' => __( 'Deactivating your license will block all premium features, but will enable you to activate the license on another site. Are you sure you want to proceed?', 'freemius' ), - 'delete-account-x-confirm' => __( 'Deleting the account will automatically deactivate your %s plan license so you can use it on other sites. If you want to terminate the recurring payments as well, click the "Cancel" button, and first "Downgrade" your account. Are you sure you would like to continue with the deletion?', 'freemius' ), - 'delete-account-confirm' => __( 'Deletion is not temporary. Only delete if you no longer want to use this plugin anymore. Are you sure you would like to continue with the deletion?', 'freemius' ), - 'downgrade-x-confirm' => __( 'Downgrading your plan will immediately stop all future recurring payments and your %s plan license will expire in %s.', 'freemius' ), - 'cancel-trial-confirm' => __( 'Cancelling the trial will immediately block access to all premium features. Are you sure?', 'freemius' ), - 'after-downgrade-non-blocking' => __( 'You can still enjoy all %s features but you will not have access to plugin updates and support.', 'freemius' ), - 'after-downgrade-blocking' => __( 'Once your license expire you can still use the Free version but you will NOT have access to the %s features.', 'freemius' ), - 'proceed-confirmation' => __( 'Are you sure you want to proceed?', 'freemius' ), - #endregion Account - - 'add-ons-for-x' => __( 'Add Ons for %s', 'freemius' ), - 'add-ons-missing' => __( 'We could\'nt load the add-ons list. It\'s probably an issue on our side, please try to come back in few minutes.', 'freemius' ), - #region Plugin Deactivation - 'deactivation-share-reason' => __( 'If you have a moment, please let us know why you are deactivating', 'freemius' ), - 'deactivation-modal-button-confirm' => __( 'Yes - Deactivate', 'freemius' ), - 'deactivation-modal-button-submit' => __( 'Submit & Deactivate', 'freemius' ), - 'deactivation-modal-button-cancel' => _x( 'Cancel', 'the text of the cancel button of the plugin deactivation dialog box.', 'freemius' ), - 'reason-no-longer-needed' => __( 'I no longer need the plugin', 'freemius' ), - 'reason-found-a-better-plugin' => __( 'I found a better plugin', 'freemius' ), - 'reason-needed-for-a-short-period' => __( 'I only needed the plugin for a short period', 'freemius' ), - 'reason-broke-my-site' => __( 'The plugin broke my site', 'freemius' ), - 'reason-suddenly-stopped-working' => __( 'The plugin suddenly stopped working', 'freemius' ), - 'reason-cant-pay-anymore' => __( "I can't pay for it anymore", 'freemius' ), - 'reason-temporary-deactivation' => __( "It's a temporary deactivation. I'm just debugging an issue.", 'freemius' ), - 'reason-other' => _x( 'Other', 'the text of the "other" reason for deactivating the plugin that is shown in the modal box.', 'freemius' ), - 'ask-for-reason-message' => __( 'Kindly tell us the reason so we can improve.', 'freemius' ), - 'placeholder-plugin-name' => __( "What's the plugin's name?", 'freemius' ), - 'placeholder-comfortable-price' => __( 'What price would you feel comfortable paying?', 'freemius' ), - 'reason-couldnt-make-it-work' => __( "I couldn't understand how to make it work", 'freemius' ), - 'reason-great-but-need-specific-feature' => __( "The plugin is great, but I need specific feature that you don't support", 'freemius' ), - 'reason-not-working' => __( 'The plugin is not working', 'freemius' ), - 'reason-not-what-i-was-looking-for' => __( "It's not what I was looking for", 'freemius' ), - 'reason-didnt-work-as-expected' => __( "The plugin didn't work as expected", 'freemius' ), - 'placeholder-feature' => __( 'What feature?', 'freemius' ), - 'placeholder-share-what-didnt-work' => __( "Kindly share what didn't work so we can fix it for future users...", 'freemius' ), - 'placeholder-what-youve-been-looking-for' => __( "What you've been looking for?", 'freemius' ), - 'placeholder-what-did-you-expect' => __( "What did you expect?", 'freemius' ), - 'reason-didnt-work' => __( "The plugin didn't work", 'freemius' ), - 'reason-dont-like-to-share-my-information' => __( "I don't like to share my information with you", 'freemius' ), - #endregion Plugin Deactivation - - #region Connect - 'hey-x' => _x( 'Hey %s,', 'greeting', 'freemius' ), - 'thanks-x' => _x( 'Thanks %s!', 'a greeting. E.g. Thanks John!', 'freemius' ), - 'connect-message' => __( 'In order to enjoy all our features and functionality, %s needs to connect your user, %s at %s, to %s', 'freemius' ), - 'connect-message_on-update' => __( 'Please help us improve %2$s! If you opt-in, some data about your usage of %2$s will be sent to %5$s. If you skip this, that\'s okay! %2$s will still work just fine.', 'freemius' ), - 'pending-activation-message' => __( 'You should receive an activation email for %s to your mailbox at %s. Please make sure you click the activation button in that email to complete the install.', 'freemius' ), - 'what-permissions' => __( 'What permissions are being granted?', 'freemius' ), - 'permissions-profile' => __( 'Your Profile Overview', 'freemius' ), - 'permissions-profile_desc' => __( 'Name and email address', 'freemius' ), - 'permissions-site' => __( 'Your Site Overview', 'freemius' ), - 'permissions-site_desc' => __( 'Site URL, WP version, PHP info, plugins & themes', 'freemius' ), - 'permissions-events' => __( 'Current Plugin Events', 'freemius' ), - 'permissions-events_desc' => __( 'Activation, deactivation and uninstall', 'freemius' ), - 'permissions-plugins_themes' => __( 'Plugins & Themes', 'freemius' ), - 'permissions-plugins_themes_desc' => __( 'Titles, versions and state.', 'freemius' ), - 'permissions-newsletter' => __( 'Newsletter', 'freemius' ), - 'permissions-newsletter_desc' => __( 'Updates, announcements, marketing, no spam', 'freemius' ), - 'privacy-policy' => __( 'Privacy Policy', 'freemius' ), - 'tos' => __( 'Terms of Service', 'freemius' ), - 'activating' => _x( 'Activating', 'as activating plugin', 'freemius' ), - 'sending-email' => _x( 'Sending email', 'as in the process of sending an email', 'freemius' ), - 'opt-in-connect' => _x( 'Allow & Continue', 'button label', 'freemius' ), - 'skip' => _x( 'Skip', 'verb', 'freemius' ), - 'resend-activation-email' => __( 'Re-send activation email', 'freemius' ), - #endregion Connect - - #region Screenshots - 'screenshots' => __( 'Screenshots', 'freemius' ), - 'view-full-size-x' => __( 'Click to view full-size screenshot %d', 'freemius' ), - #endregion Screenshots - - #region Debug - 'freemius-debug' => __( 'Freemius Debug', 'freemius' ), - 'on' => _x( 'On', 'as turned on', 'freemius' ), - 'off' => _x( 'Off', 'as turned off', 'freemius' ), - 'debugging' => _x( 'Debugging', 'as code debugging', 'freemius' ), - 'freemius-state' => __( 'Freemius State', 'freemius' ), - 'connected' => _x( 'Connected', 'as connection was successful', 'freemius' ), - 'blocked' => _x( 'Blocked', 'as connection blocked', 'freemius' ), - 'api' => _x( 'API', 'as application program interface', 'freemius' ), - 'sdk' => _x( 'SDK', 'as software development kit versions', 'freemius' ), - 'sdk-versions' => _x( 'SDK Versions', 'as software development kit versions', 'freemius' ), - 'plugin-path' => _x( 'Plugin Path', 'as plugin folder path', 'freemius' ), - 'sdk-path' => _x( 'SDK Path', 'as sdk path', 'freemius' ), - 'addons-of-x' => __( 'Add Ons of Plugin %s', 'freemius' ), - 'delete-all-confirm' => __( 'Are you sure you want to delete all Freemius data?', 'freemius' ), - 'actions' => __( 'Actions', 'freemius' ), - 'delete-all-accounts' => __( 'Delete All Accounts', 'freemius' ), - 'start-fresh' => __( 'Start Fresh', 'freemius' ), - 'clear-api-cache' => __( 'Clear API Cache', 'freemius' ), - 'sync-data-from-server' => __( 'Sync Data From Server', 'freemius' ), - 'scheduled-crons' => __( 'Scheduled Crons', 'freemius' ), - 'plugins-themes-sync' => __( 'Plugins & Themes Sync', 'freemius' ), - #endregion Debug - - #region Expressions - 'congrats' => _x( 'Congrats', 'as congratulations', 'freemius' ), - 'oops' => _x( 'Oops', 'exclamation', 'freemius' ), - 'yee-haw' => _x( 'Yee-haw', 'interjection expressing joy or exuberance', 'freemius' ), - 'woot' => _x( 'W00t', '(especially in electronic communication) used to express elation, enthusiasm, or triumph.', 'freemius' ), - 'right-on' => _x( 'Right on', 'a positive response', 'freemius' ), - 'hmm' => _x( 'Hmm', 'something somebody says when they are thinking about what you have just said. ', 'freemius' ), - 'ok' => __( 'O.K', 'freemius' ), - 'hey' => _x( 'Hey', 'exclamation', 'freemius' ), - 'heads-up' => _x( 'Heads up', 'advance notice of something that will need attention.', 'freemius' ), - #endregion Expressions - - #region Admin Notices - 'you-have-latest' => __( 'Seems like you got the latest release.', 'freemius' ), - 'you-are-good' => __( 'You are all good!', 'freemius' ), - 'user-exist-message' => __( 'Sorry, we could not complete the email update. Another user with the same email is already registered.', 'freemius' ), - 'user-exist-message_ownership' => __( 'If you would like to give up the ownership of the plugin\'s account to %s click the Change Ownership button.', 'freemius' ), - 'email-updated-message' => __( 'Your email was successfully updated. You should receive an email with confirmation instructions in few moments.', 'freemius' ), - 'name-updated-message' => __( 'Your name was successfully updated.', 'freemius' ), - 'x-updated' => __( 'You have successfully updated your %s.', 'freemius' ), - 'name-update-failed-message' => __( 'Please provide your full name.', 'freemius' ), - 'verification-email-sent-message' => __( 'Verification mail was just sent to %s. If you can\'t find it after 5 min, please check your spam box.', 'freemius' ), - 'addons-info-external-message' => __( 'Just letting you know that the add-ons information of %s is being pulled from an external server.', 'freemius' ), - 'no-cc-required' => __( 'No credit card required', 'freemius' ), - 'premium-activated-message' => __( 'Premium plugin version was successfully activated.', 'freemius' ), - 'successful-version-upgrade-message' => __( 'The upgrade of %s was successfully completed.', 'freemius' ), - 'activation-with-plan-x-message' => __( 'Your account was successfully activated with the %s plan.', 'freemius' ), - 'download-latest-x-version' => __( 'Download the latest %s version now', 'freemius' ), - 'download-latest-version' => __( 'Download the latest version now', 'freemius' ), - 'addon-successfully-purchased-message' => _x( '%s Add-on was successfully purchased.', '%s - product name, e.g. Facebook add-on was successfully...', 'freemius' ), - 'addon-successfully-upgraded-message' => __( 'Your %s Add-on plan was successfully upgraded.', 'freemius' ), - 'email-verified-message' => __( 'Your email has been successfully verified - you are AWESOME!', 'freemius' ), - 'plan-upgraded-message' => __( 'Your plan was successfully upgraded.', 'freemius' ), - 'plan-changed-to-x-message' => __( 'Your plan was successfully changed to %s.', 'freemius' ), - 'license-expired-blocking-message' => __( 'Your license has expired. You can still continue using the free plugin forever.', 'freemius' ), - 'trial-started-message' => __( 'Your trial has been successfully started.', 'freemius' ), - 'license-activated-message' => __( 'Your license was successfully activated.', 'freemius' ), - 'no-active-license-message' => __( 'It looks like your site currently doesn\'t have an active license.', 'freemius' ), - 'license-deactivation-message' => __( 'Your license was successfully deactivated, you are back to the %s plan.', 'freemius' ), - 'license-deactivation-failed-message' => __( 'It looks like the license deactivation failed.', 'freemius' ), - 'license-activation-failed-message' => __( 'It looks like the license could not be activated.', 'freemius' ), - 'server-error-message' => __( 'Error received from the server:', 'freemius' ), - 'trial-expired-message' => __( 'Your trial has expired. You can still continue using all our free features.', 'freemius' ), - 'plan-x-downgraded-message' => __( 'Your plan was successfully downgraded. Your %s plan license will expire in %s.', 'freemius' ), - 'plan-downgraded-failure-message' => __( 'Seems like we are having some temporary issue with your plan downgrade. Please try again in few minutes.', 'freemius' ), - 'trial-cancel-no-trial-message' => __( 'It looks like you are not in trial mode anymore so there\'s nothing to cancel :)', 'freemius' ), - 'trial-cancel-message' => __( 'Your %s free trial was successfully cancelled.', 'freemius' ), - 'version-x-released' => _x( 'Version %s was released.', '%s - numeric version number', 'freemius' ), - 'please-download-x' => __( 'Please download %s.', 'freemius' ), - 'latest-x-version' => _x( 'the latest %s version here', '%s - plan name, as the latest professional version here', 'freemius' ), - 'trial-x-promotion-message' => __( 'How do you like %s so far? Test all our %s premium features with a %d-day free trial.', 'freemius' ), - 'start-free-trial' => _x( 'Start free trial', 'call to action', 'freemius' ), - 'trial-cancel-failure-message' => __( 'Seems like we are having some temporary issue with your trial cancellation. Please try again in few minutes.', 'freemius' ), - 'trial-utilized' => __( 'You already utilized a trial before.', 'freemius' ), - 'in-trial-mode' => __( 'You are already running the plugin in a trial mode.', 'freemius' ), - 'trial-plan-x-not-exist' => __( 'Plan %s do not exist, therefore, can\'t start a trial.', 'freemius' ), - 'plan-x-no-trial' => __( 'Plan %s does not support a trial period.', 'freemius' ), - 'no-trials' => __( 'None of the plugin\'s plans supports a trial period.', 'freemius' ), - 'unexpected-api-error' => __( 'Unexpected API error. Please contact the plugin\'s author with the following error.', 'freemius' ), - 'no-commitment-for-x-days' => __( 'No commitment for %s days - cancel anytime!', 'freemius' ), - 'license-expired-non-blocking-message' => __( 'Your license has expired. You can still continue using all the %s features, but you\'ll need to renew your license to continue getting updates and support.', 'freemius' ), - 'could-not-activate-x' => __( 'Couldn\'t activate %s.', 'freemius' ), - 'contact-us-with-error-message' => __( 'Please contact us with the following message:', 'freemius' ), - 'plan-did-not-change-message' => __( 'It looks like you are still on the %s plan. If you did upgrade or change your plan, it\'s probably an issue on our side - sorry.', 'freemius' ), - 'contact-us-here' => __( 'Please contact us here', 'freemius' ), - 'plan-did-not-change-email-message' => __( 'I have upgraded my account but when I try to Sync the License, the plan remains %s.', 'freemius' ), - #endregion Admin Notices - #region Connectivity Issues - 'connectivity-test-fails-message' => __( 'From unknown reason, the API connectivity test failed.', 'freemius' ), - 'connectivity-test-maybe-temporary' => __( 'It\'s probably a temporary issue on our end. Just to be sure, with your permission, would it be o.k to run another connectivity test?', 'freemius' ), - 'curl-missing-message' => __( 'We use PHP cURL library for the API calls, which is a very common library and usually installed out of the box. Unfortunately, cURL is not installed on your server.', 'freemius' ), - 'cloudflare-blocks-connection-message' => __( 'From unknown reason, CloudFlare, the firewall we use, blocks the connection.', 'freemius' ), - 'x-requires-access-to-api' => _x( '%s requires an access to our API.', 'as pluginX requires an access to our API', 'freemius' ), - 'squid-blocks-connection-message' => __( 'It looks like your server is using Squid ACL (access control lists), which blocks the connection.', 'freemius' ), - 'squid-no-clue-title' => __( 'I don\'t know what is Squid or ACL, help me!', 'freemius' ), - 'squid-no-clue-desc' => __( 'We\'ll make sure to contact your hosting company and resolve the issue. You will get a follow-up email to %s once we have an update.', 'freemius' ), - 'sysadmin-title' => __( 'I\'m a system administrator', 'freemius' ), - 'squid-sysadmin-desc' => __( 'Great, please whitelist the following domains: %s. Once you done, deactivate the plugin and activate it again.', 'freemius' ), - 'curl-missing-no-clue-title' => __( 'I don\'t know what is cURL or how to install it, help me!', 'freemius' ), - 'curl-missing-no-clue-desc' => __( 'We\'ll make sure to contact your hosting company and resolve the issue. You will get a follow-up email to %s once we have an update.', 'freemius' ), - 'curl-missing-sysadmin-desc' => __( 'Great, please install cURL and enable it in your php.ini file. To make sure it was successfully activated, use \'phpinfo()\'. Once activated, deactivate the plugin and reactivate it back again.', 'freemius' ), - 'happy-to-resolve-issue-asap' => __( 'We are sure it\'s an issue on our side and more than happy to resolve it for you ASAP if you give us a chance.', 'freemius' ), - 'fix-issue-title' => __( 'Yes - I\'m giving you a chance to fix it', 'freemius' ), - 'fix-issue-desc' => __( 'We will do our best to whitelist your server and resolve this issue ASAP. You will get a follow-up email to %s once we have an update.', 'freemius' ), - 'install-previous-title' => __( 'Let\'s try your previous version', 'freemius' ), - 'install-previous-desc' => __( 'Uninstall this version and install the previous one.', 'freemius' ), - 'deactivate-plugin-title' => __( 'That\'s exhausting, please deactivate', 'freemius' ), - 'deactivate-plugin-desc' => __( 'We feel your frustration and sincerely apologize for the inconvenience. Hope to see you again in the future.', 'freemius' ), - 'fix-request-sent-message' => __( 'Thank for giving us the chance to fix it! A message was just sent to our technical staff. We will get back to you as soon as we have an update to %s. Appreciate your patience.', 'freemius' ), - 'server-blocking-access' => _x( 'Your server is blocking the access to Freemius\' API, which is crucial for %1s synchronization. Please contact your host to whitelist %2s', '%1s - plugin title, %2s - API domain', 'freemius' ), - 'wrong-authentication-param-message' => __( 'It seems like one of the authentication parameters is wrong. Update your Public Key, Secret Key & User ID, and try again.', 'freemius' ), - #endregion Connectivity Issues - #region Change Owner - 'change-owner-request-sent-x' => __( 'Please check your mailbox, you should receive an email via %s to confirm the ownership change. From security reasons, you must confirm the change within the next 15 min. If you cannot find the email, please check your spam folder.', 'freemius' ), - 'change-owner-request_owner-confirmed' => __( 'Thanks for confirming the ownership change. An email was just sent to %s for final approval.', 'freemius' ), - 'change-owner-request_candidate-confirmed' => __( '%s is the new owner of the account.', 'freemius' ), - #endregion Change Owner - 'addon-x-cannot-run-without-y' => _x( '%s cannot run without %s.', 'addonX cannot run without pluginY', 'freemius' ), - 'addon-x-cannot-run-without-parent' => _x( '%s cannot run without the plugin.', 'addonX cannot run...', 'freemius' ), - 'plugin-x-activation-message' => _x( '%s activation was successfully completed.', 'pluginX activation was successfully...', 'freemius' ), - 'features-and-pricing' => _x( 'Features & Pricing', 'Plugin installer section title', 'freemius' ), - 'free-addon-not-deployed' => __( 'Add-on must be deployed to WordPress.org or Freemius.', 'freemius' ), - 'paid-addon-not-deployed' => __( 'Paid add-on must be deployed to Freemius.', 'freemius' ), - #region Add-On Licensing - 'addon-no-license-message' => __( '%s is a premium only add-on. You have to purchase a license first before activating the plugin.', 'freemius' ), - 'addon-trial-cancelled-message' => __( '%s free trial was successfully cancelled. Since the add-on is premium only it was automatically deactivated. If you like to use it in the future, you\'ll have to purchase a license.', 'freemius' ), - #endregion Add-On Licensing - #region Billing Cycles - 'monthly' => _x( 'Monthly', 'as every month', 'freemius' ), - 'mo' => _x( 'mo', 'as monthly period', 'freemius' ), - 'annual' => _x( 'Annual', 'as once a year', 'freemius' ), - 'annually' => _x( 'Annually', 'as once a year', 'freemius' ), - 'once' => _x( 'Once', 'as once a year', 'freemius' ), - 'year' => _x( 'year', 'as annual period', 'freemius' ), - 'lifetime' => __( 'Lifetime', 'freemius' ), - 'best' => _x( 'Best', 'e.g. the best product', 'freemius' ), - 'billed-x' => _x( 'Billed %s', 'e.g. billed monthly', 'freemius' ), - 'save-x' => _x( 'Save %s', 'as a discount of $5 or 10%', 'freemius' ), - #endregion Billing Cycles - 'view-details' => __( 'View details', 'freemius' ), - ); +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.1.4 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + /** + * All strings can now be overridden. + * + * For example, if we want to override: + * 'you-are-step-away' => 'You are just one step away - %s', + * + * We can use the filter: + * fs_override_i18n( array( + * 'opt-in-connect' => __( "Yes - I'm in!", '{your-text_domain}' ), + * 'skip' => __( 'Not today', '{your-text_domain}' ), + * ), '{plugin_slug}' ); + * + * Or with the Freemius instance: + * + * my_freemius->override_i18n( array( + * 'opt-in-connect' => __( "Yes - I'm in!", '{your-text_domain}' ), + * 'skip' => __( 'Not today', '{your-text_domain}' ), + * ); + */ + global $fs_text; + + $fs_text = array( + 'account' => __( 'Account', 'freemius' ), + 'addon' => __( 'Add On', 'freemius' ), + 'contact-us' => __( 'Contact Us', 'freemius' ), + 'change-ownership' => __( 'Change Ownership', 'freemius' ), + 'support' => __( 'Support', 'freemius' ), + 'support-forum' => __( 'Support Forum', 'freemius' ), + 'add-ons' => __( 'Add Ons', 'freemius' ), + 'upgrade' => _x( 'Upgrade', 'verb', 'freemius' ), + 'awesome' => __( 'Awesome', 'freemius' ), + 'pricing' => _x( 'Pricing', 'noun', 'freemius' ), + 'price' => _x( 'Price', 'noun', 'freemius' ), + 'unlimited-updates' => __( 'Unlimited Updates', 'freemius' ), + 'downgrade' => _x( 'Downgrade', 'verb', 'freemius' ), + 'cancel-trial' => __( 'Cancel Trial', 'freemius' ), + 'free-trial' => __( 'Free Trial', 'freemius' ), + 'start-free-x' => __( 'Start my free %s', 'freemius' ), + 'no-commitment-x' => __( 'No commitment for %s - cancel anytime', 'freemius' ), + 'after-x-pay-as-little-y' => __( 'After your free %s, pay as little as %s', 'freemius' ), + 'details' => __( 'Details', 'freemius' ), + 'account-details' => __( 'Account Details', 'freemius' ), + 'delete' => _x( 'Delete', 'verb', 'freemius' ), + 'delete-account' => __( 'Delete Account', 'freemius' ), + 'dismiss' => _x( 'Dismiss', 'as close a window', 'freemius' ), + 'plan' => _x( 'Plan', 'as product pricing plan', 'freemius' ), + 'change-plan' => __( 'Change Plan', 'freemius' ), + 'download-x-version' => _x( 'Download %s Version', 'as download professional version', 'freemius' ), + 'download-x-version-now' => _x( 'Download %s version now', 'as download professional version now', 'freemius' ), + 'download-latest' => _x( 'Download Latest', 'as download latest version', 'freemius' ), + 'you-have-x-license' => _x( 'You have a %s license.', 'E.g. you have a professional license.', 'freemius' ), + 'new' => __( 'New', 'freemius' ), + 'free' => __( 'Free', 'freemius' ), + 'trial' => _x( 'Trial', 'as trial plan', 'freemius' ), + 'purchase' => _x( 'Purchase', 'verb', 'freemius' ), + 'purchase-license' => __( 'Purchase License', 'freemius' ), + 'buy' => _x( 'Buy', 'verb', 'freemius' ), + 'buy-license' => __( 'Buy License', 'freemius' ), + 'license-single-site' => __( 'Single Site License', 'freemius' ), + 'license-unlimited' => __( 'Unlimited Licenses', 'freemius' ), + 'license-x-sites' => __( 'Up to %s Sites', 'freemius' ), + 'renew-license-now' => __( '%sRenew your license now%s to access version %s features and support.', 'freemius' ), + 'x-plan' => _x( '%s Plan', 'e.g. Professional Plan', 'freemius' ), + 'you-are-step-away' => __( 'You are just one step away - %s', 'freemius' ), + 'activate-x-now' => _x( 'Complete "%s" Activation Now', '%s - plugin name. As complete "Jetpack" activation now', 'freemius' ), + 'few-plugin-tweaks' => __( 'We made a few tweaks to the plugin, %s', 'freemius' ), + 'optin-x-now' => __( 'Opt-in to make "%s" Better!', 'freemius' ), + 'error' => __( 'Error', 'freemius' ), + 'failed-finding-main-path' => __( 'Freemius SDK couldn\'t find the plugin\'s main file. Please contact sdk@freemius.com with the current error.', 'freemius' ), + #region Account + + 'expiration' => _x( 'Expiration', 'as expiration date', 'freemius' ), + 'license' => _x( 'License', 'as software license', 'freemius' ), + 'not-verified' => __( 'not verified', 'freemius' ), + 'verify-email' => __( 'Verify Email', 'freemius' ), + 'expires-in' => _x( 'Expires in %s', 'e.g. expires in 2 months', 'freemius' ), + 'renews-in' => _x( 'Auto renews in %s', 'e.g. auto renews in 2 months', 'freemius' ), + 'no-expiration' => __( 'No expiration', 'freemius' ), + 'expired' => __( 'Expired', 'freemius' ), + 'cancelled' => __( 'Cancelled', 'freemius' ), + 'in-x' => _x( 'In %s', 'e.g. In 2 hours', 'freemius' ), + 'x-ago' => _x( '%s ago', 'e.g. 2 min ago', 'freemius' ), + 'version' => _x( 'Version', 'as plugin version', 'freemius' ), + 'name' => __( 'Name', 'freemius' ), + 'email' => __( 'Email', 'freemius' ), + 'verified' => __( 'Verified', 'freemius' ), + 'plugin' => __( 'Plugin', 'freemius' ), + 'plugins' => __( 'Plugins', 'freemius' ), + 'themes' => __( 'Themes', 'freemius' ), + 'path' => _x( 'Path', 'as file/folder path', 'freemius' ), + 'title' => __( 'Title', 'freemius' ), + 'free-version' => __( 'Free version', 'freemius' ), + 'premium-version' => __( 'Premium version', 'freemius' ), + 'slug' => _x( 'Slug', 'as WP plugin slug', 'freemius' ), + 'id' => __( 'ID', 'freemius' ), + 'users' => __( 'Users', 'freemius' ), + 'plugin-installs' => __( 'Plugin Installs', 'freemius' ), + 'sites' => _x( 'Sites', 'like websites', 'freemius' ), + 'user-id' => __( 'User ID', 'freemius' ), + 'site-id' => __( 'Site ID', 'freemius' ), + 'public-key' => __( 'Public Key', 'freemius' ), + 'secret-key' => __( 'Secret Key', 'freemius' ), + 'no-secret' => _x( 'No Secret', 'as secret encryption key missing', 'freemius' ), + 'no-id' => __( 'No ID', 'freemius' ), + 'sync-license' => _x( 'Sync License', 'as synchronize license', 'freemius' ), + 'sync' => _x( 'Sync', 'as synchronize', 'freemius' ), + 'deactivate-license' => __( 'Deactivate License', 'freemius' ), + 'activate' => __( 'Activate', 'freemius' ), + 'deactivate' => __( 'Deactivate', 'freemius' ), + 'skip-deactivate' => __( 'Skip & Deactivate', 'freemius' ), + 'no-deactivate' => __( 'No - just deactivate', 'freemius' ), + 'yes-do-your-thing' => __( 'Yes - do your thing', 'freemius' ), + 'active' => _x( 'Active', 'active mode', 'freemius' ), + 'is-active' => _x( 'Is Active', 'is active mode?', 'freemius' ), + 'install-now' => __( 'Install Now', 'freemius' ), + 'install-update-now' => __( 'Install Update Now', 'freemius' ), + 'more-information-about-x' => __( 'More information about %s', 'freemius' ), + 'localhost' => __( 'Localhost', 'freemius' ), + 'activate-x-plan' => _x( 'Activate %s Plan', 'as activate Professional plan', 'freemius' ), + 'x-left' => _x( '%s left', 'as 5 licenses left', 'freemius' ), + 'last-license' => __( 'Last license', 'freemius' ), + 'what-is-your-x' => __( 'What is your %s?', 'freemius' ), + 'activate-this-addon' => __( 'Activate this add-on', 'freemius' ), + 'deactivate-license-confirm' => __( 'Deactivating your license will block all premium features, but will enable you to activate the license on another site. Are you sure you want to proceed?', 'freemius' ), + 'delete-account-x-confirm' => __( 'Deleting the account will automatically deactivate your %s plan license so you can use it on other sites. If you want to terminate the recurring payments as well, click the "Cancel" button, and first "Downgrade" your account. Are you sure you would like to continue with the deletion?', 'freemius' ), + 'delete-account-confirm' => __( 'Deletion is not temporary. Only delete if you no longer want to use this plugin anymore. Are you sure you would like to continue with the deletion?', 'freemius' ), + 'downgrade-x-confirm' => __( 'Downgrading your plan will immediately stop all future recurring payments and your %s plan license will expire in %s.', 'freemius' ), + 'cancel-trial-confirm' => __( 'Cancelling the trial will immediately block access to all premium features. Are you sure?', 'freemius' ), + 'after-downgrade-non-blocking' => __( 'You can still enjoy all %s features but you will not have access to plugin updates and support.', 'freemius' ), + 'after-downgrade-blocking' => __( 'Once your license expire you can still use the Free version but you will NOT have access to the %s features.', 'freemius' ), + 'proceed-confirmation' => __( 'Are you sure you want to proceed?', 'freemius' ), + #endregion Account + + 'add-ons-for-x' => __( 'Add Ons for %s', 'freemius' ), + 'add-ons-missing' => __( 'We could\'nt load the add-ons list. It\'s probably an issue on our side, please try to come back in few minutes.', 'freemius' ), + #region Plugin Deactivation + 'deactivation-share-reason' => __( 'If you have a moment, please let us know why you are deactivating', 'freemius' ), + 'deactivation-modal-button-confirm' => __( 'Yes - Deactivate', 'freemius' ), + 'deactivation-modal-button-submit' => __( 'Submit & Deactivate', 'freemius' ), + 'deactivation-modal-button-cancel' => _x( 'Cancel', 'the text of the cancel button of the plugin deactivation dialog box.', 'freemius' ), + 'reason-no-longer-needed' => __( 'I no longer need the plugin', 'freemius' ), + 'reason-found-a-better-plugin' => __( 'I found a better plugin', 'freemius' ), + 'reason-needed-for-a-short-period' => __( 'I only needed the plugin for a short period', 'freemius' ), + 'reason-broke-my-site' => __( 'The plugin broke my site', 'freemius' ), + 'reason-suddenly-stopped-working' => __( 'The plugin suddenly stopped working', 'freemius' ), + 'reason-cant-pay-anymore' => __( "I can't pay for it anymore", 'freemius' ), + 'reason-temporary-deactivation' => __( "It's a temporary deactivation. I'm just debugging an issue.", 'freemius' ), + 'reason-other' => _x( 'Other', 'the text of the "other" reason for deactivating the plugin that is shown in the modal box.', 'freemius' ), + 'ask-for-reason-message' => __( 'Kindly tell us the reason so we can improve.', 'freemius' ), + 'placeholder-plugin-name' => __( "What's the plugin's name?", 'freemius' ), + 'placeholder-comfortable-price' => __( 'What price would you feel comfortable paying?', 'freemius' ), + 'reason-couldnt-make-it-work' => __( "I couldn't understand how to make it work", 'freemius' ), + 'reason-great-but-need-specific-feature' => __( "The plugin is great, but I need specific feature that you don't support", 'freemius' ), + 'reason-not-working' => __( 'The plugin is not working', 'freemius' ), + 'reason-not-what-i-was-looking-for' => __( "It's not what I was looking for", 'freemius' ), + 'reason-didnt-work-as-expected' => __( "The plugin didn't work as expected", 'freemius' ), + 'placeholder-feature' => __( 'What feature?', 'freemius' ), + 'placeholder-share-what-didnt-work' => __( "Kindly share what didn't work so we can fix it for future users...", 'freemius' ), + 'placeholder-what-youve-been-looking-for' => __( "What you've been looking for?", 'freemius' ), + 'placeholder-what-did-you-expect' => __( "What did you expect?", 'freemius' ), + 'reason-didnt-work' => __( "The plugin didn't work", 'freemius' ), + 'reason-dont-like-to-share-my-information' => __( "I don't like to share my information with you", 'freemius' ), + #endregion Plugin Deactivation + + #region Connect + 'hey-x' => _x( 'Hey %s,', 'greeting', 'freemius' ), + 'thanks-x' => _x( 'Thanks %s!', 'a greeting. E.g. Thanks John!', 'freemius' ), + 'connect-message' => __( 'In order to enjoy all our features and functionality, %s needs to connect your user, %s at %s, to %s', 'freemius' ), + 'connect-message_on-update' => __( 'Please help us improve %2$s! If you opt-in, some data about your usage of %2$s will be sent to %5$s. If you skip this, that\'s okay! %2$s will still work just fine.', 'freemius' ), + 'pending-activation-message' => __( 'You should receive an activation email for %s to your mailbox at %s. Please make sure you click the activation button in that email to complete the install.', 'freemius' ), + 'what-permissions' => __( 'What permissions are being granted?', 'freemius' ), + 'permissions-profile' => __( 'Your Profile Overview', 'freemius' ), + 'permissions-profile_desc' => __( 'Name and email address', 'freemius' ), + 'permissions-site' => __( 'Your Site Overview', 'freemius' ), + 'permissions-site_desc' => __( 'Site URL, WP version, PHP info, plugins & themes', 'freemius' ), + 'permissions-events' => __( 'Current Plugin Events', 'freemius' ), + 'permissions-events_desc' => __( 'Activation, deactivation and uninstall', 'freemius' ), + 'permissions-plugins_themes' => __( 'Plugins & Themes', 'freemius' ), + 'permissions-plugins_themes_desc' => __( 'Titles, versions and state.', 'freemius' ), + 'permissions-newsletter' => __( 'Newsletter', 'freemius' ), + 'permissions-newsletter_desc' => __( 'Updates, announcements, marketing, no spam', 'freemius' ), + 'privacy-policy' => __( 'Privacy Policy', 'freemius' ), + 'tos' => __( 'Terms of Service', 'freemius' ), + 'activating' => _x( 'Activating', 'as activating plugin', 'freemius' ), + 'sending-email' => _x( 'Sending email', 'as in the process of sending an email', 'freemius' ), + 'opt-in-connect' => _x( 'Allow & Continue', 'button label', 'freemius' ), + 'skip' => _x( 'Skip', 'verb', 'freemius' ), + 'resend-activation-email' => __( 'Re-send activation email', 'freemius' ), + #endregion Connect + + #region Screenshots + 'screenshots' => __( 'Screenshots', 'freemius' ), + 'view-full-size-x' => __( 'Click to view full-size screenshot %d', 'freemius' ), + #endregion Screenshots + + #region Debug + 'freemius-debug' => __( 'Freemius Debug', 'freemius' ), + 'on' => _x( 'On', 'as turned on', 'freemius' ), + 'off' => _x( 'Off', 'as turned off', 'freemius' ), + 'debugging' => _x( 'Debugging', 'as code debugging', 'freemius' ), + 'freemius-state' => __( 'Freemius State', 'freemius' ), + 'connected' => _x( 'Connected', 'as connection was successful', 'freemius' ), + 'blocked' => _x( 'Blocked', 'as connection blocked', 'freemius' ), + 'api' => _x( 'API', 'as application program interface', 'freemius' ), + 'sdk' => _x( 'SDK', 'as software development kit versions', 'freemius' ), + 'sdk-versions' => _x( 'SDK Versions', 'as software development kit versions', 'freemius' ), + 'plugin-path' => _x( 'Plugin Path', 'as plugin folder path', 'freemius' ), + 'sdk-path' => _x( 'SDK Path', 'as sdk path', 'freemius' ), + 'addons-of-x' => __( 'Add Ons of Plugin %s', 'freemius' ), + 'delete-all-confirm' => __( 'Are you sure you want to delete all Freemius data?', 'freemius' ), + 'actions' => __( 'Actions', 'freemius' ), + 'delete-all-accounts' => __( 'Delete All Accounts', 'freemius' ), + 'start-fresh' => __( 'Start Fresh', 'freemius' ), + 'clear-api-cache' => __( 'Clear API Cache', 'freemius' ), + 'sync-data-from-server' => __( 'Sync Data From Server', 'freemius' ), + 'scheduled-crons' => __( 'Scheduled Crons', 'freemius' ), + 'plugins-themes-sync' => __( 'Plugins & Themes Sync', 'freemius' ), + #endregion Debug + + #region Expressions + 'congrats' => _x( 'Congrats', 'as congratulations', 'freemius' ), + 'oops' => _x( 'Oops', 'exclamation', 'freemius' ), + 'yee-haw' => _x( 'Yee-haw', 'interjection expressing joy or exuberance', 'freemius' ), + 'woot' => _x( 'W00t', '(especially in electronic communication) used to express elation, enthusiasm, or triumph.', 'freemius' ), + 'right-on' => _x( 'Right on', 'a positive response', 'freemius' ), + 'hmm' => _x( 'Hmm', 'something somebody says when they are thinking about what you have just said. ', 'freemius' ), + 'ok' => __( 'O.K', 'freemius' ), + 'hey' => _x( 'Hey', 'exclamation', 'freemius' ), + 'heads-up' => _x( 'Heads up', 'advance notice of something that will need attention.', 'freemius' ), + #endregion Expressions + + #region Admin Notices + 'you-have-latest' => __( 'Seems like you got the latest release.', 'freemius' ), + 'you-are-good' => __( 'You are all good!', 'freemius' ), + 'user-exist-message' => __( 'Sorry, we could not complete the email update. Another user with the same email is already registered.', 'freemius' ), + 'user-exist-message_ownership' => __( 'If you would like to give up the ownership of the plugin\'s account to %s click the Change Ownership button.', 'freemius' ), + 'email-updated-message' => __( 'Your email was successfully updated. You should receive an email with confirmation instructions in few moments.', 'freemius' ), + 'name-updated-message' => __( 'Your name was successfully updated.', 'freemius' ), + 'x-updated' => __( 'You have successfully updated your %s.', 'freemius' ), + 'name-update-failed-message' => __( 'Please provide your full name.', 'freemius' ), + 'verification-email-sent-message' => __( 'Verification mail was just sent to %s. If you can\'t find it after 5 min, please check your spam box.', 'freemius' ), + 'addons-info-external-message' => __( 'Just letting you know that the add-ons information of %s is being pulled from an external server.', 'freemius' ), + 'no-cc-required' => __( 'No credit card required', 'freemius' ), + 'premium-activated-message' => __( 'Premium plugin version was successfully activated.', 'freemius' ), + 'successful-version-upgrade-message' => __( 'The upgrade of %s was successfully completed.', 'freemius' ), + 'activation-with-plan-x-message' => __( 'Your account was successfully activated with the %s plan.', 'freemius' ), + 'download-latest-x-version' => __( 'Download the latest %s version now', 'freemius' ), + 'download-latest-version' => __( 'Download the latest version now', 'freemius' ), + 'addon-successfully-purchased-message' => _x( '%s Add-on was successfully purchased.', '%s - product name, e.g. Facebook add-on was successfully...', 'freemius' ), + 'addon-successfully-upgraded-message' => __( 'Your %s Add-on plan was successfully upgraded.', 'freemius' ), + 'email-verified-message' => __( 'Your email has been successfully verified - you are AWESOME!', 'freemius' ), + 'plan-upgraded-message' => __( 'Your plan was successfully upgraded.', 'freemius' ), + 'plan-changed-to-x-message' => __( 'Your plan was successfully changed to %s.', 'freemius' ), + 'license-expired-blocking-message' => __( 'Your license has expired. You can still continue using the free plugin forever.', 'freemius' ), + 'trial-started-message' => __( 'Your trial has been successfully started.', 'freemius' ), + 'license-activated-message' => __( 'Your license was successfully activated.', 'freemius' ), + 'no-active-license-message' => __( 'It looks like your site currently doesn\'t have an active license.', 'freemius' ), + 'license-deactivation-message' => __( 'Your license was successfully deactivated, you are back to the %s plan.', 'freemius' ), + 'license-deactivation-failed-message' => __( 'It looks like the license deactivation failed.', 'freemius' ), + 'license-activation-failed-message' => __( 'It looks like the license could not be activated.', 'freemius' ), + 'server-error-message' => __( 'Error received from the server:', 'freemius' ), + 'trial-expired-message' => __( 'Your trial has expired. You can still continue using all our free features.', 'freemius' ), + 'plan-x-downgraded-message' => __( 'Your plan was successfully downgraded. Your %s plan license will expire in %s.', 'freemius' ), + 'plan-downgraded-failure-message' => __( 'Seems like we are having some temporary issue with your plan downgrade. Please try again in few minutes.', 'freemius' ), + 'trial-cancel-no-trial-message' => __( 'It looks like you are not in trial mode anymore so there\'s nothing to cancel :)', 'freemius' ), + 'trial-cancel-message' => __( 'Your %s free trial was successfully cancelled.', 'freemius' ), + 'version-x-released' => _x( 'Version %s was released.', '%s - numeric version number', 'freemius' ), + 'please-download-x' => __( 'Please download %s.', 'freemius' ), + 'latest-x-version' => _x( 'the latest %s version here', '%s - plan name, as the latest professional version here', 'freemius' ), + 'trial-x-promotion-message' => __( 'How do you like %s so far? Test all our %s premium features with a %d-day free trial.', 'freemius' ), + 'start-free-trial' => _x( 'Start free trial', 'call to action', 'freemius' ), + 'trial-cancel-failure-message' => __( 'Seems like we are having some temporary issue with your trial cancellation. Please try again in few minutes.', 'freemius' ), + 'trial-utilized' => __( 'You already utilized a trial before.', 'freemius' ), + 'in-trial-mode' => __( 'You are already running the plugin in a trial mode.', 'freemius' ), + 'trial-plan-x-not-exist' => __( 'Plan %s do not exist, therefore, can\'t start a trial.', 'freemius' ), + 'plan-x-no-trial' => __( 'Plan %s does not support a trial period.', 'freemius' ), + 'no-trials' => __( 'None of the plugin\'s plans supports a trial period.', 'freemius' ), + 'unexpected-api-error' => __( 'Unexpected API error. Please contact the plugin\'s author with the following error.', 'freemius' ), + 'no-commitment-for-x-days' => __( 'No commitment for %s days - cancel anytime!', 'freemius' ), + 'license-expired-non-blocking-message' => __( 'Your license has expired. You can still continue using all the %s features, but you\'ll need to renew your license to continue getting updates and support.', 'freemius' ), + 'could-not-activate-x' => __( 'Couldn\'t activate %s.', 'freemius' ), + 'contact-us-with-error-message' => __( 'Please contact us with the following message:', 'freemius' ), + 'plan-did-not-change-message' => __( 'It looks like you are still on the %s plan. If you did upgrade or change your plan, it\'s probably an issue on our side - sorry.', 'freemius' ), + 'contact-us-here' => __( 'Please contact us here', 'freemius' ), + 'plan-did-not-change-email-message' => __( 'I have upgraded my account but when I try to Sync the License, the plan remains %s.', 'freemius' ), + #endregion Admin Notices + #region Connectivity Issues + 'connectivity-test-fails-message' => __( 'From unknown reason, the API connectivity test failed.', 'freemius' ), + 'connectivity-test-maybe-temporary' => __( 'It\'s probably a temporary issue on our end. Just to be sure, with your permission, would it be o.k to run another connectivity test?', 'freemius' ), + 'curl-missing-message' => __( 'We use PHP cURL library for the API calls, which is a very common library and usually installed out of the box. Unfortunately, cURL is not installed on your server.', 'freemius' ), + 'cloudflare-blocks-connection-message' => __( 'From unknown reason, CloudFlare, the firewall we use, blocks the connection.', 'freemius' ), + 'x-requires-access-to-api' => _x( '%s requires an access to our API.', 'as pluginX requires an access to our API', 'freemius' ), + 'squid-blocks-connection-message' => __( 'It looks like your server is using Squid ACL (access control lists), which blocks the connection.', 'freemius' ), + 'squid-no-clue-title' => __( 'I don\'t know what is Squid or ACL, help me!', 'freemius' ), + 'squid-no-clue-desc' => __( 'We\'ll make sure to contact your hosting company and resolve the issue. You will get a follow-up email to %s once we have an update.', 'freemius' ), + 'sysadmin-title' => __( 'I\'m a system administrator', 'freemius' ), + 'squid-sysadmin-desc' => __( 'Great, please whitelist the following domains: %s. Once you done, deactivate the plugin and activate it again.', 'freemius' ), + 'curl-missing-no-clue-title' => __( 'I don\'t know what is cURL or how to install it, help me!', 'freemius' ), + 'curl-missing-no-clue-desc' => __( 'We\'ll make sure to contact your hosting company and resolve the issue. You will get a follow-up email to %s once we have an update.', 'freemius' ), + 'curl-missing-sysadmin-desc' => __( 'Great, please install cURL and enable it in your php.ini file. To make sure it was successfully activated, use \'phpinfo()\'. Once activated, deactivate the plugin and reactivate it back again.', 'freemius' ), + 'happy-to-resolve-issue-asap' => __( 'We are sure it\'s an issue on our side and more than happy to resolve it for you ASAP if you give us a chance.', 'freemius' ), + 'fix-issue-title' => __( 'Yes - I\'m giving you a chance to fix it', 'freemius' ), + 'fix-issue-desc' => __( 'We will do our best to whitelist your server and resolve this issue ASAP. You will get a follow-up email to %s once we have an update.', 'freemius' ), + 'install-previous-title' => __( 'Let\'s try your previous version', 'freemius' ), + 'install-previous-desc' => __( 'Uninstall this version and install the previous one.', 'freemius' ), + 'deactivate-plugin-title' => __( 'That\'s exhausting, please deactivate', 'freemius' ), + 'deactivate-plugin-desc' => __( 'We feel your frustration and sincerely apologize for the inconvenience. Hope to see you again in the future.', 'freemius' ), + 'fix-request-sent-message' => __( 'Thank for giving us the chance to fix it! A message was just sent to our technical staff. We will get back to you as soon as we have an update to %s. Appreciate your patience.', 'freemius' ), + 'server-blocking-access' => _x( 'Your server is blocking the access to Freemius\' API, which is crucial for %1s synchronization. Please contact your host to whitelist %2s', '%1s - plugin title, %2s - API domain', 'freemius' ), + 'wrong-authentication-param-message' => __( 'It seems like one of the authentication parameters is wrong. Update your Public Key, Secret Key & User ID, and try again.', 'freemius' ), + #endregion Connectivity Issues + #region Change Owner + 'change-owner-request-sent-x' => __( 'Please check your mailbox, you should receive an email via %s to confirm the ownership change. From security reasons, you must confirm the change within the next 15 min. If you cannot find the email, please check your spam folder.', 'freemius' ), + 'change-owner-request_owner-confirmed' => __( 'Thanks for confirming the ownership change. An email was just sent to %s for final approval.', 'freemius' ), + 'change-owner-request_candidate-confirmed' => __( '%s is the new owner of the account.', 'freemius' ), + #endregion Change Owner + 'addon-x-cannot-run-without-y' => _x( '%s cannot run without %s.', 'addonX cannot run without pluginY', 'freemius' ), + 'addon-x-cannot-run-without-parent' => _x( '%s cannot run without the plugin.', 'addonX cannot run...', 'freemius' ), + 'plugin-x-activation-message' => _x( '%s activation was successfully completed.', 'pluginX activation was successfully...', 'freemius' ), + 'features-and-pricing' => _x( 'Features & Pricing', 'Plugin installer section title', 'freemius' ), + 'free-addon-not-deployed' => __( 'Add-on must be deployed to WordPress.org or Freemius.', 'freemius' ), + 'paid-addon-not-deployed' => __( 'Paid add-on must be deployed to Freemius.', 'freemius' ), + #region Add-On Licensing + 'addon-no-license-message' => __( '%s is a premium only add-on. You have to purchase a license first before activating the plugin.', 'freemius' ), + 'addon-trial-cancelled-message' => __( '%s free trial was successfully cancelled. Since the add-on is premium only it was automatically deactivated. If you like to use it in the future, you\'ll have to purchase a license.', 'freemius' ), + #endregion Add-On Licensing + #region Billing Cycles + 'monthly' => _x( 'Monthly', 'as every month', 'freemius' ), + 'mo' => _x( 'mo', 'as monthly period', 'freemius' ), + 'annual' => _x( 'Annual', 'as once a year', 'freemius' ), + 'annually' => _x( 'Annually', 'as once a year', 'freemius' ), + 'once' => _x( 'Once', 'as once a year', 'freemius' ), + 'year' => _x( 'year', 'as annual period', 'freemius' ), + 'lifetime' => __( 'Lifetime', 'freemius' ), + 'best' => _x( 'Best', 'e.g. the best product', 'freemius' ), + 'billed-x' => _x( 'Billed %s', 'e.g. billed monthly', 'freemius' ), + 'save-x' => _x( 'Save %s', 'as a discount of $5 or 10%', 'freemius' ), + #endregion Billing Cycles + 'view-details' => __( 'View details', 'freemius' ), + ); diff --git a/wp-content/plugins/nextgen-gallery/freemius/includes/managers/class-fs-admin-menu-manager.php b/wp-content/plugins/nextgen-gallery/freemius/includes/managers/class-fs-admin-menu-manager.php index cbc8000f7b4a5ab11e40b238c0e1431ad4f549e8..1f655b4da8c463f248a2cb6ec91d2a934aa1580a 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/includes/managers/class-fs-admin-menu-manager.php +++ b/wp-content/plugins/nextgen-gallery/freemius/includes/managers/class-fs-admin-menu-manager.php @@ -1,549 +1,549 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.1.3 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - class FS_Admin_Menu_Manager { - - #region Properties - - /** - * @var string - */ - protected $_plugin_slug; - - /** - * @since 1.0.6 - * - * @var string - */ - private $_menu_slug; - /** - * @since 1.1.3 - * - * @var string - */ - private $_parent_slug; - /** - * @since 1.1.3 - * - * @var string - */ - private $_parent_type; - /** - * @since 1.1.3 - * - * @var string - */ - private $_type; - /** - * @since 1.1.3 - * - * @var bool - */ - private $_is_top_level; - /** - * @since 1.1.3 - * - * @var bool - */ - private $_is_override_exact; - /** - * @since 1.1.3 - * - * @var string[]bool - */ - private $_default_submenu_items; - /** - * @since 1.1.3 - * - * @var string - */ - private $_first_time_path; - - #endregion Properties - - /** - * @var FS_Logger - */ - protected $_logger; - - #region Singleton - - /** - * @var FS_Admin_Menu_Manager[] - */ - private static $_instances = array(); - - /** - * @param string $plugin_slug - * - * @return FS_Admin_Notice_Manager - */ - static function instance( $plugin_slug ) { - if ( ! isset( self::$_instances[ $plugin_slug ] ) ) { - self::$_instances[ $plugin_slug ] = new FS_Admin_Menu_Manager( $plugin_slug ); - } - - return self::$_instances[ $plugin_slug ]; - } - - protected function __construct( $plugin_slug ) { - $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $plugin_slug . '_admin_menu', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); - - $this->_plugin_slug = $plugin_slug; - } - - #endregion Singleton - - #region Helpers - - private function get_option( &$options, $key, $default = false ) { - return ! empty( $options[ $key ] ) ? $options[ $key ] : $default; - } - - private function get_bool_option( &$options, $key, $default = false ) { - return isset( $options[ $key ] ) &&is_bool( $options[ $key ] ) ? $options[ $key ] : $default; - } - - #endregion Helpers - - /** - * @param array $menu - * @param bool $is_addon - */ - function init( $menu, $is_addon = false ) { - $this->_menu_slug = $menu['slug']; - - $this->_default_submenu_items = array(); - // @deprecated - $this->_type = 'page'; - $this->_is_top_level = true; - $this->_is_override_exact = false; - $this->_parent_slug = false; - // @deprecated - $this->_parent_type = 'page'; - - if ( ! $is_addon && isset( $menu ) ) { - $this->_default_submenu_items = array( - 'contact' => $this->get_bool_option( $menu, 'contact', true ), - 'support' => $this->get_bool_option( $menu, 'support', true ), - 'account' => $this->get_bool_option( $menu, 'account', true ), - 'pricing' => $this->get_bool_option( $menu, 'pricing', true ), - 'addons' => $this->get_bool_option( $menu, 'addons', true ), - ); - - // @deprecated - $this->_type = $this->get_option( $menu, 'type', 'page' ); - $this->_is_override_exact = $this->get_bool_option( $menu, 'override_exact' ); - - if ( isset( $menu['parent'] ) ) { - $this->_parent_slug = $this->get_option( $menu['parent'], 'slug' ); - // @deprecated - $this->_parent_type = $this->get_option( $menu['parent'], 'type', 'page' ); - - // If parent's slug is different, then it's NOT a top level menu item. - $this->_is_top_level = ( $this->_parent_slug === $this->_menu_slug ); - } else { - /** - * If no parent then top level if: - * - Has custom admin menu ('page') - * - CPT menu type ('cpt') - */ -// $this->_is_top_level = in_array( $this->_type, array( -// 'cpt', -// 'page' -// ) ); - } - - $this->_first_time_path = $this->get_option( $menu, 'first-path', false ); - if ( ! empty( $this->_first_time_path ) && is_string( $this->_first_time_path ) ) { - $this->_first_time_path = admin_url( $this->_first_time_path, 'admin' ); - } - } - } - - /** - * Check if top level menu. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.3 - * - * @return bool False if submenu item. - */ - function is_top_level() { - return $this->_is_top_level; - } - - /** - * Check if the page should be override on exact URL match. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.3 - * - * @return bool False if submenu item. - */ - function is_override_exact() { - return $this->_is_override_exact; - } - - - /** - * Get the path of the page the user should be forwarded to after first activation. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.3 - * - * @return string - */ - function get_first_time_path() { - return $this->_first_time_path; - } - - /** - * Check if plugin's menu item is part of a custom top level menu. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.3 - * - * @return bool - */ - function has_custom_parent() { - return ! $this->_is_top_level && is_string( $this->_parent_slug ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.3 - * - * @return string - */ -// function slug(){ -// return $this->_menu_slug; -// } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.3 - * - * @param string $id - * @param bool $default - * - * @return bool - */ - function is_submenu_item_visible( $id, $default = true ) { - return fs_apply_filter( - $this->_plugin_slug, - 'is_submenu_visible', - $this->get_bool_option( $this->_default_submenu_items, $id, $default ), - $id - ); - } - - /** - * Calculates admin settings menu slug. - * If plugin's menu slug is a file (e.g. CPT), uses plugin's slug as the menu slug. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.3 - * - * @param string $page - * - * @return string - */ - function get_slug( $page = '' ) { - return ( ( false === strpos( $this->_menu_slug, '.php?' ) ) ? - $this->_menu_slug : - $this->_plugin_slug ) . ( empty( $page ) ? '' : ( '-' . $page ) ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.3 - * - * @return string - */ - function get_parent_slug() { - return $this->_parent_slug; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.3 - * - * @return string - */ - function get_type() { - return $this->_type; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.3 - * - * @return bool - */ - function is_cpt() { - return ( 0 === strpos( $this->_menu_slug, 'edit.php?post_type=' ) || - // Back compatibility. - 'cpt' === $this->_type - ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.3 - * - * @return string - */ - function get_parent_type() { - return $this->_parent_type; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.3 - * - * @return string - */ - function get_raw_slug() { - return $this->_menu_slug; - } - - /** - * Get plugin's original menu slug. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.3 - * - * @return string - */ - function get_original_menu_slug() { - if ( 'cpt' === $this->_type ) { - return add_query_arg( array( - 'post_type' => $this->_menu_slug - ), 'edit.php' ); - } - - if ( false === strpos( $this->_menu_slug, '.php?' ) ) { - return $this->_menu_slug; - } else { - return $this->_plugin_slug; - } - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.3 - * - * @return string - */ - function get_top_level_menu_slug() { - return $this->has_custom_parent() ? - $this->get_parent_slug() : - $this->get_raw_slug(); - } - - /** - * Is user on plugin's admin activation page. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.8 - * - * @return bool - */ - function is_activation_page() { - return isset( $_GET['page'] ) && - ( ( strtolower( $this->_menu_slug ) === strtolower( $_GET['page'] ) ) || - ( strtolower( $this->_plugin_slug ) === strtolower( $_GET['page'] ) ) ); - } - - #region Submenu Override - - /** - * Override submenu's action. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.0 - * - * @param string $parent_slug - * @param string $menu_slug - * @param callable $function - * - * @return false|string If submenu exist, will return the hook name. - */ - function override_submenu_action( $parent_slug, $menu_slug, $function ) { - global $submenu; - - $menu_slug = plugin_basename( $menu_slug ); - $parent_slug = plugin_basename( $parent_slug ); - - if ( ! isset( $submenu[ $parent_slug ] ) ) { - // Parent menu not exist. - return false; - } - - $found_submenu_item = false; - foreach ( $submenu[ $parent_slug ] as $submenu_item ) { - if ( $menu_slug === $submenu_item[2] ) { - $found_submenu_item = $submenu_item; - break; - } - } - - if ( false === $found_submenu_item ) { - // Submenu item not found. - return false; - } - - // Remove current function. - $hookname = get_plugin_page_hookname( $menu_slug, $parent_slug ); - remove_all_actions( $hookname ); - - // Attach new action. - add_action( $hookname, $function ); - - return $hookname; - } - - #endregion Submenu Override - - #region Top level menu Override - - /** - * Find plugin's admin dashboard main menu item. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.2 - * - * @return string[]|false - */ - private function find_top_level_menu() { - global $menu; - - $position = - 1; - $found_menu = false; - - $menu_slug = $this->get_raw_slug(); - - $hook_name = get_plugin_page_hookname( $menu_slug, '' ); - foreach ( $menu as $pos => $m ) { - if ( $menu_slug === $m[2] ) { - $position = $pos; - $found_menu = $m; - break; - } - } - - if ( false === $found_menu ) { - return false; - } - - return array( - 'menu' => $found_menu, - 'position' => $position, - 'hook_name' => $hook_name - ); - } - - /** - * Remove all sub-menu items. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - * - * @return bool If submenu with plugin's menu slug was found. - */ - private function remove_all_submenu_items() { - global $submenu; - - $menu_slug = $this->get_raw_slug(); - - if ( ! isset( $submenu[ $menu_slug ] ) ) { - return false; - } - - $submenu[ $menu_slug ] = array(); - - return true; - } - - /** - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @return array[string]mixed - */ - function remove_menu_item() { - $this->_logger->entrance(); - - // Find main menu item. - $menu = $this->find_top_level_menu(); - - if ( false === $menu ) { - return false; - } - - // Remove it with its actions. - remove_all_actions( $menu['hook_name'] ); - - // Remove all submenu items. - $this->remove_all_submenu_items(); - - return $menu; - } - - /** - * - * @author Vova Feldman (@svovaf) - * @since 1.1.4 - * - * @param callable $function - * - * @return array[string]mixed - */ - function override_menu_item( $function ) { - $found_menu = $this->remove_menu_item(); - - if ( false === $found_menu ) { - return false; - } - - if ( ! $this->is_top_level() || ! $this->is_cpt() ) { - $menu_slug = plugin_basename( $this->get_slug() ); - - $hookname = get_plugin_page_hookname( $menu_slug, '' ); - - // Override menu action. - add_action( $hookname, $function ); - } else { - global $menu; - - // Create new top-level menu action. - $hookname = add_menu_page( - $found_menu['menu'][3], - $found_menu['menu'][0], - 'manage_options', - $this->get_slug(), - $function, - $found_menu['menu'][6], - $found_menu['position'] - ); - - // Remove original CPT menu. - unset( $menu[ $found_menu['position'] ] ); - } - - return $hookname; - } - - #endregion Top level menu Override +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.1.3 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + class FS_Admin_Menu_Manager { + + #region Properties + + /** + * @var string + */ + protected $_plugin_slug; + + /** + * @since 1.0.6 + * + * @var string + */ + private $_menu_slug; + /** + * @since 1.1.3 + * + * @var string + */ + private $_parent_slug; + /** + * @since 1.1.3 + * + * @var string + */ + private $_parent_type; + /** + * @since 1.1.3 + * + * @var string + */ + private $_type; + /** + * @since 1.1.3 + * + * @var bool + */ + private $_is_top_level; + /** + * @since 1.1.3 + * + * @var bool + */ + private $_is_override_exact; + /** + * @since 1.1.3 + * + * @var string[]bool + */ + private $_default_submenu_items; + /** + * @since 1.1.3 + * + * @var string + */ + private $_first_time_path; + + #endregion Properties + + /** + * @var FS_Logger + */ + protected $_logger; + + #region Singleton + + /** + * @var FS_Admin_Menu_Manager[] + */ + private static $_instances = array(); + + /** + * @param string $plugin_slug + * + * @return FS_Admin_Notice_Manager + */ + static function instance( $plugin_slug ) { + if ( ! isset( self::$_instances[ $plugin_slug ] ) ) { + self::$_instances[ $plugin_slug ] = new FS_Admin_Menu_Manager( $plugin_slug ); + } + + return self::$_instances[ $plugin_slug ]; + } + + protected function __construct( $plugin_slug ) { + $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $plugin_slug . '_admin_menu', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); + + $this->_plugin_slug = $plugin_slug; + } + + #endregion Singleton + + #region Helpers + + private function get_option( &$options, $key, $default = false ) { + return ! empty( $options[ $key ] ) ? $options[ $key ] : $default; + } + + private function get_bool_option( &$options, $key, $default = false ) { + return isset( $options[ $key ] ) &&is_bool( $options[ $key ] ) ? $options[ $key ] : $default; + } + + #endregion Helpers + + /** + * @param array $menu + * @param bool $is_addon + */ + function init( $menu, $is_addon = false ) { + $this->_menu_slug = $menu['slug']; + + $this->_default_submenu_items = array(); + // @deprecated + $this->_type = 'page'; + $this->_is_top_level = true; + $this->_is_override_exact = false; + $this->_parent_slug = false; + // @deprecated + $this->_parent_type = 'page'; + + if ( ! $is_addon && isset( $menu ) ) { + $this->_default_submenu_items = array( + 'contact' => $this->get_bool_option( $menu, 'contact', true ), + 'support' => $this->get_bool_option( $menu, 'support', true ), + 'account' => $this->get_bool_option( $menu, 'account', true ), + 'pricing' => $this->get_bool_option( $menu, 'pricing', true ), + 'addons' => $this->get_bool_option( $menu, 'addons', true ), + ); + + // @deprecated + $this->_type = $this->get_option( $menu, 'type', 'page' ); + $this->_is_override_exact = $this->get_bool_option( $menu, 'override_exact' ); + + if ( isset( $menu['parent'] ) ) { + $this->_parent_slug = $this->get_option( $menu['parent'], 'slug' ); + // @deprecated + $this->_parent_type = $this->get_option( $menu['parent'], 'type', 'page' ); + + // If parent's slug is different, then it's NOT a top level menu item. + $this->_is_top_level = ( $this->_parent_slug === $this->_menu_slug ); + } else { + /** + * If no parent then top level if: + * - Has custom admin menu ('page') + * - CPT menu type ('cpt') + */ +// $this->_is_top_level = in_array( $this->_type, array( +// 'cpt', +// 'page' +// ) ); + } + + $this->_first_time_path = $this->get_option( $menu, 'first-path', false ); + if ( ! empty( $this->_first_time_path ) && is_string( $this->_first_time_path ) ) { + $this->_first_time_path = admin_url( $this->_first_time_path, 'admin' ); + } + } + } + + /** + * Check if top level menu. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.3 + * + * @return bool False if submenu item. + */ + function is_top_level() { + return $this->_is_top_level; + } + + /** + * Check if the page should be override on exact URL match. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.3 + * + * @return bool False if submenu item. + */ + function is_override_exact() { + return $this->_is_override_exact; + } + + + /** + * Get the path of the page the user should be forwarded to after first activation. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.3 + * + * @return string + */ + function get_first_time_path() { + return $this->_first_time_path; + } + + /** + * Check if plugin's menu item is part of a custom top level menu. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.3 + * + * @return bool + */ + function has_custom_parent() { + return ! $this->_is_top_level && is_string( $this->_parent_slug ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.3 + * + * @return string + */ +// function slug(){ +// return $this->_menu_slug; +// } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.3 + * + * @param string $id + * @param bool $default + * + * @return bool + */ + function is_submenu_item_visible( $id, $default = true ) { + return fs_apply_filter( + $this->_plugin_slug, + 'is_submenu_visible', + $this->get_bool_option( $this->_default_submenu_items, $id, $default ), + $id + ); + } + + /** + * Calculates admin settings menu slug. + * If plugin's menu slug is a file (e.g. CPT), uses plugin's slug as the menu slug. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.3 + * + * @param string $page + * + * @return string + */ + function get_slug( $page = '' ) { + return ( ( false === strpos( $this->_menu_slug, '.php?' ) ) ? + $this->_menu_slug : + $this->_plugin_slug ) . ( empty( $page ) ? '' : ( '-' . $page ) ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.3 + * + * @return string + */ + function get_parent_slug() { + return $this->_parent_slug; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.3 + * + * @return string + */ + function get_type() { + return $this->_type; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.3 + * + * @return bool + */ + function is_cpt() { + return ( 0 === strpos( $this->_menu_slug, 'edit.php?post_type=' ) || + // Back compatibility. + 'cpt' === $this->_type + ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.3 + * + * @return string + */ + function get_parent_type() { + return $this->_parent_type; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.3 + * + * @return string + */ + function get_raw_slug() { + return $this->_menu_slug; + } + + /** + * Get plugin's original menu slug. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.3 + * + * @return string + */ + function get_original_menu_slug() { + if ( 'cpt' === $this->_type ) { + return add_query_arg( array( + 'post_type' => $this->_menu_slug + ), 'edit.php' ); + } + + if ( false === strpos( $this->_menu_slug, '.php?' ) ) { + return $this->_menu_slug; + } else { + return $this->_plugin_slug; + } + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.3 + * + * @return string + */ + function get_top_level_menu_slug() { + return $this->has_custom_parent() ? + $this->get_parent_slug() : + $this->get_raw_slug(); + } + + /** + * Is user on plugin's admin activation page. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.8 + * + * @return bool + */ + function is_activation_page() { + return isset( $_GET['page'] ) && + ( ( strtolower( $this->_menu_slug ) === strtolower( $_GET['page'] ) ) || + ( strtolower( $this->_plugin_slug ) === strtolower( $_GET['page'] ) ) ); + } + + #region Submenu Override + + /** + * Override submenu's action. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.0 + * + * @param string $parent_slug + * @param string $menu_slug + * @param callable $function + * + * @return false|string If submenu exist, will return the hook name. + */ + function override_submenu_action( $parent_slug, $menu_slug, $function ) { + global $submenu; + + $menu_slug = plugin_basename( $menu_slug ); + $parent_slug = plugin_basename( $parent_slug ); + + if ( ! isset( $submenu[ $parent_slug ] ) ) { + // Parent menu not exist. + return false; + } + + $found_submenu_item = false; + foreach ( $submenu[ $parent_slug ] as $submenu_item ) { + if ( $menu_slug === $submenu_item[2] ) { + $found_submenu_item = $submenu_item; + break; + } + } + + if ( false === $found_submenu_item ) { + // Submenu item not found. + return false; + } + + // Remove current function. + $hookname = get_plugin_page_hookname( $menu_slug, $parent_slug ); + remove_all_actions( $hookname ); + + // Attach new action. + add_action( $hookname, $function ); + + return $hookname; + } + + #endregion Submenu Override + + #region Top level menu Override + + /** + * Find plugin's admin dashboard main menu item. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.2 + * + * @return string[]|false + */ + private function find_top_level_menu() { + global $menu; + + $position = - 1; + $found_menu = false; + + $menu_slug = $this->get_raw_slug(); + + $hook_name = get_plugin_page_hookname( $menu_slug, '' ); + foreach ( $menu as $pos => $m ) { + if ( $menu_slug === $m[2] ) { + $position = $pos; + $found_menu = $m; + break; + } + } + + if ( false === $found_menu ) { + return false; + } + + return array( + 'menu' => $found_menu, + 'position' => $position, + 'hook_name' => $hook_name + ); + } + + /** + * Remove all sub-menu items. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + * + * @return bool If submenu with plugin's menu slug was found. + */ + private function remove_all_submenu_items() { + global $submenu; + + $menu_slug = $this->get_raw_slug(); + + if ( ! isset( $submenu[ $menu_slug ] ) ) { + return false; + } + + $submenu[ $menu_slug ] = array(); + + return true; + } + + /** + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @return array[string]mixed + */ + function remove_menu_item() { + $this->_logger->entrance(); + + // Find main menu item. + $menu = $this->find_top_level_menu(); + + if ( false === $menu ) { + return false; + } + + // Remove it with its actions. + remove_all_actions( $menu['hook_name'] ); + + // Remove all submenu items. + $this->remove_all_submenu_items(); + + return $menu; + } + + /** + * + * @author Vova Feldman (@svovaf) + * @since 1.1.4 + * + * @param callable $function + * + * @return array[string]mixed + */ + function override_menu_item( $function ) { + $found_menu = $this->remove_menu_item(); + + if ( false === $found_menu ) { + return false; + } + + if ( ! $this->is_top_level() || ! $this->is_cpt() ) { + $menu_slug = plugin_basename( $this->get_slug() ); + + $hookname = get_plugin_page_hookname( $menu_slug, '' ); + + // Override menu action. + add_action( $hookname, $function ); + } else { + global $menu; + + // Create new top-level menu action. + $hookname = add_menu_page( + $found_menu['menu'][3], + $found_menu['menu'][0], + 'manage_options', + $this->get_slug(), + $function, + $found_menu['menu'][6], + $found_menu['position'] + ); + + // Remove original CPT menu. + unset( $menu[ $found_menu['position'] ] ); + } + + return $hookname; + } + + #endregion Top level menu Override } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/includes/managers/class-fs-admin-notice-manager.php b/wp-content/plugins/nextgen-gallery/freemius/includes/managers/class-fs-admin-notice-manager.php index 67e0e47c5b0a72d7d3349e35d313afa6bb3fcdaf..be94dbfc38b2094a751e6f93bea07b937a0e5147 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/includes/managers/class-fs-admin-notice-manager.php +++ b/wp-content/plugins/nextgen-gallery/freemius/includes/managers/class-fs-admin-notice-manager.php @@ -1,310 +1,310 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.7 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - class FS_Admin_Notice_Manager { - /** - * @var string - */ - protected $_slug; - /** - * @var string - */ - protected $_title; - /** - * @var array[] - */ - private $_admin_messages = array(); - /** - * @var FS_Key_Value_Storage - */ - private $_sticky_storage; - /** - * @var FS_Plugin_Manager[] - */ - private static $_instances = array(); - /** - * @var FS_Logger - */ - protected $_logger; - - /** - * @param string $slug - * @param string $title - * - * @return FS_Admin_Notice_Manager - */ - static function instance( $slug, $title = '' ) { - if ( ! isset( self::$_instances[ $slug ] ) ) { - self::$_instances[ $slug ] = new FS_Admin_Notice_Manager( $slug, $title ); - } - - return self::$_instances[ $slug ]; - } - - protected function __construct( $slug, $title = '' ) { - $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $slug . '_data', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); - - $this->_slug = $slug; - $this->_title = ! empty( $title ) ? $title : ''; - $this->_sticky_storage = FS_Key_Value_Storage::instance( 'admin_notices', $this->_slug ); - - if ( is_admin() ) { - if ( 0 < count( $this->_sticky_storage ) ) { - // If there are sticky notices for the current slug, add a callback - // to the AJAX action that handles message dismiss. - add_action( "wp_ajax_{$slug}_dismiss_notice_action", array( - &$this, - 'dismiss_notice_ajax_callback' - ) ); - - foreach ( $this->_sticky_storage as $id => $msg ) { - // Add admin notice. - $this->add( - $msg['message'], - $msg['title'], - $msg['type'], - true, - $msg['all'], - $msg['id'], - false - ); - } - } - } - } - - /** - * Remove sticky message by ID. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - * - */ - function dismiss_notice_ajax_callback() { - $this->_sticky_storage->remove( $_POST['message_id'] ); - wp_die(); - } - - /** - * Rendered sticky message dismiss JavaScript. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - */ - static function _add_sticky_dismiss_javascript() { - $params = array(); - fs_require_once_template( 'sticky-admin-notice-js.php', $params ); - } - - private static $_added_sticky_javascript = false; - - /** - * Hook to the admin_footer to add sticky message dismiss JavaScript handler. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - */ - private static function has_sticky_messages() { - if ( ! self::$_added_sticky_javascript ) { - add_action( 'admin_footer', array( 'FS_Admin_Notice_Manager', '_add_sticky_dismiss_javascript' ) ); - } - } - - /** - * Handle admin_notices by printing the admin messages stacked in the queue. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - * - */ - function _admin_notices_hook() { - $notice_type = 'admin_notices'; - - if ( function_exists( 'current_user_can' ) && - ! current_user_can( 'manage_options' ) - ) { - // Only show messages to admins. - return; - } - - if ( ! isset( $this->_admin_messages[ $notice_type ] ) || ! is_array( $this->_admin_messages[ $notice_type ] ) ) { - return; - } - - foreach ( $this->_admin_messages[ $notice_type ] as $id => $msg ) { - fs_require_template( 'admin-notice.php', $msg ); - - if ( $msg['sticky'] ) { - self::has_sticky_messages(); - } - } - } - - /** - * Handle all_admin_notices by printing the admin messages stacked in the queue. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - * - */ - function _all_admin_notices_hook() { - $notice_type = 'all_admin_notices'; - - if ( ! isset( $this->_admin_messages[ $notice_type ] ) || ! is_array( $this->_admin_messages[ $notice_type ] ) ) { - return; - } - - foreach ( $this->_admin_messages[ $notice_type ] as $id => $msg ) { - fs_require_template( 'all-admin-notice.php', $msg ); - } - } - - /** - * Enqueue common stylesheet to style admin notice. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - */ - function _enqueue_styles() { - fs_enqueue_local_style( 'fs_common', '/admin/common.css' ); - } - - /** - * Add admin message to admin messages queue, and hook to admin_notices / all_admin_notices if not yet hooked. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - * - * @param string $message - * @param string $title - * @param string $type - * @param bool $is_sticky - * @param bool $all_admin - * @param string $id Message ID - * @param bool $store_if_sticky - * - * @uses add_action() - */ - function add( $message, $title = '', $type = 'success', $is_sticky = false, $all_admin = false, $id = '', $store_if_sticky = true ) { - $key = ( $all_admin ? 'all_admin_notices' : 'admin_notices' ); - - if ( ! isset( $this->_admin_messages[ $key ] ) ) { - $this->_admin_messages[ $key ] = array(); - - add_action( $key, array( &$this, "_{$key}_hook" ) ); - add_action( 'admin_enqueue_scripts', array( &$this, '_enqueue_styles' ) ); - - } - - if ( '' === $id ) { - $id = md5( $title . ' ' . $message . ' ' . $type ); - } - - $message_object = array( - 'message' => $message, - 'title' => $title, - 'type' => $type, - 'sticky' => $is_sticky, - 'id' => $id, - 'all' => $all_admin, - 'slug' => $this->_slug, - 'plugin' => $this->_title, - ); - - if ( $is_sticky && $store_if_sticky ) { - $this->_sticky_storage->{$id} = $message_object; - } - - $this->_admin_messages[ $key ][ $id ] = $message_object; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - * - * @param string $ids - */ - function remove_sticky( $ids ) { - if ( ! is_array( $ids ) ) { - $ids = array( $ids ); - } - - foreach ( $ids as $id ) { - // Remove from sticky storage. - $this->_sticky_storage->remove( $id ); - - // Remove from current admin messages. - if ( isset( $this->_admin_messages['all_admin_notices'] ) && isset( $this->_admin_messages['all_admin_notices'][ $id ] ) ) { - unset( $this->_admin_messages['all_admin_notices'][ $id ] ); - } - if ( isset( $this->_admin_messages['admin_notices'] ) && isset( $this->_admin_messages['admin_notices'][ $id ] ) ) { - unset( $this->_admin_messages['admin_notices'][ $id ] ); - } - } - } - - /** - * Check if sticky message exists by id. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @param $id - * - * @return bool - */ - function has_sticky( $id ) { - return isset( $this->_sticky_storage[ $id ] ); - } - - /** - * Adds sticky admin notification. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - * - * @param string $message - * @param string $id Message ID - * @param string $title - * @param string $type - * @param bool $all_admin - */ - function add_sticky( $message, $id, $title = '', $type = 'success', $all_admin = false ) { - $this->add( $message, $title, $type, true, $all_admin, $id ); - } - - /** - * Clear all sticky messages. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.8 - */ - function clear_all_sticky() { - $this->_sticky_storage->clear_all(); - } - - /** - * Add admin message to all admin messages queue, and hook to all_admin_notices if not yet hooked. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.4 - * - * @param string $message - * @param string $title - * @param string $type - * @param bool $is_sticky - * @param string $id Message ID - */ - function add_all( $message, $title = '', $type = 'success', $is_sticky = false, $id = '' ) { - $this->add( $message, $title, $type, $is_sticky, true, $id ); - } +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.7 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + class FS_Admin_Notice_Manager { + /** + * @var string + */ + protected $_slug; + /** + * @var string + */ + protected $_title; + /** + * @var array[] + */ + private $_admin_messages = array(); + /** + * @var FS_Key_Value_Storage + */ + private $_sticky_storage; + /** + * @var FS_Plugin_Manager[] + */ + private static $_instances = array(); + /** + * @var FS_Logger + */ + protected $_logger; + + /** + * @param string $slug + * @param string $title + * + * @return FS_Admin_Notice_Manager + */ + static function instance( $slug, $title = '' ) { + if ( ! isset( self::$_instances[ $slug ] ) ) { + self::$_instances[ $slug ] = new FS_Admin_Notice_Manager( $slug, $title ); + } + + return self::$_instances[ $slug ]; + } + + protected function __construct( $slug, $title = '' ) { + $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $slug . '_data', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); + + $this->_slug = $slug; + $this->_title = ! empty( $title ) ? $title : ''; + $this->_sticky_storage = FS_Key_Value_Storage::instance( 'admin_notices', $this->_slug ); + + if ( is_admin() ) { + if ( 0 < count( $this->_sticky_storage ) ) { + // If there are sticky notices for the current slug, add a callback + // to the AJAX action that handles message dismiss. + add_action( "wp_ajax_{$slug}_dismiss_notice_action", array( + &$this, + 'dismiss_notice_ajax_callback' + ) ); + + foreach ( $this->_sticky_storage as $id => $msg ) { + // Add admin notice. + $this->add( + $msg['message'], + $msg['title'], + $msg['type'], + true, + $msg['all'], + $msg['id'], + false + ); + } + } + } + } + + /** + * Remove sticky message by ID. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + * + */ + function dismiss_notice_ajax_callback() { + $this->_sticky_storage->remove( $_POST['message_id'] ); + wp_die(); + } + + /** + * Rendered sticky message dismiss JavaScript. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + */ + static function _add_sticky_dismiss_javascript() { + $params = array(); + fs_require_once_template( 'sticky-admin-notice-js.php', $params ); + } + + private static $_added_sticky_javascript = false; + + /** + * Hook to the admin_footer to add sticky message dismiss JavaScript handler. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + */ + private static function has_sticky_messages() { + if ( ! self::$_added_sticky_javascript ) { + add_action( 'admin_footer', array( 'FS_Admin_Notice_Manager', '_add_sticky_dismiss_javascript' ) ); + } + } + + /** + * Handle admin_notices by printing the admin messages stacked in the queue. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + * + */ + function _admin_notices_hook() { + $notice_type = 'admin_notices'; + + if ( function_exists( 'current_user_can' ) && + ! current_user_can( 'manage_options' ) + ) { + // Only show messages to admins. + return; + } + + if ( ! isset( $this->_admin_messages[ $notice_type ] ) || ! is_array( $this->_admin_messages[ $notice_type ] ) ) { + return; + } + + foreach ( $this->_admin_messages[ $notice_type ] as $id => $msg ) { + fs_require_template( 'admin-notice.php', $msg ); + + if ( $msg['sticky'] ) { + self::has_sticky_messages(); + } + } + } + + /** + * Handle all_admin_notices by printing the admin messages stacked in the queue. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + * + */ + function _all_admin_notices_hook() { + $notice_type = 'all_admin_notices'; + + if ( ! isset( $this->_admin_messages[ $notice_type ] ) || ! is_array( $this->_admin_messages[ $notice_type ] ) ) { + return; + } + + foreach ( $this->_admin_messages[ $notice_type ] as $id => $msg ) { + fs_require_template( 'all-admin-notice.php', $msg ); + } + } + + /** + * Enqueue common stylesheet to style admin notice. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + */ + function _enqueue_styles() { + fs_enqueue_local_style( 'fs_common', '/admin/common.css' ); + } + + /** + * Add admin message to admin messages queue, and hook to admin_notices / all_admin_notices if not yet hooked. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + * + * @param string $message + * @param string $title + * @param string $type + * @param bool $is_sticky + * @param bool $all_admin + * @param string $id Message ID + * @param bool $store_if_sticky + * + * @uses add_action() + */ + function add( $message, $title = '', $type = 'success', $is_sticky = false, $all_admin = false, $id = '', $store_if_sticky = true ) { + $key = ( $all_admin ? 'all_admin_notices' : 'admin_notices' ); + + if ( ! isset( $this->_admin_messages[ $key ] ) ) { + $this->_admin_messages[ $key ] = array(); + + add_action( $key, array( &$this, "_{$key}_hook" ) ); + add_action( 'admin_enqueue_scripts', array( &$this, '_enqueue_styles' ) ); + + } + + if ( '' === $id ) { + $id = md5( $title . ' ' . $message . ' ' . $type ); + } + + $message_object = array( + 'message' => $message, + 'title' => $title, + 'type' => $type, + 'sticky' => $is_sticky, + 'id' => $id, + 'all' => $all_admin, + 'slug' => $this->_slug, + 'plugin' => $this->_title, + ); + + if ( $is_sticky && $store_if_sticky ) { + $this->_sticky_storage->{$id} = $message_object; + } + + $this->_admin_messages[ $key ][ $id ] = $message_object; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + * + * @param string $ids + */ + function remove_sticky( $ids ) { + if ( ! is_array( $ids ) ) { + $ids = array( $ids ); + } + + foreach ( $ids as $id ) { + // Remove from sticky storage. + $this->_sticky_storage->remove( $id ); + + // Remove from current admin messages. + if ( isset( $this->_admin_messages['all_admin_notices'] ) && isset( $this->_admin_messages['all_admin_notices'][ $id ] ) ) { + unset( $this->_admin_messages['all_admin_notices'][ $id ] ); + } + if ( isset( $this->_admin_messages['admin_notices'] ) && isset( $this->_admin_messages['admin_notices'][ $id ] ) ) { + unset( $this->_admin_messages['admin_notices'][ $id ] ); + } + } + } + + /** + * Check if sticky message exists by id. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @param $id + * + * @return bool + */ + function has_sticky( $id ) { + return isset( $this->_sticky_storage[ $id ] ); + } + + /** + * Adds sticky admin notification. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + * + * @param string $message + * @param string $id Message ID + * @param string $title + * @param string $type + * @param bool $all_admin + */ + function add_sticky( $message, $id, $title = '', $type = 'success', $all_admin = false ) { + $this->add( $message, $title, $type, true, $all_admin, $id ); + } + + /** + * Clear all sticky messages. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.8 + */ + function clear_all_sticky() { + $this->_sticky_storage->clear_all(); + } + + /** + * Add admin message to all admin messages queue, and hook to all_admin_notices if not yet hooked. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.4 + * + * @param string $message + * @param string $title + * @param string $type + * @param bool $is_sticky + * @param string $id Message ID + */ + function add_all( $message, $title = '', $type = 'success', $is_sticky = false, $id = '' ) { + $this->add( $message, $title, $type, $is_sticky, true, $id ); + } } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/includes/managers/class-fs-cache-manager.php b/wp-content/plugins/nextgen-gallery/freemius/includes/managers/class-fs-cache-manager.php index 595f49848f208ed072b248177c7f625d7a5e3f6f..4868e726f6e436d8e2f8b569fe324d5dfba2a4ef 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/includes/managers/class-fs-cache-manager.php +++ b/wp-content/plugins/nextgen-gallery/freemius/includes/managers/class-fs-cache-manager.php @@ -1,237 +1,237 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.1.6 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - class FS_Cache_Manager { - /** - * @var FS_Option_Manager - */ - private $_options; - /** - * @var FS_Logger - */ - private $_logger; - - /** - * @var FS_Cache_Manager[] - */ - private static $_MANAGERS = array(); - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.3 - * - * @param string $id - */ - private function __construct( $id ) { - $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_cach_mngr_' . $id, WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); - - $this->_logger->entrance(); - $this->_logger->log( 'id = ' . $id ); - - $this->_options = FS_Option_Manager::get_manager( $id, true ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.6 - * - * @param $id - * - * @return FS_Cache_Manager - */ - static function get_manager( $id ) { - $id = strtolower( $id ); - - if ( ! isset( self::$_MANAGERS[ $id ] ) ) { - self::$_MANAGERS[ $id ] = new FS_Cache_Manager( $id ); - } - - return self::$_MANAGERS[ $id ]; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.6 - * - * @return bool - */ - function is_empty() { - $this->_logger->entrance(); - - return $this->_options->is_empty(); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.6 - */ - function clear() { - $this->_logger->entrance(); - - $this->_options->clear( true ); - } - - /** - * Delete cache manager from DB. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - */ - function delete() { - $this->_options->delete(); - } - - /** - * Check if there's a cached item. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.6 - * - * @param string $key - * - * @return bool - */ - function has( $key ) { - $cache_entry = $this->_options->get_option( $key, false ); - - return ( is_object( $cache_entry ) && - isset( $cache_entry->timestamp ) && - is_numeric( $cache_entry->timestamp ) - ); - } - - /** - * Check if there's a valid cached item. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.6 - * - * @param string $key - * - * @return bool - */ - function has_valid( $key ) { - $cache_entry = $this->_options->get_option( $key, false ); - - return ( is_object( $cache_entry ) && - isset( $cache_entry->timestamp ) && - is_numeric( $cache_entry->timestamp ) && - $cache_entry->timestamp > WP_FS__SCRIPT_START_TIME - ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.6 - * - * @param string $key - * @param mixed $default - * - * @return mixed - */ - function get( $key, $default = null ) { - $this->_logger->entrance( 'key = ' . $key ); - - $cache_entry = $this->_options->get_option( $key, false ); - - if ( is_object( $cache_entry ) && - isset( $cache_entry->timestamp ) && - is_numeric( $cache_entry->timestamp ) - ) { - return $cache_entry->result; - } - - return $default; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.6 - * - * @param string $key - * @param mixed $default - * - * @return mixed - */ - function get_valid( $key, $default = null ) { - $this->_logger->entrance( 'key = ' . $key ); - - $cache_entry = $this->_options->get_option( $key, false ); - - if ( is_object( $cache_entry ) && - isset( $cache_entry->timestamp ) && - is_numeric( $cache_entry->timestamp ) && - $cache_entry->timestamp > WP_FS__SCRIPT_START_TIME - ) { - return $cache_entry->result; - } - - return $default; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.1.6 - * - * @param string $key - * @param mixed $value - * @param int $expiration - */ - function set( $key, $value, $expiration = WP_FS__TIME_24_HOURS_IN_SEC ) { - $this->_logger->entrance( 'key = ' . $key ); - - $cache_entry = new stdClass(); - $cache_entry->result = $value; - $cache_entry->timestamp = WP_FS__SCRIPT_START_TIME + $expiration; - $this->_options->set_option( $key, $cache_entry, true ); - } - - /** - * Get cached record expiration, or false if not cached or expired. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.7.3 - * - * @param string $key - * - * @return bool|int - */ - function get_record_expiration( $key ) { - $this->_logger->entrance( 'key = ' . $key ); - - $cache_entry = $this->_options->get_option( $key, false ); - - if ( is_object( $cache_entry ) && - isset( $cache_entry->timestamp ) && - is_numeric( $cache_entry->timestamp ) && - $cache_entry->timestamp > WP_FS__SCRIPT_START_TIME - ) { - return $cache_entry->timestamp; - } - - return false; - } - - /** - * Purge cached item. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.6 - * - * @param string $key - */ - function purge( $key ) { - $this->_logger->entrance( 'key = ' . $key ); - - $this->_options->unset_option( $key, true ); - } +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.1.6 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + class FS_Cache_Manager { + /** + * @var FS_Option_Manager + */ + private $_options; + /** + * @var FS_Logger + */ + private $_logger; + + /** + * @var FS_Cache_Manager[] + */ + private static $_MANAGERS = array(); + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.3 + * + * @param string $id + */ + private function __construct( $id ) { + $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_cach_mngr_' . $id, WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); + + $this->_logger->entrance(); + $this->_logger->log( 'id = ' . $id ); + + $this->_options = FS_Option_Manager::get_manager( $id, true ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.6 + * + * @param $id + * + * @return FS_Cache_Manager + */ + static function get_manager( $id ) { + $id = strtolower( $id ); + + if ( ! isset( self::$_MANAGERS[ $id ] ) ) { + self::$_MANAGERS[ $id ] = new FS_Cache_Manager( $id ); + } + + return self::$_MANAGERS[ $id ]; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.6 + * + * @return bool + */ + function is_empty() { + $this->_logger->entrance(); + + return $this->_options->is_empty(); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.6 + */ + function clear() { + $this->_logger->entrance(); + + $this->_options->clear( true ); + } + + /** + * Delete cache manager from DB. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + */ + function delete() { + $this->_options->delete(); + } + + /** + * Check if there's a cached item. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.6 + * + * @param string $key + * + * @return bool + */ + function has( $key ) { + $cache_entry = $this->_options->get_option( $key, false ); + + return ( is_object( $cache_entry ) && + isset( $cache_entry->timestamp ) && + is_numeric( $cache_entry->timestamp ) + ); + } + + /** + * Check if there's a valid cached item. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.6 + * + * @param string $key + * + * @return bool + */ + function has_valid( $key ) { + $cache_entry = $this->_options->get_option( $key, false ); + + return ( is_object( $cache_entry ) && + isset( $cache_entry->timestamp ) && + is_numeric( $cache_entry->timestamp ) && + $cache_entry->timestamp > WP_FS__SCRIPT_START_TIME + ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.6 + * + * @param string $key + * @param mixed $default + * + * @return mixed + */ + function get( $key, $default = null ) { + $this->_logger->entrance( 'key = ' . $key ); + + $cache_entry = $this->_options->get_option( $key, false ); + + if ( is_object( $cache_entry ) && + isset( $cache_entry->timestamp ) && + is_numeric( $cache_entry->timestamp ) + ) { + return $cache_entry->result; + } + + return $default; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.6 + * + * @param string $key + * @param mixed $default + * + * @return mixed + */ + function get_valid( $key, $default = null ) { + $this->_logger->entrance( 'key = ' . $key ); + + $cache_entry = $this->_options->get_option( $key, false ); + + if ( is_object( $cache_entry ) && + isset( $cache_entry->timestamp ) && + is_numeric( $cache_entry->timestamp ) && + $cache_entry->timestamp > WP_FS__SCRIPT_START_TIME + ) { + return $cache_entry->result; + } + + return $default; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.1.6 + * + * @param string $key + * @param mixed $value + * @param int $expiration + */ + function set( $key, $value, $expiration = WP_FS__TIME_24_HOURS_IN_SEC ) { + $this->_logger->entrance( 'key = ' . $key ); + + $cache_entry = new stdClass(); + $cache_entry->result = $value; + $cache_entry->timestamp = WP_FS__SCRIPT_START_TIME + $expiration; + $this->_options->set_option( $key, $cache_entry, true ); + } + + /** + * Get cached record expiration, or false if not cached or expired. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.7.3 + * + * @param string $key + * + * @return bool|int + */ + function get_record_expiration( $key ) { + $this->_logger->entrance( 'key = ' . $key ); + + $cache_entry = $this->_options->get_option( $key, false ); + + if ( is_object( $cache_entry ) && + isset( $cache_entry->timestamp ) && + is_numeric( $cache_entry->timestamp ) && + $cache_entry->timestamp > WP_FS__SCRIPT_START_TIME + ) { + return $cache_entry->timestamp; + } + + return false; + } + + /** + * Purge cached item. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.6 + * + * @param string $key + */ + function purge( $key ) { + $this->_logger->entrance( 'key = ' . $key ); + + $this->_options->unset_option( $key, true ); + } } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/includes/managers/class-fs-key-value-storage.php b/wp-content/plugins/nextgen-gallery/freemius/includes/managers/class-fs-key-value-storage.php index 17f8d15f413e9545d4fe7cc78ab1ca7d758a7b47..f2d73719d1d454125ad6b27a185cfcf9e9116752 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/includes/managers/class-fs-key-value-storage.php +++ b/wp-content/plugins/nextgen-gallery/freemius/includes/managers/class-fs-key-value-storage.php @@ -1,295 +1,295 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.7 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - class FS_Key_Value_Storage implements ArrayAccess, Iterator, Countable { - /** - * @var string - */ - protected $_id; - /** - * @var string - */ - protected $_slug; - /** - * @var array - */ - protected $_data; - - /** - * @var FS_Plugin_Manager[] - */ - private static $_instances = array(); - /** - * @var FS_Logger - */ - protected $_logger; - - /** - * @param string $id - * @param string $slug - * - * @return FS_Key_Value_Storage - */ - static function instance( $id, $slug ) { - $key = $id . ':' . $slug; - if ( ! isset( self::$_instances[ $key ] ) ) { - self::$_instances[ $key ] = new FS_Key_Value_Storage( $id, $slug ); - } - - return self::$_instances[ $key ]; - } - - protected function __construct( $id, $slug ) { - $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $slug . '_' . $id, WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); - - $this->_slug = $slug; - $this->_id = $id; - $this->load(); - } - - protected function get_option_manager() { - return FS_Option_Manager::get_manager( WP_FS__ACCOUNTS_OPTION_NAME, true ); - } - - protected function get_all_data() { - return $this->get_option_manager()->get_option( $this->_id, array() ); - } - - /** - * Load plugin data from local DB. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - */ - function load() { - $all_plugins_data = $this->get_all_data(); - $this->_data = isset( $all_plugins_data[ $this->_slug ] ) ? - $all_plugins_data[ $this->_slug ] : - array(); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - * - * @param string $key - * @param mixed $value - * @param bool $flush - */ - function store( $key, $value, $flush = true ) { - if ( $this->_logger->is_on() ) { - $this->_logger->entrance( $key . ' = ' . var_export( $value, true ) ); - } - - if ( array_key_exists( $key, $this->_data ) && $value === $this->_data[ $key ] ) { - // No need to store data if the value wasn't changed. - return; - } - - $all_data = $this->get_all_data(); - - $this->_data[ $key ] = $value; - - $all_data[ $this->_slug ] = $this->_data; - - $options_manager = $this->get_option_manager(); - $options_manager->set_option( $this->_id, $all_data, $flush ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - * - * @param bool $store - * @param string[] $exceptions Set of keys to keep and not clear. - */ - function clear_all( $store = true, $exceptions = array() ) { - $new_data = array(); - foreach ( $exceptions as $key ) { - if ( isset( $this->_data[ $key ] ) ) { - $new_data[ $key ] = $this->_data[ $key ]; - } - } - - $this->_data = $new_data; - - if ( $store ) { - $all_data = $this->get_all_data(); - $all_data[ $this->_slug ] = $this->_data; - $options_manager = $this->get_option_manager(); - $options_manager->set_option( $this->_id, $all_data, true ); - } - } - - /** - * Delete key-value storage. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - */ - function delete() { - $this->_data = array(); - - $all_data = $this->get_all_data(); - unset( $all_data[ $this->_slug ] ); - $options_manager = $this->get_option_manager(); - $options_manager->set_option( $this->_id, $all_data, true ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - * - * @param string $key - * @param bool $store - */ - function remove( $key, $store = true ) { - if ( ! array_key_exists( $key, $this->_data ) ) { - return; - } - - unset( $this->_data[ $key ] ); - - if ( $store ) { - $all_data = $this->get_all_data(); - $all_data[ $this->_slug ] = $this->_data; - $options_manager = $this->get_option_manager(); - $options_manager->set_option( $this->_id, $all_data, true ); - } - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - * - * @param string $key - * @param mixed $default - * - * @return bool|\FS_Plugin - */ - function get( $key, $default = false ) { - return array_key_exists( $key, $this->_data ) ? - $this->_data[ $key ] : - $default; - } - - - /* ArrayAccess + Magic Access (better for refactoring) - -----------------------------------------------------------------------------------*/ - function __set( $k, $v ) { - $this->store( $k, $v ); - } - - function __isset( $k ) { - return array_key_exists( $k, $this->_data ); - } - - function __unset( $k ) { - $this->remove( $k ); - } - - function __get( $k ) { - return $this->get( $k, null ); - } - - function offsetSet( $k, $v ) { - if ( is_null( $k ) ) { - throw new Exception( 'Can\'t append value to request params.' ); - } else { - $this->{$k} = $v; - } - } - - function offsetExists( $k ) { - return array_key_exists( $k, $this->_data ); - } - - function offsetUnset( $k ) { - unset( $this->$k ); - } - - function offsetGet( $k ) { - return $this->get( $k, null ); - } - - /** - * (PHP 5 >= 5.0.0)<br/> - * Return the current element - * - * @link http://php.net/manual/en/iterator.current.php - * @return mixed Can return any type. - */ - public function current() { - return current( $this->_data ); - } - - /** - * (PHP 5 >= 5.0.0)<br/> - * Move forward to next element - * - * @link http://php.net/manual/en/iterator.next.php - * @return void Any returned value is ignored. - */ - public function next() { - next( $this->_data ); - } - - /** - * (PHP 5 >= 5.0.0)<br/> - * Return the key of the current element - * - * @link http://php.net/manual/en/iterator.key.php - * @return mixed scalar on success, or null on failure. - */ - public function key() { - return key( $this->_data ); - } - - /** - * (PHP 5 >= 5.0.0)<br/> - * Checks if current position is valid - * - * @link http://php.net/manual/en/iterator.valid.php - * @return boolean The return value will be casted to boolean and then evaluated. - * Returns true on success or false on failure. - */ - public function valid() { - $key = key( $this->_data ); - - return ( $key !== null && $key !== false ); - } - - /** - * (PHP 5 >= 5.0.0)<br/> - * Rewind the Iterator to the first element - * - * @link http://php.net/manual/en/iterator.rewind.php - * @return void Any returned value is ignored. - */ - public function rewind() { - reset( $this->_data ); - } - - /** - * (PHP 5 >= 5.1.0)<br/> - * Count elements of an object - * - * @link http://php.net/manual/en/countable.count.php - * @return int The custom count as an integer. - * </p> - * <p> - * The return value is cast to an integer. - */ - public function count() { - return count( $this->_data ); - } +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.7 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + class FS_Key_Value_Storage implements ArrayAccess, Iterator, Countable { + /** + * @var string + */ + protected $_id; + /** + * @var string + */ + protected $_slug; + /** + * @var array + */ + protected $_data; + + /** + * @var FS_Plugin_Manager[] + */ + private static $_instances = array(); + /** + * @var FS_Logger + */ + protected $_logger; + + /** + * @param string $id + * @param string $slug + * + * @return FS_Key_Value_Storage + */ + static function instance( $id, $slug ) { + $key = $id . ':' . $slug; + if ( ! isset( self::$_instances[ $key ] ) ) { + self::$_instances[ $key ] = new FS_Key_Value_Storage( $id, $slug ); + } + + return self::$_instances[ $key ]; + } + + protected function __construct( $id, $slug ) { + $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $slug . '_' . $id, WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); + + $this->_slug = $slug; + $this->_id = $id; + $this->load(); + } + + protected function get_option_manager() { + return FS_Option_Manager::get_manager( WP_FS__ACCOUNTS_OPTION_NAME, true ); + } + + protected function get_all_data() { + return $this->get_option_manager()->get_option( $this->_id, array() ); + } + + /** + * Load plugin data from local DB. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + */ + function load() { + $all_plugins_data = $this->get_all_data(); + $this->_data = isset( $all_plugins_data[ $this->_slug ] ) ? + $all_plugins_data[ $this->_slug ] : + array(); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + * + * @param string $key + * @param mixed $value + * @param bool $flush + */ + function store( $key, $value, $flush = true ) { + if ( $this->_logger->is_on() ) { + $this->_logger->entrance( $key . ' = ' . var_export( $value, true ) ); + } + + if ( array_key_exists( $key, $this->_data ) && $value === $this->_data[ $key ] ) { + // No need to store data if the value wasn't changed. + return; + } + + $all_data = $this->get_all_data(); + + $this->_data[ $key ] = $value; + + $all_data[ $this->_slug ] = $this->_data; + + $options_manager = $this->get_option_manager(); + $options_manager->set_option( $this->_id, $all_data, $flush ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + * + * @param bool $store + * @param string[] $exceptions Set of keys to keep and not clear. + */ + function clear_all( $store = true, $exceptions = array() ) { + $new_data = array(); + foreach ( $exceptions as $key ) { + if ( isset( $this->_data[ $key ] ) ) { + $new_data[ $key ] = $this->_data[ $key ]; + } + } + + $this->_data = $new_data; + + if ( $store ) { + $all_data = $this->get_all_data(); + $all_data[ $this->_slug ] = $this->_data; + $options_manager = $this->get_option_manager(); + $options_manager->set_option( $this->_id, $all_data, true ); + } + } + + /** + * Delete key-value storage. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + */ + function delete() { + $this->_data = array(); + + $all_data = $this->get_all_data(); + unset( $all_data[ $this->_slug ] ); + $options_manager = $this->get_option_manager(); + $options_manager->set_option( $this->_id, $all_data, true ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + * + * @param string $key + * @param bool $store + */ + function remove( $key, $store = true ) { + if ( ! array_key_exists( $key, $this->_data ) ) { + return; + } + + unset( $this->_data[ $key ] ); + + if ( $store ) { + $all_data = $this->get_all_data(); + $all_data[ $this->_slug ] = $this->_data; + $options_manager = $this->get_option_manager(); + $options_manager->set_option( $this->_id, $all_data, true ); + } + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + * + * @param string $key + * @param mixed $default + * + * @return bool|\FS_Plugin + */ + function get( $key, $default = false ) { + return array_key_exists( $key, $this->_data ) ? + $this->_data[ $key ] : + $default; + } + + + /* ArrayAccess + Magic Access (better for refactoring) + -----------------------------------------------------------------------------------*/ + function __set( $k, $v ) { + $this->store( $k, $v ); + } + + function __isset( $k ) { + return array_key_exists( $k, $this->_data ); + } + + function __unset( $k ) { + $this->remove( $k ); + } + + function __get( $k ) { + return $this->get( $k, null ); + } + + function offsetSet( $k, $v ) { + if ( is_null( $k ) ) { + throw new Exception( 'Can\'t append value to request params.' ); + } else { + $this->{$k} = $v; + } + } + + function offsetExists( $k ) { + return array_key_exists( $k, $this->_data ); + } + + function offsetUnset( $k ) { + unset( $this->$k ); + } + + function offsetGet( $k ) { + return $this->get( $k, null ); + } + + /** + * (PHP 5 >= 5.0.0)<br/> + * Return the current element + * + * @link http://php.net/manual/en/iterator.current.php + * @return mixed Can return any type. + */ + public function current() { + return current( $this->_data ); + } + + /** + * (PHP 5 >= 5.0.0)<br/> + * Move forward to next element + * + * @link http://php.net/manual/en/iterator.next.php + * @return void Any returned value is ignored. + */ + public function next() { + next( $this->_data ); + } + + /** + * (PHP 5 >= 5.0.0)<br/> + * Return the key of the current element + * + * @link http://php.net/manual/en/iterator.key.php + * @return mixed scalar on success, or null on failure. + */ + public function key() { + return key( $this->_data ); + } + + /** + * (PHP 5 >= 5.0.0)<br/> + * Checks if current position is valid + * + * @link http://php.net/manual/en/iterator.valid.php + * @return boolean The return value will be casted to boolean and then evaluated. + * Returns true on success or false on failure. + */ + public function valid() { + $key = key( $this->_data ); + + return ( $key !== null && $key !== false ); + } + + /** + * (PHP 5 >= 5.0.0)<br/> + * Rewind the Iterator to the first element + * + * @link http://php.net/manual/en/iterator.rewind.php + * @return void Any returned value is ignored. + */ + public function rewind() { + reset( $this->_data ); + } + + /** + * (PHP 5 >= 5.1.0)<br/> + * Count elements of an object + * + * @link http://php.net/manual/en/countable.count.php + * @return int The custom count as an integer. + * </p> + * <p> + * The return value is cast to an integer. + */ + public function count() { + return count( $this->_data ); + } } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/includes/managers/class-fs-option-manager.php b/wp-content/plugins/nextgen-gallery/freemius/includes/managers/class-fs-option-manager.php index 19c7069646920ace00de19d94ca6df7571d386c3..3d60b3990e10b210ea7e0d17a29a0e68798e9c4a 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/includes/managers/class-fs-option-manager.php +++ b/wp-content/plugins/nextgen-gallery/freemius/includes/managers/class-fs-option-manager.php @@ -1,302 +1,302 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.3 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - /** - * 3-layer lazy options manager. - * layer 3: Memory - * layer 2: Cache (if there's any caching plugin and if WP_FS__DEBUG_SDK is FALSE) - * layer 1: Database (options table). All options stored as one option record in the DB to reduce number of DB - * queries. - * - * If load() is not explicitly called, starts as empty manager. Same thing about saving the data - you have to - * explicitly call store(). - * - * Class Freemius_Option_Manager - */ - class FS_Option_Manager { - /** - * @var string - */ - private $_id; - /** - * @var array - */ - private $_options; - /** - * @var FS_Logger - */ - private $_logger; - - /** - * @var FS_Option_Manager[] - */ - private static $_MANAGERS = array(); - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.3 - * - * @param string $id - * @param bool $load - */ - private function __construct( $id, $load = false ) { - $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_opt_mngr_' . $id, WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); - - $this->_logger->entrance(); - $this->_logger->log( 'id = ' . $id ); - - $this->_id = $id; - - if ( $load ) { - $this->load(); - } - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.3 - * - * @param $id - * @param $load - * - * @return FS_Option_Manager - */ - static function get_manager( $id, $load = false ) { - $id = strtolower( $id ); - - if ( ! isset( self::$_MANAGERS[ $id ] ) ) { - self::$_MANAGERS[ $id ] = new FS_Option_Manager( $id, $load ); - } // If load required but not yet loaded, load. - else if ( $load && ! self::$_MANAGERS[ $id ]->is_loaded() ) { - self::$_MANAGERS[ $id ]->load(); - } - - return self::$_MANAGERS[ $id ]; - } - - private function _get_option_manager_name() { -// return WP_FS__SLUG . '_' . $this->_id; - return $this->_id; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.3 - * - * @param bool $flush - */ - function load( $flush = false ) { - $this->_logger->entrance(); - - $option_name = $this->_get_option_manager_name(); - - if ( $flush || ! isset( $this->_options ) ) { - if ( isset( $this->_options ) ) { - // Clear prev options. - $this->clear(); - } - - if ( ! WP_FS__DEBUG_SDK ) { - $this->_options = wp_cache_get( $option_name, WP_FS__SLUG ); - } - -// $this->_logger->info('wp_cache_get = ' . var_export($this->_options, true)); - -// if ( is_array( $this->_options ) ) { -// $this->clear(); -// } - - $cached = true; - - if ( empty( $this->_options ) ) { - $this->_options = get_option( $option_name ); - - if ( is_string( $this->_options ) ) { - $this->_options = json_decode( $this->_options ); - } - -// $this->_logger->info('get_option = ' . var_export($this->_options, true)); - - if ( false === $this->_options ) { - $this->clear(); - } - - $cached = false; - } - - if ( ! WP_FS__DEBUG_SDK && ! $cached ) // Set non encoded cache. - { - wp_cache_set( $option_name, $this->_options, WP_FS__SLUG ); - } - } - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.3 - * - * @return bool - */ - function is_loaded() { - return isset( $this->_options ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.3 - * - * @return bool - */ - function is_empty() { - return ( $this->is_loaded() && false === $this->_options ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @param bool $flush - */ - function clear( $flush = false ) { - $this->_logger->entrance(); - - $this->_options = array(); - - if ( $flush ) { - $this->store(); - } - } - - /** - * Delete options manager from DB. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - */ - function delete() { - delete_option( $this->_get_option_manager_name() ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.6 - * - * @param string $option - * - * @return bool - */ - function has_option( $option ) { - return array_key_exists( $option, $this->_options ); - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.3 - * - * @param string $option - * @param mixed $default - * - * @return mixed - */ - function get_option( $option, $default = null ) { - $this->_logger->entrance( 'option = ' . $option ); - - if ( is_array( $this->_options ) ) { - return isset( $this->_options[ $option ] ) ? $this->_options[ $option ] : $default; - } else if ( is_object( $this->_options ) ) { - return isset( $this->_options->{$option} ) ? $this->_options->{$option} : $default; - } - - return $default; - } - - /** - * @author Vova Feldman (@svovaf) - * @since 1.0.3 - * - * @param string $option - * @param mixed $value - * @param bool $flush - */ - function set_option( $option, $value, $flush = false ) { - $this->_logger->entrance( 'option = ' . $option ); - - if ( ! $this->is_loaded() ) { - $this->clear(); - } - - if ( is_array( $this->_options ) ) { - $this->_options[ $option ] = $value; - } else if ( is_object( $this->_options ) ) { - $this->_options->{$option} = $value; - } - - if ( $flush ) { - $this->store(); - } - } - - /** - * Unset option. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.3 - * - * @param string $option - * @param bool $flush - */ - function unset_option( $option, $flush = false ) { - $this->_logger->entrance( 'option = ' . $option ); - - if ( is_array( $this->_options ) ) { - if ( ! isset( $this->_options[ $option ] ) ) { - return; - } - - unset( $this->_options[ $option ] ); - - } else if ( is_object( $this->_options ) ) { - if ( ! isset( $this->_options->{$option} ) ) { - return; - } - - unset( $this->_options->{$option} ); - } - - if ( $flush ) { - $this->store(); - } - } - - /** - * Dump options to database. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.3 - */ - function store() { - $this->_logger->entrance(); - - $option_name = $this->_get_option_manager_name(); - - if ( $this->_logger->is_on() ) { - $this->_logger->info( $option_name . ' = ' . var_export( $this->_options, true ) ); - } - - // Update DB. - update_option( $option_name, $this->_options ); - - if ( ! WP_FS__DEBUG_SDK ) { - wp_cache_set( $option_name, $this->_options, WP_FS__SLUG ); - } - } +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.3 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + /** + * 3-layer lazy options manager. + * layer 3: Memory + * layer 2: Cache (if there's any caching plugin and if WP_FS__DEBUG_SDK is FALSE) + * layer 1: Database (options table). All options stored as one option record in the DB to reduce number of DB + * queries. + * + * If load() is not explicitly called, starts as empty manager. Same thing about saving the data - you have to + * explicitly call store(). + * + * Class Freemius_Option_Manager + */ + class FS_Option_Manager { + /** + * @var string + */ + private $_id; + /** + * @var array + */ + private $_options; + /** + * @var FS_Logger + */ + private $_logger; + + /** + * @var FS_Option_Manager[] + */ + private static $_MANAGERS = array(); + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.3 + * + * @param string $id + * @param bool $load + */ + private function __construct( $id, $load = false ) { + $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_opt_mngr_' . $id, WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); + + $this->_logger->entrance(); + $this->_logger->log( 'id = ' . $id ); + + $this->_id = $id; + + if ( $load ) { + $this->load(); + } + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.3 + * + * @param $id + * @param $load + * + * @return FS_Option_Manager + */ + static function get_manager( $id, $load = false ) { + $id = strtolower( $id ); + + if ( ! isset( self::$_MANAGERS[ $id ] ) ) { + self::$_MANAGERS[ $id ] = new FS_Option_Manager( $id, $load ); + } // If load required but not yet loaded, load. + else if ( $load && ! self::$_MANAGERS[ $id ]->is_loaded() ) { + self::$_MANAGERS[ $id ]->load(); + } + + return self::$_MANAGERS[ $id ]; + } + + private function _get_option_manager_name() { +// return WP_FS__SLUG . '_' . $this->_id; + return $this->_id; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.3 + * + * @param bool $flush + */ + function load( $flush = false ) { + $this->_logger->entrance(); + + $option_name = $this->_get_option_manager_name(); + + if ( $flush || ! isset( $this->_options ) ) { + if ( isset( $this->_options ) ) { + // Clear prev options. + $this->clear(); + } + + if ( ! WP_FS__DEBUG_SDK ) { + $this->_options = wp_cache_get( $option_name, WP_FS__SLUG ); + } + +// $this->_logger->info('wp_cache_get = ' . var_export($this->_options, true)); + +// if ( is_array( $this->_options ) ) { +// $this->clear(); +// } + + $cached = true; + + if ( empty( $this->_options ) ) { + $this->_options = get_option( $option_name ); + + if ( is_string( $this->_options ) ) { + $this->_options = json_decode( $this->_options ); + } + +// $this->_logger->info('get_option = ' . var_export($this->_options, true)); + + if ( false === $this->_options ) { + $this->clear(); + } + + $cached = false; + } + + if ( ! WP_FS__DEBUG_SDK && ! $cached ) // Set non encoded cache. + { + wp_cache_set( $option_name, $this->_options, WP_FS__SLUG ); + } + } + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.3 + * + * @return bool + */ + function is_loaded() { + return isset( $this->_options ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.3 + * + * @return bool + */ + function is_empty() { + return ( $this->is_loaded() && false === $this->_options ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @param bool $flush + */ + function clear( $flush = false ) { + $this->_logger->entrance(); + + $this->_options = array(); + + if ( $flush ) { + $this->store(); + } + } + + /** + * Delete options manager from DB. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + */ + function delete() { + delete_option( $this->_get_option_manager_name() ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.6 + * + * @param string $option + * + * @return bool + */ + function has_option( $option ) { + return array_key_exists( $option, $this->_options ); + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.3 + * + * @param string $option + * @param mixed $default + * + * @return mixed + */ + function get_option( $option, $default = null ) { + $this->_logger->entrance( 'option = ' . $option ); + + if ( is_array( $this->_options ) ) { + return isset( $this->_options[ $option ] ) ? $this->_options[ $option ] : $default; + } else if ( is_object( $this->_options ) ) { + return isset( $this->_options->{$option} ) ? $this->_options->{$option} : $default; + } + + return $default; + } + + /** + * @author Vova Feldman (@svovaf) + * @since 1.0.3 + * + * @param string $option + * @param mixed $value + * @param bool $flush + */ + function set_option( $option, $value, $flush = false ) { + $this->_logger->entrance( 'option = ' . $option ); + + if ( ! $this->is_loaded() ) { + $this->clear(); + } + + if ( is_array( $this->_options ) ) { + $this->_options[ $option ] = $value; + } else if ( is_object( $this->_options ) ) { + $this->_options->{$option} = $value; + } + + if ( $flush ) { + $this->store(); + } + } + + /** + * Unset option. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.3 + * + * @param string $option + * @param bool $flush + */ + function unset_option( $option, $flush = false ) { + $this->_logger->entrance( 'option = ' . $option ); + + if ( is_array( $this->_options ) ) { + if ( ! isset( $this->_options[ $option ] ) ) { + return; + } + + unset( $this->_options[ $option ] ); + + } else if ( is_object( $this->_options ) ) { + if ( ! isset( $this->_options->{$option} ) ) { + return; + } + + unset( $this->_options->{$option} ); + } + + if ( $flush ) { + $this->store(); + } + } + + /** + * Dump options to database. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.3 + */ + function store() { + $this->_logger->entrance(); + + $option_name = $this->_get_option_manager_name(); + + if ( $this->_logger->is_on() ) { + $this->_logger->info( $option_name . ' = ' . var_export( $this->_options, true ) ); + } + + // Update DB. + update_option( $option_name, $this->_options ); + + if ( ! WP_FS__DEBUG_SDK ) { + wp_cache_set( $option_name, $this->_options, WP_FS__SLUG ); + } + } } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/includes/managers/class-fs-plan-manager.php b/wp-content/plugins/nextgen-gallery/freemius/includes/managers/class-fs-plan-manager.php index ddd9015ba98ea8a02cfa7be480b9448baac0539f..9e8608126acb681d3c8f41f5a3d33d2e9a12ff15 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/includes/managers/class-fs-plan-manager.php +++ b/wp-content/plugins/nextgen-gallery/freemius/includes/managers/class-fs-plan-manager.php @@ -1,162 +1,162 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.6 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - class FS_Plan_Manager { - /** - * @var FS_Plan_Manager - */ - private static $_instance; - - /** - * @return FS_Plan_Manager - */ - static function instance() { - if ( ! isset( self::$_instance ) ) { - self::$_instance = new FS_Plan_Manager(); - } - - return self::$_instance; - } - - private function __construct() { - } - - /** - * @param FS_Plugin_License[] $licenses - * - * @return bool - */ - function has_premium_license( $licenses ) { - if ( is_array( $licenses ) ) { - /** - * @var FS_Plugin_License[] $licenses - */ - foreach ( $licenses as $license ) { - if ( ! $license->is_utilized() && $license->is_features_enabled() ) { - return true; - } - } - } - - return false; - } - - /** - * Check if plugin has any paid plans. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - * - * @param FS_Plugin_Plan[] $plans - * - * @return bool - */ - function has_paid_plan( $plans ) { - if ( ! is_array( $plans ) || 0 === count( $plans ) ) { - return false; - } - - /** - * @var FS_Plugin_Plan[] $plans - */ - for ( $i = 0, $len = count( $plans ); $i < $len; $i ++ ) { - if ( ! $plans[ $i ]->is_free() ) { - return true; - } - } - - return false; - } - - /** - * Check if plugin has any free plan, or is it premium only. - * - * Note: If no plans configured, assume plugin is free. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.7 - * - * @param FS_Plugin_Plan[] $plans - * - * @return bool - */ - function has_free_plan( $plans ) { - if ( ! is_array( $plans ) || 0 === count( $plans ) ) { - return true; - } - - /** - * @var FS_Plugin_Plan[] $plans - */ - for ( $i = 0, $len = count( $plans ); $i < $len; $i ++ ) { - if ( $plans[ $i ]->is_free() ) { - return true; - } - } - - return false; - } - - /** - * Find all plans that have trial. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @param FS_Plugin_Plan[] $plans - * - * @return FS_Plugin_Plan[] - */ - function get_trial_plans( $plans ) { - $trial_plans = array(); - - if ( is_array( $plans ) && 0 < count( $plans ) ) { - /** - * @var FS_Plugin_Plan[] $plans - */ - for ( $i = 0, $len = count( $plans ); $i < $len; $i ++ ) { - if ( $plans[ $i ]->has_trial() ) { - $trial_plans[] = $plans[ $i ]; - } - } - } - - return $trial_plans; - } - - /** - * Check if plugin has any trial plan. - * - * @author Vova Feldman (@svovaf) - * @since 1.0.9 - * - * @param FS_Plugin_Plan[] $plans - * - * @return bool - */ - function has_trial_plan( $plans ) { - if ( ! is_array( $plans ) || 0 === count( $plans ) ) { - return true; - } - - /** - * @var FS_Plugin_Plan[] $plans - */ - for ( $i = 0, $len = count( $plans ); $i < $len; $i ++ ) { - if ( $plans[ $i ]->has_trial() ) { - return true; - } - } - - return false; - } +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.6 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + class FS_Plan_Manager { + /** + * @var FS_Plan_Manager + */ + private static $_instance; + + /** + * @return FS_Plan_Manager + */ + static function instance() { + if ( ! isset( self::$_instance ) ) { + self::$_instance = new FS_Plan_Manager(); + } + + return self::$_instance; + } + + private function __construct() { + } + + /** + * @param FS_Plugin_License[] $licenses + * + * @return bool + */ + function has_premium_license( $licenses ) { + if ( is_array( $licenses ) ) { + /** + * @var FS_Plugin_License[] $licenses + */ + foreach ( $licenses as $license ) { + if ( ! $license->is_utilized() && $license->is_features_enabled() ) { + return true; + } + } + } + + return false; + } + + /** + * Check if plugin has any paid plans. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + * + * @param FS_Plugin_Plan[] $plans + * + * @return bool + */ + function has_paid_plan( $plans ) { + if ( ! is_array( $plans ) || 0 === count( $plans ) ) { + return false; + } + + /** + * @var FS_Plugin_Plan[] $plans + */ + for ( $i = 0, $len = count( $plans ); $i < $len; $i ++ ) { + if ( ! $plans[ $i ]->is_free() ) { + return true; + } + } + + return false; + } + + /** + * Check if plugin has any free plan, or is it premium only. + * + * Note: If no plans configured, assume plugin is free. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.7 + * + * @param FS_Plugin_Plan[] $plans + * + * @return bool + */ + function has_free_plan( $plans ) { + if ( ! is_array( $plans ) || 0 === count( $plans ) ) { + return true; + } + + /** + * @var FS_Plugin_Plan[] $plans + */ + for ( $i = 0, $len = count( $plans ); $i < $len; $i ++ ) { + if ( $plans[ $i ]->is_free() ) { + return true; + } + } + + return false; + } + + /** + * Find all plans that have trial. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @param FS_Plugin_Plan[] $plans + * + * @return FS_Plugin_Plan[] + */ + function get_trial_plans( $plans ) { + $trial_plans = array(); + + if ( is_array( $plans ) && 0 < count( $plans ) ) { + /** + * @var FS_Plugin_Plan[] $plans + */ + for ( $i = 0, $len = count( $plans ); $i < $len; $i ++ ) { + if ( $plans[ $i ]->has_trial() ) { + $trial_plans[] = $plans[ $i ]; + } + } + } + + return $trial_plans; + } + + /** + * Check if plugin has any trial plan. + * + * @author Vova Feldman (@svovaf) + * @since 1.0.9 + * + * @param FS_Plugin_Plan[] $plans + * + * @return bool + */ + function has_trial_plan( $plans ) { + if ( ! is_array( $plans ) || 0 === count( $plans ) ) { + return true; + } + + /** + * @var FS_Plugin_Plan[] $plans + */ + for ( $i = 0, $len = count( $plans ); $i < $len; $i ++ ) { + if ( $plans[ $i ]->has_trial() ) { + return true; + } + } + + return false; + } } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/includes/sdk/Exceptions/ArgumentNotExistException.php b/wp-content/plugins/nextgen-gallery/freemius/includes/sdk/Exceptions/ArgumentNotExistException.php index 911531879bbf71731fc04d11b187441aca8b241e..b69c77014b1c598777ad6b9962e51d85dc3f15e6 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/includes/sdk/Exceptions/ArgumentNotExistException.php +++ b/wp-content/plugins/nextgen-gallery/freemius/includes/sdk/Exceptions/ArgumentNotExistException.php @@ -1,6 +1,6 @@ -<?php - if ( ! class_exists( 'Freemius_InvalidArgumentException' ) ) { - exit; - } - +<?php + if ( ! class_exists( 'Freemius_InvalidArgumentException' ) ) { + exit; + } + class Freemius_ArgumentNotExistException extends Freemius_InvalidArgumentException { } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/includes/sdk/Exceptions/EmptyArgumentException.php b/wp-content/plugins/nextgen-gallery/freemius/includes/sdk/Exceptions/EmptyArgumentException.php index 78e34f98ccc18796e2fee05ee1e44c4c9e29860c..dff1a4ed80897a52ea02a631b2d83673026feab4 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/includes/sdk/Exceptions/EmptyArgumentException.php +++ b/wp-content/plugins/nextgen-gallery/freemius/includes/sdk/Exceptions/EmptyArgumentException.php @@ -1,6 +1,6 @@ -<?php - if ( ! class_exists( 'Freemius_InvalidArgumentException' ) ) { - exit; - } - +<?php + if ( ! class_exists( 'Freemius_InvalidArgumentException' ) ) { + exit; + } + class Freemius_EmptyArgumentException extends Freemius_InvalidArgumentException { } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/includes/sdk/Exceptions/Exception.php b/wp-content/plugins/nextgen-gallery/freemius/includes/sdk/Exceptions/Exception.php index cef4cab807f1ff66ced4b6eeac393136bd1effc0..cc64350f17c39a87f0a11c3b3c8cca268718726b 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/includes/sdk/Exceptions/Exception.php +++ b/wp-content/plugins/nextgen-gallery/freemius/includes/sdk/Exceptions/Exception.php @@ -1,75 +1,75 @@ -<?php - /** - * Thrown when an API call returns an exception. - * - */ - class Freemius_Exception extends Exception - { - protected $_result; - protected $_type; - protected $_code; - - /** - * Make a new API Exception with the given result. - * - * @param array $result The result from the API server. - */ - public function __construct($result) - { - $this->_result = $result; - - $code = 0; - $message = 'Unknown error, please check GetResult().'; - $type = ''; - - if (isset($result['error']) && is_array($result['error'])) - { - if (isset($result['error']['code'])) - $code = $result['error']['code']; - if (isset($result['error']['message'])) - $message = $result['error']['message']; - if (isset($result['error']['type'])) - $type = $result['error']['type']; - } - - $this->_type = $type; - $this->_code = $code; - - parent::__construct($message, is_numeric($code) ? $code : 0); - } - - /** - * Return the associated result object returned by the API server. - * - * @return array The result from the API server - */ - public function getResult() - { - return $this->_result; - } - - public function getStringCode() - { - return $this->_code; - } - - public function getType() - { - return $this->_type; - } - - /** - * To make debugging easier. - * - * @return string The string representation of the error - */ - public function __toString() - { - $str = $this->getType() . ': '; - - if ($this->code != 0) - $str .= $this->getStringCode() . ': '; - - return $str . $this->getMessage(); - } +<?php + /** + * Thrown when an API call returns an exception. + * + */ + class Freemius_Exception extends Exception + { + protected $_result; + protected $_type; + protected $_code; + + /** + * Make a new API Exception with the given result. + * + * @param array $result The result from the API server. + */ + public function __construct($result) + { + $this->_result = $result; + + $code = 0; + $message = 'Unknown error, please check GetResult().'; + $type = ''; + + if (isset($result['error']) && is_array($result['error'])) + { + if (isset($result['error']['code'])) + $code = $result['error']['code']; + if (isset($result['error']['message'])) + $message = $result['error']['message']; + if (isset($result['error']['type'])) + $type = $result['error']['type']; + } + + $this->_type = $type; + $this->_code = $code; + + parent::__construct($message, is_numeric($code) ? $code : 0); + } + + /** + * Return the associated result object returned by the API server. + * + * @return array The result from the API server + */ + public function getResult() + { + return $this->_result; + } + + public function getStringCode() + { + return $this->_code; + } + + public function getType() + { + return $this->_type; + } + + /** + * To make debugging easier. + * + * @return string The string representation of the error + */ + public function __toString() + { + $str = $this->getType() . ': '; + + if ($this->code != 0) + $str .= $this->getStringCode() . ': '; + + return $str . $this->getMessage(); + } } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/includes/sdk/Exceptions/InvalidArgumentException.php b/wp-content/plugins/nextgen-gallery/freemius/includes/sdk/Exceptions/InvalidArgumentException.php index 967798c13fc5e3b9c4a69634319a6cddcd0cfccb..63b3a45e34745c7331aa80a6e976047fcd280d07 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/includes/sdk/Exceptions/InvalidArgumentException.php +++ b/wp-content/plugins/nextgen-gallery/freemius/includes/sdk/Exceptions/InvalidArgumentException.php @@ -1,6 +1,6 @@ -<?php - if ( ! class_exists( 'Freemius_Exception' ) ) { - exit; - } - +<?php + if ( ! class_exists( 'Freemius_Exception' ) ) { + exit; + } + class Freemius_InvalidArgumentException extends Freemius_Exception { } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/includes/sdk/Exceptions/OAuthException.php b/wp-content/plugins/nextgen-gallery/freemius/includes/sdk/Exceptions/OAuthException.php index 4b65873fbd3fc606c6fedcf6179d1d9c81801c08..a1434a20946398615c6ae7c143a4fcc599a81612 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/includes/sdk/Exceptions/OAuthException.php +++ b/wp-content/plugins/nextgen-gallery/freemius/includes/sdk/Exceptions/OAuthException.php @@ -1,12 +1,12 @@ -<?php - if ( ! class_exists( 'Freemius_Exception' ) ) { - exit; - } - - class Freemius_OAuthException extends Freemius_Exception - { - public function __construct($pResult) - { - parent::__construct($pResult); - } +<?php + if ( ! class_exists( 'Freemius_Exception' ) ) { + exit; + } + + class Freemius_OAuthException extends Freemius_Exception + { + public function __construct($pResult) + { + parent::__construct($pResult); + } } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/includes/sdk/Freemius.php b/wp-content/plugins/nextgen-gallery/freemius/includes/sdk/Freemius.php index 6784454995bc5a782e37c874188e12817f7e6c8b..64cac3237c254c858786b3b254d815295cc70522 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/includes/sdk/Freemius.php +++ b/wp-content/plugins/nextgen-gallery/freemius/includes/sdk/Freemius.php @@ -1,574 +1,574 @@ -<?php - /** - * Copyright 2014 Freemius, Inc. - * - * Licensed under the GPL v2 (the "License"); you may - * not use this file except in compliance with the License. You may obtain - * a copy of the License at - * - * http://choosealicense.com/licenses/gpl-v2/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - - require_once( dirname( __FILE__ ) . '/FreemiusBase.php' ); - - define( 'FS_SDK__USER_AGENT', 'fs-php-' . Freemius_Api_Base::VERSION ); - - if ( ! defined( 'FS_SDK__SIMULATE_NO_CURL' ) ) { - define( 'FS_SDK__SIMULATE_NO_CURL', false ); - } - - if ( ! defined( 'FS_SDK__SIMULATE_NO_API_CONNECTIVITY_CLOUDFLARE' ) ) { - define( 'FS_SDK__SIMULATE_NO_API_CONNECTIVITY_CLOUDFLARE', false ); - } - - if ( ! defined( 'FS_SDK__SIMULATE_NO_API_CONNECTIVITY_SQUID_ACL' ) ) { - define( 'FS_SDK__SIMULATE_NO_API_CONNECTIVITY_SQUID_ACL', false ); - } - - define( 'FS_SDK__HAS_CURL', ! FS_SDK__SIMULATE_NO_CURL && function_exists( 'curl_version' ) ); - - if ( ! FS_SDK__HAS_CURL ) { - $curl_version = array( 'version' => '7.0.0' ); - } else { - $curl_version = curl_version(); - } - - define( 'FS_API__PROTOCOL', version_compare( $curl_version['version'], '7.37', '>=' ) ? 'https' : 'http' ); - - if ( ! defined( 'FS_API__LOGGER_ON' ) ) { - define( 'FS_API__LOGGER_ON', false ); - } - - if ( ! defined( 'FS_API__ADDRESS' ) ) { - define( 'FS_API__ADDRESS', '://api.freemius.com' ); - } - if ( ! defined( 'FS_API__SANDBOX_ADDRESS' ) ) { - define( 'FS_API__SANDBOX_ADDRESS', '://sandbox-api.freemius.com' ); - } - - class Freemius_Api extends Freemius_Api_Base { - private static $_logger = array(); - - /** - * @param string $pScope 'app', 'developer', 'user' or 'install'. - * @param number $pID Element's id. - * @param string $pPublic Public key. - * @param string|bool $pSecret Element's secret key. - * @param bool $pSandbox Whether or not to run API in sandbox mode. - */ - public function __construct( $pScope, $pID, $pPublic, $pSecret = false, $pSandbox = false ) { - // If secret key not provided, use public key encryption. - if ( is_bool( $pSecret ) ) { - $pSecret = $pPublic; - } - - parent::Init( $pScope, $pID, $pPublic, $pSecret, $pSandbox ); - } - - public static function GetUrl( $pCanonizedPath = '', $pIsSandbox = false ) { - $address = ( $pIsSandbox ? FS_API__SANDBOX_ADDRESS : FS_API__ADDRESS ); - - if ( ':' === $address[0] ) { - $address = self::$_protocol . $address; - } - - return $address . $pCanonizedPath; - } - - #region Servers Clock Diff ------------------------------------------------------ - - /** - * @var int Clock diff in seconds between current server to API server. - */ - private static $_clock_diff = 0; - - /** - * Set clock diff for all API calls. - * - * @since 1.0.3 - * - * @param $pSeconds - */ - public static function SetClockDiff( $pSeconds ) { - self::$_clock_diff = $pSeconds; - } - - /** - * Find clock diff between current server to API server. - * - * @since 1.0.2 - * @return int Clock diff in seconds. - */ - public static function FindClockDiff() { - $time = time(); - $pong = self::Ping(); - - return ( $time - strtotime( $pong->timestamp ) ); - } - - #endregion Servers Clock Diff ------------------------------------------------------ - - /** - * @var string http or https - */ - private static $_protocol = FS_API__PROTOCOL; - - /** - * Set API connection protocol. - * - * @since 1.0.4 - */ - public static function SetHttp() { - self::$_protocol = 'http'; - } - - /** - * @since 1.0.4 - * - * @return bool - */ - public static function IsHttps() { - return ( 'https' === self::$_protocol ); - } - - /** - * Sign request with the following HTTP headers: - * Content-MD5: MD5(HTTP Request body) - * Date: Current date (i.e Sat, 14 Feb 2015 20:24:46 +0000) - * Authorization: FS {scope_entity_id}:{scope_entity_public_key}:base64encode(sha256(string_to_sign, - * {scope_entity_secret_key})) - * - * @param string $pResourceUrl - * @param array $pCurlOptions - * - * @return array - */ - function SignRequest( $pResourceUrl, $pCurlOptions ) { - $eol = "\n"; - $content_md5 = ''; - $now = ( time() - self::$_clock_diff ); - $date = date( 'r', $now ); - $content_type = ''; - - if ( isset( $pCurlOptions[ CURLOPT_POST ] ) && 0 < $pCurlOptions[ CURLOPT_POST ] ) { - $content_md5 = md5( $pCurlOptions[ CURLOPT_POSTFIELDS ] ); - $pCurlOptions[ CURLOPT_HTTPHEADER ][] = 'Content-MD5: ' . $content_md5; - $content_type = 'application/json'; - } - - $pCurlOptions[ CURLOPT_HTTPHEADER ][] = 'Date: ' . $date; - - $string_to_sign = implode( $eol, array( - $pCurlOptions[ CURLOPT_CUSTOMREQUEST ], - $content_md5, - $content_type, - $date, - $pResourceUrl - ) ); - - // If secret and public keys are identical, it means that - // the signature uses public key hash encoding. - $auth_type = ( $this->_secret !== $this->_public ) ? 'FS' : 'FSP'; - - // Add authorization header. - $pCurlOptions[ CURLOPT_HTTPHEADER ][] = 'Authorization: ' . - $auth_type . ' ' . - $this->_id . ':' . - $this->_public . ':' . - self::Base64UrlEncode( - hash_hmac( 'sha256', $string_to_sign, $this->_secret ) - ); - - return $pCurlOptions; - } - - /** - * Get API request URL signed via query string. - * - * @param string $pPath - * - * @throws Freemius_Exception - * - * @return string - */ - function GetSignedUrl( $pPath ) { - $resource = explode( '?', $this->CanonizePath( $pPath ) ); - $pResourceUrl = $resource[0]; - - $eol = "\n"; - $content_md5 = ''; - $content_type = ''; - $now = ( time() - self::$_clock_diff ); - $date = date( 'r', $now ); - - $string_to_sign = implode( $eol, array( - 'GET', - $content_md5, - $content_type, - $date, - $pResourceUrl - ) ); - - // If secret and public keys are identical, it means that - // the signature uses public key hash encoding. - $auth_type = ( $this->_secret !== $this->_public ) ? 'FS' : 'FSP'; - - return Freemius_Api::GetUrl( - $pResourceUrl . '?' . - ( 1 < count( $resource ) && ! empty( $resource[1] ) ? $resource[1] . '&' : '' ) . - http_build_query( array( - 'auth_date' => $date, - 'authorization' => $auth_type . ' ' . $this->_id . ':' . - $this->_public . ':' . - self::Base64UrlEncode( hash_hmac( - 'sha256', $string_to_sign, $this->_secret - ) ) - ) ), $this->_isSandbox ); - } - - /** - * @param resource $pCurlHandler - * @param array $pCurlOptions - * - * @return mixed - */ - private static function ExecuteRequest( &$pCurlHandler, &$pCurlOptions ) { - $start = microtime( true ); - - $result = curl_exec( $pCurlHandler ); - - if ( FS_API__LOGGER_ON ) { - $end = microtime( true ); - - $has_body = ( isset( $pCurlOptions[ CURLOPT_POST ] ) && 0 < $pCurlOptions[ CURLOPT_POST ] ); - - self::$_logger[] = array( - 'id' => count( self::$_logger ), - 'start' => $start, - 'end' => $end, - 'total' => ( $end - $start ), - 'method' => $pCurlOptions[ CURLOPT_CUSTOMREQUEST ], - 'path' => $pCurlOptions[ CURLOPT_URL ], - 'body' => $has_body ? $pCurlOptions[ CURLOPT_POSTFIELDS ] : null, - 'result' => $result, - 'code' => curl_getinfo( $pCurlHandler, CURLINFO_HTTP_CODE ), - 'backtrace' => debug_backtrace(), - ); - } - - return $result; - } - - /** - * @return array - */ - static function GetLogger() { - return self::$_logger; - } - - /** - * @param string $pCanonizedPath - * @param string $pMethod - * @param array $pParams - * @param null|resource $pCurlHandler - * @param bool $pIsSandbox - * @param null|callable $pBeforeExecutionFunction - * - * @return object[]|object|null - * - * @throws \Freemius_Exception - */ - private static function MakeStaticRequest( - $pCanonizedPath, - $pMethod = 'GET', - $pParams = array(), - $pCurlHandler = null, - $pIsSandbox = false, - $pBeforeExecutionFunction = null - ) { - if ( ! FS_SDK__HAS_CURL ) { - self::ThrowNoCurlException(); - } - - // Connectivity errors simulation. - if ( FS_SDK__SIMULATE_NO_API_CONNECTIVITY_CLOUDFLARE ) { - self::ThrowCloudFlareDDoSException(); - } else if ( FS_SDK__SIMULATE_NO_API_CONNECTIVITY_SQUID_ACL ) { - self::ThrowSquidAclException(); - } - - if ( ! $pCurlHandler ) { - $pCurlHandler = curl_init(); - } - - $opts = array( - CURLOPT_CONNECTTIMEOUT => 10, - CURLOPT_RETURNTRANSFER => true, - CURLOPT_TIMEOUT => 60, - CURLOPT_USERAGENT => FS_SDK__USER_AGENT, - ); - - if ( ! isset( $opts[ CURLOPT_HTTPHEADER ] ) || ! is_array( $opts[ CURLOPT_HTTPHEADER ] ) ) { - $opts[ CURLOPT_HTTPHEADER ] = array(); - } - - if ( 'POST' === $pMethod || 'PUT' === $pMethod ) { - if ( is_array( $pParams ) && 0 < count( $pParams ) ) { - $opts[ CURLOPT_HTTPHEADER ][] = 'Content-Type: application/json'; - $opts[ CURLOPT_POST ] = count( $pParams ); - $opts[ CURLOPT_POSTFIELDS ] = json_encode( $pParams ); - } - - $opts[ CURLOPT_RETURNTRANSFER ] = true; - } - - $opts[ CURLOPT_URL ] = Freemius_Api::GetUrl( $pCanonizedPath, $pIsSandbox ); - $opts[ CURLOPT_CUSTOMREQUEST ] = $pMethod; - - $resource = explode( '?', $pCanonizedPath ); - - // disable the 'Expect: 100-continue' behaviour. This causes CURL to wait - // for 2 seconds if the server does not support this header. - $opts[ CURLOPT_HTTPHEADER ][] = 'Expect:'; - - if ( 'https' === substr( strtolower( $pCanonizedPath ), 0, 5 ) ) { - $opts[ CURLOPT_SSL_VERIFYHOST ] = false; - $opts[ CURLOPT_SSL_VERIFYPEER ] = false; - } - - if ( false !== $pBeforeExecutionFunction && - is_callable( $pBeforeExecutionFunction ) - ) { - $opts = call_user_func( $pBeforeExecutionFunction, $resource[0], $opts ); - } - - curl_setopt_array( $pCurlHandler, $opts ); - $result = self::ExecuteRequest( $pCurlHandler, $opts ); - - /*if (curl_errno($ch) == 60) // CURLE_SSL_CACERT - { - self::errorLog('Invalid or no certificate authority found, using bundled information'); - curl_setopt($ch, CURLOPT_CAINFO, - dirname(__FILE__) . '/fb_ca_chain_bundle.crt'); - $result = curl_exec($ch); - }*/ - - // With dual stacked DNS responses, it's possible for a server to - // have IPv6 enabled but not have IPv6 connectivity. If this is - // the case, curl will try IPv4 first and if that fails, then it will - // fall back to IPv6 and the error EHOSTUNREACH is returned by the - // operating system. - if ( false === $result && empty( $opts[ CURLOPT_IPRESOLVE ] ) ) { - $matches = array(); - $regex = '/Failed to connect to ([^:].*): Network is unreachable/'; - if ( preg_match( $regex, curl_error( $pCurlHandler ), $matches ) ) { - if ( strlen( @inet_pton( $matches[1] ) ) === 16 ) { -// self::errorLog('Invalid IPv6 configuration on server, Please disable or get native IPv6 on your server.'); - $opts[ CURLOPT_IPRESOLVE ] = CURL_IPRESOLVE_V4; - curl_setopt( $pCurlHandler, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 ); - $result = self::ExecuteRequest( $pCurlHandler, $opts ); - } - } - } - - if ( $result === false ) { - self::ThrowCurlException( $pCurlHandler ); - } - - curl_close( $pCurlHandler ); - - if ( empty( $result ) ) { - return null; - } - - $decoded = json_decode( $result ); - - if ( is_null( $decoded ) ) { - if ( preg_match( '/Please turn JavaScript on/i', $result ) && - preg_match( '/text\/javascript/', $result ) - ) { - self::ThrowCloudFlareDDoSException( $result ); - } else if ( preg_match( '/Access control configuration prevents your request from being allowed at this time. Please contact your service provider if you feel this is incorrect./', $result ) && - preg_match( '/squid/', $result ) - ) { - self::ThrowSquidAclException( $result ); - } else { - $decoded = (object) array( - 'error' => (object) array( - 'type' => 'Unknown', - 'message' => $result, - 'code' => 'unknown', - 'http' => 402 - ) - ); - } - } - - return $decoded; - } - - - /** - * Makes an HTTP request. This method can be overridden by subclasses if - * developers want to do fancier things or use something other than curl to - * make the request. - * - * @param string $pCanonizedPath The URL to make the request to - * @param string $pMethod HTTP method - * @param array $pParams The parameters to use for the POST body - * @param null|resource $pCurlHandler Initialized curl handle - * - * @return object[]|object|null - * - * @throws Freemius_Exception - */ - public function MakeRequest( - $pCanonizedPath, - $pMethod = 'GET', - $pParams = array(), - $pCurlHandler = null - ) { - $resource = explode( '?', $pCanonizedPath ); - - // Only sign request if not ping.json connectivity test. - $sign_request = ( '/v1/ping.json' !== strtolower( substr( $resource[0], - strlen( '/v1/ping.json' ) ) ) ); - - return self::MakeStaticRequest( - $pCanonizedPath, - $pMethod, - $pParams, - $pCurlHandler, - $this->_isSandbox, - $sign_request ? array( &$this, 'SignRequest' ) : null - ); - } - - #region Connectivity Test ------------------------------------------------------ - - /** - * If successful connectivity to the API endpoint using ping.json endpoint. - * - * - OR - - * - * Validate if ping result object is valid. - * - * @param mixed $pPong - * - * @return bool - */ - public static function Test( $pPong = null ) { - $pong = is_null( $pPong ) ? - self::Ping() : - $pPong; - - return ( - is_object( $pong ) && - isset( $pong->api ) && - 'pong' === $pong->api - ); - } - - /** - * Ping API to test connectivity. - * - * @return object - */ - public static function Ping() { - try { - $result = self::MakeStaticRequest( '/v' . FS_API__VERSION . '/ping.json' ); - } catch ( Freemius_Exception $e ) { - // Map to error object. - $result = (object) $e->getResult(); - } catch ( Exception $e ) { - // Map to error object. - $result = (object) array( - 'error' => array( - 'type' => 'Unknown', - 'message' => $e->getMessage() . ' (' . $e->getFile() . ': ' . $e->getLine() . ')', - 'code' => 'unknown', - 'http' => 402 - ) - ); - } - - return $result; - } - - #endregion Connectivity Test ------------------------------------------------------ - - #region Connectivity Exceptions ------------------------------------------------------ - - /** - * @param resource $pCurlHandler - * - * @throws Freemius_Exception - */ - private static function ThrowCurlException( $pCurlHandler ) { - $e = new Freemius_Exception( array( - 'error' => array( - 'code' => curl_errno( $pCurlHandler ), - 'message' => curl_error( $pCurlHandler ), - 'type' => 'CurlException', - ), - ) ); - - curl_close( $pCurlHandler ); - throw $e; - } - - /** - * @param string $pResult - * - * @throws Freemius_Exception - */ - private static function ThrowNoCurlException( $pResult = '' ) { - throw new Freemius_Exception( array( - 'error' => (object) array( - 'type' => 'cUrlMissing', - 'message' => $pResult, - 'code' => 'curl_missing', - 'http' => 402 - ) - ) ); - } - - /** - * @param string $pResult - * - * @throws Freemius_Exception - */ - private static function ThrowCloudFlareDDoSException( $pResult = '' ) { - throw new Freemius_Exception( array( - 'error' => (object) array( - 'type' => 'CloudFlareDDoSProtection', - 'message' => $pResult, - 'code' => 'cloudflare_ddos_protection', - 'http' => 402 - ) - ) ); - } - - /** - * @param string $pResult - * - * @throws Freemius_Exception - */ - private static function ThrowSquidAclException( $pResult = '' ) { - throw new Freemius_Exception( array( - 'error' => (object) array( - 'type' => 'SquidCacheBlock', - 'message' => $pResult, - 'code' => 'squid_cache_block', - 'http' => 402 - ) - ) ); - } - - #endregion Connectivity Exceptions ------------------------------------------------------ +<?php + /** + * Copyright 2014 Freemius, Inc. + * + * Licensed under the GPL v2 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://choosealicense.com/licenses/gpl-v2/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + + require_once( dirname( __FILE__ ) . '/FreemiusBase.php' ); + + define( 'FS_SDK__USER_AGENT', 'fs-php-' . Freemius_Api_Base::VERSION ); + + if ( ! defined( 'FS_SDK__SIMULATE_NO_CURL' ) ) { + define( 'FS_SDK__SIMULATE_NO_CURL', false ); + } + + if ( ! defined( 'FS_SDK__SIMULATE_NO_API_CONNECTIVITY_CLOUDFLARE' ) ) { + define( 'FS_SDK__SIMULATE_NO_API_CONNECTIVITY_CLOUDFLARE', false ); + } + + if ( ! defined( 'FS_SDK__SIMULATE_NO_API_CONNECTIVITY_SQUID_ACL' ) ) { + define( 'FS_SDK__SIMULATE_NO_API_CONNECTIVITY_SQUID_ACL', false ); + } + + define( 'FS_SDK__HAS_CURL', ! FS_SDK__SIMULATE_NO_CURL && function_exists( 'curl_version' ) ); + + if ( ! FS_SDK__HAS_CURL ) { + $curl_version = array( 'version' => '7.0.0' ); + } else { + $curl_version = curl_version(); + } + + define( 'FS_API__PROTOCOL', version_compare( $curl_version['version'], '7.37', '>=' ) ? 'https' : 'http' ); + + if ( ! defined( 'FS_API__LOGGER_ON' ) ) { + define( 'FS_API__LOGGER_ON', false ); + } + + if ( ! defined( 'FS_API__ADDRESS' ) ) { + define( 'FS_API__ADDRESS', '://api.freemius.com' ); + } + if ( ! defined( 'FS_API__SANDBOX_ADDRESS' ) ) { + define( 'FS_API__SANDBOX_ADDRESS', '://sandbox-api.freemius.com' ); + } + + class Freemius_Api extends Freemius_Api_Base { + private static $_logger = array(); + + /** + * @param string $pScope 'app', 'developer', 'user' or 'install'. + * @param number $pID Element's id. + * @param string $pPublic Public key. + * @param string|bool $pSecret Element's secret key. + * @param bool $pSandbox Whether or not to run API in sandbox mode. + */ + public function __construct( $pScope, $pID, $pPublic, $pSecret = false, $pSandbox = false ) { + // If secret key not provided, use public key encryption. + if ( is_bool( $pSecret ) ) { + $pSecret = $pPublic; + } + + parent::Init( $pScope, $pID, $pPublic, $pSecret, $pSandbox ); + } + + public static function GetUrl( $pCanonizedPath = '', $pIsSandbox = false ) { + $address = ( $pIsSandbox ? FS_API__SANDBOX_ADDRESS : FS_API__ADDRESS ); + + if ( ':' === $address[0] ) { + $address = self::$_protocol . $address; + } + + return $address . $pCanonizedPath; + } + + #region Servers Clock Diff ------------------------------------------------------ + + /** + * @var int Clock diff in seconds between current server to API server. + */ + private static $_clock_diff = 0; + + /** + * Set clock diff for all API calls. + * + * @since 1.0.3 + * + * @param $pSeconds + */ + public static function SetClockDiff( $pSeconds ) { + self::$_clock_diff = $pSeconds; + } + + /** + * Find clock diff between current server to API server. + * + * @since 1.0.2 + * @return int Clock diff in seconds. + */ + public static function FindClockDiff() { + $time = time(); + $pong = self::Ping(); + + return ( $time - strtotime( $pong->timestamp ) ); + } + + #endregion Servers Clock Diff ------------------------------------------------------ + + /** + * @var string http or https + */ + private static $_protocol = FS_API__PROTOCOL; + + /** + * Set API connection protocol. + * + * @since 1.0.4 + */ + public static function SetHttp() { + self::$_protocol = 'http'; + } + + /** + * @since 1.0.4 + * + * @return bool + */ + public static function IsHttps() { + return ( 'https' === self::$_protocol ); + } + + /** + * Sign request with the following HTTP headers: + * Content-MD5: MD5(HTTP Request body) + * Date: Current date (i.e Sat, 14 Feb 2015 20:24:46 +0000) + * Authorization: FS {scope_entity_id}:{scope_entity_public_key}:base64encode(sha256(string_to_sign, + * {scope_entity_secret_key})) + * + * @param string $pResourceUrl + * @param array $pCurlOptions + * + * @return array + */ + function SignRequest( $pResourceUrl, $pCurlOptions ) { + $eol = "\n"; + $content_md5 = ''; + $now = ( time() - self::$_clock_diff ); + $date = date( 'r', $now ); + $content_type = ''; + + if ( isset( $pCurlOptions[ CURLOPT_POST ] ) && 0 < $pCurlOptions[ CURLOPT_POST ] ) { + $content_md5 = md5( $pCurlOptions[ CURLOPT_POSTFIELDS ] ); + $pCurlOptions[ CURLOPT_HTTPHEADER ][] = 'Content-MD5: ' . $content_md5; + $content_type = 'application/json'; + } + + $pCurlOptions[ CURLOPT_HTTPHEADER ][] = 'Date: ' . $date; + + $string_to_sign = implode( $eol, array( + $pCurlOptions[ CURLOPT_CUSTOMREQUEST ], + $content_md5, + $content_type, + $date, + $pResourceUrl + ) ); + + // If secret and public keys are identical, it means that + // the signature uses public key hash encoding. + $auth_type = ( $this->_secret !== $this->_public ) ? 'FS' : 'FSP'; + + // Add authorization header. + $pCurlOptions[ CURLOPT_HTTPHEADER ][] = 'Authorization: ' . + $auth_type . ' ' . + $this->_id . ':' . + $this->_public . ':' . + self::Base64UrlEncode( + hash_hmac( 'sha256', $string_to_sign, $this->_secret ) + ); + + return $pCurlOptions; + } + + /** + * Get API request URL signed via query string. + * + * @param string $pPath + * + * @throws Freemius_Exception + * + * @return string + */ + function GetSignedUrl( $pPath ) { + $resource = explode( '?', $this->CanonizePath( $pPath ) ); + $pResourceUrl = $resource[0]; + + $eol = "\n"; + $content_md5 = ''; + $content_type = ''; + $now = ( time() - self::$_clock_diff ); + $date = date( 'r', $now ); + + $string_to_sign = implode( $eol, array( + 'GET', + $content_md5, + $content_type, + $date, + $pResourceUrl + ) ); + + // If secret and public keys are identical, it means that + // the signature uses public key hash encoding. + $auth_type = ( $this->_secret !== $this->_public ) ? 'FS' : 'FSP'; + + return Freemius_Api::GetUrl( + $pResourceUrl . '?' . + ( 1 < count( $resource ) && ! empty( $resource[1] ) ? $resource[1] . '&' : '' ) . + http_build_query( array( + 'auth_date' => $date, + 'authorization' => $auth_type . ' ' . $this->_id . ':' . + $this->_public . ':' . + self::Base64UrlEncode( hash_hmac( + 'sha256', $string_to_sign, $this->_secret + ) ) + ) ), $this->_isSandbox ); + } + + /** + * @param resource $pCurlHandler + * @param array $pCurlOptions + * + * @return mixed + */ + private static function ExecuteRequest( &$pCurlHandler, &$pCurlOptions ) { + $start = microtime( true ); + + $result = curl_exec( $pCurlHandler ); + + if ( FS_API__LOGGER_ON ) { + $end = microtime( true ); + + $has_body = ( isset( $pCurlOptions[ CURLOPT_POST ] ) && 0 < $pCurlOptions[ CURLOPT_POST ] ); + + self::$_logger[] = array( + 'id' => count( self::$_logger ), + 'start' => $start, + 'end' => $end, + 'total' => ( $end - $start ), + 'method' => $pCurlOptions[ CURLOPT_CUSTOMREQUEST ], + 'path' => $pCurlOptions[ CURLOPT_URL ], + 'body' => $has_body ? $pCurlOptions[ CURLOPT_POSTFIELDS ] : null, + 'result' => $result, + 'code' => curl_getinfo( $pCurlHandler, CURLINFO_HTTP_CODE ), + 'backtrace' => debug_backtrace(), + ); + } + + return $result; + } + + /** + * @return array + */ + static function GetLogger() { + return self::$_logger; + } + + /** + * @param string $pCanonizedPath + * @param string $pMethod + * @param array $pParams + * @param null|resource $pCurlHandler + * @param bool $pIsSandbox + * @param null|callable $pBeforeExecutionFunction + * + * @return object[]|object|null + * + * @throws \Freemius_Exception + */ + private static function MakeStaticRequest( + $pCanonizedPath, + $pMethod = 'GET', + $pParams = array(), + $pCurlHandler = null, + $pIsSandbox = false, + $pBeforeExecutionFunction = null + ) { + if ( ! FS_SDK__HAS_CURL ) { + self::ThrowNoCurlException(); + } + + // Connectivity errors simulation. + if ( FS_SDK__SIMULATE_NO_API_CONNECTIVITY_CLOUDFLARE ) { + self::ThrowCloudFlareDDoSException(); + } else if ( FS_SDK__SIMULATE_NO_API_CONNECTIVITY_SQUID_ACL ) { + self::ThrowSquidAclException(); + } + + if ( ! $pCurlHandler ) { + $pCurlHandler = curl_init(); + } + + $opts = array( + CURLOPT_CONNECTTIMEOUT => 10, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_TIMEOUT => 60, + CURLOPT_USERAGENT => FS_SDK__USER_AGENT, + ); + + if ( ! isset( $opts[ CURLOPT_HTTPHEADER ] ) || ! is_array( $opts[ CURLOPT_HTTPHEADER ] ) ) { + $opts[ CURLOPT_HTTPHEADER ] = array(); + } + + if ( 'POST' === $pMethod || 'PUT' === $pMethod ) { + if ( is_array( $pParams ) && 0 < count( $pParams ) ) { + $opts[ CURLOPT_HTTPHEADER ][] = 'Content-Type: application/json'; + $opts[ CURLOPT_POST ] = count( $pParams ); + $opts[ CURLOPT_POSTFIELDS ] = json_encode( $pParams ); + } + + $opts[ CURLOPT_RETURNTRANSFER ] = true; + } + + $opts[ CURLOPT_URL ] = Freemius_Api::GetUrl( $pCanonizedPath, $pIsSandbox ); + $opts[ CURLOPT_CUSTOMREQUEST ] = $pMethod; + + $resource = explode( '?', $pCanonizedPath ); + + // disable the 'Expect: 100-continue' behaviour. This causes CURL to wait + // for 2 seconds if the server does not support this header. + $opts[ CURLOPT_HTTPHEADER ][] = 'Expect:'; + + if ( 'https' === substr( strtolower( $pCanonizedPath ), 0, 5 ) ) { + $opts[ CURLOPT_SSL_VERIFYHOST ] = false; + $opts[ CURLOPT_SSL_VERIFYPEER ] = false; + } + + if ( false !== $pBeforeExecutionFunction && + is_callable( $pBeforeExecutionFunction ) + ) { + $opts = call_user_func( $pBeforeExecutionFunction, $resource[0], $opts ); + } + + curl_setopt_array( $pCurlHandler, $opts ); + $result = self::ExecuteRequest( $pCurlHandler, $opts ); + + /*if (curl_errno($ch) == 60) // CURLE_SSL_CACERT + { + self::errorLog('Invalid or no certificate authority found, using bundled information'); + curl_setopt($ch, CURLOPT_CAINFO, + dirname(__FILE__) . '/fb_ca_chain_bundle.crt'); + $result = curl_exec($ch); + }*/ + + // With dual stacked DNS responses, it's possible for a server to + // have IPv6 enabled but not have IPv6 connectivity. If this is + // the case, curl will try IPv4 first and if that fails, then it will + // fall back to IPv6 and the error EHOSTUNREACH is returned by the + // operating system. + if ( false === $result && empty( $opts[ CURLOPT_IPRESOLVE ] ) ) { + $matches = array(); + $regex = '/Failed to connect to ([^:].*): Network is unreachable/'; + if ( preg_match( $regex, curl_error( $pCurlHandler ), $matches ) ) { + if ( strlen( @inet_pton( $matches[1] ) ) === 16 ) { +// self::errorLog('Invalid IPv6 configuration on server, Please disable or get native IPv6 on your server.'); + $opts[ CURLOPT_IPRESOLVE ] = CURL_IPRESOLVE_V4; + curl_setopt( $pCurlHandler, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 ); + $result = self::ExecuteRequest( $pCurlHandler, $opts ); + } + } + } + + if ( $result === false ) { + self::ThrowCurlException( $pCurlHandler ); + } + + curl_close( $pCurlHandler ); + + if ( empty( $result ) ) { + return null; + } + + $decoded = json_decode( $result ); + + if ( is_null( $decoded ) ) { + if ( preg_match( '/Please turn JavaScript on/i', $result ) && + preg_match( '/text\/javascript/', $result ) + ) { + self::ThrowCloudFlareDDoSException( $result ); + } else if ( preg_match( '/Access control configuration prevents your request from being allowed at this time. Please contact your service provider if you feel this is incorrect./', $result ) && + preg_match( '/squid/', $result ) + ) { + self::ThrowSquidAclException( $result ); + } else { + $decoded = (object) array( + 'error' => (object) array( + 'type' => 'Unknown', + 'message' => $result, + 'code' => 'unknown', + 'http' => 402 + ) + ); + } + } + + return $decoded; + } + + + /** + * Makes an HTTP request. This method can be overridden by subclasses if + * developers want to do fancier things or use something other than curl to + * make the request. + * + * @param string $pCanonizedPath The URL to make the request to + * @param string $pMethod HTTP method + * @param array $pParams The parameters to use for the POST body + * @param null|resource $pCurlHandler Initialized curl handle + * + * @return object[]|object|null + * + * @throws Freemius_Exception + */ + public function MakeRequest( + $pCanonizedPath, + $pMethod = 'GET', + $pParams = array(), + $pCurlHandler = null + ) { + $resource = explode( '?', $pCanonizedPath ); + + // Only sign request if not ping.json connectivity test. + $sign_request = ( '/v1/ping.json' !== strtolower( substr( $resource[0], - strlen( '/v1/ping.json' ) ) ) ); + + return self::MakeStaticRequest( + $pCanonizedPath, + $pMethod, + $pParams, + $pCurlHandler, + $this->_isSandbox, + $sign_request ? array( &$this, 'SignRequest' ) : null + ); + } + + #region Connectivity Test ------------------------------------------------------ + + /** + * If successful connectivity to the API endpoint using ping.json endpoint. + * + * - OR - + * + * Validate if ping result object is valid. + * + * @param mixed $pPong + * + * @return bool + */ + public static function Test( $pPong = null ) { + $pong = is_null( $pPong ) ? + self::Ping() : + $pPong; + + return ( + is_object( $pong ) && + isset( $pong->api ) && + 'pong' === $pong->api + ); + } + + /** + * Ping API to test connectivity. + * + * @return object + */ + public static function Ping() { + try { + $result = self::MakeStaticRequest( '/v' . FS_API__VERSION . '/ping.json' ); + } catch ( Freemius_Exception $e ) { + // Map to error object. + $result = (object) $e->getResult(); + } catch ( Exception $e ) { + // Map to error object. + $result = (object) array( + 'error' => array( + 'type' => 'Unknown', + 'message' => $e->getMessage() . ' (' . $e->getFile() . ': ' . $e->getLine() . ')', + 'code' => 'unknown', + 'http' => 402 + ) + ); + } + + return $result; + } + + #endregion Connectivity Test ------------------------------------------------------ + + #region Connectivity Exceptions ------------------------------------------------------ + + /** + * @param resource $pCurlHandler + * + * @throws Freemius_Exception + */ + private static function ThrowCurlException( $pCurlHandler ) { + $e = new Freemius_Exception( array( + 'error' => array( + 'code' => curl_errno( $pCurlHandler ), + 'message' => curl_error( $pCurlHandler ), + 'type' => 'CurlException', + ), + ) ); + + curl_close( $pCurlHandler ); + throw $e; + } + + /** + * @param string $pResult + * + * @throws Freemius_Exception + */ + private static function ThrowNoCurlException( $pResult = '' ) { + throw new Freemius_Exception( array( + 'error' => (object) array( + 'type' => 'cUrlMissing', + 'message' => $pResult, + 'code' => 'curl_missing', + 'http' => 402 + ) + ) ); + } + + /** + * @param string $pResult + * + * @throws Freemius_Exception + */ + private static function ThrowCloudFlareDDoSException( $pResult = '' ) { + throw new Freemius_Exception( array( + 'error' => (object) array( + 'type' => 'CloudFlareDDoSProtection', + 'message' => $pResult, + 'code' => 'cloudflare_ddos_protection', + 'http' => 402 + ) + ) ); + } + + /** + * @param string $pResult + * + * @throws Freemius_Exception + */ + private static function ThrowSquidAclException( $pResult = '' ) { + throw new Freemius_Exception( array( + 'error' => (object) array( + 'type' => 'SquidCacheBlock', + 'message' => $pResult, + 'code' => 'squid_cache_block', + 'http' => 402 + ) + ) ); + } + + #endregion Connectivity Exceptions ------------------------------------------------------ } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/includes/sdk/FreemiusBase.php b/wp-content/plugins/nextgen-gallery/freemius/includes/sdk/FreemiusBase.php index 921623a03f59118e48642d3ddeff89abde7c2644..efe58156709364c445f21f6112436380ebae3a56 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/includes/sdk/FreemiusBase.php +++ b/wp-content/plugins/nextgen-gallery/freemius/includes/sdk/FreemiusBase.php @@ -1,178 +1,178 @@ -<?php - /** - * Copyright 2014 Freemius, Inc. - * - * Licensed under the GPL v2 (the "License"); you may - * not use this file except in compliance with the License. You may obtain - * a copy of the License at - * - * http://choosealicense.com/licenses/gpl-v2/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - - define( 'FS_API__VERSION', '1' ); - define( 'FS_SDK__PATH', dirname( __FILE__ ) ); - define( 'FS_SDK__EXCEPTIONS_PATH', FS_SDK__PATH . '/Exceptions/' ); - - if ( ! function_exists( 'json_decode' ) ) { - throw new Exception( 'Freemius needs the JSON PHP extension.' ); - } - - // Include all exception files. - $exceptions = array( - 'Exception', - 'InvalidArgumentException', - 'ArgumentNotExistException', - 'EmptyArgumentException', - 'OAuthException' - ); - - foreach ( $exceptions as $e ) { - require FS_SDK__EXCEPTIONS_PATH . $e . '.php'; - } - - abstract class Freemius_Api_Base { - const VERSION = '1.0.4'; - const FORMAT = 'json'; - - protected $_id; - protected $_public; - protected $_secret; - protected $_scope; - protected $_isSandbox; - - /** - * @param string $pScope 'app', 'developer', 'user' or 'install'. - * @param number $pID Element's id. - * @param string $pPublic Public key. - * @param string $pSecret Element's secret key. - * @param bool $pIsSandbox Whether or not to run API in sandbox mode. - */ - public function Init( $pScope, $pID, $pPublic, $pSecret, $pIsSandbox = false ) { - $this->_id = $pID; - $this->_public = $pPublic; - $this->_secret = $pSecret; - $this->_scope = $pScope; - $this->_isSandbox = $pIsSandbox; - } - - public function IsSandbox() { - return $this->_isSandbox; - } - - function CanonizePath( $pPath ) { - $pPath = trim( $pPath, '/' ); - $query_pos = strpos( $pPath, '?' ); - $query = ''; - - if ( false !== $query_pos ) { - $query = substr( $pPath, $query_pos ); - $pPath = substr( $pPath, 0, $query_pos ); - } - - // Trim '.json' suffix. - $format_length = strlen( '.' . self::FORMAT ); - $start = $format_length * ( - 1 ); //negative - if ( substr( strtolower( $pPath ), $start ) === ( '.' . self::FORMAT ) ) { - $pPath = substr( $pPath, 0, strlen( $pPath ) - $format_length ); - } - - switch ( $this->_scope ) { - case 'app': - $base = '/apps/' . $this->_id; - break; - case 'developer': - $base = '/developers/' . $this->_id; - break; - case 'user': - $base = '/users/' . $this->_id; - break; - case 'plugin': - $base = '/plugins/' . $this->_id; - break; - case 'install': - $base = '/installs/' . $this->_id; - break; - default: - throw new Freemius_Exception( 'Scope not implemented.' ); - } - - return '/v' . FS_API__VERSION . $base . - ( ! empty( $pPath ) ? '/' : '' ) . $pPath . - ( ( false === strpos( $pPath, '.' ) ) ? '.' . self::FORMAT : '' ) . $query; - } - - abstract function MakeRequest( $pCanonizedPath, $pMethod = 'GET', $pParams = array() ); - - /** - * @param string $pPath - * @param string $pMethod - * @param array $pParams - * - * @return object[]|object|null - */ - private function _Api( $pPath, $pMethod = 'GET', $pParams = array() ) { - $pMethod = strtoupper( $pMethod ); - - try { - $result = $this->MakeRequest( $pPath, $pMethod, $pParams ); - } catch ( Freemius_Exception $e ) { - // Map to error object. - $result = (object) $e->getResult(); - } catch ( Exception $e ) { - // Map to error object. - $result = (object) array( - 'error' => array( - 'type' => 'Unknown', - 'message' => $e->getMessage() . ' (' . $e->getFile() . ': ' . $e->getLine() . ')', - 'code' => 'unknown', - 'http' => 402 - ) - ); - } - - return $result; - } - - public function Api( $pPath, $pMethod = 'GET', $pParams = array() ) { - return $this->_Api( $this->CanonizePath( $pPath ), $pMethod, $pParams ); - } - - /** - * Base64 encoding that does not need to be urlencode()ed. - * Exactly the same as base64_encode except it uses - * - instead of + - * _ instead of / - * No padded = - * - * @param string $input base64UrlEncoded string - * - * @return string - */ - protected static function Base64UrlDecode( $input ) { - return base64_decode( strtr( $input, '-_', '+/' ) ); - } - - /** - * Base64 encoding that does not need to be urlencode()ed. - * Exactly the same as base64_encode except it uses - * - instead of + - * _ instead of / - * - * @param string $input string - * - * @return string base64Url encoded string - */ - protected static function Base64UrlEncode( $input ) { - $str = strtr( base64_encode( $input ), '+/', '-_' ); - $str = str_replace( '=', '', $str ); - - return $str; - } - - } +<?php + /** + * Copyright 2014 Freemius, Inc. + * + * Licensed under the GPL v2 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://choosealicense.com/licenses/gpl-v2/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + + define( 'FS_API__VERSION', '1' ); + define( 'FS_SDK__PATH', dirname( __FILE__ ) ); + define( 'FS_SDK__EXCEPTIONS_PATH', FS_SDK__PATH . '/Exceptions/' ); + + if ( ! function_exists( 'json_decode' ) ) { + throw new Exception( 'Freemius needs the JSON PHP extension.' ); + } + + // Include all exception files. + $exceptions = array( + 'Exception', + 'InvalidArgumentException', + 'ArgumentNotExistException', + 'EmptyArgumentException', + 'OAuthException' + ); + + foreach ( $exceptions as $e ) { + require FS_SDK__EXCEPTIONS_PATH . $e . '.php'; + } + + abstract class Freemius_Api_Base { + const VERSION = '1.0.4'; + const FORMAT = 'json'; + + protected $_id; + protected $_public; + protected $_secret; + protected $_scope; + protected $_isSandbox; + + /** + * @param string $pScope 'app', 'developer', 'user' or 'install'. + * @param number $pID Element's id. + * @param string $pPublic Public key. + * @param string $pSecret Element's secret key. + * @param bool $pIsSandbox Whether or not to run API in sandbox mode. + */ + public function Init( $pScope, $pID, $pPublic, $pSecret, $pIsSandbox = false ) { + $this->_id = $pID; + $this->_public = $pPublic; + $this->_secret = $pSecret; + $this->_scope = $pScope; + $this->_isSandbox = $pIsSandbox; + } + + public function IsSandbox() { + return $this->_isSandbox; + } + + function CanonizePath( $pPath ) { + $pPath = trim( $pPath, '/' ); + $query_pos = strpos( $pPath, '?' ); + $query = ''; + + if ( false !== $query_pos ) { + $query = substr( $pPath, $query_pos ); + $pPath = substr( $pPath, 0, $query_pos ); + } + + // Trim '.json' suffix. + $format_length = strlen( '.' . self::FORMAT ); + $start = $format_length * ( - 1 ); //negative + if ( substr( strtolower( $pPath ), $start ) === ( '.' . self::FORMAT ) ) { + $pPath = substr( $pPath, 0, strlen( $pPath ) - $format_length ); + } + + switch ( $this->_scope ) { + case 'app': + $base = '/apps/' . $this->_id; + break; + case 'developer': + $base = '/developers/' . $this->_id; + break; + case 'user': + $base = '/users/' . $this->_id; + break; + case 'plugin': + $base = '/plugins/' . $this->_id; + break; + case 'install': + $base = '/installs/' . $this->_id; + break; + default: + throw new Freemius_Exception( 'Scope not implemented.' ); + } + + return '/v' . FS_API__VERSION . $base . + ( ! empty( $pPath ) ? '/' : '' ) . $pPath . + ( ( false === strpos( $pPath, '.' ) ) ? '.' . self::FORMAT : '' ) . $query; + } + + abstract function MakeRequest( $pCanonizedPath, $pMethod = 'GET', $pParams = array() ); + + /** + * @param string $pPath + * @param string $pMethod + * @param array $pParams + * + * @return object[]|object|null + */ + private function _Api( $pPath, $pMethod = 'GET', $pParams = array() ) { + $pMethod = strtoupper( $pMethod ); + + try { + $result = $this->MakeRequest( $pPath, $pMethod, $pParams ); + } catch ( Freemius_Exception $e ) { + // Map to error object. + $result = (object) $e->getResult(); + } catch ( Exception $e ) { + // Map to error object. + $result = (object) array( + 'error' => array( + 'type' => 'Unknown', + 'message' => $e->getMessage() . ' (' . $e->getFile() . ': ' . $e->getLine() . ')', + 'code' => 'unknown', + 'http' => 402 + ) + ); + } + + return $result; + } + + public function Api( $pPath, $pMethod = 'GET', $pParams = array() ) { + return $this->_Api( $this->CanonizePath( $pPath ), $pMethod, $pParams ); + } + + /** + * Base64 encoding that does not need to be urlencode()ed. + * Exactly the same as base64_encode except it uses + * - instead of + + * _ instead of / + * No padded = + * + * @param string $input base64UrlEncoded string + * + * @return string + */ + protected static function Base64UrlDecode( $input ) { + return base64_decode( strtr( $input, '-_', '+/' ) ); + } + + /** + * Base64 encoding that does not need to be urlencode()ed. + * Exactly the same as base64_encode except it uses + * - instead of + + * _ instead of / + * + * @param string $input string + * + * @return string base64Url encoded string + */ + protected static function Base64UrlEncode( $input ) { + $str = strtr( base64_encode( $input ), '+/', '-_' ); + $str = str_replace( '=', '', $str ); + + return $str; + } + + } diff --git a/wp-content/plugins/nextgen-gallery/freemius/includes/supplements/fs-essential-functions-1.1.7.1.php b/wp-content/plugins/nextgen-gallery/freemius/includes/supplements/fs-essential-functions-1.1.7.1.php index 2f0a67aad8891c922c79fec25ffd46beca4d11bf..a94f9899de5d1575b43e19406cc7d5cf8cfe9023 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/includes/supplements/fs-essential-functions-1.1.7.1.php +++ b/wp-content/plugins/nextgen-gallery/freemius/includes/supplements/fs-essential-functions-1.1.7.1.php @@ -1,45 +1,45 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.1.7 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - /** - * Find the plugin main file path based on any give file inside the plugin's folder. - * - * @author Vova Feldman (@svovaf) - * @since 1.1.7.1 - * - * @param string $file Absolute path to a file inside a plugin's folder. - * - * @return string - */ - function fs_find_direct_caller_plugin_file( $file ) { - /** - * All the code below will be executed once on activation. - * If the user changes the main plugin's file name, the file_exists() - * will catch it. - */ - if ( ! function_exists( 'get_plugins' ) ) { - require_once( ABSPATH . 'wp-admin/includes/plugin.php' ); - } - - $all_plugins = get_plugins(); - - $file_real_path = fs_normalize_path( realpath( $file ) ); - - // Get active plugin's main files real full names (might be symlinks). - foreach ( $all_plugins as $relative_path => &$data ) { - if ( 0 === strpos( $file_real_path, fs_normalize_path( dirname( realpath( WP_PLUGIN_DIR . '/' . $relative_path ) ) ) ) ) { - return $relative_path; - } - } - - return null; +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.1.7 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + /** + * Find the plugin main file path based on any give file inside the plugin's folder. + * + * @author Vova Feldman (@svovaf) + * @since 1.1.7.1 + * + * @param string $file Absolute path to a file inside a plugin's folder. + * + * @return string + */ + function fs_find_direct_caller_plugin_file( $file ) { + /** + * All the code below will be executed once on activation. + * If the user changes the main plugin's file name, the file_exists() + * will catch it. + */ + if ( ! function_exists( 'get_plugins' ) ) { + require_once( ABSPATH . 'wp-admin/includes/plugin.php' ); + } + + $all_plugins = get_plugins(); + + $file_real_path = fs_normalize_path( realpath( $file ) ); + + // Get active plugin's main files real full names (might be symlinks). + foreach ( $all_plugins as $relative_path => &$data ) { + if ( 0 === strpos( $file_real_path, fs_normalize_path( dirname( realpath( WP_PLUGIN_DIR . '/' . $relative_path ) ) ) ) ) { + return $relative_path; + } + } + + return null; } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/start.php b/wp-content/plugins/nextgen-gallery/freemius/start.php index b245c6be97661ef25fc59083a3141658c5e32e34..eba031309f73922bd7defbdd4ad8205c1ba19ecb 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/start.php +++ b/wp-content/plugins/nextgen-gallery/freemius/start.php @@ -1,341 +1,341 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.3 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - /** - * Freemius SDK Version. - * - * @var string - */ - $this_sdk_version = '1.1.8.1'; - - #region SDK Selection Logic -------------------------------------------------------------------- - - /** - * Special logic added on 1.1.6 to make sure that every Freemius powered plugin - * will ALWAYS be loaded with the newest SDK from the active Freemius powered plugins. - * - * Since Freemius SDK is backward compatible, this will make sure that all Freemius powered - * plugins will run correctly. - * - * @since 1.1.6 - */ - - global $fs_active_plugins; - - $this_sdk_relative_path = plugin_basename( dirname( __FILE__ ) ); - - if ( ! isset( $fs_active_plugins ) ) { - // Require SDK essentials. - require_once dirname( __FILE__ ) . '/includes/fs-essential-functions.php'; - - // Load all Freemius powered active plugins. - $fs_active_plugins = get_option( 'fs_active_plugins', new stdClass() ); - - if ( ! isset( $fs_active_plugins->plugins ) ) { - $fs_active_plugins->plugins = array(); - } - } - - if ( ! function_exists( 'fs_find_direct_caller_plugin_file' ) ) { - require_once dirname( __FILE__ ) . '/includes/supplements/fs-essential-functions-1.1.7.1.php'; - } - - // Update current SDK info based on the SDK path. - if ( ! isset( $fs_active_plugins->plugins[ $this_sdk_relative_path ] ) || - $this_sdk_version != $fs_active_plugins->plugins[ $this_sdk_relative_path ]->version - ) { - $fs_active_plugins->plugins[ $this_sdk_relative_path ] = (object) array( - 'version' => $this_sdk_version, - 'timestamp' => time(), - 'plugin_path' => plugin_basename( fs_find_direct_caller_plugin_file( __FILE__ ) ), - ); - } - - $is_current_sdk_newest = isset( $fs_active_plugins->newest ) && ( $this_sdk_relative_path == $fs_active_plugins->newest->sdk_path ); - - if ( ! isset( $fs_active_plugins->newest ) ) { - /** - * This will be executed only once, for the first time a Freemius powered plugin is activated. - */ - fs_update_sdk_newest_version( $this_sdk_relative_path, $fs_active_plugins->plugins[ $this_sdk_relative_path ]->plugin_path ); - - $is_current_sdk_newest = true; - } else if ( version_compare( $fs_active_plugins->newest->version, $this_sdk_version, '<' ) ) { - /** - * Current SDK is newer than the newest stored SDK. - */ - fs_update_sdk_newest_version( $this_sdk_relative_path, $fs_active_plugins->plugins[ $this_sdk_relative_path ]->plugin_path ); - - if ( class_exists( 'Freemius' ) ) { - // Older SDK version was already loaded. - - if ( ! $fs_active_plugins->newest->in_activation ) { - // Re-order plugins to load this plugin first. - fs_newest_sdk_plugin_first(); - } - - // Refresh page. - if ( fs_redirect( $_SERVER['REQUEST_URI'] ) ) { - exit(); - } - } - } else { - if ( ! function_exists( 'get_plugins' ) ) { - require_once( ABSPATH . 'wp-admin/includes/plugin.php' ); - } - - $is_newest_sdk_plugin_activate = is_plugin_active( $fs_active_plugins->newest->plugin_path ); - - if ( $is_current_sdk_newest && - ! $is_newest_sdk_plugin_activate && - ! $fs_active_plugins->newest->in_activation - ) { - // If current SDK is the newest and the plugin is NOT active, it means - // that the current plugin in activation mode. - $fs_active_plugins->newest->in_activation = true; - update_option( 'fs_active_plugins', $fs_active_plugins ); - } - - $is_newest_sdk_path_valid = ( $is_newest_sdk_plugin_activate || $fs_active_plugins->newest->in_activation ) && file_exists( fs_normalize_path( WP_PLUGIN_DIR . '/' . $this_sdk_relative_path . '/start.php' ) ); - - if ( ! $is_newest_sdk_path_valid && ! $is_current_sdk_newest ) { - // Plugin with newest SDK is no longer active, or SDK was moved to a different location. - unset( $fs_active_plugins->plugins[ $fs_active_plugins->newest->sdk_path ] ); - } - - if ( ! ( $is_newest_sdk_plugin_activate || $fs_active_plugins->newest->in_activation ) || - ! $is_newest_sdk_path_valid || - // Is newest SDK downgraded. - ( $this_sdk_relative_path == $fs_active_plugins->newest->sdk_path && - version_compare( $fs_active_plugins->newest->version, $this_sdk_version, '>' ) ) - ) { - /** - * Plugin with newest SDK is no longer active. - * OR - * The newest SDK was in the current plugin. BUT, seems like the version of - * the SDK was downgraded to a lower SDK. - */ - // Find the active plugin with the newest SDK version and update the newest reference. - fs_fallback_to_newest_active_sdk(); - } else { - if ( $is_newest_sdk_plugin_activate && - $this_sdk_relative_path == $fs_active_plugins->newest->sdk_path && - ( $fs_active_plugins->newest->in_activation || - ( class_exists( 'Freemius' ) && ( ! defined( 'WP_FS__SDK_VERSION' ) || version_compare( WP_FS__SDK_VERSION, $this_sdk_version, '<' ) ) ) - ) - - ) { - if ( $fs_active_plugins->newest->in_activation ) { - // Plugin no more in activation. - $fs_active_plugins->newest->in_activation = false; - update_option( 'fs_active_plugins', $fs_active_plugins ); - } - - // Reorder plugins to load plugin with newest SDK first. - if ( fs_newest_sdk_plugin_first() ) { - // Refresh page after re-order to make sure activated plugin loads newest SDK. - if ( class_exists( 'Freemius' ) ) { - if ( fs_redirect( $_SERVER['REQUEST_URI'] ) ) { - exit(); - } - } - } - } - } - } - - if ( class_exists( 'Freemius' ) ) { - // SDK was already loaded. - return; - } - - if ( version_compare( $this_sdk_version, $fs_active_plugins->newest->version, '<' ) ) { - $newest_sdk_starter = fs_normalize_path( WP_PLUGIN_DIR . '/' . $fs_active_plugins->newest->sdk_path . '/start.php' ); - - if ( file_exists( $newest_sdk_starter ) ) { - // Reorder plugins to load plugin with newest SDK first. - fs_newest_sdk_plugin_first(); - - // There's a newer SDK version, load it instead of the current one! - require_once $newest_sdk_starter; - - return; - } - } - - #endregion SDK Selection Logic -------------------------------------------------------------------- - - #region Hooks & Filters Collection -------------------------------------------------------------------- - - /** - * Freemius hooks (actions & filters) tags structure: - * - * fs_{filter/action_name}_{plugin_slug} - * - * -------------------------------------------------------- - * - * Usage with WordPress' add_action() / add_filter(): - * - * add_action('fs_{filter/action_name}_{plugin_slug}', $callable); - * - * -------------------------------------------------------- - * - * Usage with Freemius' instance add_action() / add_filter(): - * - * // No need to add 'fs_' prefix nor '_{plugin_slug}' suffix. - * my_freemius()->add_action('{action_name}', $callable); - * - * -------------------------------------------------------- - * - * Freemius filters collection: - * - * fs_connect_url_{plugin_slug} - * fs_trial_promotion_message_{plugin_slug} - * fs_is_long_term_user_{plugin_slug} - * fs_uninstall_reasons_{plugin_slug} - * fs_is_plugin_update_{plugin_slug} - * fs_api_domains_{plugin_slug} - * fs_email_template_sections_{plugin_slug} - * fs_support_forum_submenu_{plugin_slug} - * fs_support_forum_url_{plugin_slug} - * fs_connect_message_{plugin_slug} - * fs_connect_message_on_update_{plugin_slug} - * fs_uninstall_confirmation_message_{plugin_slug} - * fs_pending_activation_message_{plugin_slug} - * fs_is_submenu_visible_{plugin_slug} - * fs_plugin_icon_{plugin_slug} - * fs_show_trial_{plugin_slug} - * - * -------------------------------------------------------- - * - * Freemius actions collection: - * - * fs_after_license_loaded_{plugin_slug} - * fs_after_license_change_{plugin_slug} - * fs_after_plans_sync_{plugin_slug} - * - * fs_after_account_details_{plugin_slug} - * fs_after_account_user_sync_{plugin_slug} - * fs_after_account_plan_sync_{plugin_slug} - * fs_before_account_load_{plugin_slug} - * fs_after_account_connection_{plugin_slug} - * fs_account_property_edit_{plugin_slug} - * fs_account_email_verified_{plugin_slug} - * fs_account_page_load_before_departure_{plugin_slug} - * fs_before_account_delete_{plugin_slug} - * fs_after_account_delete_{plugin_slug} - * - * fs_sdk_version_update_{plugin_slug} - * fs_plugin_version_update_{plugin_slug} - * - * fs_initiated_{plugin_slug} - * fs_after_init_plugin_registered_{plugin_slug} - * fs_after_init_plugin_anonymous_{plugin_slug} - * fs_after_init_plugin_pending_activations_{plugin_slug} - * fs_after_init_addon_registered_{plugin_slug} - * fs_after_init_addon_anonymous_{plugin_slug} - * fs_after_init_addon_pending_activations_{plugin_slug} - * - * fs_after_premium_version_activation_{plugin_slug} - * fs_after_free_version_reactivation_{plugin_slug} - * - * fs_after_uninstall_{plugin_slug} - * fs_before_admin_menu_init_{plugin_slug} - */ - - #endregion Hooks & Filters Collection -------------------------------------------------------------------- - - if ( ! class_exists( 'Freemius' ) ) { - - if ( ! defined( 'WP_FS__SDK_VERSION' ) ) { - define( 'WP_FS__SDK_VERSION', $this_sdk_version ); - } - - // Configuration should be loaded first. - require_once dirname( __FILE__ ) . '/config.php'; - - // Logger must be loaded before any other. - require_once WP_FS__DIR_INCLUDES . '/class-fs-logger.php'; - require_once WP_FS__DIR_INCLUDES . '/debug/debug-bar-start.php'; - - require_once WP_FS__DIR_INCLUDES . '/fs-core-functions.php'; -// require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-abstract-manager.php'; - require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-option-manager.php'; - require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-cache-manager.php'; - require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-admin-notice-manager.php'; - require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-admin-menu-manager.php'; - require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-key-value-storage.php'; - require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-license-manager.php'; - require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-plan-manager.php'; - require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-plugin-manager.php'; - require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-entity.php'; - require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-scope-entity.php'; - require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-user.php'; - require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-site.php'; - require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-plugin.php'; - require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-plugin-info.php'; - require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-plugin-tag.php'; - require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-plugin-plan.php'; - require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-pricing.php'; - require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-plugin-license.php'; - require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-subscription.php'; - require_once WP_FS__DIR_INCLUDES . '/class-fs-api.php'; - require_once WP_FS__DIR_INCLUDES . '/class-fs-plugin-updater.php'; - require_once WP_FS__DIR_INCLUDES . '/class-fs-security.php'; - require_once WP_FS__DIR_INCLUDES . '/class-freemius-abstract.php'; - require_once WP_FS__DIR_INCLUDES . '/class-freemius.php'; - - /** - * Quick shortcut to get Freemius for specified plugin. - * Used by various templates. - * - * @param string $slug - * - * @return Freemius - */ - function freemius( $slug ) { - return Freemius::instance( $slug ); - } - - /** - * @param string $slug - * @param number $plugin_id - * @param string $public_key - * @param bool $is_live Is live or test plugin. - * @param bool $is_premium Hints freemius if running the premium plugin or not. - * - * @return Freemius - */ - function fs_init( $slug, $plugin_id, $public_key, $is_live = true, $is_premium = true ) { - $fs = Freemius::instance( $slug ); - $fs->init( $plugin_id, $public_key, $is_live, $is_premium ); - - return $fs; - } - - /** - * @param array [string]string $plugin - * - * @return Freemius - * @throws Freemius_Exception - */ - function fs_dynamic_init( $plugin ) { - $fs = Freemius::instance( $plugin['slug'] ); - $fs->dynamic_init( $plugin ); - - return $fs; - } - - function fs_dump_log() { - FS_Logger::dump(); - } +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.3 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + /** + * Freemius SDK Version. + * + * @var string + */ + $this_sdk_version = '1.1.8.1'; + + #region SDK Selection Logic -------------------------------------------------------------------- + + /** + * Special logic added on 1.1.6 to make sure that every Freemius powered plugin + * will ALWAYS be loaded with the newest SDK from the active Freemius powered plugins. + * + * Since Freemius SDK is backward compatible, this will make sure that all Freemius powered + * plugins will run correctly. + * + * @since 1.1.6 + */ + + global $fs_active_plugins; + + $this_sdk_relative_path = plugin_basename( dirname( __FILE__ ) ); + + if ( ! isset( $fs_active_plugins ) ) { + // Require SDK essentials. + require_once dirname( __FILE__ ) . '/includes/fs-essential-functions.php'; + + // Load all Freemius powered active plugins. + $fs_active_plugins = get_option( 'fs_active_plugins', new stdClass() ); + + if ( ! isset( $fs_active_plugins->plugins ) ) { + $fs_active_plugins->plugins = array(); + } + } + + if ( ! function_exists( 'fs_find_direct_caller_plugin_file' ) ) { + require_once dirname( __FILE__ ) . '/includes/supplements/fs-essential-functions-1.1.7.1.php'; + } + + // Update current SDK info based on the SDK path. + if ( ! isset( $fs_active_plugins->plugins[ $this_sdk_relative_path ] ) || + $this_sdk_version != $fs_active_plugins->plugins[ $this_sdk_relative_path ]->version + ) { + $fs_active_plugins->plugins[ $this_sdk_relative_path ] = (object) array( + 'version' => $this_sdk_version, + 'timestamp' => time(), + 'plugin_path' => plugin_basename( fs_find_direct_caller_plugin_file( __FILE__ ) ), + ); + } + + $is_current_sdk_newest = isset( $fs_active_plugins->newest ) && ( $this_sdk_relative_path == $fs_active_plugins->newest->sdk_path ); + + if ( ! isset( $fs_active_plugins->newest ) ) { + /** + * This will be executed only once, for the first time a Freemius powered plugin is activated. + */ + fs_update_sdk_newest_version( $this_sdk_relative_path, $fs_active_plugins->plugins[ $this_sdk_relative_path ]->plugin_path ); + + $is_current_sdk_newest = true; + } else if ( version_compare( $fs_active_plugins->newest->version, $this_sdk_version, '<' ) ) { + /** + * Current SDK is newer than the newest stored SDK. + */ + fs_update_sdk_newest_version( $this_sdk_relative_path, $fs_active_plugins->plugins[ $this_sdk_relative_path ]->plugin_path ); + + if ( class_exists( 'Freemius' ) ) { + // Older SDK version was already loaded. + + if ( ! $fs_active_plugins->newest->in_activation ) { + // Re-order plugins to load this plugin first. + fs_newest_sdk_plugin_first(); + } + + // Refresh page. + if ( fs_redirect( $_SERVER['REQUEST_URI'] ) ) { + exit(); + } + } + } else { + if ( ! function_exists( 'get_plugins' ) ) { + require_once( ABSPATH . 'wp-admin/includes/plugin.php' ); + } + + $is_newest_sdk_plugin_activate = is_plugin_active( $fs_active_plugins->newest->plugin_path ); + + if ( $is_current_sdk_newest && + ! $is_newest_sdk_plugin_activate && + ! $fs_active_plugins->newest->in_activation + ) { + // If current SDK is the newest and the plugin is NOT active, it means + // that the current plugin in activation mode. + $fs_active_plugins->newest->in_activation = true; + update_option( 'fs_active_plugins', $fs_active_plugins ); + } + + $is_newest_sdk_path_valid = ( $is_newest_sdk_plugin_activate || $fs_active_plugins->newest->in_activation ) && file_exists( fs_normalize_path( WP_PLUGIN_DIR . '/' . $this_sdk_relative_path . '/start.php' ) ); + + if ( ! $is_newest_sdk_path_valid && ! $is_current_sdk_newest ) { + // Plugin with newest SDK is no longer active, or SDK was moved to a different location. + unset( $fs_active_plugins->plugins[ $fs_active_plugins->newest->sdk_path ] ); + } + + if ( ! ( $is_newest_sdk_plugin_activate || $fs_active_plugins->newest->in_activation ) || + ! $is_newest_sdk_path_valid || + // Is newest SDK downgraded. + ( $this_sdk_relative_path == $fs_active_plugins->newest->sdk_path && + version_compare( $fs_active_plugins->newest->version, $this_sdk_version, '>' ) ) + ) { + /** + * Plugin with newest SDK is no longer active. + * OR + * The newest SDK was in the current plugin. BUT, seems like the version of + * the SDK was downgraded to a lower SDK. + */ + // Find the active plugin with the newest SDK version and update the newest reference. + fs_fallback_to_newest_active_sdk(); + } else { + if ( $is_newest_sdk_plugin_activate && + $this_sdk_relative_path == $fs_active_plugins->newest->sdk_path && + ( $fs_active_plugins->newest->in_activation || + ( class_exists( 'Freemius' ) && ( ! defined( 'WP_FS__SDK_VERSION' ) || version_compare( WP_FS__SDK_VERSION, $this_sdk_version, '<' ) ) ) + ) + + ) { + if ( $fs_active_plugins->newest->in_activation ) { + // Plugin no more in activation. + $fs_active_plugins->newest->in_activation = false; + update_option( 'fs_active_plugins', $fs_active_plugins ); + } + + // Reorder plugins to load plugin with newest SDK first. + if ( fs_newest_sdk_plugin_first() ) { + // Refresh page after re-order to make sure activated plugin loads newest SDK. + if ( class_exists( 'Freemius' ) ) { + if ( fs_redirect( $_SERVER['REQUEST_URI'] ) ) { + exit(); + } + } + } + } + } + } + + if ( class_exists( 'Freemius' ) ) { + // SDK was already loaded. + return; + } + + if ( version_compare( $this_sdk_version, $fs_active_plugins->newest->version, '<' ) ) { + $newest_sdk_starter = fs_normalize_path( WP_PLUGIN_DIR . '/' . $fs_active_plugins->newest->sdk_path . '/start.php' ); + + if ( file_exists( $newest_sdk_starter ) ) { + // Reorder plugins to load plugin with newest SDK first. + fs_newest_sdk_plugin_first(); + + // There's a newer SDK version, load it instead of the current one! + require_once $newest_sdk_starter; + + return; + } + } + + #endregion SDK Selection Logic -------------------------------------------------------------------- + + #region Hooks & Filters Collection -------------------------------------------------------------------- + + /** + * Freemius hooks (actions & filters) tags structure: + * + * fs_{filter/action_name}_{plugin_slug} + * + * -------------------------------------------------------- + * + * Usage with WordPress' add_action() / add_filter(): + * + * add_action('fs_{filter/action_name}_{plugin_slug}', $callable); + * + * -------------------------------------------------------- + * + * Usage with Freemius' instance add_action() / add_filter(): + * + * // No need to add 'fs_' prefix nor '_{plugin_slug}' suffix. + * my_freemius()->add_action('{action_name}', $callable); + * + * -------------------------------------------------------- + * + * Freemius filters collection: + * + * fs_connect_url_{plugin_slug} + * fs_trial_promotion_message_{plugin_slug} + * fs_is_long_term_user_{plugin_slug} + * fs_uninstall_reasons_{plugin_slug} + * fs_is_plugin_update_{plugin_slug} + * fs_api_domains_{plugin_slug} + * fs_email_template_sections_{plugin_slug} + * fs_support_forum_submenu_{plugin_slug} + * fs_support_forum_url_{plugin_slug} + * fs_connect_message_{plugin_slug} + * fs_connect_message_on_update_{plugin_slug} + * fs_uninstall_confirmation_message_{plugin_slug} + * fs_pending_activation_message_{plugin_slug} + * fs_is_submenu_visible_{plugin_slug} + * fs_plugin_icon_{plugin_slug} + * fs_show_trial_{plugin_slug} + * + * -------------------------------------------------------- + * + * Freemius actions collection: + * + * fs_after_license_loaded_{plugin_slug} + * fs_after_license_change_{plugin_slug} + * fs_after_plans_sync_{plugin_slug} + * + * fs_after_account_details_{plugin_slug} + * fs_after_account_user_sync_{plugin_slug} + * fs_after_account_plan_sync_{plugin_slug} + * fs_before_account_load_{plugin_slug} + * fs_after_account_connection_{plugin_slug} + * fs_account_property_edit_{plugin_slug} + * fs_account_email_verified_{plugin_slug} + * fs_account_page_load_before_departure_{plugin_slug} + * fs_before_account_delete_{plugin_slug} + * fs_after_account_delete_{plugin_slug} + * + * fs_sdk_version_update_{plugin_slug} + * fs_plugin_version_update_{plugin_slug} + * + * fs_initiated_{plugin_slug} + * fs_after_init_plugin_registered_{plugin_slug} + * fs_after_init_plugin_anonymous_{plugin_slug} + * fs_after_init_plugin_pending_activations_{plugin_slug} + * fs_after_init_addon_registered_{plugin_slug} + * fs_after_init_addon_anonymous_{plugin_slug} + * fs_after_init_addon_pending_activations_{plugin_slug} + * + * fs_after_premium_version_activation_{plugin_slug} + * fs_after_free_version_reactivation_{plugin_slug} + * + * fs_after_uninstall_{plugin_slug} + * fs_before_admin_menu_init_{plugin_slug} + */ + + #endregion Hooks & Filters Collection -------------------------------------------------------------------- + + if ( ! class_exists( 'Freemius' ) ) { + + if ( ! defined( 'WP_FS__SDK_VERSION' ) ) { + define( 'WP_FS__SDK_VERSION', $this_sdk_version ); + } + + // Configuration should be loaded first. + require_once dirname( __FILE__ ) . '/config.php'; + + // Logger must be loaded before any other. + require_once WP_FS__DIR_INCLUDES . '/class-fs-logger.php'; + require_once WP_FS__DIR_INCLUDES . '/debug/debug-bar-start.php'; + + require_once WP_FS__DIR_INCLUDES . '/fs-core-functions.php'; +// require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-abstract-manager.php'; + require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-option-manager.php'; + require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-cache-manager.php'; + require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-admin-notice-manager.php'; + require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-admin-menu-manager.php'; + require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-key-value-storage.php'; + require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-license-manager.php'; + require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-plan-manager.php'; + require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-plugin-manager.php'; + require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-entity.php'; + require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-scope-entity.php'; + require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-user.php'; + require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-site.php'; + require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-plugin.php'; + require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-plugin-info.php'; + require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-plugin-tag.php'; + require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-plugin-plan.php'; + require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-pricing.php'; + require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-plugin-license.php'; + require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-subscription.php'; + require_once WP_FS__DIR_INCLUDES . '/class-fs-api.php'; + require_once WP_FS__DIR_INCLUDES . '/class-fs-plugin-updater.php'; + require_once WP_FS__DIR_INCLUDES . '/class-fs-security.php'; + require_once WP_FS__DIR_INCLUDES . '/class-freemius-abstract.php'; + require_once WP_FS__DIR_INCLUDES . '/class-freemius.php'; + + /** + * Quick shortcut to get Freemius for specified plugin. + * Used by various templates. + * + * @param string $slug + * + * @return Freemius + */ + function freemius( $slug ) { + return Freemius::instance( $slug ); + } + + /** + * @param string $slug + * @param number $plugin_id + * @param string $public_key + * @param bool $is_live Is live or test plugin. + * @param bool $is_premium Hints freemius if running the premium plugin or not. + * + * @return Freemius + */ + function fs_init( $slug, $plugin_id, $public_key, $is_live = true, $is_premium = true ) { + $fs = Freemius::instance( $slug ); + $fs->init( $plugin_id, $public_key, $is_live, $is_premium ); + + return $fs; + } + + /** + * @param array [string]string $plugin + * + * @return Freemius + * @throws Freemius_Exception + */ + function fs_dynamic_init( $plugin ) { + $fs = Freemius::instance( $plugin['slug'] ); + $fs->dynamic_init( $plugin ); + + return $fs; + } + + function fs_dump_log() { + FS_Logger::dump(); + } } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/templates/account.php b/wp-content/plugins/nextgen-gallery/freemius/templates/account.php index 59e22d6ef75e8efd9ba960dc28925617de1f09b1..adc0659029055089e1ca42d03a638ff07b8742b7 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/templates/account.php +++ b/wp-content/plugins/nextgen-gallery/freemius/templates/account.php @@ -1,625 +1,625 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.3 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - $slug = $VARS['slug']; - /** - * @var Freemius $fs - */ - $fs = freemius( $slug ); - - /** - * @var FS_Plugin_Tag $update - */ - $update = $fs->get_update( false, false ); - - $is_paying = $fs->is_paying(); - $user = $fs->get_user(); - $site = $fs->get_site(); - $name = $user->get_name(); - $license = $fs->_get_license(); - $subscription = $fs->_get_subscription(); - $plan = $fs->get_plan(); - $is_active_subscription = ( is_object( $subscription ) && $subscription->is_active() ); - $is_paid_trial = $fs->is_paid_trial(); - $show_upgrade = ( ! $is_paying && ! $is_paid_trial ); -?> - -<div class="wrap"> -<h2 class="nav-tab-wrapper"> - <a href="<?php $fs->get_account_url() ?>" class="nav-tab nav-tab-active"><?php _efs( 'account', $slug ) ?></a> - <?php if ( $fs->has_addons() ) : ?> - <a href="<?php echo $fs->_get_admin_page_url( 'addons' ) ?>" - class="nav-tab"><?php _efs( 'add-ons', $slug ) ?></a> - <?php endif ?> - <?php if ( $fs->is_not_paying() && $fs->has_paid_plan() ) : ?> - <a href="<?php echo $fs->get_upgrade_url() ?>" class="nav-tab"><?php _efs( 'upgrade', $slug ) ?></a> - <?php if ( $fs->apply_filters( 'show_trial', true ) && ! $fs->is_trial_utilized() && $fs->has_trial_plan() ) : ?> - <a href="<?php echo $fs->get_trial_url() ?>" class="nav-tab"><?php _efs( 'free-trial', $slug ) ?></a> - <?php endif ?> - <?php endif ?> -</h2> - -<div id="poststuff"> -<div id="fs_account"> -<div class="has-sidebar has-right-sidebar"> -<div class="has-sidebar-content"> -<div class="postbox"> -<h3><?php _efs('account-details', $slug) ?></h3> - -<div class="fs-header-actions"> - <ul> - <li> - <form action="<?php echo $fs->_get_admin_page_url('account') ?>" method="POST"> - <input type="hidden" name="fs_action" value="delete_account"> - <?php wp_nonce_field('delete_account') ?> - <a href="#" onclick="if (confirm('<?php - if ($is_active_subscription) { - echo esc_attr(sprintf(__fs('delete-account-x-confirm', $slug), $plan->title)); - } else { - _efs('delete-account-confirm', $slug); - } - ?>')) this.parentNode.submit(); return false;"><i - class="dashicons dashicons-no"></i> <?php _efs('delete-account', $slug) ?></a> - </form> - </li> - <?php if ($is_paying) : ?> - <li> - • - <form action="<?php echo $fs->_get_admin_page_url('account') ?>" method="POST"> - <input type="hidden" name="fs_action" value="deactivate_license"> - <?php wp_nonce_field('deactivate_license') ?> - <a href="#" - onclick="if (confirm('<?php _efs('deactivate-license-confirm', $slug) ?>')) this.parentNode.submit(); return false;"><i - class="dashicons dashicons-admin-network"></i> <?php _efs('deactivate-license', $slug) ?> - </a> - </form> - </li> - <?php if (! $license->is_lifetime() && - $is_active_subscription - ) : ?> - <li> - • - <form action="<?php echo $fs->_get_admin_page_url('account') ?>" method="POST"> - <input type="hidden" name="fs_action" value="downgrade_account"> - <?php wp_nonce_field('downgrade_account') ?> - <a href="#" - onclick="if (confirm('<?php printf(__fs('downgrade-x-confirm', $slug), $plan->title, human_time_diff(time(), strtotime($license->expiration))) ?> <?php if (! $license->is_block_features) { - printf(__fs('after-downgrade-non-blocking', $slug), $plan->title); - } else { - printf(__fs('after-downgrade-blocking', $slug), $plan->title); - }?> <?php _efs('proceed-confirmation', $slug) ?>')) this.parentNode.submit(); return false;"><i - class="dashicons dashicons-download"></i> <?php _efs('downgrade', $slug) ?></a> - </form> - </li> - <?php endif ?> - <li> - • - <a href="<?php echo $fs->get_upgrade_url() ?>"><i - class="dashicons dashicons-grid-view"></i> <?php _efs('change-plan', $slug) ?></a> - </li> - <?php elseif ($is_paid_trial) : ?> - <li> - • - <form action="<?php echo $fs->_get_admin_page_url('account') ?>" method="POST"> - <input type="hidden" name="fs_action" value="cancel_trial"> - <?php wp_nonce_field('cancel_trial') ?> - <a href="#" - onclick="if (confirm('<?php _efs('cancel-trial-confirm') ?>')) this.parentNode.submit(); return false;"><i - class="dashicons dashicons-download"></i> <?php _efs('cancel-trial', $slug) ?></a> - </form> - </li> - <?php endif ?> - <li> - • - <form action="<?php echo $fs->_get_admin_page_url('account') ?>" method="POST"> - <input type="hidden" name="fs_action" value="<?php echo $slug ?>_sync_license"> - <?php wp_nonce_field($slug . '_sync_license') ?> - <a href="#" onclick="this.parentNode.submit(); return false;"><i - class="dashicons dashicons-image-rotate"></i> <?php _efs('sync', $slug) ?></a> - </form> - </li> - - </ul> -</div> -<div class="inside"> - <table id="fs_account_details" cellspacing="0" class="fs-key-value-table"> - <?php - $profile = array(); - $profile[] = array( - 'id' => 'user_name', - 'title' => __fs('name', $slug), - 'value' => $name - ); - // if (isset($user->email) && false !== strpos($user->email, '@')) - $profile[] = array( - 'id' => 'email', - 'title' => __fs('email', $slug), - 'value' => $user->email - ); - if (is_numeric($user->id)) { - $profile[] = array( - 'id' => 'user_id', - 'title' => __fs('user-id', $slug), - 'value' => $user->id - ); - } - - $profile[] = array( - 'id' => 'site_id', - 'title' => __fs('site-id', $slug), - 'value' => is_string($site->id) ? - $site->id : - __fs('no-id', $slug) - ); - - $profile[] = array( - 'id' => 'site_public_key', - 'title' => __fs('public-key', $slug), - 'value' => $site->public_key - ); - - $profile[] = array( - 'id' => 'site_secret_key', - 'title' => __fs('secret-key', $slug), - 'value' => ((is_string($site->secret_key)) ? - $site->secret_key : - __fs('no-secret', $slug) - ) - ); - - if ($fs->has_paid_plan()) { - if ($fs->is_trial()) { - $trial_plan = $fs->get_trial_plan(); - - $profile[] = array( - 'id' => 'plan', - 'title' => __fs('plan', $slug), - 'value' => (is_string($trial_plan->name) ? - strtoupper($trial_plan->title) : - __fs('trial', $slug)) - ); - } else { - $profile[] = array( - 'id' => 'plan', - 'title' => __fs('plan', $slug), - 'value' => is_string($site->plan->name) ? - strtoupper($site->plan->title) : - strtoupper(__fs('free', $slug)) - ); - } - } - - $profile[] = array( - 'id' => 'version', - 'title' => __fs('version', $slug), - 'value' => $fs->get_plugin_version() - ); - ?> - <?php $odd = true; - foreach ($profile as $p) : ?> - <?php - if ('plan' === $p['id'] && ! $fs->has_paid_plan()) { - // If plugin don't have any paid plans, there's no reason - // to show current plan. - continue; - } - ?> - <tr class="fs-field-<?php echo $p['id'] ?><?php if ($odd) : ?> alternate<?php endif ?>"> - <td> - <nobr><?php echo $p['title'] ?>:</nobr> - </td> - <td> - <code><?php echo htmlspecialchars($p['value']) ?></code> - <?php if ('email' === $p['id'] && ! $user->is_verified()) : ?> - <label class="fs-tag fs-warn"><?php _efs('not-verified', $slug) ?></label> - <?php endif ?> - <?php if ('plan' === $p['id']) : ?> - <?php if ($fs->is_trial()) : ?> - <label class="fs-tag fs-success"><?php _efs('trial', $slug) ?></label> - <?php endif ?> - <?php if (is_object($license) && ! $license->is_lifetime()) : ?> - <?php if (! $is_active_subscription && ! $license->is_first_payment_pending()) : ?> - <label - class="fs-tag fs-warn"><?php printf(__fs('expires-in', $slug), human_time_diff(time(), strtotime($license->expiration))) ?></label> - <?php elseif ($is_active_subscription && ! $subscription->is_first_payment_pending()) : ?> - <label - class="fs-tag fs-success"><?php printf(__fs('renews-in', $slug), human_time_diff(time(), strtotime($subscription->next_payment))) ?></label> - <?php endif ?> - <?php elseif ($fs->is_trial()) : ?> - <label - class="fs-tag fs-warn"><?php printf(__fs('expires-in', $slug), human_time_diff(time(), strtotime($site->trial_ends))) ?></label> - <?php endif ?> - <?php endif ?> - <?php if ('version' === $p['id'] && $fs->has_paid_plan()) : ?> - <?php if ($fs->is_premium()) : ?> - <label - class="fs-tag fs-<?php echo $fs->can_use_premium_code() ? 'success' : 'warn' ?>"><?php _efs('premium-version') ?></label> - <?php elseif ($fs->can_use_premium_code()) : ?> - <label class="fs-tag fs-warn"><?php _efs('free-version') ?></label> - <?php endif ?> - <?php endif ?> - </td> - <td class="fs-right"> - <?php if ('email' === $p['id'] && ! $user->is_verified()) : ?> - <form action="<?php echo $fs->_get_admin_page_url('account') ?>" method="POST"> - <input type="hidden" name="fs_action" value="verify_email"> - <?php wp_nonce_field('verify_email') ?> - <input type="submit" class="button button-small" - value="<?php _efs('verify-email', $slug) ?>"> - </form> - <?php endif ?> - <?php if ('plan' === $p['id']) : ?> - <div class="button-group"> - <?php $license = $fs->is_free_plan() ? $fs->_get_available_premium_license() : false ?> - <?php if (false !== $license && ($license->left() > 0 || ($site->is_localhost() && $license->is_free_localhost))) : ?> - <?php $premium_plan = $fs->_get_plan_by_id($license->plan_id) ?> - <form action="<?php echo $fs->_get_admin_page_url('account') ?>" - method="POST"> - <input type="hidden" name="fs_action" value="activate_license"> - <input type="hidden" name="license_id" value="<?php echo $license->id ?>"> - <?php wp_nonce_field('activate_license') ?> - <input type="submit" class="button button-primary" - value="<?php printf( - __fs( 'activate-x-plan', $slug ) . '%s', - $premium_plan->title, - ( $site->is_localhost() && $license->is_free_localhost ) ? - ' [' . __fs( 'localhost', $slug ) . ']' : - ( $license->is_single_site() ? - '' : - ' [' . ( 1 < $license->left() ? - sprintf( __fs( 'x-left', $slug ), $license->left() ) : - strtolower( __fs( 'last-license', $slug ) ) ) . ']' - ) - ) ?> "> - </form> - <?php else : ?> - <form action="<?php echo $fs->_get_admin_page_url('account') ?>" - method="POST" class="button-group"> - <input type="submit" class="button" - value="<?php _efs('sync-license', $slug) ?>"> - <input type="hidden" name="fs_action" - value="<?php echo $slug ?>_sync_license"> - <?php wp_nonce_field($slug . '_sync_license') ?> - <a href="<?php echo $fs->get_upgrade_url() ?>" - class="button<?php if ($show_upgrade) { - echo ' button-primary'; - } ?> button-upgrade"><i - class="dashicons dashicons-cart"></i> <?php ($show_upgrade) ? - _efs('upgrade', $slug) : - _efs('change-plan', $slug) - ?></a> - </form> - <?php endif ?> - </div> - <?php elseif ('version' === $p['id']) : ?> - <div class="button-group"> - <?php if ($is_paying || $fs->is_trial()) : ?> - <?php if (! $fs->is_allowed_to_install()) : ?> - <a target="_blank" class="button button-primary" - href="<?php echo $fs->_get_latest_download_local_url() ?>"><?php echo sprintf(__fs('download-x-version', $slug), $site->plan->title) . (is_object($update) ? ' [' . $update->version . ']' : '') ?></a> - <?php elseif (is_object($update)) : ?> - <a class="button button-primary" - href="<?php echo wp_nonce_url(self_admin_url('update.php?action=upgrade-plugin&plugin=' . $fs->get_plugin_basename()), 'upgrade-plugin_' . $fs->get_plugin_basename()) ?>"><?php echo __fs('install-update-now', $slug) . ' [' . $update->version . ']' ?></a> - <?php endif ?> - <?php endif; ?> - </div> - <?php - elseif (/*in_array($p['id'], array('site_secret_key', 'site_id', 'site_public_key')) ||*/ - (is_string($user->secret_key) && in_array($p['id'], array( - 'email', - 'user_name' - ))) - ) : ?> - <form action="<?php echo $fs->_get_admin_page_url('account') ?>" method="POST" - onsubmit="var val = prompt('<?php printf(__fs('what-is-your-x', $slug), $p['title']) ?>', '<?php echo $p['value'] ?>'); if (null == val || '' === val) return false; jQuery('input[name=fs_<?php echo $p['id'] ?>_<?php echo $slug ?>]').val(val); return true;"> - <input type="hidden" name="fs_action" value="update_<?php echo $p['id'] ?>"> - <input type="hidden" name="fs_<?php echo $p['id'] ?>_<?php echo $slug ?>" - value=""> - <?php wp_nonce_field('update_' . $p['id']) ?> - <input type="submit" class="button button-small" - value="<?php _ex('Edit', 'verb', 'freemius') ?>"> - </form> - <?php endif ?> - </td> - </tr> - <?php $odd = ! $odd; - endforeach ?> - </table> -</div> -</div> -<?php - $account_addons = $fs->get_account_addons(); - if (! is_array($account_addons)) { - $account_addons = array(); - } - - $installed_addons = $fs->get_installed_addons(); - $installed_addons_ids = array(); - foreach ($installed_addons as $fs_addon) { - $installed_addons_ids[] = $fs_addon->get_id(); - } - - $addons_to_show = array_unique(array_merge($installed_addons_ids, $account_addons)); -?> - <?php if (0 < count($addons_to_show)) : ?> -<div class="postbox"> -<div class=""> -<!-- <div class="inside">--> -<table id="fs_addons" class="widefat"> -<thead> -<tr> - <th><h3><?php _efs('add-ons', $slug) ?></h3></th> - <th><?php _efs('id', $slug) ?></th> - <th><?php _efs('version', $slug) ?></th> - <th><?php _efs('plan', $slug) ?></th> - <th><?php _efs('license', $slug) ?></th> - <th></th> - <?php if (defined('WP_FS__DEV_MODE') && WP_FS__DEV_MODE) : ?> - <th></th> - <?php endif ?> -</tr> -</thead> -<tbody> -<?php $odd = true; - foreach ($addons_to_show as $addon_id) : ?> - <?php - $addon = $fs->get_addon($addon_id); - $is_addon_activated = $fs->is_addon_activated($addon->slug); - $is_addon_connected = $fs->is_addon_connected($addon->slug); - - $fs_addon = $is_addon_connected ? freemius($addon->slug) : false; - if (is_object($fs_addon)) { - $is_paying = $fs_addon->is_paying(); - $user = $fs_addon->get_user(); - $site = $fs_addon->get_site(); - $license = $fs_addon->_get_license(); - $subscription = $fs_addon->_get_subscription(); - $plan = $fs_addon->get_plan(); - $is_active_subscription = (is_object($subscription) && $subscription->is_active()); - $is_paid_trial = $fs_addon->is_paid_trial(); - $show_upgrade = (! $is_paying && ! $is_paid_trial && ! $fs_addon->_has_premium_license()); - $is_current_license_expired = is_object($license) && $license->is_expired(); - } - - // var_dump( $is_paid_trial, $license, $site, $subscription ); - -?> -<tr<?php if ($odd) { - echo ' class="alternate"'; - } ?>> -<td> - <!-- Title --> - <?php echo $addon->title ?> -</td> -<?php if ($is_addon_connected) : ?> - <?php // Add-on Installed ?> - <?php $addon_site = $fs_addon->get_site(); ?> -<td> - <!-- ID --> - <?php echo $addon_site->id ?> -</td> -<td> - <!-- Version --> - <?php echo $fs_addon->get_plugin_version() ?> -</td> -<td> - <!-- Plan Title --> - <?php echo is_string($addon_site->plan->name) ? strtoupper($addon_site->plan->title) : 'FREE' ?> -</td> -<td> - <!-- Expiration --> - <?php - $tags = array(); - - if ($fs_addon->is_trial()) { - $tags[] = array('label' => __fs('trial', $slug), 'type' => 'success'); - - $tags[] = array( - 'label' => sprintf(__fs(($is_paid_trial ? 'renews-in' : 'expires-in'), $slug), human_time_diff(time(), strtotime($site->trial_ends))), - 'type' => ($is_paid_trial ? 'success' : 'warn') - ); - } else { - if (is_object($license)) { - if ($license->is_cancelled) { - $tags[] = array( - 'label' => __fs('cancelled', $slug), - 'type' => 'error' - ); - } else if ($license->is_expired()) { - $tags[] = array( - 'label' => __fs('expired', $slug), - 'type' => 'error' - ); - } else if ($license->is_lifetime()) { - $tags[] = array( - 'label' => __fs('no-expiration', $slug), - 'type' => 'success' - ); - } else if (! $is_active_subscription && ! $license->is_first_payment_pending()) { - $tags[] = array( - 'label' => sprintf(__fs('expires-in', $slug), human_time_diff(time(), strtotime($license->expiration))), - 'type' => 'warn' - ); - } else if ($is_active_subscription && ! $subscription->is_first_payment_pending()) { - $tags[] = array( - 'label' => sprintf(__fs('renews-in', $slug), human_time_diff(time(), strtotime($subscription->next_payment))), - 'type' => 'success' - ); - } - } - } - - foreach ($tags as $t) { - printf('<label class="fs-tag fs-%s">%s</label>' . "\n", $t['type'], $t['label']); - } - ?> -</td> -<?php - $buttons = array(); - if ($is_addon_activated) { - if ($is_paying) { - $buttons[] = fs_ui_get_action_button( - $slug, - 'account', - 'deactivate_license', - __fs('deactivate-license', $slug), - array('plugin_id' => $addon_id), - false - ); - } else if ($is_paid_trial) { - $buttons[] = fs_ui_get_action_button( - $slug, - 'account', - 'cancel_trial', - __fs('cancel-trial', $slug), - array('plugin_id' => $addon_id), - false, - 'dashicons dashicons-download', - __fs('cancel-trial-confirm', $slug), - 'POST' - ); - } else { - $premium_license = $fs_addon->_get_available_premium_license(); - - if (is_object($premium_license)) { - $site = $fs_addon->get_site(); - - $buttons[] = fs_ui_get_action_button( - $slug, - 'account', - 'activate_license', - sprintf(__fs('activate-x-plan', $slug), $fs_addon->get_plan_title(), ($site->is_localhost() && $premium_license->is_free_localhost) ? '[localhost]' : (1 < $premium_license->left() ? $premium_license->left() . ' left' : '')), - array( - 'plugin_id' => $addon_id, - 'license_id' => $premium_license->id, - ) - ); - } - } - - if (0 == count($buttons)) { - // Add sync license only if non of the other CTAs are visible. - $buttons[] = fs_ui_get_action_button( - $slug, - 'account', - $slug . '_sync_license', - __fs('sync-license', $slug), - array('plugin_id' => $addon_id), - false - ); - - } - } else if (! $show_upgrade) { - if ($fs->is_addon_installed($addon->slug)) { - $addon_file = $fs->get_addon_basename($addon->slug); - $buttons[] = sprintf( - '<a class="button button-primary" href="%s" title="%s" class="edit">%s</a>', - wp_nonce_url('plugins.php?action=activate&plugin=' . $addon_file, 'activate-plugin_' . $addon_file), - esc_attr(__fs('activate-this-addon', $slug)), - __fs('activate', $slug) - ); - } else { - if ($fs->is_allowed_to_install()) { - $buttons[] = sprintf( - '<a class="button button-primary" href="%s" class="edit">%s</a>', - wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=' . $addon->slug), 'install-plugin_' . $addon->slug), - __fs('install-now', $slug) - ); - } else { - $buttons[] = sprintf( - '<a target="_blank" class="button button-primary" href="%s" class="edit">%s</a>', - $fs->_get_latest_download_local_url($addon_id), - __fs('download-latest', $slug) - ); - } - } - } - - if ($show_upgrade) { - $buttons[] = sprintf('<a href="%s" class="thickbox button button-primary" aria-label="%s" data-title="%s"><i class="dashicons dashicons-cart"></i> %s</a>', - esc_url(network_admin_url('plugin-install.php?tab=plugin-information&parent_plugin_id=' . $fs->get_id() . '&plugin=' . $addon->slug . - '&TB_iframe=true&width=600&height=550')), - esc_attr(sprintf(__fs('more-information-about-x', $slug), $addon->title)), - esc_attr($addon->title), - __fs(($fs_addon->has_free_plan() ? 'upgrade' : 'purchase'), $slug) - ); - } - - $buttons_count = count($buttons); -?> - -<td> - <!-- Actions --> - <?php if ($buttons_count > 1) : ?> - <div class="button-group"> - <?php endif ?> - <?php foreach ($buttons as $button) : ?> - <?php echo $button ?> - <?php endforeach ?> - <?php if ($buttons_count > 1) : ?> - </div> - <?php endif ?> -</td> -<?php else : ?> - <?php // Add-on NOT Installed or was never connected. -?> -<td colspan="4"> - <!-- Action --> - <?php if ($fs->is_addon_installed($addon->slug)) : ?> - <?php $addon_file = $fs->get_addon_basename($addon->slug) ?> - <a class="button button-primary" - href="<?php echo wp_nonce_url('plugins.php?action=activate&plugin=' . $addon_file, 'activate-plugin_' . $addon_file) ?>" - title="<?php esc_attr(__fs('activate-this-addon', $slug)) ?>" - class="edit"><?php _efs('activate', $slug) ?></a> - <?php else : ?> - <?php if ($fs->is_allowed_to_install()) : ?> - <a class="button button-primary" - href="<?php echo wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=' . $addon->slug), 'install-plugin_' . $addon->slug) ?>"><?php _efs('install-now', $slug) ?></a> - <?php else : ?> - <a target="_blank" class="button button-primary" - href="<?php echo $fs->_get_latest_download_local_url($addon_id) ?>"><?php _efs('download-latest', $slug) ?></a> - <?php endif ?> - <?php endif ?> -</td> -<?php endif ?> - <?php if (defined('WP_FS__DEV_MODE') && WP_FS__DEV_MODE) : ?> -<td> - <!-- Optional Delete Action --> - <?php - if ($is_addon_activated) { - fs_ui_action_button( - $slug, 'account', - 'delete_account', - __fs('delete', $slug), - array('plugin_id' => $addon_id), - false - ); - } - ?> -</td> -<?php endif ?> -</tr> -<?php $odd = ! $odd; - endforeach ?> -</tbody> -</table> -</div> -</div> -<?php endif ?> - - <?php $fs->do_action('after_account_details') ?> -</div> -</div> -</div> -</div> -</div> +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.3 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + $slug = $VARS['slug']; + /** + * @var Freemius $fs + */ + $fs = freemius( $slug ); + + /** + * @var FS_Plugin_Tag $update + */ + $update = $fs->get_update( false, false ); + + $is_paying = $fs->is_paying(); + $user = $fs->get_user(); + $site = $fs->get_site(); + $name = $user->get_name(); + $license = $fs->_get_license(); + $subscription = $fs->_get_subscription(); + $plan = $fs->get_plan(); + $is_active_subscription = ( is_object( $subscription ) && $subscription->is_active() ); + $is_paid_trial = $fs->is_paid_trial(); + $show_upgrade = ( ! $is_paying && ! $is_paid_trial ); +?> + +<div class="wrap"> +<h2 class="nav-tab-wrapper"> + <a href="<?php $fs->get_account_url() ?>" class="nav-tab nav-tab-active"><?php _efs( 'account', $slug ) ?></a> + <?php if ( $fs->has_addons() ) : ?> + <a href="<?php echo $fs->_get_admin_page_url( 'addons' ) ?>" + class="nav-tab"><?php _efs( 'add-ons', $slug ) ?></a> + <?php endif ?> + <?php if ( $fs->is_not_paying() && $fs->has_paid_plan() ) : ?> + <a href="<?php echo $fs->get_upgrade_url() ?>" class="nav-tab"><?php _efs( 'upgrade', $slug ) ?></a> + <?php if ( $fs->apply_filters( 'show_trial', true ) && ! $fs->is_trial_utilized() && $fs->has_trial_plan() ) : ?> + <a href="<?php echo $fs->get_trial_url() ?>" class="nav-tab"><?php _efs( 'free-trial', $slug ) ?></a> + <?php endif ?> + <?php endif ?> +</h2> + +<div id="poststuff"> +<div id="fs_account"> +<div class="has-sidebar has-right-sidebar"> +<div class="has-sidebar-content"> +<div class="postbox"> +<h3><?php _efs('account-details', $slug) ?></h3> + +<div class="fs-header-actions"> + <ul> + <li> + <form action="<?php echo $fs->_get_admin_page_url('account') ?>" method="POST"> + <input type="hidden" name="fs_action" value="delete_account"> + <?php wp_nonce_field('delete_account') ?> + <a href="#" onclick="if (confirm('<?php + if ($is_active_subscription) { + echo esc_attr(sprintf(__fs('delete-account-x-confirm', $slug), $plan->title)); + } else { + _efs('delete-account-confirm', $slug); + } + ?>')) this.parentNode.submit(); return false;"><i + class="dashicons dashicons-no"></i> <?php _efs('delete-account', $slug) ?></a> + </form> + </li> + <?php if ($is_paying) : ?> + <li> + • + <form action="<?php echo $fs->_get_admin_page_url('account') ?>" method="POST"> + <input type="hidden" name="fs_action" value="deactivate_license"> + <?php wp_nonce_field('deactivate_license') ?> + <a href="#" + onclick="if (confirm('<?php _efs('deactivate-license-confirm', $slug) ?>')) this.parentNode.submit(); return false;"><i + class="dashicons dashicons-admin-network"></i> <?php _efs('deactivate-license', $slug) ?> + </a> + </form> + </li> + <?php if (! $license->is_lifetime() && + $is_active_subscription + ) : ?> + <li> + • + <form action="<?php echo $fs->_get_admin_page_url('account') ?>" method="POST"> + <input type="hidden" name="fs_action" value="downgrade_account"> + <?php wp_nonce_field('downgrade_account') ?> + <a href="#" + onclick="if (confirm('<?php printf(__fs('downgrade-x-confirm', $slug), $plan->title, human_time_diff(time(), strtotime($license->expiration))) ?> <?php if (! $license->is_block_features) { + printf(__fs('after-downgrade-non-blocking', $slug), $plan->title); + } else { + printf(__fs('after-downgrade-blocking', $slug), $plan->title); + }?> <?php _efs('proceed-confirmation', $slug) ?>')) this.parentNode.submit(); return false;"><i + class="dashicons dashicons-download"></i> <?php _efs('downgrade', $slug) ?></a> + </form> + </li> + <?php endif ?> + <li> + • + <a href="<?php echo $fs->get_upgrade_url() ?>"><i + class="dashicons dashicons-grid-view"></i> <?php _efs('change-plan', $slug) ?></a> + </li> + <?php elseif ($is_paid_trial) : ?> + <li> + • + <form action="<?php echo $fs->_get_admin_page_url('account') ?>" method="POST"> + <input type="hidden" name="fs_action" value="cancel_trial"> + <?php wp_nonce_field('cancel_trial') ?> + <a href="#" + onclick="if (confirm('<?php _efs('cancel-trial-confirm') ?>')) this.parentNode.submit(); return false;"><i + class="dashicons dashicons-download"></i> <?php _efs('cancel-trial', $slug) ?></a> + </form> + </li> + <?php endif ?> + <li> + • + <form action="<?php echo $fs->_get_admin_page_url('account') ?>" method="POST"> + <input type="hidden" name="fs_action" value="<?php echo $slug ?>_sync_license"> + <?php wp_nonce_field($slug . '_sync_license') ?> + <a href="#" onclick="this.parentNode.submit(); return false;"><i + class="dashicons dashicons-image-rotate"></i> <?php _efs('sync', $slug) ?></a> + </form> + </li> + + </ul> +</div> +<div class="inside"> + <table id="fs_account_details" cellspacing="0" class="fs-key-value-table"> + <?php + $profile = array(); + $profile[] = array( + 'id' => 'user_name', + 'title' => __fs('name', $slug), + 'value' => $name + ); + // if (isset($user->email) && false !== strpos($user->email, '@')) + $profile[] = array( + 'id' => 'email', + 'title' => __fs('email', $slug), + 'value' => $user->email + ); + if (is_numeric($user->id)) { + $profile[] = array( + 'id' => 'user_id', + 'title' => __fs('user-id', $slug), + 'value' => $user->id + ); + } + + $profile[] = array( + 'id' => 'site_id', + 'title' => __fs('site-id', $slug), + 'value' => is_string($site->id) ? + $site->id : + __fs('no-id', $slug) + ); + + $profile[] = array( + 'id' => 'site_public_key', + 'title' => __fs('public-key', $slug), + 'value' => $site->public_key + ); + + $profile[] = array( + 'id' => 'site_secret_key', + 'title' => __fs('secret-key', $slug), + 'value' => ((is_string($site->secret_key)) ? + $site->secret_key : + __fs('no-secret', $slug) + ) + ); + + if ($fs->has_paid_plan()) { + if ($fs->is_trial()) { + $trial_plan = $fs->get_trial_plan(); + + $profile[] = array( + 'id' => 'plan', + 'title' => __fs('plan', $slug), + 'value' => (is_string($trial_plan->name) ? + strtoupper($trial_plan->title) : + __fs('trial', $slug)) + ); + } else { + $profile[] = array( + 'id' => 'plan', + 'title' => __fs('plan', $slug), + 'value' => is_string($site->plan->name) ? + strtoupper($site->plan->title) : + strtoupper(__fs('free', $slug)) + ); + } + } + + $profile[] = array( + 'id' => 'version', + 'title' => __fs('version', $slug), + 'value' => $fs->get_plugin_version() + ); + ?> + <?php $odd = true; + foreach ($profile as $p) : ?> + <?php + if ('plan' === $p['id'] && ! $fs->has_paid_plan()) { + // If plugin don't have any paid plans, there's no reason + // to show current plan. + continue; + } + ?> + <tr class="fs-field-<?php echo $p['id'] ?><?php if ($odd) : ?> alternate<?php endif ?>"> + <td> + <nobr><?php echo $p['title'] ?>:</nobr> + </td> + <td> + <code><?php echo htmlspecialchars($p['value']) ?></code> + <?php if ('email' === $p['id'] && ! $user->is_verified()) : ?> + <label class="fs-tag fs-warn"><?php _efs('not-verified', $slug) ?></label> + <?php endif ?> + <?php if ('plan' === $p['id']) : ?> + <?php if ($fs->is_trial()) : ?> + <label class="fs-tag fs-success"><?php _efs('trial', $slug) ?></label> + <?php endif ?> + <?php if (is_object($license) && ! $license->is_lifetime()) : ?> + <?php if (! $is_active_subscription && ! $license->is_first_payment_pending()) : ?> + <label + class="fs-tag fs-warn"><?php printf(__fs('expires-in', $slug), human_time_diff(time(), strtotime($license->expiration))) ?></label> + <?php elseif ($is_active_subscription && ! $subscription->is_first_payment_pending()) : ?> + <label + class="fs-tag fs-success"><?php printf(__fs('renews-in', $slug), human_time_diff(time(), strtotime($subscription->next_payment))) ?></label> + <?php endif ?> + <?php elseif ($fs->is_trial()) : ?> + <label + class="fs-tag fs-warn"><?php printf(__fs('expires-in', $slug), human_time_diff(time(), strtotime($site->trial_ends))) ?></label> + <?php endif ?> + <?php endif ?> + <?php if ('version' === $p['id'] && $fs->has_paid_plan()) : ?> + <?php if ($fs->is_premium()) : ?> + <label + class="fs-tag fs-<?php echo $fs->can_use_premium_code() ? 'success' : 'warn' ?>"><?php _efs('premium-version') ?></label> + <?php elseif ($fs->can_use_premium_code()) : ?> + <label class="fs-tag fs-warn"><?php _efs('free-version') ?></label> + <?php endif ?> + <?php endif ?> + </td> + <td class="fs-right"> + <?php if ('email' === $p['id'] && ! $user->is_verified()) : ?> + <form action="<?php echo $fs->_get_admin_page_url('account') ?>" method="POST"> + <input type="hidden" name="fs_action" value="verify_email"> + <?php wp_nonce_field('verify_email') ?> + <input type="submit" class="button button-small" + value="<?php _efs('verify-email', $slug) ?>"> + </form> + <?php endif ?> + <?php if ('plan' === $p['id']) : ?> + <div class="button-group"> + <?php $license = $fs->is_free_plan() ? $fs->_get_available_premium_license() : false ?> + <?php if (false !== $license && ($license->left() > 0 || ($site->is_localhost() && $license->is_free_localhost))) : ?> + <?php $premium_plan = $fs->_get_plan_by_id($license->plan_id) ?> + <form action="<?php echo $fs->_get_admin_page_url('account') ?>" + method="POST"> + <input type="hidden" name="fs_action" value="activate_license"> + <input type="hidden" name="license_id" value="<?php echo $license->id ?>"> + <?php wp_nonce_field('activate_license') ?> + <input type="submit" class="button button-primary" + value="<?php printf( + __fs( 'activate-x-plan', $slug ) . '%s', + $premium_plan->title, + ( $site->is_localhost() && $license->is_free_localhost ) ? + ' [' . __fs( 'localhost', $slug ) . ']' : + ( $license->is_single_site() ? + '' : + ' [' . ( 1 < $license->left() ? + sprintf( __fs( 'x-left', $slug ), $license->left() ) : + strtolower( __fs( 'last-license', $slug ) ) ) . ']' + ) + ) ?> "> + </form> + <?php else : ?> + <form action="<?php echo $fs->_get_admin_page_url('account') ?>" + method="POST" class="button-group"> + <input type="submit" class="button" + value="<?php _efs('sync-license', $slug) ?>"> + <input type="hidden" name="fs_action" + value="<?php echo $slug ?>_sync_license"> + <?php wp_nonce_field($slug . '_sync_license') ?> + <a href="<?php echo $fs->get_upgrade_url() ?>" + class="button<?php if ($show_upgrade) { + echo ' button-primary'; + } ?> button-upgrade"><i + class="dashicons dashicons-cart"></i> <?php ($show_upgrade) ? + _efs('upgrade', $slug) : + _efs('change-plan', $slug) + ?></a> + </form> + <?php endif ?> + </div> + <?php elseif ('version' === $p['id']) : ?> + <div class="button-group"> + <?php if ($is_paying || $fs->is_trial()) : ?> + <?php if (! $fs->is_allowed_to_install()) : ?> + <a target="_blank" class="button button-primary" + href="<?php echo $fs->_get_latest_download_local_url() ?>"><?php echo sprintf(__fs('download-x-version', $slug), $site->plan->title) . (is_object($update) ? ' [' . $update->version . ']' : '') ?></a> + <?php elseif (is_object($update)) : ?> + <a class="button button-primary" + href="<?php echo wp_nonce_url(self_admin_url('update.php?action=upgrade-plugin&plugin=' . $fs->get_plugin_basename()), 'upgrade-plugin_' . $fs->get_plugin_basename()) ?>"><?php echo __fs('install-update-now', $slug) . ' [' . $update->version . ']' ?></a> + <?php endif ?> + <?php endif; ?> + </div> + <?php + elseif (/*in_array($p['id'], array('site_secret_key', 'site_id', 'site_public_key')) ||*/ + (is_string($user->secret_key) && in_array($p['id'], array( + 'email', + 'user_name' + ))) + ) : ?> + <form action="<?php echo $fs->_get_admin_page_url('account') ?>" method="POST" + onsubmit="var val = prompt('<?php printf(__fs('what-is-your-x', $slug), $p['title']) ?>', '<?php echo $p['value'] ?>'); if (null == val || '' === val) return false; jQuery('input[name=fs_<?php echo $p['id'] ?>_<?php echo $slug ?>]').val(val); return true;"> + <input type="hidden" name="fs_action" value="update_<?php echo $p['id'] ?>"> + <input type="hidden" name="fs_<?php echo $p['id'] ?>_<?php echo $slug ?>" + value=""> + <?php wp_nonce_field('update_' . $p['id']) ?> + <input type="submit" class="button button-small" + value="<?php _ex('Edit', 'verb', 'freemius') ?>"> + </form> + <?php endif ?> + </td> + </tr> + <?php $odd = ! $odd; + endforeach ?> + </table> +</div> +</div> +<?php + $account_addons = $fs->get_account_addons(); + if (! is_array($account_addons)) { + $account_addons = array(); + } + + $installed_addons = $fs->get_installed_addons(); + $installed_addons_ids = array(); + foreach ($installed_addons as $fs_addon) { + $installed_addons_ids[] = $fs_addon->get_id(); + } + + $addons_to_show = array_unique(array_merge($installed_addons_ids, $account_addons)); +?> + <?php if (0 < count($addons_to_show)) : ?> +<div class="postbox"> +<div class=""> +<!-- <div class="inside">--> +<table id="fs_addons" class="widefat"> +<thead> +<tr> + <th><h3><?php _efs('add-ons', $slug) ?></h3></th> + <th><?php _efs('id', $slug) ?></th> + <th><?php _efs('version', $slug) ?></th> + <th><?php _efs('plan', $slug) ?></th> + <th><?php _efs('license', $slug) ?></th> + <th></th> + <?php if (defined('WP_FS__DEV_MODE') && WP_FS__DEV_MODE) : ?> + <th></th> + <?php endif ?> +</tr> +</thead> +<tbody> +<?php $odd = true; + foreach ($addons_to_show as $addon_id) : ?> + <?php + $addon = $fs->get_addon($addon_id); + $is_addon_activated = $fs->is_addon_activated($addon->slug); + $is_addon_connected = $fs->is_addon_connected($addon->slug); + + $fs_addon = $is_addon_connected ? freemius($addon->slug) : false; + if (is_object($fs_addon)) { + $is_paying = $fs_addon->is_paying(); + $user = $fs_addon->get_user(); + $site = $fs_addon->get_site(); + $license = $fs_addon->_get_license(); + $subscription = $fs_addon->_get_subscription(); + $plan = $fs_addon->get_plan(); + $is_active_subscription = (is_object($subscription) && $subscription->is_active()); + $is_paid_trial = $fs_addon->is_paid_trial(); + $show_upgrade = (! $is_paying && ! $is_paid_trial && ! $fs_addon->_has_premium_license()); + $is_current_license_expired = is_object($license) && $license->is_expired(); + } + + // var_dump( $is_paid_trial, $license, $site, $subscription ); + +?> +<tr<?php if ($odd) { + echo ' class="alternate"'; + } ?>> +<td> + <!-- Title --> + <?php echo $addon->title ?> +</td> +<?php if ($is_addon_connected) : ?> + <?php // Add-on Installed ?> + <?php $addon_site = $fs_addon->get_site(); ?> +<td> + <!-- ID --> + <?php echo $addon_site->id ?> +</td> +<td> + <!-- Version --> + <?php echo $fs_addon->get_plugin_version() ?> +</td> +<td> + <!-- Plan Title --> + <?php echo is_string($addon_site->plan->name) ? strtoupper($addon_site->plan->title) : 'FREE' ?> +</td> +<td> + <!-- Expiration --> + <?php + $tags = array(); + + if ($fs_addon->is_trial()) { + $tags[] = array('label' => __fs('trial', $slug), 'type' => 'success'); + + $tags[] = array( + 'label' => sprintf(__fs(($is_paid_trial ? 'renews-in' : 'expires-in'), $slug), human_time_diff(time(), strtotime($site->trial_ends))), + 'type' => ($is_paid_trial ? 'success' : 'warn') + ); + } else { + if (is_object($license)) { + if ($license->is_cancelled) { + $tags[] = array( + 'label' => __fs('cancelled', $slug), + 'type' => 'error' + ); + } else if ($license->is_expired()) { + $tags[] = array( + 'label' => __fs('expired', $slug), + 'type' => 'error' + ); + } else if ($license->is_lifetime()) { + $tags[] = array( + 'label' => __fs('no-expiration', $slug), + 'type' => 'success' + ); + } else if (! $is_active_subscription && ! $license->is_first_payment_pending()) { + $tags[] = array( + 'label' => sprintf(__fs('expires-in', $slug), human_time_diff(time(), strtotime($license->expiration))), + 'type' => 'warn' + ); + } else if ($is_active_subscription && ! $subscription->is_first_payment_pending()) { + $tags[] = array( + 'label' => sprintf(__fs('renews-in', $slug), human_time_diff(time(), strtotime($subscription->next_payment))), + 'type' => 'success' + ); + } + } + } + + foreach ($tags as $t) { + printf('<label class="fs-tag fs-%s">%s</label>' . "\n", $t['type'], $t['label']); + } + ?> +</td> +<?php + $buttons = array(); + if ($is_addon_activated) { + if ($is_paying) { + $buttons[] = fs_ui_get_action_button( + $slug, + 'account', + 'deactivate_license', + __fs('deactivate-license', $slug), + array('plugin_id' => $addon_id), + false + ); + } else if ($is_paid_trial) { + $buttons[] = fs_ui_get_action_button( + $slug, + 'account', + 'cancel_trial', + __fs('cancel-trial', $slug), + array('plugin_id' => $addon_id), + false, + 'dashicons dashicons-download', + __fs('cancel-trial-confirm', $slug), + 'POST' + ); + } else { + $premium_license = $fs_addon->_get_available_premium_license(); + + if (is_object($premium_license)) { + $site = $fs_addon->get_site(); + + $buttons[] = fs_ui_get_action_button( + $slug, + 'account', + 'activate_license', + sprintf(__fs('activate-x-plan', $slug), $fs_addon->get_plan_title(), ($site->is_localhost() && $premium_license->is_free_localhost) ? '[localhost]' : (1 < $premium_license->left() ? $premium_license->left() . ' left' : '')), + array( + 'plugin_id' => $addon_id, + 'license_id' => $premium_license->id, + ) + ); + } + } + + if (0 == count($buttons)) { + // Add sync license only if non of the other CTAs are visible. + $buttons[] = fs_ui_get_action_button( + $slug, + 'account', + $slug . '_sync_license', + __fs('sync-license', $slug), + array('plugin_id' => $addon_id), + false + ); + + } + } else if (! $show_upgrade) { + if ($fs->is_addon_installed($addon->slug)) { + $addon_file = $fs->get_addon_basename($addon->slug); + $buttons[] = sprintf( + '<a class="button button-primary" href="%s" title="%s" class="edit">%s</a>', + wp_nonce_url('plugins.php?action=activate&plugin=' . $addon_file, 'activate-plugin_' . $addon_file), + esc_attr(__fs('activate-this-addon', $slug)), + __fs('activate', $slug) + ); + } else { + if ($fs->is_allowed_to_install()) { + $buttons[] = sprintf( + '<a class="button button-primary" href="%s" class="edit">%s</a>', + wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=' . $addon->slug), 'install-plugin_' . $addon->slug), + __fs('install-now', $slug) + ); + } else { + $buttons[] = sprintf( + '<a target="_blank" class="button button-primary" href="%s" class="edit">%s</a>', + $fs->_get_latest_download_local_url($addon_id), + __fs('download-latest', $slug) + ); + } + } + } + + if ($show_upgrade) { + $buttons[] = sprintf('<a href="%s" class="thickbox button button-primary" aria-label="%s" data-title="%s"><i class="dashicons dashicons-cart"></i> %s</a>', + esc_url(network_admin_url('plugin-install.php?tab=plugin-information&parent_plugin_id=' . $fs->get_id() . '&plugin=' . $addon->slug . + '&TB_iframe=true&width=600&height=550')), + esc_attr(sprintf(__fs('more-information-about-x', $slug), $addon->title)), + esc_attr($addon->title), + __fs(($fs_addon->has_free_plan() ? 'upgrade' : 'purchase'), $slug) + ); + } + + $buttons_count = count($buttons); +?> + +<td> + <!-- Actions --> + <?php if ($buttons_count > 1) : ?> + <div class="button-group"> + <?php endif ?> + <?php foreach ($buttons as $button) : ?> + <?php echo $button ?> + <?php endforeach ?> + <?php if ($buttons_count > 1) : ?> + </div> + <?php endif ?> +</td> +<?php else : ?> + <?php // Add-on NOT Installed or was never connected. +?> +<td colspan="4"> + <!-- Action --> + <?php if ($fs->is_addon_installed($addon->slug)) : ?> + <?php $addon_file = $fs->get_addon_basename($addon->slug) ?> + <a class="button button-primary" + href="<?php echo wp_nonce_url('plugins.php?action=activate&plugin=' . $addon_file, 'activate-plugin_' . $addon_file) ?>" + title="<?php esc_attr(__fs('activate-this-addon', $slug)) ?>" + class="edit"><?php _efs('activate', $slug) ?></a> + <?php else : ?> + <?php if ($fs->is_allowed_to_install()) : ?> + <a class="button button-primary" + href="<?php echo wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=' . $addon->slug), 'install-plugin_' . $addon->slug) ?>"><?php _efs('install-now', $slug) ?></a> + <?php else : ?> + <a target="_blank" class="button button-primary" + href="<?php echo $fs->_get_latest_download_local_url($addon_id) ?>"><?php _efs('download-latest', $slug) ?></a> + <?php endif ?> + <?php endif ?> +</td> +<?php endif ?> + <?php if (defined('WP_FS__DEV_MODE') && WP_FS__DEV_MODE) : ?> +<td> + <!-- Optional Delete Action --> + <?php + if ($is_addon_activated) { + fs_ui_action_button( + $slug, 'account', + 'delete_account', + __fs('delete', $slug), + array('plugin_id' => $addon_id), + false + ); + } + ?> +</td> +<?php endif ?> +</tr> +<?php $odd = ! $odd; + endforeach ?> +</tbody> +</table> +</div> +</div> +<?php endif ?> + + <?php $fs->do_action('after_account_details') ?> +</div> +</div> +</div> +</div> +</div> <?php fs_require_template('powered-by.php') ?> \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/templates/add-ons.php b/wp-content/plugins/nextgen-gallery/freemius/templates/add-ons.php index d6a87fe35c71bcdfb1dd6ccbb9d16869cdadc361..e82d43a789a655a71f910879724345cdbd3209b7 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/templates/add-ons.php +++ b/wp-content/plugins/nextgen-gallery/freemius/templates/add-ons.php @@ -1,144 +1,144 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.3 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - $slug = $VARS['slug']; - /** - * @var Freemius - */ - $fs = freemius( $slug ); - - $open_addon_slug = fs_request_get( 'slug' ); - - $open_addon = false; - - /** - * @var FS_Plugin[] - */ - $addons = $fs->get_addons(); - - $has_addons = ( is_array( $addons ) && 0 < count( $addons ) ); -?> - <div id="fs_addons" class="wrap"> - <h2><?php printf( __fs( 'add-ons-for-x', $slug ), $fs->get_plugin_name() ) ?></h2> - - <div id="poststuff"> - <?php if ( ! $has_addons ) : ?> - <h3><?php printf( - '%s... %s', - __fs( 'oops', $slug ), - __fs( 'add-ons-missing', $slug ) - ) ?></h3> - <?php endif ?> - <ul class="fs-cards-list"> - <?php if ( $has_addons ) : ?> - <?php foreach ( $addons as $addon ) : ?> - <?php - $open_addon = ( $open_addon || ( $open_addon_slug === $addon->slug ) ); - - $price = 0; - $plan = null; - $plans_result = $fs->get_api_site_or_plugin_scope()->get( "/addons/{$addon->id}/plans.json" ); - if ( ! isset( $plans_result->error ) ) { - $plans = $plans_result->plans; - if ( is_array( $plans ) && 0 < count( $plans ) ) { - $plan = new FS_Plugin_Plan( $plans[0] ); - $pricing_result = $fs->get_api_site_or_plugin_scope()->get( "/addons/{$addon->id}/plans/{$plan->id}/pricing.json" ); - if ( ! isset( $pricing_result->error ) ) { - // Update plan's pricing. - $plan->pricing = $pricing_result->pricing; - - if ( is_array( $plan->pricing ) && 0 < count( $plan->pricing ) ) { - $min_price = 999999; - foreach ( $plan->pricing as $pricing ) { - if ( ! is_null( $pricing->annual_price ) && $pricing->annual_price > 0 ) { - $min_price = min( $min_price, $pricing->annual_price ); - } else if ( ! is_null( $pricing->monthly_price ) && $pricing->monthly_price > 0 ) { - $min_price = min( $min_price, 12 * $pricing->monthly_price ); - } - } - - if ( $min_price < 999999 ) { - $price = $min_price; - } - } - } - } - } - ?> - <li class="fs-card fs-addon" data-slug="<?php echo $addon->slug ?>"> - <?php - echo sprintf( '<a href="%s" class="thickbox fs-overlay" aria-label="%s" data-title="%s"></a>', - esc_url( network_admin_url( 'plugin-install.php?tab=plugin-information&parent_plugin_id=' . $fs->get_id() . '&plugin=' . $addon->slug . - '&TB_iframe=true&width=600&height=550' ) ), - esc_attr( sprintf( __fs( 'more-information-about-x', $slug ), $addon->title ) ), - esc_attr( $addon->title ) - ); - ?> - <?php - if ( is_null( $addon->info ) ) { - $addon->info = new stdClass(); - } - if ( ! isset( $addon->info->card_banner_url ) ) { - $addon->info->card_banner_url = '//dashboard.freemius.com/assets/img/marketing/blueprint-300x100.jpg'; - } - if ( ! isset( $addon->info->short_description ) ) { - $addon->info->short_description = 'What\'s the one thing your add-on does really, really well?'; - } - ?> - <div class="fs-inner"> - <ul> - <li class="fs-card-banner" - style="background-image: url('<?php echo $addon->info->card_banner_url ?>');"></li> -<!-- <li class="fs-tag"></li>--> - <li class="fs-title"><?php echo $addon->title ?></li> - <li class="fs-offer"> - <span - class="fs-price"><?php echo ( 0 == $price ) ? __fs( 'free', $slug ) : ('$' . number_format( $price, 2 ) . ($plan->has_trial() ? ' - ' . __fs('trial', $slug) : '')) ?></span> - </li> - <li class="fs-description"><?php echo ! empty( $addon->info->short_description ) ? $addon->info->short_description : 'SHORT DESCRIPTION' ?></li> - <li class="fs-cta"><a class="button"><?php _efs( 'view-details', $slug ) ?></a></li> - </ul> - </div> - </li> - <?php endforeach ?> - <?php endif ?> - </ul> - </div> - </div> - <script type="text/javascript"> - (function ($) { - <?php if ( $open_addon ) : ?> - - var interval = setInterval(function () { - // Open add-on information page. - $('.fs-card[data-slug=<?php echo $open_addon_slug ?>] a').click(); - if ($('#TB_iframeContent').length > 0) { - clearInterval(interval); - interval = null; - } - }, 200); - - <?php else : ?> - - - $('.fs-card.fs-addon').mouseover(function(){ - $(this).find('.fs-cta .button').addClass('button-primary'); - }); - - $('.fs-card.fs-addon').mouseout(function(){ - $(this).find('.fs-cta .button').removeClass('button-primary'); - }); - - <?php endif ?> - })(jQuery); - </script> +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.3 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + $slug = $VARS['slug']; + /** + * @var Freemius + */ + $fs = freemius( $slug ); + + $open_addon_slug = fs_request_get( 'slug' ); + + $open_addon = false; + + /** + * @var FS_Plugin[] + */ + $addons = $fs->get_addons(); + + $has_addons = ( is_array( $addons ) && 0 < count( $addons ) ); +?> + <div id="fs_addons" class="wrap"> + <h2><?php printf( __fs( 'add-ons-for-x', $slug ), $fs->get_plugin_name() ) ?></h2> + + <div id="poststuff"> + <?php if ( ! $has_addons ) : ?> + <h3><?php printf( + '%s... %s', + __fs( 'oops', $slug ), + __fs( 'add-ons-missing', $slug ) + ) ?></h3> + <?php endif ?> + <ul class="fs-cards-list"> + <?php if ( $has_addons ) : ?> + <?php foreach ( $addons as $addon ) : ?> + <?php + $open_addon = ( $open_addon || ( $open_addon_slug === $addon->slug ) ); + + $price = 0; + $plan = null; + $plans_result = $fs->get_api_site_or_plugin_scope()->get( "/addons/{$addon->id}/plans.json" ); + if ( ! isset( $plans_result->error ) ) { + $plans = $plans_result->plans; + if ( is_array( $plans ) && 0 < count( $plans ) ) { + $plan = new FS_Plugin_Plan( $plans[0] ); + $pricing_result = $fs->get_api_site_or_plugin_scope()->get( "/addons/{$addon->id}/plans/{$plan->id}/pricing.json" ); + if ( ! isset( $pricing_result->error ) ) { + // Update plan's pricing. + $plan->pricing = $pricing_result->pricing; + + if ( is_array( $plan->pricing ) && 0 < count( $plan->pricing ) ) { + $min_price = 999999; + foreach ( $plan->pricing as $pricing ) { + if ( ! is_null( $pricing->annual_price ) && $pricing->annual_price > 0 ) { + $min_price = min( $min_price, $pricing->annual_price ); + } else if ( ! is_null( $pricing->monthly_price ) && $pricing->monthly_price > 0 ) { + $min_price = min( $min_price, 12 * $pricing->monthly_price ); + } + } + + if ( $min_price < 999999 ) { + $price = $min_price; + } + } + } + } + } + ?> + <li class="fs-card fs-addon" data-slug="<?php echo $addon->slug ?>"> + <?php + echo sprintf( '<a href="%s" class="thickbox fs-overlay" aria-label="%s" data-title="%s"></a>', + esc_url( network_admin_url( 'plugin-install.php?tab=plugin-information&parent_plugin_id=' . $fs->get_id() . '&plugin=' . $addon->slug . + '&TB_iframe=true&width=600&height=550' ) ), + esc_attr( sprintf( __fs( 'more-information-about-x', $slug ), $addon->title ) ), + esc_attr( $addon->title ) + ); + ?> + <?php + if ( is_null( $addon->info ) ) { + $addon->info = new stdClass(); + } + if ( ! isset( $addon->info->card_banner_url ) ) { + $addon->info->card_banner_url = '//dashboard.freemius.com/assets/img/marketing/blueprint-300x100.jpg'; + } + if ( ! isset( $addon->info->short_description ) ) { + $addon->info->short_description = 'What\'s the one thing your add-on does really, really well?'; + } + ?> + <div class="fs-inner"> + <ul> + <li class="fs-card-banner" + style="background-image: url('<?php echo $addon->info->card_banner_url ?>');"></li> +<!-- <li class="fs-tag"></li>--> + <li class="fs-title"><?php echo $addon->title ?></li> + <li class="fs-offer"> + <span + class="fs-price"><?php echo ( 0 == $price ) ? __fs( 'free', $slug ) : ('$' . number_format( $price, 2 ) . ($plan->has_trial() ? ' - ' . __fs('trial', $slug) : '')) ?></span> + </li> + <li class="fs-description"><?php echo ! empty( $addon->info->short_description ) ? $addon->info->short_description : 'SHORT DESCRIPTION' ?></li> + <li class="fs-cta"><a class="button"><?php _efs( 'view-details', $slug ) ?></a></li> + </ul> + </div> + </li> + <?php endforeach ?> + <?php endif ?> + </ul> + </div> + </div> + <script type="text/javascript"> + (function ($) { + <?php if ( $open_addon ) : ?> + + var interval = setInterval(function () { + // Open add-on information page. + $('.fs-card[data-slug=<?php echo $open_addon_slug ?>] a').click(); + if ($('#TB_iframeContent').length > 0) { + clearInterval(interval); + interval = null; + } + }, 200); + + <?php else : ?> + + + $('.fs-card.fs-addon').mouseover(function(){ + $(this).find('.fs-cta .button').addClass('button-primary'); + }); + + $('.fs-card.fs-addon').mouseout(function(){ + $(this).find('.fs-cta .button').removeClass('button-primary'); + }); + + <?php endif ?> + })(jQuery); + </script> <?php fs_require_template( 'powered-by.php' ) ?> \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/templates/admin-notice.php b/wp-content/plugins/nextgen-gallery/freemius/templates/admin-notice.php index db205eb7d9f520c3ba5b6b0396642c9297d1d2c3..dd1750a74235633bbb49922d9b265de7e997b573 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/templates/admin-notice.php +++ b/wp-content/plugins/nextgen-gallery/freemius/templates/admin-notice.php @@ -1,46 +1,46 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.3 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } -?> -<div<?php if ( ! empty( $VARS['id'] ) ) : ?> data-id="<?php echo $VARS['id'] ?>"<?php endif ?><?php if ( ! empty( $VARS['slug'] ) ) : ?> data-slug="<?php echo $VARS['slug'] ?>"<?php endif ?> - class="<?php - switch ( $VARS['type'] ) { - case 'error': - echo 'error form-invalid'; - break; - case 'promotion': - echo 'updated promotion'; - break; - case 'update': -// echo 'update-nag update'; -// break; - case 'success': - default: - echo 'updated success'; - break; - } - ?> fs-notice<?php if ( ! empty( $VARS['sticky'] ) ) { - echo ' fs-sticky'; - } ?><?php if ( ! empty( $VARS['plugin'] ) ) { - echo ' fs-has-title'; - } ?>"><?php if ( ! empty( $VARS['plugin'] ) ) : ?> - <label class="fs-plugin-title"><?php echo $VARS['plugin'] ?></label> - <?php endif ?> - <?php if ( ! empty( $VARS['sticky'] ) ) : ?> - <div class="fs-close"><i class="dashicons dashicons-no" - title="<?php _efs( 'dismiss' ) ?>"></i> <span><?php _efs( 'dismiss' ) ?></span> - </div> - <?php endif ?> - <div class="fs-notice-body"> - <?php if ( ! empty( $VARS['title'] ) ) : ?><b><?php echo $VARS['title'] ?></b> <?php endif ?> - <?php echo $VARS['message'] ?> - </div> -</div> +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.3 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } +?> +<div<?php if ( ! empty( $VARS['id'] ) ) : ?> data-id="<?php echo $VARS['id'] ?>"<?php endif ?><?php if ( ! empty( $VARS['slug'] ) ) : ?> data-slug="<?php echo $VARS['slug'] ?>"<?php endif ?> + class="<?php + switch ( $VARS['type'] ) { + case 'error': + echo 'error form-invalid'; + break; + case 'promotion': + echo 'updated promotion'; + break; + case 'update': +// echo 'update-nag update'; +// break; + case 'success': + default: + echo 'updated success'; + break; + } + ?> fs-notice<?php if ( ! empty( $VARS['sticky'] ) ) { + echo ' fs-sticky'; + } ?><?php if ( ! empty( $VARS['plugin'] ) ) { + echo ' fs-has-title'; + } ?>"><?php if ( ! empty( $VARS['plugin'] ) ) : ?> + <label class="fs-plugin-title"><?php echo $VARS['plugin'] ?></label> + <?php endif ?> + <?php if ( ! empty( $VARS['sticky'] ) ) : ?> + <div class="fs-close"><i class="dashicons dashicons-no" + title="<?php _efs( 'dismiss' ) ?>"></i> <span><?php _efs( 'dismiss' ) ?></span> + </div> + <?php endif ?> + <div class="fs-notice-body"> + <?php if ( ! empty( $VARS['title'] ) ) : ?><b><?php echo $VARS['title'] ?></b> <?php endif ?> + <?php echo $VARS['message'] ?> + </div> +</div> diff --git a/wp-content/plugins/nextgen-gallery/freemius/templates/all-admin-notice.php b/wp-content/plugins/nextgen-gallery/freemius/templates/all-admin-notice.php index a7ff579d21e22f4ff2512e066dc4d3f19678512b..31f7d40d06a0e66f99c33a78990bde349dbc28df 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/templates/all-admin-notice.php +++ b/wp-content/plugins/nextgen-gallery/freemius/templates/all-admin-notice.php @@ -1,35 +1,35 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.3 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } -?> -<div class="<?php - switch ($VARS['type']) { - case 'error': - echo 'error form-invalid'; - break; - case 'update-nag': - echo 'update-nag '; - break; - case 'update': - case 'success': - default: - echo 'updated success'; - break; - } -?> fs-notice"> - <?php if ('update-nag' !== $VARS['type']) : ?><p><?php endif ?> - <?php if (!empty($VARS['title'])) : ?> - <b><?php echo $VARS['title'] ?></b> - <?php endif ?> - <?php echo $VARS['message'] ?> - <?php if ('update-nag' !== $VARS['type']) : ?></p><?php endif ?> - <?php if ($VARS['sticky']) : ?><i class="dashicons dashicons-no"></i><?php endif ?> +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.3 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } +?> +<div class="<?php + switch ($VARS['type']) { + case 'error': + echo 'error form-invalid'; + break; + case 'update-nag': + echo 'update-nag '; + break; + case 'update': + case 'success': + default: + echo 'updated success'; + break; + } +?> fs-notice"> + <?php if ('update-nag' !== $VARS['type']) : ?><p><?php endif ?> + <?php if (!empty($VARS['title'])) : ?> + <b><?php echo $VARS['title'] ?></b> + <?php endif ?> + <?php echo $VARS['message'] ?> + <?php if ('update-nag' !== $VARS['type']) : ?></p><?php endif ?> + <?php if ($VARS['sticky']) : ?><i class="dashicons dashicons-no"></i><?php endif ?> </div> \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/templates/checkout.php b/wp-content/plugins/nextgen-gallery/freemius/templates/checkout.php index 680fbc6e73c45409d746580855ab6eb0155544d0..87ba26acd7120ee9534ee3095236c1ca2afcbc89 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/templates/checkout.php +++ b/wp-content/plugins/nextgen-gallery/freemius/templates/checkout.php @@ -1,260 +1,260 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.3 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - wp_enqueue_script( 'jquery' ); - wp_enqueue_script( 'json2' ); - fs_enqueue_local_script( 'postmessage', 'nojquery.ba-postmessage.min.js' ); - fs_enqueue_local_script( 'fs-postmessage', 'postmessage.js' ); - fs_enqueue_local_style( 'fs_common', '/admin/common.css' ); - - $slug = $VARS['slug']; - $fs = freemius( $slug ); - - $timestamp = time(); - - $context_params = array( - 'plugin_id' => $fs->get_id(), - 'plugin_public_key' => $fs->get_public_key(), - 'plugin_version' => $fs->get_plugin_version(), - ); - - // Get site context secure params. - if ( $fs->is_registered() ) { - $site = $fs->get_site(); - $plugin_id = fs_request_get( 'plugin_id', $fs->get_id() ); - - if ($plugin_id != $fs->get_id()) { - if ( $fs->is_addon_activated( $plugin_id ) ) { - $fs_addon = Freemius::get_instance_by_id( $plugin_id ); - $site = $fs_addon->get_site(); - } - } - - $context_params = array_merge( $context_params, FS_Security::instance()->get_context_params( - $site, - $timestamp, - 'checkout' - ) ); - } else { - $current_user = Freemius::_get_current_wp_user(); - - // Add site and user info to the request, this information - // is NOT being stored unless the user complete the purchase - // and agrees to the TOS. - $context_params = array_merge( $context_params, array( - 'user_firstname' => $current_user->user_firstname, - 'user_lastname' => $current_user->user_lastname, - 'user_email' => $current_user->user_email, -// 'user_nickname' => $current_user->user_nicename, -// 'plugin_slug' => $slug, -// 'site_url' => get_site_url(), -// 'site_name' => get_bloginfo( 'name' ), -// 'platform_version' => get_bloginfo( 'version' ), -// 'language' => get_bloginfo( 'language' ), -// 'charset' => get_bloginfo( 'charset' ), -// 'account_url' => fs_nonce_url( $fs->_get_admin_page_url( -// 'account', -// array( 'fs_action' => 'sync_user' ) -// ), 'sync_user' ), - ) ); - - $fs_user = Freemius::_get_user_by_email( $current_user->user_email ); - - if ( is_object( $fs_user ) ) { - $context_params = array_merge( $context_params, FS_Security::instance()->get_context_params( - $fs_user, - $timestamp, - 'checkout' - ) ); - } - } - - if ( $fs->is_payments_sandbox() ) - { - // Append plugin secure token for sandbox mode authentication. - $context_params['sandbox'] = FS_Security::instance()->get_secure_token( - $fs->get_plugin(), - $timestamp, - 'checkout' - ); - - /** - * @since 1.1.7.3 Add security timestamp for sandbox even for anonymous user. - */ - if ( empty( $context_params['s_ctx_ts'] ) ) { - $context_params['s_ctx_ts'] = $timestamp; - } - } - - $return_url = fs_nonce_url( $fs->_get_admin_page_url( - 'account', - array( - 'fs_action' => $slug . '_sync_license', - 'plugin_id' => isset( $_GET['plugin_id'] ) ? $_GET['plugin_id'] : $fs->get_id() - ) - ), $slug . '_sync_license' ); - - $query_params = array_merge( $context_params, $_GET, array( - // Current plugin version. - 'plugin_version' => $fs->get_plugin_version(), - 'return_url' => $return_url, - // Admin CSS URL for style/design competability. -// 'wp_admin_css' => get_bloginfo('wpurl') . "/wp-admin/load-styles.php?c=1&load=buttons,wp-admin,dashicons", - ) ); -?> - <div class="fs-secure-notice"> - <i class="dashicons dashicons-lock"></i> - <span><b>Secure HTTPS Checkout</b> - PCI compliant, running via iframe from external domain</span> - </div> - <div id="fs_contact" class="wrap" style="margin: 40px 0 -65px -20px;"> - <div id="iframe"></div> - <script type="text/javascript"> - // http://stackoverflow.com/questions/4583703/jquery-post-request-not-ajax - jQuery(function ($) { - $.extend({ - form: function (url, data, method) { - if (method == null) method = 'POST'; - if (data == null) data = {}; - - var form = $('<form>').attr({ - method: method, - action: url - }).css({ - display: 'none' - }); - - var addData = function (name, data) { - if ($.isArray(data)) { - for (var i = 0; i < data.length; i++) { - var value = data[i]; - addData(name + '[]', value); - } - } else if (typeof data === 'object') { - for (var key in data) { - if (data.hasOwnProperty(key)) { - addData(name + '[' + key + ']', data[key]); - } - } - } else if (data != null) { - form.append($('<input>').attr({ - type : 'hidden', - name : String(name), - value: String(data) - })); - } - }; - - for (var key in data) { - if (data.hasOwnProperty(key)) { - addData(key, data[key]); - } - } - - return form.appendTo('body'); - } - }); - }); - - (function ($) { - $(function () { - - var - // Keep track of the iframe height. - iframe_height = 800, - base_url = '<?php echo WP_FS__ADDRESS ?>', - // Pass the parent page URL into the Iframe in a meaningful way (this URL could be - // passed via query string or hard coded into the child page, it depends on your needs). - src = base_url + '/checkout/?<?php echo (isset($_REQUEST['XDEBUG_SESSION']) ? 'XDEBUG_SESSION=' . $_REQUEST['XDEBUG_SESSION'] . '&' : '') . http_build_query($query_params) ?>#' + encodeURIComponent(document.location.href), - - // Append the Iframe into the DOM. - iframe = $('<iframe " src="' + src + '" width="100%" height="' + iframe_height + 'px" scrolling="no" frameborder="0" style="background: transparent;"><\/iframe>') - .appendTo('#iframe'); - - FS.PostMessage.init(base_url); - FS.PostMessage.receiveOnce('height', function (data) { - var h = data.height; - if (!isNaN(h) && h > 0 && h != iframe_height) { - iframe_height = h; - $("#iframe iframe").height(iframe_height + 'px'); - } - }); - - FS.PostMessage.receiveOnce('install', function (data) { - // Post data to activation URL. - $.form('<?php echo fs_nonce_url($fs->_get_admin_page_url('account', array( - 'fs_action' => $slug . '_activate_new', - 'plugin_id' => isset($_GET['plugin_id']) ? $_GET['plugin_id'] : $fs->get_id() - )), $slug . '_activate_new') ?>', { - user_id : data.user.id, - user_secret_key : data.user.secret_key, - user_public_key : data.user.public_key, - install_id : data.install.id, - install_secret_key: data.install.secret_key, - install_public_key: data.install.public_key - }).submit(); - }); - - FS.PostMessage.receiveOnce('pending_activation', function (data) { - $.form('<?php echo fs_nonce_url($fs->_get_admin_page_url('account', array( - 'fs_action' => $slug . '_activate_new', - 'plugin_id' => fs_request_get('plugin_id', $fs->get_id()), - 'pending_activation' => true, - )), $slug . '_activate_new') ?>', { - user_email: data.user_email - }).submit(); - }); - - FS.PostMessage.receiveOnce('get_context', function () { - console.debug('receiveOnce', 'get_context'); - - // If the user didn't connect his account with Freemius, - // once he accepts the Terms of Service and Privacy Policy, - // and then click the purchase button, the context information - // of the user will be shared with Freemius in order to complete the - // purchase workflow and activate the license for the right user. - FS.PostMessage.post('context', { - plugin_id : '<?php echo $fs->get_id() ?>', - plugin_public_key: '<?php echo $fs->get_public_key() ?>', - plugin_version : '<?php echo $fs->get_plugin_version() ?>', - plugin_slug : '<?php echo $slug ?>', - site_name : '<?php echo get_bloginfo('name') ?>', - platform_version : '<?php echo get_bloginfo('version') ?>', - language : '<?php echo get_bloginfo('language') ?>', - charset : '<?php echo get_bloginfo('charset') ?>', - return_url : '<?php echo $return_url ?>', - account_url : '<?php echo fs_nonce_url($fs->_get_admin_page_url( - 'account', - array('fs_action' => 'sync_user') - ), 'sync_user') ?>', - activation_url : '<?php echo fs_nonce_url($fs->_get_admin_page_url('', - array( - 'fs_action' => $slug . '_activate_new', - 'plugin_id' => fs_request_get('plugin_id', $fs->get_id()), - - )), - $slug . '_activate_new') ?>' - }, iframe[0]); - }); - - FS.PostMessage.receiveOnce('get_dimensions', function (data) { - console.debug('receiveOnce', 'get_dimensions'); - - FS.PostMessage.post('dimensions', { - height : $(document.body).height(), - scrollTop: $(document).scrollTop() - }, iframe[0]); - }); - }); - })(jQuery); - </script> - </div> +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.3 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + wp_enqueue_script( 'jquery' ); + wp_enqueue_script( 'json2' ); + fs_enqueue_local_script( 'postmessage', 'nojquery.ba-postmessage.min.js' ); + fs_enqueue_local_script( 'fs-postmessage', 'postmessage.js' ); + fs_enqueue_local_style( 'fs_common', '/admin/common.css' ); + + $slug = $VARS['slug']; + $fs = freemius( $slug ); + + $timestamp = time(); + + $context_params = array( + 'plugin_id' => $fs->get_id(), + 'plugin_public_key' => $fs->get_public_key(), + 'plugin_version' => $fs->get_plugin_version(), + ); + + // Get site context secure params. + if ( $fs->is_registered() ) { + $site = $fs->get_site(); + $plugin_id = fs_request_get( 'plugin_id', $fs->get_id() ); + + if ($plugin_id != $fs->get_id()) { + if ( $fs->is_addon_activated( $plugin_id ) ) { + $fs_addon = Freemius::get_instance_by_id( $plugin_id ); + $site = $fs_addon->get_site(); + } + } + + $context_params = array_merge( $context_params, FS_Security::instance()->get_context_params( + $site, + $timestamp, + 'checkout' + ) ); + } else { + $current_user = Freemius::_get_current_wp_user(); + + // Add site and user info to the request, this information + // is NOT being stored unless the user complete the purchase + // and agrees to the TOS. + $context_params = array_merge( $context_params, array( + 'user_firstname' => $current_user->user_firstname, + 'user_lastname' => $current_user->user_lastname, + 'user_email' => $current_user->user_email, +// 'user_nickname' => $current_user->user_nicename, +// 'plugin_slug' => $slug, +// 'site_url' => get_site_url(), +// 'site_name' => get_bloginfo( 'name' ), +// 'platform_version' => get_bloginfo( 'version' ), +// 'language' => get_bloginfo( 'language' ), +// 'charset' => get_bloginfo( 'charset' ), +// 'account_url' => fs_nonce_url( $fs->_get_admin_page_url( +// 'account', +// array( 'fs_action' => 'sync_user' ) +// ), 'sync_user' ), + ) ); + + $fs_user = Freemius::_get_user_by_email( $current_user->user_email ); + + if ( is_object( $fs_user ) ) { + $context_params = array_merge( $context_params, FS_Security::instance()->get_context_params( + $fs_user, + $timestamp, + 'checkout' + ) ); + } + } + + if ( $fs->is_payments_sandbox() ) + { + // Append plugin secure token for sandbox mode authentication. + $context_params['sandbox'] = FS_Security::instance()->get_secure_token( + $fs->get_plugin(), + $timestamp, + 'checkout' + ); + + /** + * @since 1.1.7.3 Add security timestamp for sandbox even for anonymous user. + */ + if ( empty( $context_params['s_ctx_ts'] ) ) { + $context_params['s_ctx_ts'] = $timestamp; + } + } + + $return_url = fs_nonce_url( $fs->_get_admin_page_url( + 'account', + array( + 'fs_action' => $slug . '_sync_license', + 'plugin_id' => isset( $_GET['plugin_id'] ) ? $_GET['plugin_id'] : $fs->get_id() + ) + ), $slug . '_sync_license' ); + + $query_params = array_merge( $context_params, $_GET, array( + // Current plugin version. + 'plugin_version' => $fs->get_plugin_version(), + 'return_url' => $return_url, + // Admin CSS URL for style/design competability. +// 'wp_admin_css' => get_bloginfo('wpurl') . "/wp-admin/load-styles.php?c=1&load=buttons,wp-admin,dashicons", + ) ); +?> + <div class="fs-secure-notice"> + <i class="dashicons dashicons-lock"></i> + <span><b>Secure HTTPS Checkout</b> - PCI compliant, running via iframe from external domain</span> + </div> + <div id="fs_contact" class="wrap" style="margin: 40px 0 -65px -20px;"> + <div id="iframe"></div> + <script type="text/javascript"> + // http://stackoverflow.com/questions/4583703/jquery-post-request-not-ajax + jQuery(function ($) { + $.extend({ + form: function (url, data, method) { + if (method == null) method = 'POST'; + if (data == null) data = {}; + + var form = $('<form>').attr({ + method: method, + action: url + }).css({ + display: 'none' + }); + + var addData = function (name, data) { + if ($.isArray(data)) { + for (var i = 0; i < data.length; i++) { + var value = data[i]; + addData(name + '[]', value); + } + } else if (typeof data === 'object') { + for (var key in data) { + if (data.hasOwnProperty(key)) { + addData(name + '[' + key + ']', data[key]); + } + } + } else if (data != null) { + form.append($('<input>').attr({ + type : 'hidden', + name : String(name), + value: String(data) + })); + } + }; + + for (var key in data) { + if (data.hasOwnProperty(key)) { + addData(key, data[key]); + } + } + + return form.appendTo('body'); + } + }); + }); + + (function ($) { + $(function () { + + var + // Keep track of the iframe height. + iframe_height = 800, + base_url = '<?php echo WP_FS__ADDRESS ?>', + // Pass the parent page URL into the Iframe in a meaningful way (this URL could be + // passed via query string or hard coded into the child page, it depends on your needs). + src = base_url + '/checkout/?<?php echo (isset($_REQUEST['XDEBUG_SESSION']) ? 'XDEBUG_SESSION=' . $_REQUEST['XDEBUG_SESSION'] . '&' : '') . http_build_query($query_params) ?>#' + encodeURIComponent(document.location.href), + + // Append the Iframe into the DOM. + iframe = $('<iframe " src="' + src + '" width="100%" height="' + iframe_height + 'px" scrolling="no" frameborder="0" style="background: transparent;"><\/iframe>') + .appendTo('#iframe'); + + FS.PostMessage.init(base_url); + FS.PostMessage.receiveOnce('height', function (data) { + var h = data.height; + if (!isNaN(h) && h > 0 && h != iframe_height) { + iframe_height = h; + $("#iframe iframe").height(iframe_height + 'px'); + } + }); + + FS.PostMessage.receiveOnce('install', function (data) { + // Post data to activation URL. + $.form('<?php echo fs_nonce_url($fs->_get_admin_page_url('account', array( + 'fs_action' => $slug . '_activate_new', + 'plugin_id' => isset($_GET['plugin_id']) ? $_GET['plugin_id'] : $fs->get_id() + )), $slug . '_activate_new') ?>', { + user_id : data.user.id, + user_secret_key : data.user.secret_key, + user_public_key : data.user.public_key, + install_id : data.install.id, + install_secret_key: data.install.secret_key, + install_public_key: data.install.public_key + }).submit(); + }); + + FS.PostMessage.receiveOnce('pending_activation', function (data) { + $.form('<?php echo fs_nonce_url($fs->_get_admin_page_url('account', array( + 'fs_action' => $slug . '_activate_new', + 'plugin_id' => fs_request_get('plugin_id', $fs->get_id()), + 'pending_activation' => true, + )), $slug . '_activate_new') ?>', { + user_email: data.user_email + }).submit(); + }); + + FS.PostMessage.receiveOnce('get_context', function () { + console.debug('receiveOnce', 'get_context'); + + // If the user didn't connect his account with Freemius, + // once he accepts the Terms of Service and Privacy Policy, + // and then click the purchase button, the context information + // of the user will be shared with Freemius in order to complete the + // purchase workflow and activate the license for the right user. + FS.PostMessage.post('context', { + plugin_id : '<?php echo $fs->get_id() ?>', + plugin_public_key: '<?php echo $fs->get_public_key() ?>', + plugin_version : '<?php echo $fs->get_plugin_version() ?>', + plugin_slug : '<?php echo $slug ?>', + site_name : '<?php echo get_bloginfo('name') ?>', + platform_version : '<?php echo get_bloginfo('version') ?>', + language : '<?php echo get_bloginfo('language') ?>', + charset : '<?php echo get_bloginfo('charset') ?>', + return_url : '<?php echo $return_url ?>', + account_url : '<?php echo fs_nonce_url($fs->_get_admin_page_url( + 'account', + array('fs_action' => 'sync_user') + ), 'sync_user') ?>', + activation_url : '<?php echo fs_nonce_url($fs->_get_admin_page_url('', + array( + 'fs_action' => $slug . '_activate_new', + 'plugin_id' => fs_request_get('plugin_id', $fs->get_id()), + + )), + $slug . '_activate_new') ?>' + }, iframe[0]); + }); + + FS.PostMessage.receiveOnce('get_dimensions', function (data) { + console.debug('receiveOnce', 'get_dimensions'); + + FS.PostMessage.post('dimensions', { + height : $(document.body).height(), + scrollTop: $(document).scrollTop() + }, iframe[0]); + }); + }); + })(jQuery); + </script> + </div> <?php fs_require_template( 'powered-by.php' ) ?> \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/templates/connect.php b/wp-content/plugins/nextgen-gallery/freemius/templates/connect.php index 1389c06622538595be6697d52868633c8cc6d790..147a07ef4d5803fe05794714b9533278bd857522 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/templates/connect.php +++ b/wp-content/plugins/nextgen-gallery/freemius/templates/connect.php @@ -1,206 +1,206 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.7 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - $slug = $VARS['slug']; - $fs = freemius( $slug ); - $is_pending_activation = $fs->is_pending_activation(); - - $fs->_enqueue_connect_essentials(); - - $current_user = Freemius::_get_current_wp_user(); - - $first_name = $current_user->user_firstname; - if ( empty( $first_name ) ) { - $first_name = $current_user->nickname; - } - - $site_url = get_site_url(); - $protocol_pos = strpos( $site_url, '://' ); - if ( false !== $protocol_pos ) { - $site_url = substr( $site_url, $protocol_pos + 3 ); - } - - $freemius_site_url = $fs->has_paid_plan() ? - 'https://freemius.com/wordpress/' : - // Insights platform information. - 'https://freemius.com/wordpress/usage-tracking/'; -?> -<div id="fs_connect" class="wrap<?php if ( ! $fs->enable_anonymous() || $is_pending_activation ) { - echo ' fs-anonymous-disabled'; -} ?>"> - <div class="fs-visual"> - <b class="fs-site-icon"><i class="dashicons dashicons-wordpress"></i></b> - <i class="dashicons dashicons-plus fs-first"></i> - <?php - $vars = array( 'slug' => $slug ); - fs_require_once_template( 'plugin-icon.php', $vars ); - ?> - <i class="dashicons dashicons-plus fs-second"></i> - <img class="fs-connect-logo" width="80" height="80" src="//img.freemius.com/connect-logo.png"/> - </div> - <div class="fs-content"> - <p><?php - if ( $is_pending_activation ) { - echo $fs->apply_filters( 'pending_activation_message', sprintf( - __fs( 'thanks-x', $slug ) . '<br>' . - __fs( 'pending-activation-message', $slug ), - $first_name, - '<b>' . $fs->get_plugin_name() . '</b>', - '<b>' . $current_user->user_email . '</b>' - ) ); - } else { - $filter = 'connect_message'; - $default_optin_message = 'connect-message'; - - if ( $fs->is_plugin_update() ) { - // If Freemius was added on a plugin update, set different - // opt-in message. - $default_optin_message = 'connect-message_on-update'; - - // If user customized the opt-in message on update, use - // that message. Otherwise, fallback to regular opt-in - // custom message if exist. - if ( $fs->has_filter( 'connect_message_on_update' ) ) { - $filter = 'connect_message_on_update'; - } - } - - echo $fs->apply_filters( $filter, - sprintf( - __fs( 'hey-x', $slug ) . '<br>' . - __fs( $default_optin_message, $slug ), - $first_name, - '<b>' . $fs->get_plugin_name() . '</b>', - '<b>' . $current_user->user_login . '</b>', - '<a href="' . $site_url . '" target="_blank">' . $site_url . '</a>', - '<a href="' . $freemius_site_url . '" target="_blank">freemius.com</a>' - ), - $first_name, - $fs->get_plugin_name(), - $current_user->user_login, - '<a href="' . $site_url . '" target="_blank">' . $site_url . '</a>', - '<a href="' . $freemius_site_url . '" target="_blank">freemius.com</a>' - ); - } - ?></p> - </div> - <div class="fs-actions"> - <?php if ( $fs->enable_anonymous() && ! $is_pending_activation ) : ?> - <a href="<?php echo wp_nonce_url( $fs->_get_admin_page_url( '', array( 'fs_action' => $slug . '_skip_activation' ) ), $slug . '_skip_activation' ) ?>" - class="button button-secondary" tabindex="2"><?php _efs( 'skip', $slug ) ?></a> - <?php endif ?> - - <?php $fs_user = Freemius::_get_user_by_email( $current_user->user_email ) ?> - <?php if ( is_object( $fs_user ) && ! $is_pending_activation ) : ?> - <form action="" method="POST"> - <input type="hidden" name="fs_action" value="<?php echo $slug ?>_activate_existing"> - <?php wp_nonce_field( 'activate_existing_' . $fs->get_public_key() ) ?> - <button class="button button-primary" tabindex="1" - type="submit"><?php _efs( 'opt-in-connect', $slug ) ?></button> - </form> - <?php else : ?> - <form method="post" action="<?php echo WP_FS__ADDRESS ?>/action/service/user/install/"> - <?php $params = $fs->get_opt_in_params() ?> - <?php foreach ( $params as $name => $value ) : ?> - <input type="hidden" name="<?php echo $name ?>" value="<?php echo esc_attr( $value ) ?>"> - <?php endforeach ?> - <button class="button button-primary" tabindex="1" - type="submit"><?php _efs( $is_pending_activation ? 'resend-activation-email' : 'opt-in-connect', $slug ) ?></button> - </form> - <?php endif ?> - </div><?php - - // Set core permission list items. - $permissions = array( - 'profile' => array( - 'icon-class' => 'dashicons dashicons-admin-users', - 'label' => __fs( 'permissions-profile' ), - 'desc' => __fs( 'permissions-profile_desc' ), - 'priority' => 5, - ), - 'site' => array( - 'icon-class' => 'dashicons dashicons-admin-settings', - 'label' => __fs( 'permissions-site' ), - 'desc' => __fs( 'permissions-site_desc' ), - 'priority' => 10, - ), - 'events' => array( - 'icon-class' => 'dashicons dashicons-admin-plugins', - 'label' => __fs( 'permissions-events' ), - 'desc' => __fs( 'permissions-events_desc' ), - 'priority' => 20, - ), -// 'plugins_themes' => array( -// 'icon-class' => 'dashicons dashicons-admin-settings', -// 'label' => __fs( 'permissions-plugins_themes' ), -// 'desc' => __fs( 'permissions-plugins_themes_desc' ), -// 'priority' => 30, -// ), - ); - - // Add newsletter permissions if enabled. - if ( $fs->is_permission_requested( 'newsletter' ) ) { - $permissions['newsletter'] = array( - 'icon-class' => 'dashicons dashicons-email-alt', - 'label' => __fs( 'permissions-newsletter' ), - 'desc' => __fs( 'permissions-newsletter_desc' ), - 'priority' => 15, - ); - } - - // Allow filtering of the permissions list. - $permissions = $fs->apply_filters( 'permission_list', $permissions ); - - // Sort by priority. - uasort( $permissions, 'fs_sort_by_priority' ); - - if ( ! empty( $permissions ) ) : ?> - <div class="fs-permissions"> - <a class="fs-trigger" href="#"><?php _efs( 'what-permissions', $slug ) ?></a> - <ul><?php - foreach ( $permissions as $id => $permission ) : ?> - <li id="fs-permission-<?php esc_attr_e( $id ); ?>" - class="fs-permission fs-<?php esc_attr_e( $id ); ?>"> - <i class="<?php esc_attr_e( $permission['icon-class'] ); ?>"></i> - - <div> - <span><?php esc_html_e( $permission['label'] ); ?></span> - - <p><?php esc_html_e( $permission['desc'] ); ?></p> - </div> - </li> - <?php endforeach; ?> - </ul> - </div> - <?php endif; ?> - - <div class="fs-terms"> - <a href="https://freemius.com/privacy/" target="_blank"><?php _efs( 'privacy-policy', $slug ) ?></a> - - - <a href="https://freemius.com/terms/" target="_blank"><?php _efs( 'tos', $slug ) ?></a> - </div> -</div> -<script type="text/javascript"> - (function ($) { - $('.button').on('click', function () { - // Set loading mode. - $(document.body).css({'cursor': 'wait'}); - }); - $('.button.button-primary').on('click', function () { - $(this).addClass('fs-loading'); - $(this).html('<?php _efs( $is_pending_activation ? 'sending-email' : 'activating' , $slug ) ?>...').css({'cursor': 'wait'}); - }); - $('.fs-permissions .fs-trigger').on('click', function () { - $('.fs-permissions').toggleClass('fs-open'); - }); - })(jQuery); +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.7 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + $slug = $VARS['slug']; + $fs = freemius( $slug ); + $is_pending_activation = $fs->is_pending_activation(); + + $fs->_enqueue_connect_essentials(); + + $current_user = Freemius::_get_current_wp_user(); + + $first_name = $current_user->user_firstname; + if ( empty( $first_name ) ) { + $first_name = $current_user->nickname; + } + + $site_url = get_site_url(); + $protocol_pos = strpos( $site_url, '://' ); + if ( false !== $protocol_pos ) { + $site_url = substr( $site_url, $protocol_pos + 3 ); + } + + $freemius_site_url = $fs->has_paid_plan() ? + 'https://freemius.com/wordpress/' : + // Insights platform information. + 'https://freemius.com/wordpress/usage-tracking/'; +?> +<div id="fs_connect" class="wrap<?php if ( ! $fs->enable_anonymous() || $is_pending_activation ) { + echo ' fs-anonymous-disabled'; +} ?>"> + <div class="fs-visual"> + <b class="fs-site-icon"><i class="dashicons dashicons-wordpress"></i></b> + <i class="dashicons dashicons-plus fs-first"></i> + <?php + $vars = array( 'slug' => $slug ); + fs_require_once_template( 'plugin-icon.php', $vars ); + ?> + <i class="dashicons dashicons-plus fs-second"></i> + <img class="fs-connect-logo" width="80" height="80" src="//img.freemius.com/connect-logo.png"/> + </div> + <div class="fs-content"> + <p><?php + if ( $is_pending_activation ) { + echo $fs->apply_filters( 'pending_activation_message', sprintf( + __fs( 'thanks-x', $slug ) . '<br>' . + __fs( 'pending-activation-message', $slug ), + $first_name, + '<b>' . $fs->get_plugin_name() . '</b>', + '<b>' . $current_user->user_email . '</b>' + ) ); + } else { + $filter = 'connect_message'; + $default_optin_message = 'connect-message'; + + if ( $fs->is_plugin_update() ) { + // If Freemius was added on a plugin update, set different + // opt-in message. + $default_optin_message = 'connect-message_on-update'; + + // If user customized the opt-in message on update, use + // that message. Otherwise, fallback to regular opt-in + // custom message if exist. + if ( $fs->has_filter( 'connect_message_on_update' ) ) { + $filter = 'connect_message_on_update'; + } + } + + echo $fs->apply_filters( $filter, + sprintf( + __fs( 'hey-x', $slug ) . '<br>' . + __fs( $default_optin_message, $slug ), + $first_name, + '<b>' . $fs->get_plugin_name() . '</b>', + '<b>' . $current_user->user_login . '</b>', + '<a href="' . $site_url . '" target="_blank">' . $site_url . '</a>', + '<a href="' . $freemius_site_url . '" target="_blank">freemius.com</a>' + ), + $first_name, + $fs->get_plugin_name(), + $current_user->user_login, + '<a href="' . $site_url . '" target="_blank">' . $site_url . '</a>', + '<a href="' . $freemius_site_url . '" target="_blank">freemius.com</a>' + ); + } + ?></p> + </div> + <div class="fs-actions"> + <?php if ( $fs->enable_anonymous() && ! $is_pending_activation ) : ?> + <a href="<?php echo wp_nonce_url( $fs->_get_admin_page_url( '', array( 'fs_action' => $slug . '_skip_activation' ) ), $slug . '_skip_activation' ) ?>" + class="button button-secondary" tabindex="2"><?php _efs( 'skip', $slug ) ?></a> + <?php endif ?> + + <?php $fs_user = Freemius::_get_user_by_email( $current_user->user_email ) ?> + <?php if ( is_object( $fs_user ) && ! $is_pending_activation ) : ?> + <form action="" method="POST"> + <input type="hidden" name="fs_action" value="<?php echo $slug ?>_activate_existing"> + <?php wp_nonce_field( 'activate_existing_' . $fs->get_public_key() ) ?> + <button class="button button-primary" tabindex="1" + type="submit"><?php _efs( 'opt-in-connect', $slug ) ?></button> + </form> + <?php else : ?> + <form method="post" action="<?php echo WP_FS__ADDRESS ?>/action/service/user/install/"> + <?php $params = $fs->get_opt_in_params() ?> + <?php foreach ( $params as $name => $value ) : ?> + <input type="hidden" name="<?php echo $name ?>" value="<?php echo esc_attr( $value ) ?>"> + <?php endforeach ?> + <button class="button button-primary" tabindex="1" + type="submit"><?php _efs( $is_pending_activation ? 'resend-activation-email' : 'opt-in-connect', $slug ) ?></button> + </form> + <?php endif ?> + </div><?php + + // Set core permission list items. + $permissions = array( + 'profile' => array( + 'icon-class' => 'dashicons dashicons-admin-users', + 'label' => __fs( 'permissions-profile' ), + 'desc' => __fs( 'permissions-profile_desc' ), + 'priority' => 5, + ), + 'site' => array( + 'icon-class' => 'dashicons dashicons-admin-settings', + 'label' => __fs( 'permissions-site' ), + 'desc' => __fs( 'permissions-site_desc' ), + 'priority' => 10, + ), + 'events' => array( + 'icon-class' => 'dashicons dashicons-admin-plugins', + 'label' => __fs( 'permissions-events' ), + 'desc' => __fs( 'permissions-events_desc' ), + 'priority' => 20, + ), +// 'plugins_themes' => array( +// 'icon-class' => 'dashicons dashicons-admin-settings', +// 'label' => __fs( 'permissions-plugins_themes' ), +// 'desc' => __fs( 'permissions-plugins_themes_desc' ), +// 'priority' => 30, +// ), + ); + + // Add newsletter permissions if enabled. + if ( $fs->is_permission_requested( 'newsletter' ) ) { + $permissions['newsletter'] = array( + 'icon-class' => 'dashicons dashicons-email-alt', + 'label' => __fs( 'permissions-newsletter' ), + 'desc' => __fs( 'permissions-newsletter_desc' ), + 'priority' => 15, + ); + } + + // Allow filtering of the permissions list. + $permissions = $fs->apply_filters( 'permission_list', $permissions ); + + // Sort by priority. + uasort( $permissions, 'fs_sort_by_priority' ); + + if ( ! empty( $permissions ) ) : ?> + <div class="fs-permissions"> + <a class="fs-trigger" href="#"><?php _efs( 'what-permissions', $slug ) ?></a> + <ul><?php + foreach ( $permissions as $id => $permission ) : ?> + <li id="fs-permission-<?php esc_attr_e( $id ); ?>" + class="fs-permission fs-<?php esc_attr_e( $id ); ?>"> + <i class="<?php esc_attr_e( $permission['icon-class'] ); ?>"></i> + + <div> + <span><?php esc_html_e( $permission['label'] ); ?></span> + + <p><?php esc_html_e( $permission['desc'] ); ?></p> + </div> + </li> + <?php endforeach; ?> + </ul> + </div> + <?php endif; ?> + + <div class="fs-terms"> + <a href="https://freemius.com/privacy/" target="_blank"><?php _efs( 'privacy-policy', $slug ) ?></a> + - + <a href="https://freemius.com/terms/" target="_blank"><?php _efs( 'tos', $slug ) ?></a> + </div> +</div> +<script type="text/javascript"> + (function ($) { + $('.button').on('click', function () { + // Set loading mode. + $(document.body).css({'cursor': 'wait'}); + }); + $('.button.button-primary').on('click', function () { + $(this).addClass('fs-loading'); + $(this).html('<?php _efs( $is_pending_activation ? 'sending-email' : 'activating' , $slug ) ?>...').css({'cursor': 'wait'}); + }); + $('.fs-permissions .fs-trigger').on('click', function () { + $('.fs-permissions').toggleClass('fs-open'); + }); + })(jQuery); </script> \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/templates/contact.php b/wp-content/plugins/nextgen-gallery/freemius/templates/contact.php index 4e1f6065ab10d9749bc4122191ca2f2a4f45d3e1..eda05c27eaec804e62de75a2307118e8c6a45b21 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/templates/contact.php +++ b/wp-content/plugins/nextgen-gallery/freemius/templates/contact.php @@ -1,77 +1,77 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.3 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - wp_enqueue_script( 'jquery' ); - wp_enqueue_script( 'json2' ); - fs_enqueue_local_script( 'postmessage', 'nojquery.ba-postmessage.min.js' ); - fs_enqueue_local_script( 'fs-postmessage', 'postmessage.js' ); - fs_enqueue_local_style( 'fs_checkout', '/admin/common.css' ); - - $slug = $VARS['slug']; - $fs = freemius( $slug ); - - $context_params = array( - 'plugin_id' => $fs->get_id(), - 'plugin_public_key' => $fs->get_public_key(), - 'plugin_version' => $fs->get_plugin_version(), - ); - - - // Get site context secure params. - if ( $fs->is_registered() ) { - $context_params = array_merge( $context_params, FS_Security::instance()->get_context_params( - $fs->get_site(), - time(), - 'contact' - ) ); - } - - $query_params = array_merge( $_GET, array_merge( $context_params, array( - 'plugin_version' => $fs->get_plugin_version(), - 'wp_login_url' => wp_login_url(), - 'site_url' => get_site_url(), -// 'wp_admin_css' => get_bloginfo('wpurl') . "/wp-admin/load-styles.php?c=1&load=buttons,wp-admin,dashicons", - ) ) ); -?> - <div class="fs-secure-notice"> - <i class="dashicons dashicons-lock"></i> - <span><b>Secure HTTPS contact page</b>, running via iframe from external domain</span> - </div> - <div id="fs_contact" class="wrap" style="margin: 40px 0 -65px -20px;"> - <div id="iframe"></div> - <script type="text/javascript"> - (function ($) { - $(function () { - - var - // Keep track of the iframe height. - iframe_height = 800, - base_url = '<?php echo WP_FS__ADDRESS ?>', - src = base_url + '/contact/?<?php echo http_build_query($query_params) ?>#' + encodeURIComponent(document.location.href), - - // Append the Iframe into the DOM. - iframe = $('<iframe " src="' + src + '" width="100%" height="' + iframe_height + 'px" scrolling="no" frameborder="0" style="background: transparent;"><\/iframe>') - .appendTo('#iframe'); - - FS.PostMessage.init(base_url); - FS.PostMessage.receive('height', function (data) { - var h = data.height; - if (!isNaN(h) && h > 0 && h != iframe_height) { - iframe_height = h; - $("#iframe iframe").height(iframe_height + 'px'); - } - }); - }); - })(jQuery); - </script> - </div> +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.3 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + wp_enqueue_script( 'jquery' ); + wp_enqueue_script( 'json2' ); + fs_enqueue_local_script( 'postmessage', 'nojquery.ba-postmessage.min.js' ); + fs_enqueue_local_script( 'fs-postmessage', 'postmessage.js' ); + fs_enqueue_local_style( 'fs_checkout', '/admin/common.css' ); + + $slug = $VARS['slug']; + $fs = freemius( $slug ); + + $context_params = array( + 'plugin_id' => $fs->get_id(), + 'plugin_public_key' => $fs->get_public_key(), + 'plugin_version' => $fs->get_plugin_version(), + ); + + + // Get site context secure params. + if ( $fs->is_registered() ) { + $context_params = array_merge( $context_params, FS_Security::instance()->get_context_params( + $fs->get_site(), + time(), + 'contact' + ) ); + } + + $query_params = array_merge( $_GET, array_merge( $context_params, array( + 'plugin_version' => $fs->get_plugin_version(), + 'wp_login_url' => wp_login_url(), + 'site_url' => get_site_url(), +// 'wp_admin_css' => get_bloginfo('wpurl') . "/wp-admin/load-styles.php?c=1&load=buttons,wp-admin,dashicons", + ) ) ); +?> + <div class="fs-secure-notice"> + <i class="dashicons dashicons-lock"></i> + <span><b>Secure HTTPS contact page</b>, running via iframe from external domain</span> + </div> + <div id="fs_contact" class="wrap" style="margin: 40px 0 -65px -20px;"> + <div id="iframe"></div> + <script type="text/javascript"> + (function ($) { + $(function () { + + var + // Keep track of the iframe height. + iframe_height = 800, + base_url = '<?php echo WP_FS__ADDRESS ?>', + src = base_url + '/contact/?<?php echo http_build_query($query_params) ?>#' + encodeURIComponent(document.location.href), + + // Append the Iframe into the DOM. + iframe = $('<iframe " src="' + src + '" width="100%" height="' + iframe_height + 'px" scrolling="no" frameborder="0" style="background: transparent;"><\/iframe>') + .appendTo('#iframe'); + + FS.PostMessage.init(base_url); + FS.PostMessage.receive('height', function (data) { + var h = data.height; + if (!isNaN(h) && h > 0 && h != iframe_height) { + iframe_height = h; + $("#iframe iframe").height(iframe_height + 'px'); + } + }); + }); + })(jQuery); + </script> + </div> <?php fs_require_template( 'powered-by.php' ) ?> \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/templates/deactivation-feedback-modal.php b/wp-content/plugins/nextgen-gallery/freemius/templates/deactivation-feedback-modal.php index 917bcade5a8762b8dcbec437aa5fe92f91ecc758..31980c8dd9687366f1cbaa0c1e54367c8231a782 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/templates/deactivation-feedback-modal.php +++ b/wp-content/plugins/nextgen-gallery/freemius/templates/deactivation-feedback-modal.php @@ -1,282 +1,282 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.1.2 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - $slug = $VARS['slug']; - $fs = freemius( $slug ); - - $confirmation_message = $fs->apply_filters( 'uninstall_confirmation_message', '' ); - - $reasons = $VARS['reasons']; - - $reasons_list_items_html = ''; - - foreach ( $reasons as $reason ) { - $list_item_classes = 'reason' . ( ! empty( $reason['input_type'] ) ? ' has-input' : '' ); - $reasons_list_items_html .= '<li class="' . $list_item_classes . '" data-input-type="' . $reason['input_type'] . '" data-input-placeholder="' . $reason['input_placeholder'] . '"><label><span><input type="radio" name="selected-reason" value="' . $reason['id'] . '"/></span><span>' . $reason['text'] . '</span></label></li>'; - } -?> -<script type="text/javascript"> -(function ($) { - var reasonsHtml = <?php echo json_encode( $reasons_list_items_html ); ?>, - modalHtml = - '<div class="fs-modal<?php echo empty( $confirmation_message ) ? ' no-confirmation-message' : ''; ?>">' - + ' <div class="fs-modal-dialog">' - + ' <div class="fs-modal-body">' - + ' <div class="fs-modal-panel" data-panel-id="confirm"><p><?php echo $confirmation_message; ?></p></div>' - + ' <div class="fs-modal-panel active" data-panel-id="reasons"><h3><strong><?php printf( __fs( 'deactivation-share-reason' , $slug ) ); ?>:</strong></h3><ul id="reasons-list">' + reasonsHtml + '</ul></div>' - + ' </div>' - + ' <div class="fs-modal-footer">' - + ' <a href="#" class="button button-secondary button-deactivate"></a>' - + ' <a href="#" class="button button-primary button-close"><?php printf( __fs( 'deactivation-modal-button-cancel' , $slug ) ); ?></a>' - + ' </div>' - + ' </div>' - + '</div>', - $modal = $(modalHtml), - $deactivateLink = $('#the-list .deactivate > [data-slug=<?php echo $VARS['slug']; ?>].fs-slug').prev(), - selectedReasonID = false; - - $modal.appendTo($('body')); - - registerEventHandlers(); - - function registerEventHandlers() { - $deactivateLink.click(function (evt) { - evt.preventDefault(); - - showModal(); - }); - - $modal.on('input propertychange', '.reason-input input', function () { - if (!isOtherReasonSelected()) { - return; - } - - var reason = $(this).val().trim(); - - /** - * If reason is not empty, remove the error-message class of the message container - * to change the message color back to default. - */ - if (reason.length > 0) { - $('.message').removeClass('error-message'); - enableDeactivateButton(); - } - }); - - $modal.on('blur', '.reason-input input', function () { - var $userReason = $(this); - - setTimeout(function () { - if (!isOtherReasonSelected()) { - return; - } - - /** - * If reason is empty, add the error-message class to the message container - * to change the message color to red. - */ - if (0 === $userReason.val().trim().length) { - $('.message').addClass('error-message'); - disableDeactivateButton(); - } - }, 150); - }); - - $modal.on('click', '.button', function (evt) { - evt.preventDefault(); - - if ($(this).hasClass('disabled')) { - return; - } - - var _parent = $(this).parents('.fs-modal:first'); - var _this = $(this); - - if (_this.hasClass('allow-deactivate')) { - var $radio = $('input[type="radio"]:checked'); - - if (0 === $radio.length) { - // If no selected reason, just deactivate the plugin. - window.location.href = $deactivateLink.attr('href'); - return; - } - - var $selected_reason = $radio.parents('li:first'), - $input = $selected_reason.find('textarea, input[type="text"]'), - userReason = ( 0 !== $input.length ) ? $input.val().trim() : ''; - - if (isOtherReasonSelected() && ( '' === userReason )) { - return; - } - - $.ajax({ - url : ajaxurl, - method : 'POST', - data : { - 'action' : 'submit-uninstall-reason', - 'reason_id' : $radio.val(), - 'reason_info': userReason - }, - beforeSend: function () { - _parent.find('.button').addClass('disabled'); - _parent.find('.button-secondary').text('Processing...'); - }, - complete : function () { - // Do not show the dialog box, deactivate the plugin. - window.location.href = $deactivateLink.attr('href'); - } - }); - } else if (_this.hasClass('button-deactivate')) { - // Change the Deactivate button's text and show the reasons panel. - _parent.find('.button-deactivate').addClass('allow-deactivate'); - - showPanel('reasons'); - } - }); - - $modal.on('click', 'input[type="radio"]', function () { - var $selectedReasonOption = $(this); - - // If the selection has not changed, do not proceed. - if (selectedReasonID === $selectedReasonOption.val()) - return; - - selectedReasonID = $selectedReasonOption.val(); - - var _parent = $(this).parents('li:first'); - - $modal.find('.reason-input').remove(); - $modal.find('.button-deactivate').text('<?php printf( __fs( 'deactivation-modal-button-submit' , $slug ) ); ?>'); - - enableDeactivateButton(); - - if (_parent.hasClass('has-input')) { - var inputType = _parent.data('input-type'), - inputPlaceholder = _parent.data('input-placeholder'), - reasonInputHtml = '<div class="reason-input"><span class="message"></span>' + ( ( 'textfield' === inputType ) ? '<input type="text" />' : '<textarea rows="5"></textarea>' ) + '</div>'; - - _parent.append($(reasonInputHtml)); - _parent.find('input, textarea').attr('placeholder', inputPlaceholder).focus(); - - if (isOtherReasonSelected()) { - showMessage('<?php printf( __fs( 'ask-for-reason-message' , $slug ) ); ?>'); - disableDeactivateButton(); - } - } - }); - - // If the user has clicked outside the window, cancel it. - $modal.on('click', function (evt) { - var $target = $(evt.target); - - // If the user has clicked anywhere in the modal dialog, just return. - if ($target.hasClass('fs-modal-body') || $target.hasClass('fs-modal-footer')) { - return; - } - - // If the user has not clicked the close button and the clicked element is inside the modal dialog, just return. - if (!$target.hasClass('button-close') && ( $target.parents('.fs-modal-body').length > 0 || $target.parents('.fs-modal-footer').length > 0 )) { - return; - } - - closeModal(); - }); - } - - function isOtherReasonSelected() { - // Get the selected radio input element. - var $selectedReasonOption = $modal.find('input[type="radio"]:checked'), - selectedReason = $selectedReasonOption.parent().next().text().trim(); - - return ( 'Other' === selectedReason ); - } - - function showModal() { - resetModal(); - - // Display the dialog box. - $modal.addClass('active'); - - $('body').addClass('has-fs-modal'); - } - - function closeModal() { - $modal.removeClass('active'); - - $('body').removeClass('has-fs-modal'); - } - - function resetModal() { - selectedReasonID = false; - - enableDeactivateButton(); - - // Uncheck all radio buttons. - $modal.find('input[type="radio"]').prop('checked', false); - - // Remove all input fields ( textfield, textarea ). - $modal.find('.reason-input').remove(); - - $modal.find('.message').hide(); - - var $deactivateButton = $modal.find('.button-deactivate'); - - /* - * If the modal dialog has no confirmation message, that is, it has only one panel, then ensure - * that clicking the deactivate button will actually deactivate the plugin. - */ - if ($modal.hasClass('no-confirmation-message')) { - $deactivateButton.addClass('allow-deactivate'); - - showPanel('reasons'); - } else { - $deactivateButton.removeClass('allow-deactivate'); - - showPanel('confirm'); - } - } - - function showMessage(message) { - $modal.find('.message').text(message).show(); - } - - function enableDeactivateButton() { - $modal.find('.button-deactivate').removeClass('disabled'); - } - - function disableDeactivateButton() { - $modal.find('.button-deactivate').addClass('disabled'); - } - - function showPanel(panelType) { - $modal.find('.fs-modal-panel').removeClass('active '); - $modal.find('[data-panel-id="' + panelType + '"]').addClass('active'); - - updateButtonLabels(); - } - - function updateButtonLabels() { - var $deactivateButton = $modal.find('.button-deactivate'); - - // Reset the deactivate button's text. - if ('confirm' === getCurrentPanel()) { - $deactivateButton.text('<?php printf( __fs( 'deactivation-modal-button-confirm' , $slug ) ); ?>'); - } else { - $deactivateButton.text('<?php printf( __fs( 'skip-deactivate' , $slug ) ); ?>'); - } - } - - function getCurrentPanel() { - return $modal.find('.fs-modal-panel.active').attr('data-panel-id'); - } -})(jQuery); -</script> +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.1.2 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + $slug = $VARS['slug']; + $fs = freemius( $slug ); + + $confirmation_message = $fs->apply_filters( 'uninstall_confirmation_message', '' ); + + $reasons = $VARS['reasons']; + + $reasons_list_items_html = ''; + + foreach ( $reasons as $reason ) { + $list_item_classes = 'reason' . ( ! empty( $reason['input_type'] ) ? ' has-input' : '' ); + $reasons_list_items_html .= '<li class="' . $list_item_classes . '" data-input-type="' . $reason['input_type'] . '" data-input-placeholder="' . $reason['input_placeholder'] . '"><label><span><input type="radio" name="selected-reason" value="' . $reason['id'] . '"/></span><span>' . $reason['text'] . '</span></label></li>'; + } +?> +<script type="text/javascript"> +(function ($) { + var reasonsHtml = <?php echo json_encode( $reasons_list_items_html ); ?>, + modalHtml = + '<div class="fs-modal<?php echo empty( $confirmation_message ) ? ' no-confirmation-message' : ''; ?>">' + + ' <div class="fs-modal-dialog">' + + ' <div class="fs-modal-body">' + + ' <div class="fs-modal-panel" data-panel-id="confirm"><p><?php echo $confirmation_message; ?></p></div>' + + ' <div class="fs-modal-panel active" data-panel-id="reasons"><h3><strong><?php printf( __fs( 'deactivation-share-reason' , $slug ) ); ?>:</strong></h3><ul id="reasons-list">' + reasonsHtml + '</ul></div>' + + ' </div>' + + ' <div class="fs-modal-footer">' + + ' <a href="#" class="button button-secondary button-deactivate"></a>' + + ' <a href="#" class="button button-primary button-close"><?php printf( __fs( 'deactivation-modal-button-cancel' , $slug ) ); ?></a>' + + ' </div>' + + ' </div>' + + '</div>', + $modal = $(modalHtml), + $deactivateLink = $('#the-list .deactivate > [data-slug=<?php echo $VARS['slug']; ?>].fs-slug').prev(), + selectedReasonID = false; + + $modal.appendTo($('body')); + + registerEventHandlers(); + + function registerEventHandlers() { + $deactivateLink.click(function (evt) { + evt.preventDefault(); + + showModal(); + }); + + $modal.on('input propertychange', '.reason-input input', function () { + if (!isOtherReasonSelected()) { + return; + } + + var reason = $(this).val().trim(); + + /** + * If reason is not empty, remove the error-message class of the message container + * to change the message color back to default. + */ + if (reason.length > 0) { + $('.message').removeClass('error-message'); + enableDeactivateButton(); + } + }); + + $modal.on('blur', '.reason-input input', function () { + var $userReason = $(this); + + setTimeout(function () { + if (!isOtherReasonSelected()) { + return; + } + + /** + * If reason is empty, add the error-message class to the message container + * to change the message color to red. + */ + if (0 === $userReason.val().trim().length) { + $('.message').addClass('error-message'); + disableDeactivateButton(); + } + }, 150); + }); + + $modal.on('click', '.button', function (evt) { + evt.preventDefault(); + + if ($(this).hasClass('disabled')) { + return; + } + + var _parent = $(this).parents('.fs-modal:first'); + var _this = $(this); + + if (_this.hasClass('allow-deactivate')) { + var $radio = $('input[type="radio"]:checked'); + + if (0 === $radio.length) { + // If no selected reason, just deactivate the plugin. + window.location.href = $deactivateLink.attr('href'); + return; + } + + var $selected_reason = $radio.parents('li:first'), + $input = $selected_reason.find('textarea, input[type="text"]'), + userReason = ( 0 !== $input.length ) ? $input.val().trim() : ''; + + if (isOtherReasonSelected() && ( '' === userReason )) { + return; + } + + $.ajax({ + url : ajaxurl, + method : 'POST', + data : { + 'action' : 'submit-uninstall-reason', + 'reason_id' : $radio.val(), + 'reason_info': userReason + }, + beforeSend: function () { + _parent.find('.button').addClass('disabled'); + _parent.find('.button-secondary').text('Processing...'); + }, + complete : function () { + // Do not show the dialog box, deactivate the plugin. + window.location.href = $deactivateLink.attr('href'); + } + }); + } else if (_this.hasClass('button-deactivate')) { + // Change the Deactivate button's text and show the reasons panel. + _parent.find('.button-deactivate').addClass('allow-deactivate'); + + showPanel('reasons'); + } + }); + + $modal.on('click', 'input[type="radio"]', function () { + var $selectedReasonOption = $(this); + + // If the selection has not changed, do not proceed. + if (selectedReasonID === $selectedReasonOption.val()) + return; + + selectedReasonID = $selectedReasonOption.val(); + + var _parent = $(this).parents('li:first'); + + $modal.find('.reason-input').remove(); + $modal.find('.button-deactivate').text('<?php printf( __fs( 'deactivation-modal-button-submit' , $slug ) ); ?>'); + + enableDeactivateButton(); + + if (_parent.hasClass('has-input')) { + var inputType = _parent.data('input-type'), + inputPlaceholder = _parent.data('input-placeholder'), + reasonInputHtml = '<div class="reason-input"><span class="message"></span>' + ( ( 'textfield' === inputType ) ? '<input type="text" />' : '<textarea rows="5"></textarea>' ) + '</div>'; + + _parent.append($(reasonInputHtml)); + _parent.find('input, textarea').attr('placeholder', inputPlaceholder).focus(); + + if (isOtherReasonSelected()) { + showMessage('<?php printf( __fs( 'ask-for-reason-message' , $slug ) ); ?>'); + disableDeactivateButton(); + } + } + }); + + // If the user has clicked outside the window, cancel it. + $modal.on('click', function (evt) { + var $target = $(evt.target); + + // If the user has clicked anywhere in the modal dialog, just return. + if ($target.hasClass('fs-modal-body') || $target.hasClass('fs-modal-footer')) { + return; + } + + // If the user has not clicked the close button and the clicked element is inside the modal dialog, just return. + if (!$target.hasClass('button-close') && ( $target.parents('.fs-modal-body').length > 0 || $target.parents('.fs-modal-footer').length > 0 )) { + return; + } + + closeModal(); + }); + } + + function isOtherReasonSelected() { + // Get the selected radio input element. + var $selectedReasonOption = $modal.find('input[type="radio"]:checked'), + selectedReason = $selectedReasonOption.parent().next().text().trim(); + + return ( 'Other' === selectedReason ); + } + + function showModal() { + resetModal(); + + // Display the dialog box. + $modal.addClass('active'); + + $('body').addClass('has-fs-modal'); + } + + function closeModal() { + $modal.removeClass('active'); + + $('body').removeClass('has-fs-modal'); + } + + function resetModal() { + selectedReasonID = false; + + enableDeactivateButton(); + + // Uncheck all radio buttons. + $modal.find('input[type="radio"]').prop('checked', false); + + // Remove all input fields ( textfield, textarea ). + $modal.find('.reason-input').remove(); + + $modal.find('.message').hide(); + + var $deactivateButton = $modal.find('.button-deactivate'); + + /* + * If the modal dialog has no confirmation message, that is, it has only one panel, then ensure + * that clicking the deactivate button will actually deactivate the plugin. + */ + if ($modal.hasClass('no-confirmation-message')) { + $deactivateButton.addClass('allow-deactivate'); + + showPanel('reasons'); + } else { + $deactivateButton.removeClass('allow-deactivate'); + + showPanel('confirm'); + } + } + + function showMessage(message) { + $modal.find('.message').text(message).show(); + } + + function enableDeactivateButton() { + $modal.find('.button-deactivate').removeClass('disabled'); + } + + function disableDeactivateButton() { + $modal.find('.button-deactivate').addClass('disabled'); + } + + function showPanel(panelType) { + $modal.find('.fs-modal-panel').removeClass('active '); + $modal.find('[data-panel-id="' + panelType + '"]').addClass('active'); + + updateButtonLabels(); + } + + function updateButtonLabels() { + var $deactivateButton = $modal.find('.button-deactivate'); + + // Reset the deactivate button's text. + if ('confirm' === getCurrentPanel()) { + $deactivateButton.text('<?php printf( __fs( 'deactivation-modal-button-confirm' , $slug ) ); ?>'); + } else { + $deactivateButton.text('<?php printf( __fs( 'skip-deactivate' , $slug ) ); ?>'); + } + } + + function getCurrentPanel() { + return $modal.find('.fs-modal-panel.active').attr('data-panel-id'); + } +})(jQuery); +</script> diff --git a/wp-content/plugins/nextgen-gallery/freemius/templates/debug.php b/wp-content/plugins/nextgen-gallery/freemius/templates/debug.php index 9163f1046c86d9db97bac804828aac974aa6375e..341cb1c0920dd8c6517f2c514339477b4d96c920 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/templates/debug.php +++ b/wp-content/plugins/nextgen-gallery/freemius/templates/debug.php @@ -1,250 +1,250 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.1.1 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - global $fs_active_plugins; - - $fs_options = FS_Option_Manager::get_manager( WP_FS__ACCOUNTS_OPTION_NAME, true ); -?> - <h1><?php echo __fs( 'Freemius Debug' ) . ' - ' . __fs( 'SDK' ) . ' v.' . $fs_active_plugins->newest->version ?></h1> - <div> - <!-- Debugging Switch --> - <?php //$debug_mode = get_option( 'fs_debug_mode', null ) ?> - <span class="switch-label"><?php _efs( 'debugging' ) ?></span> - - <div class="switch <?php echo WP_FS__DEBUG_SDK ? 'off' : 'on' ?>"> - <div class="toggle"></div> - <span class="on"><?php _efs( 'on' ) ?></span> - <span class="off"><?php _efs( 'off' ) ?></span> - </div> - <script type="text/javascript"> - (function ($) { - $(document).ready(function () { - // Switch toggle - $('.switch').click(function () { - $(this) - .toggleClass('on') - .toggleClass('off'); - - $.post(ajaxurl, { - action: 'fs_toggle_debug_mode', - is_on : ($(this).hasClass('off') ? 1 : 0) - }, function (response) { - if (1 == response) { - // Refresh page on success. - location.reload(); - } - }); - }); - }); - }(jQuery)); - </script> - </div> - <h2><?php _efs( 'actions' ) ?></h2> - <table> - <tbody> - <tr> - <td> - <!-- Delete All Accounts --> - <form action="" method="POST"> - <input type="hidden" name="fs_action" value="restart_freemius"> - <?php wp_nonce_field( 'restart_freemius' ) ?> - <button class="button button-primary" - onclick="if (confirm('<?php _efs( 'delete-all-confirm' ) ?>')) this.parentNode.submit(); return false;"><?php _efs( 'delete-all-accounts' ) ?></button> - </form> - </td> - <td> - <!-- Clear API Cache --> - <form action="" method="POST"> - <input type="hidden" name="fs_clear_api_cache" value="true"> - <button class="button button-primary"><?php _efs( 'clear-api-cache' ) ?></button> - </form> - </td> - <td> - <!-- Sync Data with Server --> - <form action="" method="POST"> - <input type="hidden" name="background_sync" value="true"> - <button class="button button-primary"><?php _efs( 'sync-data-from-server' ) ?></button> - </form> - </td> - </tr> - </tbody> - </table> - <h2><?php _efs( 'sdk-versions' ) ?></h2> - <table id="fs_sdks" class="widefat"> - <thead> - <tr> - <th><?php _efs( 'version' ) ?></th> - <th><?php _efs( 'sdk-path' ) ?></th> - <th><?php _efs( 'plugin-path' ) ?></th> - <th><?php _efs( 'is-active' ) ?></th> - </tr> - </thead> - <tbody> - <?php foreach ( $fs_active_plugins->plugins as $sdk_path => &$data ) : ?> - <?php $is_active = ( WP_FS__SDK_VERSION == $data->version ) ?> - <tr<?php if ( $is_active ) { - echo ' style="background: #E6FFE6; font-weight: bold"'; - } ?>> - <td><?php echo $data->version ?></td> - <td><?php echo $sdk_path ?></td> - <td><?php echo $data->plugin_path ?></td> - <td><?php echo ( $is_active ) ? 'Active' : 'Inactive' ?></td> - </tr> - <?php endforeach ?> - </tbody> - </table> -<?php $plugins = $fs_options->get_option( 'plugins' ) ?> -<?php if ( is_array( $plugins ) && 0 < count( $plugins ) ) : ?> - <h2><?php _efs( 'plugins' ) ?></h2> - <table id="fs_plugins" class="widefat"> - <thead> - <tr> - <th><?php _efs( 'id' ) ?></th> - <th><?php _efs( 'slug' ) ?></th> - <th><?php _efs( 'version' ) ?></th> - <th><?php _efs( 'title' ) ?></th> - <th><?php _efs( 'api' ) ?></th> - <th><?php _efs( 'freemius-state' ) ?></th> - <th><?php _efs( 'plugin-path' ) ?></th> - <th><?php _efs( 'public-key' ) ?></th> - </tr> - </thead> - <tbody> - <?php foreach ( $plugins as $slug => $data ) : ?> - <?php $is_active = is_plugin_active( $data->file ) ?> - <?php $fs = $is_active ? freemius( $slug ) : null ?> - <tr<?php if ( $is_active ) { - echo ' style="background: #E6FFE6; font-weight: bold"'; - } ?>> - <td><?php echo $data->id ?></td> - <td><?php echo $slug ?></td> - <td><?php echo $data->version ?></td> - <td><?php echo $data->title ?></td> - <td><?php if ( $is_active ) { - echo $fs->has_api_connectivity() ? - __fs( 'connected' ) : - __fs( 'blocked' ); - } ?></td> - <td><?php if ( $is_active ) { - echo $fs->is_on() ? - __fs( 'on' ) : - __fs( 'off' ); - } ?></td> - <td><?php echo $data->file ?></td> - <td><?php echo $data->public_key ?></td> - </tr> - <?php endforeach ?> - </tbody> - </table> -<?php endif ?> -<?php - /** - * @var FS_Site[] $sites - */ - $sites = $VARS['sites']; -?> -<?php if ( is_array( $sites ) && 0 < count( $sites ) ) : ?> - <h2><?php _efs( 'plugin-installs' ) ?> / <?php _efs( 'sites' ) ?></h2> - <table id="fs_installs" class="widefat"> - <thead> - <tr> - <th><?php _efs( 'id' ) ?></th> - <th><?php _efs( 'slug' ) ?></th> - <th><?php _efs( 'plan' ) ?></th> - <th><?php _efs( 'public-key' ) ?></th> - <th><?php _efs( 'secret-key' ) ?></th> - </tr> - </thead> - <tbody> - <?php foreach ( $sites as $slug => $site ) : ?> - <tr> - <td><?php echo $site->id ?></td> - <td><?php echo $slug ?></td> - <td><?php - echo is_object( $site->plan ) ? - base64_decode( $site->plan->name ) : - '' - ?></td> - <td><?php echo $site->public_key ?></td> - <td><?php echo $site->secret_key ?></td> - </tr> - <?php endforeach ?> - </tbody> - </table> -<?php endif ?> -<?php - $addons = $VARS['addons']; -?> -<?php foreach ( $addons as $plugin_id => $plugin_addons ) : ?> - <h2><?php printf( __fs( 'addons-of-x' ), $plugin_id ) ?></h2> - <table id="fs_addons" class="widefat"> - <thead> - <tr> - <th><?php _efs( 'id' ) ?></th> - <th><?php _efs( 'title' ) ?></th> - <th><?php _efs( 'slug' ) ?></th> - <th><?php _efs( 'version' ) ?></th> - <th><?php _efs( 'public-key' ) ?></th> - <th><?php _efs( 'secret-key' ) ?></th> - </tr> - </thead> - <tbody> - <?php - /** - * @var FS_Plugin[] $plugin_addons - */ - foreach ( $plugin_addons as $addon ) : ?> - <tr> - <td><?php echo $addon->id ?></td> - <td><?php echo $addon->title ?></td> - <td><?php echo $addon->slug ?></td> - <td><?php echo $addon->version ?></td> - <td><?php echo $addon->public_key ?></td> - <td><?php echo $addon->secret_key ?></td> - </tr> - <?php endforeach ?> - </tbody> - </table> -<?php endforeach ?> -<?php - /** - * @var FS_User[] $users - */ - $users = $VARS['users']; -?> -<?php if ( is_array( $users ) && 0 < count( $users ) ) : ?> - <h2><?php _efs( 'users' ) ?></h2> - <table id="fs_users" class="widefat"> - <thead> - <tr> - <th><?php _efs( 'id' ) ?></th> - <th><?php _efs( 'name' ) ?></th> - <th><?php _efs( 'email' ) ?></th> - <th><?php _efs( 'verified' ) ?></th> - <th><?php _efs( 'public-key' ) ?></th> - <th><?php _efs( 'secret-key' ) ?></th> - </tr> - </thead> - <tbody> - <?php foreach ( $users as $user_id => $user ) : ?> - <tr> - <td><?php echo $user->id ?></td> - <td><?php echo $user->get_name() ?></td> - <td><a href="mailto:<?php esc_attr_e($user->email) ?>"><?php echo $user->email ?></a></td> - <td><?php echo json_encode( $user->is_verified ) ?></td> - <td><?php echo $user->public_key ?></td> - <td><?php echo $user->secret_key ?></td> - </tr> - <?php endforeach ?> - </tbody> - </table> +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.1.1 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + global $fs_active_plugins; + + $fs_options = FS_Option_Manager::get_manager( WP_FS__ACCOUNTS_OPTION_NAME, true ); +?> + <h1><?php echo __fs( 'Freemius Debug' ) . ' - ' . __fs( 'SDK' ) . ' v.' . $fs_active_plugins->newest->version ?></h1> + <div> + <!-- Debugging Switch --> + <?php //$debug_mode = get_option( 'fs_debug_mode', null ) ?> + <span class="switch-label"><?php _efs( 'debugging' ) ?></span> + + <div class="switch <?php echo WP_FS__DEBUG_SDK ? 'off' : 'on' ?>"> + <div class="toggle"></div> + <span class="on"><?php _efs( 'on' ) ?></span> + <span class="off"><?php _efs( 'off' ) ?></span> + </div> + <script type="text/javascript"> + (function ($) { + $(document).ready(function () { + // Switch toggle + $('.switch').click(function () { + $(this) + .toggleClass('on') + .toggleClass('off'); + + $.post(ajaxurl, { + action: 'fs_toggle_debug_mode', + is_on : ($(this).hasClass('off') ? 1 : 0) + }, function (response) { + if (1 == response) { + // Refresh page on success. + location.reload(); + } + }); + }); + }); + }(jQuery)); + </script> + </div> + <h2><?php _efs( 'actions' ) ?></h2> + <table> + <tbody> + <tr> + <td> + <!-- Delete All Accounts --> + <form action="" method="POST"> + <input type="hidden" name="fs_action" value="restart_freemius"> + <?php wp_nonce_field( 'restart_freemius' ) ?> + <button class="button button-primary" + onclick="if (confirm('<?php _efs( 'delete-all-confirm' ) ?>')) this.parentNode.submit(); return false;"><?php _efs( 'delete-all-accounts' ) ?></button> + </form> + </td> + <td> + <!-- Clear API Cache --> + <form action="" method="POST"> + <input type="hidden" name="fs_clear_api_cache" value="true"> + <button class="button button-primary"><?php _efs( 'clear-api-cache' ) ?></button> + </form> + </td> + <td> + <!-- Sync Data with Server --> + <form action="" method="POST"> + <input type="hidden" name="background_sync" value="true"> + <button class="button button-primary"><?php _efs( 'sync-data-from-server' ) ?></button> + </form> + </td> + </tr> + </tbody> + </table> + <h2><?php _efs( 'sdk-versions' ) ?></h2> + <table id="fs_sdks" class="widefat"> + <thead> + <tr> + <th><?php _efs( 'version' ) ?></th> + <th><?php _efs( 'sdk-path' ) ?></th> + <th><?php _efs( 'plugin-path' ) ?></th> + <th><?php _efs( 'is-active' ) ?></th> + </tr> + </thead> + <tbody> + <?php foreach ( $fs_active_plugins->plugins as $sdk_path => &$data ) : ?> + <?php $is_active = ( WP_FS__SDK_VERSION == $data->version ) ?> + <tr<?php if ( $is_active ) { + echo ' style="background: #E6FFE6; font-weight: bold"'; + } ?>> + <td><?php echo $data->version ?></td> + <td><?php echo $sdk_path ?></td> + <td><?php echo $data->plugin_path ?></td> + <td><?php echo ( $is_active ) ? 'Active' : 'Inactive' ?></td> + </tr> + <?php endforeach ?> + </tbody> + </table> +<?php $plugins = $fs_options->get_option( 'plugins' ) ?> +<?php if ( is_array( $plugins ) && 0 < count( $plugins ) ) : ?> + <h2><?php _efs( 'plugins' ) ?></h2> + <table id="fs_plugins" class="widefat"> + <thead> + <tr> + <th><?php _efs( 'id' ) ?></th> + <th><?php _efs( 'slug' ) ?></th> + <th><?php _efs( 'version' ) ?></th> + <th><?php _efs( 'title' ) ?></th> + <th><?php _efs( 'api' ) ?></th> + <th><?php _efs( 'freemius-state' ) ?></th> + <th><?php _efs( 'plugin-path' ) ?></th> + <th><?php _efs( 'public-key' ) ?></th> + </tr> + </thead> + <tbody> + <?php foreach ( $plugins as $slug => $data ) : ?> + <?php $is_active = is_plugin_active( $data->file ) ?> + <?php $fs = $is_active ? freemius( $slug ) : null ?> + <tr<?php if ( $is_active ) { + echo ' style="background: #E6FFE6; font-weight: bold"'; + } ?>> + <td><?php echo $data->id ?></td> + <td><?php echo $slug ?></td> + <td><?php echo $data->version ?></td> + <td><?php echo $data->title ?></td> + <td><?php if ( $is_active ) { + echo $fs->has_api_connectivity() ? + __fs( 'connected' ) : + __fs( 'blocked' ); + } ?></td> + <td><?php if ( $is_active ) { + echo $fs->is_on() ? + __fs( 'on' ) : + __fs( 'off' ); + } ?></td> + <td><?php echo $data->file ?></td> + <td><?php echo $data->public_key ?></td> + </tr> + <?php endforeach ?> + </tbody> + </table> +<?php endif ?> +<?php + /** + * @var FS_Site[] $sites + */ + $sites = $VARS['sites']; +?> +<?php if ( is_array( $sites ) && 0 < count( $sites ) ) : ?> + <h2><?php _efs( 'plugin-installs' ) ?> / <?php _efs( 'sites' ) ?></h2> + <table id="fs_installs" class="widefat"> + <thead> + <tr> + <th><?php _efs( 'id' ) ?></th> + <th><?php _efs( 'slug' ) ?></th> + <th><?php _efs( 'plan' ) ?></th> + <th><?php _efs( 'public-key' ) ?></th> + <th><?php _efs( 'secret-key' ) ?></th> + </tr> + </thead> + <tbody> + <?php foreach ( $sites as $slug => $site ) : ?> + <tr> + <td><?php echo $site->id ?></td> + <td><?php echo $slug ?></td> + <td><?php + echo is_object( $site->plan ) ? + base64_decode( $site->plan->name ) : + '' + ?></td> + <td><?php echo $site->public_key ?></td> + <td><?php echo $site->secret_key ?></td> + </tr> + <?php endforeach ?> + </tbody> + </table> +<?php endif ?> +<?php + $addons = $VARS['addons']; +?> +<?php foreach ( $addons as $plugin_id => $plugin_addons ) : ?> + <h2><?php printf( __fs( 'addons-of-x' ), $plugin_id ) ?></h2> + <table id="fs_addons" class="widefat"> + <thead> + <tr> + <th><?php _efs( 'id' ) ?></th> + <th><?php _efs( 'title' ) ?></th> + <th><?php _efs( 'slug' ) ?></th> + <th><?php _efs( 'version' ) ?></th> + <th><?php _efs( 'public-key' ) ?></th> + <th><?php _efs( 'secret-key' ) ?></th> + </tr> + </thead> + <tbody> + <?php + /** + * @var FS_Plugin[] $plugin_addons + */ + foreach ( $plugin_addons as $addon ) : ?> + <tr> + <td><?php echo $addon->id ?></td> + <td><?php echo $addon->title ?></td> + <td><?php echo $addon->slug ?></td> + <td><?php echo $addon->version ?></td> + <td><?php echo $addon->public_key ?></td> + <td><?php echo $addon->secret_key ?></td> + </tr> + <?php endforeach ?> + </tbody> + </table> +<?php endforeach ?> +<?php + /** + * @var FS_User[] $users + */ + $users = $VARS['users']; +?> +<?php if ( is_array( $users ) && 0 < count( $users ) ) : ?> + <h2><?php _efs( 'users' ) ?></h2> + <table id="fs_users" class="widefat"> + <thead> + <tr> + <th><?php _efs( 'id' ) ?></th> + <th><?php _efs( 'name' ) ?></th> + <th><?php _efs( 'email' ) ?></th> + <th><?php _efs( 'verified' ) ?></th> + <th><?php _efs( 'public-key' ) ?></th> + <th><?php _efs( 'secret-key' ) ?></th> + </tr> + </thead> + <tbody> + <?php foreach ( $users as $user_id => $user ) : ?> + <tr> + <td><?php echo $user->id ?></td> + <td><?php echo $user->get_name() ?></td> + <td><a href="mailto:<?php esc_attr_e($user->email) ?>"><?php echo $user->email ?></a></td> + <td><?php echo json_encode( $user->is_verified ) ?></td> + <td><?php echo $user->public_key ?></td> + <td><?php echo $user->secret_key ?></td> + </tr> + <?php endforeach ?> + </tbody> + </table> <?php endif ?> \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/templates/debug/api-calls.php b/wp-content/plugins/nextgen-gallery/freemius/templates/debug/api-calls.php index c795c8e73422361d8663d60d0968ee53b15b900e..fd83f5c3ce868375b2feda09d5e95e18042ed25d 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/templates/debug/api-calls.php +++ b/wp-content/plugins/nextgen-gallery/freemius/templates/debug/api-calls.php @@ -1,138 +1,138 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.1.7.3 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - if ( class_exists( 'Freemius_Api' ) ) { - $logger = Freemius_Api::GetLogger(); - } else { - $logger = array(); - } - - $counters = array( - 'GET' => 0, - 'POST' => 0, - 'PUT' => 0, - 'DELETE' => 0 - ); - - $show_body = false; - foreach ( $logger as $log ) { - $counters[ $log['method'] ] ++; - - if ( ! is_null( $log['body'] ) ) { - $show_body = true; - } - } - - $pretty_print = $show_body && defined( 'JSON_PRETTY_PRINT' ) && version_compare( phpversion(), '5.3', '>=' ); - - $root_path_len = strlen( ABSPATH ); -?> -<h1><?php _efs( 'API' ) ?></h1> - -<h2><span>Total Time:</span><?php echo Freemius_Debug_Bar_Panel::total_time() ?></h2> - -<h2><span>Total Requests:</span><?php echo Freemius_Debug_Bar_Panel::requests_count() ?></h2> -<?php foreach ( $counters as $method => $count ) : ?> - <h2><span><?php echo $method ?>:</span><?php echo number_format( $count ) ?></h2> -<?php endforeach ?> -<table class="widefat"> - <thead> - <tr> - <th>#</th> - <th><?php _efs( 'Method' ) ?></th> - <th><?php _efs( 'Code' ) ?></th> - <th><?php _efs( 'Length' ) ?></th> - <th><?php _efs( 'Path' ) ?></th> - <?php if ( $show_body ) : ?> - <th><?php _efs( 'Body' ) ?></th> - <?php endif ?> - <th><?php _efs( 'Result' ) ?></th> - <th><?php _efs( 'Start' ) ?></th> - <th><?php _efs( 'End' ) ?></th> - </tr> - </thead> - <tbody> - <?php foreach ( $logger as $log ) : ?> - <tr> - <td><?php echo $log['id'] ?>.</td> - <td><?php echo $log['method'] ?></td> - <td><?php echo $log['code'] ?></td> - <td><?php echo number_format( 100 * $log['total'], 2 ) . ' ' . __fs( 'ms' ) ?></td> - <td> - <?php - printf( '<a href="#" onclick="jQuery(this).parent().find(\'table\').toggle(); return false;">%s</a>', - $log['path'] - ); - ?> - <table class="widefat" style="display: none"> - <tbody> - <?php for ( $i = 0, $bt = $log['backtrace'], $len = count( $bt ); $i < $len; $i ++ ) : ?> - <tr> - <td><?php echo( $len - $i ) ?></td> - <td><?php if ( isset( $bt[ $i ]['function'] ) ) { - echo ( isset( $bt[ $i ]['class'] ) ? $bt[ $i ]['class'] . $bt[ $i ]['type'] : '' ) . $bt[ $i ]['function']; - } ?></td> - <td><?php if ( isset( $bt[ $i ]['file'] ) ) { - echo substr( $bt[ $i ]['file'], $root_path_len ) . ':' . $bt[ $i ]['line']; - } ?></td> - </tr> - <?php endfor ?> - </tbody> - </table> - </td> - <?php if ( $show_body ) : ?> - <td> - <?php if ( 'GET' !== $log['method'] ) : ?> - <?php - $body = $log['body']; - printf( - '<a href="#" onclick="jQuery(this).parent().find(\'pre\').toggle(); return false;">%s</a>', - substr( $body, 0, 32 ) . ( 32 < strlen( $body ) ? '...' : '' ) - ); - if ( $pretty_print ) { - $body = json_encode( json_decode( $log['body'] ), JSON_PRETTY_PRINT ); - } - ?> - <pre style="display: none"><code><?php echo esc_html( $body ) ?></code></pre> - <?php endif ?> - </td> - <?php endif ?> - <td> - <?php - $result = $log['result']; - - $is_not_empty_result = ( is_string( $result ) && ! empty( $result ) ); - - if ( $is_not_empty_result ) { - printf( - '<a href="#" onclick="jQuery(this).parent().find(\'pre\').toggle(); return false;">%s</a>', - substr( $result, 0, 32 ) . ( 32 < strlen( $result ) ? '...' : '' ) - ); - } - - if ( $is_not_empty_result && $pretty_print ) { - $decoded = json_decode( $result ); - if ( ! is_null( $decoded ) ) { - $result = json_encode( $decoded, JSON_PRETTY_PRINT ); - } - } else { - $result = is_string( $result ) ? $result : json_encode( $result ); - } - ?> - <pre<?php if ( $is_not_empty_result ) : ?> style="display: none"<?php endif ?>><code><?php echo esc_html( $result ) ?></code></pre> - </td> - <td><?php echo number_format( 100 * ( $log['start'] - WP_FS__SCRIPT_START_TIME ), 2 ) . ' ' . __fs( 'ms' ) ?></td> - <td><?php echo number_format( 100 * ( $log['end'] - WP_FS__SCRIPT_START_TIME ), 2 ) . ' ' . __fs( 'ms' ) ?></td> - </tr> - <?php endforeach ?> - </tbody> +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.1.7.3 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + if ( class_exists( 'Freemius_Api' ) ) { + $logger = Freemius_Api::GetLogger(); + } else { + $logger = array(); + } + + $counters = array( + 'GET' => 0, + 'POST' => 0, + 'PUT' => 0, + 'DELETE' => 0 + ); + + $show_body = false; + foreach ( $logger as $log ) { + $counters[ $log['method'] ] ++; + + if ( ! is_null( $log['body'] ) ) { + $show_body = true; + } + } + + $pretty_print = $show_body && defined( 'JSON_PRETTY_PRINT' ) && version_compare( phpversion(), '5.3', '>=' ); + + $root_path_len = strlen( ABSPATH ); +?> +<h1><?php _efs( 'API' ) ?></h1> + +<h2><span>Total Time:</span><?php echo Freemius_Debug_Bar_Panel::total_time() ?></h2> + +<h2><span>Total Requests:</span><?php echo Freemius_Debug_Bar_Panel::requests_count() ?></h2> +<?php foreach ( $counters as $method => $count ) : ?> + <h2><span><?php echo $method ?>:</span><?php echo number_format( $count ) ?></h2> +<?php endforeach ?> +<table class="widefat"> + <thead> + <tr> + <th>#</th> + <th><?php _efs( 'Method' ) ?></th> + <th><?php _efs( 'Code' ) ?></th> + <th><?php _efs( 'Length' ) ?></th> + <th><?php _efs( 'Path' ) ?></th> + <?php if ( $show_body ) : ?> + <th><?php _efs( 'Body' ) ?></th> + <?php endif ?> + <th><?php _efs( 'Result' ) ?></th> + <th><?php _efs( 'Start' ) ?></th> + <th><?php _efs( 'End' ) ?></th> + </tr> + </thead> + <tbody> + <?php foreach ( $logger as $log ) : ?> + <tr> + <td><?php echo $log['id'] ?>.</td> + <td><?php echo $log['method'] ?></td> + <td><?php echo $log['code'] ?></td> + <td><?php echo number_format( 100 * $log['total'], 2 ) . ' ' . __fs( 'ms' ) ?></td> + <td> + <?php + printf( '<a href="#" onclick="jQuery(this).parent().find(\'table\').toggle(); return false;">%s</a>', + $log['path'] + ); + ?> + <table class="widefat" style="display: none"> + <tbody> + <?php for ( $i = 0, $bt = $log['backtrace'], $len = count( $bt ); $i < $len; $i ++ ) : ?> + <tr> + <td><?php echo( $len - $i ) ?></td> + <td><?php if ( isset( $bt[ $i ]['function'] ) ) { + echo ( isset( $bt[ $i ]['class'] ) ? $bt[ $i ]['class'] . $bt[ $i ]['type'] : '' ) . $bt[ $i ]['function']; + } ?></td> + <td><?php if ( isset( $bt[ $i ]['file'] ) ) { + echo substr( $bt[ $i ]['file'], $root_path_len ) . ':' . $bt[ $i ]['line']; + } ?></td> + </tr> + <?php endfor ?> + </tbody> + </table> + </td> + <?php if ( $show_body ) : ?> + <td> + <?php if ( 'GET' !== $log['method'] ) : ?> + <?php + $body = $log['body']; + printf( + '<a href="#" onclick="jQuery(this).parent().find(\'pre\').toggle(); return false;">%s</a>', + substr( $body, 0, 32 ) . ( 32 < strlen( $body ) ? '...' : '' ) + ); + if ( $pretty_print ) { + $body = json_encode( json_decode( $log['body'] ), JSON_PRETTY_PRINT ); + } + ?> + <pre style="display: none"><code><?php echo esc_html( $body ) ?></code></pre> + <?php endif ?> + </td> + <?php endif ?> + <td> + <?php + $result = $log['result']; + + $is_not_empty_result = ( is_string( $result ) && ! empty( $result ) ); + + if ( $is_not_empty_result ) { + printf( + '<a href="#" onclick="jQuery(this).parent().find(\'pre\').toggle(); return false;">%s</a>', + substr( $result, 0, 32 ) . ( 32 < strlen( $result ) ? '...' : '' ) + ); + } + + if ( $is_not_empty_result && $pretty_print ) { + $decoded = json_decode( $result ); + if ( ! is_null( $decoded ) ) { + $result = json_encode( $decoded, JSON_PRETTY_PRINT ); + } + } else { + $result = is_string( $result ) ? $result : json_encode( $result ); + } + ?> + <pre<?php if ( $is_not_empty_result ) : ?> style="display: none"<?php endif ?>><code><?php echo esc_html( $result ) ?></code></pre> + </td> + <td><?php echo number_format( 100 * ( $log['start'] - WP_FS__SCRIPT_START_TIME ), 2 ) . ' ' . __fs( 'ms' ) ?></td> + <td><?php echo number_format( 100 * ( $log['end'] - WP_FS__SCRIPT_START_TIME ), 2 ) . ' ' . __fs( 'ms' ) ?></td> + </tr> + <?php endforeach ?> + </tbody> </table> \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/templates/debug/logger.php b/wp-content/plugins/nextgen-gallery/freemius/templates/debug/logger.php index 3fc925a0ee2e4481c6396c9fb7102ace7880ae91..c7272026206570925b40820c5f338bbbdcaa86ab 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/templates/debug/logger.php +++ b/wp-content/plugins/nextgen-gallery/freemius/templates/debug/logger.php @@ -1,60 +1,60 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.1.7.3 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - $log_book = FS_Logger::get_log(); -?> -<h1><?php _efs( 'Log' ) ?></h1> - -<table class="widefat" style="font-size: 11px;"> - <thead> - <tr> - <th>#</th> - <th><?php _efs( 'id' ) ?></th> - <th><?php _efs( 'type' ) ?></th> - <th><?php _efs( 'function' ) ?></th> - <th><?php _efs( 'message' ) ?></th> - <th><?php _efs( 'file' ) ?></th> - <th><?php _efs( 'timestamp' ) ?></th> - </tr> - </thead> - <tbody> - - <?php $i = 0; - foreach ( $log_book as $log ) : ?> - <tr<?php if ( $i % 2 ) { - echo ' class="alternate"'; - } ?>> - <td><?php echo $log['cnt'] ?>.</td> - <td><?php echo $log['logger']->get_id() ?></td> - <td><?php echo $log['type'] ?></td> - <td><b><code style="color: blue;"><?php echo $log['function'] ?></code></b></td> - <td> - <?php - printf( - '<a href="#" style="color: darkorange !important;" onclick="jQuery(this).parent().find(\'div\').toggle(); return false;"><nobr>%s</nobr></a>', - substr( $log['msg'], 0, 32 ) . ( 32 < strlen( $log['msg'] ) ? '...' : '' ) - ); - ?> - <div style="display: none;"> - <b style="color: darkorange;"><?php echo $log['msg'] ?></b> - </div> - </td> - <td><?php - if ( isset( $log['file'] ) ) { - echo substr( $log['file'], $log['logger']->get_file() ) . ':' . $log['line'] . ')'; - } - ?></td> - <td><?php echo number_format( 100 * ( $log['timestamp'] - WP_FS__SCRIPT_START_TIME ), 2 ) . ' ' . __fs( 'ms' ) ?></td> - </tr> - <?php $i ++; endforeach ?> - </tbody> +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.1.7.3 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + $log_book = FS_Logger::get_log(); +?> +<h1><?php _efs( 'Log' ) ?></h1> + +<table class="widefat" style="font-size: 11px;"> + <thead> + <tr> + <th>#</th> + <th><?php _efs( 'id' ) ?></th> + <th><?php _efs( 'type' ) ?></th> + <th><?php _efs( 'function' ) ?></th> + <th><?php _efs( 'message' ) ?></th> + <th><?php _efs( 'file' ) ?></th> + <th><?php _efs( 'timestamp' ) ?></th> + </tr> + </thead> + <tbody> + + <?php $i = 0; + foreach ( $log_book as $log ) : ?> + <tr<?php if ( $i % 2 ) { + echo ' class="alternate"'; + } ?>> + <td><?php echo $log['cnt'] ?>.</td> + <td><?php echo $log['logger']->get_id() ?></td> + <td><?php echo $log['type'] ?></td> + <td><b><code style="color: blue;"><?php echo $log['function'] ?></code></b></td> + <td> + <?php + printf( + '<a href="#" style="color: darkorange !important;" onclick="jQuery(this).parent().find(\'div\').toggle(); return false;"><nobr>%s</nobr></a>', + substr( $log['msg'], 0, 32 ) . ( 32 < strlen( $log['msg'] ) ? '...' : '' ) + ); + ?> + <div style="display: none;"> + <b style="color: darkorange;"><?php echo $log['msg'] ?></b> + </div> + </td> + <td><?php + if ( isset( $log['file'] ) ) { + echo substr( $log['file'], $log['logger']->get_file() ) . ':' . $log['line'] . ')'; + } + ?></td> + <td><?php echo number_format( 100 * ( $log['timestamp'] - WP_FS__SCRIPT_START_TIME ), 2 ) . ' ' . __fs( 'ms' ) ?></td> + </tr> + <?php $i ++; endforeach ?> + </tbody> </table> \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/templates/debug/plugins-themes-sync.php b/wp-content/plugins/nextgen-gallery/freemius/templates/debug/plugins-themes-sync.php index a7616220a28798205fa268d5446a5fce389891ee..d5cb0c1b006ec99311bdedd71bc43ae49e3ad867 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/templates/debug/plugins-themes-sync.php +++ b/wp-content/plugins/nextgen-gallery/freemius/templates/debug/plugins-themes-sync.php @@ -1,68 +1,68 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.1.7.3 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - $fs_options = FS_Option_Manager::get_manager( WP_FS__ACCOUNTS_OPTION_NAME, true ); - $all_plugins = $fs_options->get_option( 'all_plugins' ); - $all_themes = $fs_options->get_option( 'all_themes' ); -?> -<h1><?php _efs( 'plugins-themes-sync' ) ?></h1> -<table class="widefat"> - <thead> - <tr> - <th></th> - <th><?php _efs( 'total' ) ?></th> - <th><?php _efs( 'Last' ) ?></th> - </tr> - </thead> - <tbody> - <?php if ( is_object( $all_plugins ) ) : ?> - <tr> - <td><?php _efs( 'plugins' ) ?></td> - <td><?php echo count( $all_plugins->plugins ) ?></td> - <td><?php - if ( isset( $all_plugins->timestamp ) && is_numeric( $all_plugins->timestamp ) ) { - $diff = abs( WP_FS__SCRIPT_START_TIME - $all_plugins->timestamp ); - $human_diff = ( $diff < MINUTE_IN_SECONDS ) ? - $diff . ' ' . __fs( 'sec' ) : - human_time_diff( WP_FS__SCRIPT_START_TIME, $all_plugins->timestamp ); - - if ( WP_FS__SCRIPT_START_TIME < $all_plugins->timestamp ) { - printf( __fs( 'in-x' ), $human_diff ); - } else { - printf( __fs( 'x-ago' ), $human_diff ); - } - } - ?></td> - </tr> - <?php endif ?> - <?php if ( is_object( $all_themes ) ) : ?> - <tr> - <td><?php _efs( 'themes' ) ?></td> - <td><?php echo count( $all_themes->themes ) ?></td> - <td><?php - if ( isset( $all_themes->timestamp ) && is_numeric( $all_themes->timestamp ) ) { - $diff = abs( WP_FS__SCRIPT_START_TIME - $all_themes->timestamp ); - $human_diff = ( $diff < MINUTE_IN_SECONDS ) ? - $diff . ' ' . __fs( 'sec' ) : - human_time_diff( WP_FS__SCRIPT_START_TIME, $all_themes->timestamp ); - - if ( WP_FS__SCRIPT_START_TIME < $all_themes->timestamp ) { - printf( __fs( 'in-x' ), $human_diff ); - } else { - printf( __fs( 'x-ago' ), $human_diff ); - } - } - ?></td> - </tr> - <?php endif ?> - </tbody> -</table> +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.1.7.3 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + $fs_options = FS_Option_Manager::get_manager( WP_FS__ACCOUNTS_OPTION_NAME, true ); + $all_plugins = $fs_options->get_option( 'all_plugins' ); + $all_themes = $fs_options->get_option( 'all_themes' ); +?> +<h1><?php _efs( 'plugins-themes-sync' ) ?></h1> +<table class="widefat"> + <thead> + <tr> + <th></th> + <th><?php _efs( 'total' ) ?></th> + <th><?php _efs( 'Last' ) ?></th> + </tr> + </thead> + <tbody> + <?php if ( is_object( $all_plugins ) ) : ?> + <tr> + <td><?php _efs( 'plugins' ) ?></td> + <td><?php echo count( $all_plugins->plugins ) ?></td> + <td><?php + if ( isset( $all_plugins->timestamp ) && is_numeric( $all_plugins->timestamp ) ) { + $diff = abs( WP_FS__SCRIPT_START_TIME - $all_plugins->timestamp ); + $human_diff = ( $diff < MINUTE_IN_SECONDS ) ? + $diff . ' ' . __fs( 'sec' ) : + human_time_diff( WP_FS__SCRIPT_START_TIME, $all_plugins->timestamp ); + + if ( WP_FS__SCRIPT_START_TIME < $all_plugins->timestamp ) { + printf( __fs( 'in-x' ), $human_diff ); + } else { + printf( __fs( 'x-ago' ), $human_diff ); + } + } + ?></td> + </tr> + <?php endif ?> + <?php if ( is_object( $all_themes ) ) : ?> + <tr> + <td><?php _efs( 'themes' ) ?></td> + <td><?php echo count( $all_themes->themes ) ?></td> + <td><?php + if ( isset( $all_themes->timestamp ) && is_numeric( $all_themes->timestamp ) ) { + $diff = abs( WP_FS__SCRIPT_START_TIME - $all_themes->timestamp ); + $human_diff = ( $diff < MINUTE_IN_SECONDS ) ? + $diff . ' ' . __fs( 'sec' ) : + human_time_diff( WP_FS__SCRIPT_START_TIME, $all_themes->timestamp ); + + if ( WP_FS__SCRIPT_START_TIME < $all_themes->timestamp ) { + printf( __fs( 'in-x' ), $human_diff ); + } else { + printf( __fs( 'x-ago' ), $human_diff ); + } + } + ?></td> + </tr> + <?php endif ?> + </tbody> +</table> diff --git a/wp-content/plugins/nextgen-gallery/freemius/templates/debug/scheduled-crons.php b/wp-content/plugins/nextgen-gallery/freemius/templates/debug/scheduled-crons.php index 5a93316535b1694b515392541ad3fae15b51d565..758024dacfbcc471fbc547333b92b3a63ccc22b9 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/templates/debug/scheduled-crons.php +++ b/wp-content/plugins/nextgen-gallery/freemius/templates/debug/scheduled-crons.php @@ -1,100 +1,100 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.1.7.3 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - $fs_options = FS_Option_Manager::get_manager( WP_FS__ACCOUNTS_OPTION_NAME, true ); - $plugins = $fs_options->get_option( 'plugins' ); - $scheduled_crons = array(); - if ( is_array( $plugins ) && 0 < count( $plugins ) ) { - foreach ( $plugins as $slug => $data ) { - $fs = freemius( $slug ); - - $next_execution = $fs->next_sync_cron(); - $last_execution = $fs->last_sync_cron(); - - if ( false !== $next_execution ) { - $scheduled_crons[ $slug ][] = array( - 'name' => $fs->get_plugin_name(), - 'slug' => $slug, - 'type' => 'sync_cron', - 'last' => $last_execution, - 'next' => $next_execution, - ); - } - - $next_install_execution = $fs->next_install_sync(); - $last_install_execution = $fs->last_install_sync(); - - if ( false !== $next_install_execution || false !== $last_install_execution ) { - $scheduled_crons[ $slug ][] = array( - 'name' => $fs->get_plugin_name(), - 'slug' => $slug, - 'type' => 'install_sync', - 'last' => $last_install_execution, - 'next' => $next_install_execution, - ); - } - } - } -?> -<h1><?php _efs( 'scheduled-crons' ) ?></h1> -<table class="widefat"> - <thead> - <tr> - <th><?php _efs( 'slug' ) ?></th> - <th><?php _efs( 'plugin' ) ?></th> - <th><?php _efs( 'type' ) ?></th> - <th><?php _efs( 'Last' ) ?></th> - <th><?php _efs( 'Next' ) ?></th> - </tr> - </thead> - <tbody> - <?php foreach ( $scheduled_crons as $slug => $crons ) : ?> - <?php foreach ( $crons as $cron ) : ?> - <tr> - <td><?php echo $slug ?></td> - <td><?php echo $cron['name'] ?></td> - <td><?php echo $cron['type'] ?></td> - <td><?php - if (is_numeric($cron['last'])) { - $diff = abs( WP_FS__SCRIPT_START_TIME - $cron['last'] ); - $human_diff = ( $diff < MINUTE_IN_SECONDS ) ? - $diff . ' ' . __fs( 'sec' ) : - human_time_diff( WP_FS__SCRIPT_START_TIME, $cron['last'] ); - - if ( WP_FS__SCRIPT_START_TIME < $cron['last'] ) { - printf( __fs( 'in-x' ), $human_diff ); - } else { - printf( __fs( 'x-ago' ), $human_diff ); - } - -// echo ' ' . $cron['last']; - } - ?></td> - <td><?php - if (is_numeric($cron['next'])) { - $diff = abs( WP_FS__SCRIPT_START_TIME - $cron['next'] ); - $human_diff = ( $diff < MINUTE_IN_SECONDS ) ? - $diff . ' ' . __fs( 'sec' ) : - human_time_diff( WP_FS__SCRIPT_START_TIME, $cron['next'] ); - - if ( WP_FS__SCRIPT_START_TIME < $cron['next'] ) { - printf( __fs( 'in-x' ), $human_diff ); - } else { - printf( __fs( 'x-ago' ), $human_diff ); - } - } - ?></td> - </tr> - <?php endforeach ?> - <?php endforeach ?> - </tbody> -</table> +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.1.7.3 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + $fs_options = FS_Option_Manager::get_manager( WP_FS__ACCOUNTS_OPTION_NAME, true ); + $plugins = $fs_options->get_option( 'plugins' ); + $scheduled_crons = array(); + if ( is_array( $plugins ) && 0 < count( $plugins ) ) { + foreach ( $plugins as $slug => $data ) { + $fs = freemius( $slug ); + + $next_execution = $fs->next_sync_cron(); + $last_execution = $fs->last_sync_cron(); + + if ( false !== $next_execution ) { + $scheduled_crons[ $slug ][] = array( + 'name' => $fs->get_plugin_name(), + 'slug' => $slug, + 'type' => 'sync_cron', + 'last' => $last_execution, + 'next' => $next_execution, + ); + } + + $next_install_execution = $fs->next_install_sync(); + $last_install_execution = $fs->last_install_sync(); + + if ( false !== $next_install_execution || false !== $last_install_execution ) { + $scheduled_crons[ $slug ][] = array( + 'name' => $fs->get_plugin_name(), + 'slug' => $slug, + 'type' => 'install_sync', + 'last' => $last_install_execution, + 'next' => $next_install_execution, + ); + } + } + } +?> +<h1><?php _efs( 'scheduled-crons' ) ?></h1> +<table class="widefat"> + <thead> + <tr> + <th><?php _efs( 'slug' ) ?></th> + <th><?php _efs( 'plugin' ) ?></th> + <th><?php _efs( 'type' ) ?></th> + <th><?php _efs( 'Last' ) ?></th> + <th><?php _efs( 'Next' ) ?></th> + </tr> + </thead> + <tbody> + <?php foreach ( $scheduled_crons as $slug => $crons ) : ?> + <?php foreach ( $crons as $cron ) : ?> + <tr> + <td><?php echo $slug ?></td> + <td><?php echo $cron['name'] ?></td> + <td><?php echo $cron['type'] ?></td> + <td><?php + if (is_numeric($cron['last'])) { + $diff = abs( WP_FS__SCRIPT_START_TIME - $cron['last'] ); + $human_diff = ( $diff < MINUTE_IN_SECONDS ) ? + $diff . ' ' . __fs( 'sec' ) : + human_time_diff( WP_FS__SCRIPT_START_TIME, $cron['last'] ); + + if ( WP_FS__SCRIPT_START_TIME < $cron['last'] ) { + printf( __fs( 'in-x' ), $human_diff ); + } else { + printf( __fs( 'x-ago' ), $human_diff ); + } + +// echo ' ' . $cron['last']; + } + ?></td> + <td><?php + if (is_numeric($cron['next'])) { + $diff = abs( WP_FS__SCRIPT_START_TIME - $cron['next'] ); + $human_diff = ( $diff < MINUTE_IN_SECONDS ) ? + $diff . ' ' . __fs( 'sec' ) : + human_time_diff( WP_FS__SCRIPT_START_TIME, $cron['next'] ); + + if ( WP_FS__SCRIPT_START_TIME < $cron['next'] ) { + printf( __fs( 'in-x' ), $human_diff ); + } else { + printf( __fs( 'x-ago' ), $human_diff ); + } + } + ?></td> + </tr> + <?php endforeach ?> + <?php endforeach ?> + </tbody> +</table> diff --git a/wp-content/plugins/nextgen-gallery/freemius/templates/email.php b/wp-content/plugins/nextgen-gallery/freemius/templates/email.php index 1a6cf5bfc86a54a9512778703cf7b6f82dc86dcd..671aa2ad5ef48f741f1255ad24561d60f8f872cd 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/templates/email.php +++ b/wp-content/plugins/nextgen-gallery/freemius/templates/email.php @@ -1,46 +1,46 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.1.1 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - $sections = $VARS['sections']; -?> -<table> - <?php - foreach ( $sections as $section_id => $section ) { - ?> - <thead> - <tr><th colspan="2" style="text-align: left; background: #333; color: #fff; padding: 5px;"><?php echo $section['title']; ?></th></tr> - </thead> - <tbody> - <?php - foreach ( $section['rows'] as $row_id => $row ) { - $col_count = count( $row ); - ?> - <tr> - <?php - if ( 1 === $col_count ) { ?> - <td style="vertical-align: top;" colspan="2"><?php echo $row[0]; ?></td> - <?php - } else { ?> - <td style="vertical-align: top;"><b><?php echo $row[0]; ?>:</b></td> - <td><?php echo $row[1]; ?></td> - <?php - } - ?> - </tr> - <?php - } - ?> - </tbody> - <?php - } - ?> +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.1.1 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + $sections = $VARS['sections']; +?> +<table> + <?php + foreach ( $sections as $section_id => $section ) { + ?> + <thead> + <tr><th colspan="2" style="text-align: left; background: #333; color: #fff; padding: 5px;"><?php echo $section['title']; ?></th></tr> + </thead> + <tbody> + <?php + foreach ( $section['rows'] as $row_id => $row ) { + $col_count = count( $row ); + ?> + <tr> + <?php + if ( 1 === $col_count ) { ?> + <td style="vertical-align: top;" colspan="2"><?php echo $row[0]; ?></td> + <?php + } else { ?> + <td style="vertical-align: top;"><b><?php echo $row[0]; ?>:</b></td> + <td><?php echo $row[1]; ?></td> + <?php + } + ?> + </tr> + <?php + } + ?> + </tbody> + <?php + } + ?> </table> \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/templates/firewall-issues-js.php b/wp-content/plugins/nextgen-gallery/freemius/templates/firewall-issues-js.php index 305c5853d4fe5d27ded18654c09ee12b6349a36f..83450cec648ceaa7272eaff8dc2eda53335ce76c 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/templates/firewall-issues-js.php +++ b/wp-content/plugins/nextgen-gallery/freemius/templates/firewall-issues-js.php @@ -1,60 +1,60 @@ -<?php - /** - * API connectivity issues (CloudFlare's firewall) handler for handling different - * scenarios selected by the user after connectivity issue is detected, by sending - * AJAX call to the server in order to make the actual actions. - * - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.9 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } -?> -<script type="text/javascript"> - jQuery(document).ready(function ($) { - $('#fs_firewall_issue_options a.fs-resolve').click(function () { - var - error_type = $(this).attr('data-type'), - notice = $(this).parents('.fs-notice'), - slug = notice.attr('data-slug'); - - var data = { - action : slug + '_resolve_firewall_issues', - slug : slug, - error_type: error_type - }; - - if ('squid' === error_type) { - data.hosting_company = prompt('What is the name or URL of your hosting company?'); - if (null == data.hosting_company) - return false; - - if ('' === data.hosting_company) { - alert('We won\'t be able to help without knowing your hosting company.'); - return false; - } - } - - if ('retry_ping' === error_type) { - data.action = slug + '_retry_connectivity_test'; - } - - $(this).css({'cursor': 'wait'}); - - // since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php - $.post(ajaxurl, data, function (response) { - if (1 == response) { - // Refresh page on success. - location.reload(); - } else if ('http' === response.substr(0, 4)) { - // Ping actually worked, redirect. - window.location = response; - } - }); - }); - }); +<?php + /** + * API connectivity issues (CloudFlare's firewall) handler for handling different + * scenarios selected by the user after connectivity issue is detected, by sending + * AJAX call to the server in order to make the actual actions. + * + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.9 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } +?> +<script type="text/javascript"> + jQuery(document).ready(function ($) { + $('#fs_firewall_issue_options a.fs-resolve').click(function () { + var + error_type = $(this).attr('data-type'), + notice = $(this).parents('.fs-notice'), + slug = notice.attr('data-slug'); + + var data = { + action : slug + '_resolve_firewall_issues', + slug : slug, + error_type: error_type + }; + + if ('squid' === error_type) { + data.hosting_company = prompt('What is the name or URL of your hosting company?'); + if (null == data.hosting_company) + return false; + + if ('' === data.hosting_company) { + alert('We won\'t be able to help without knowing your hosting company.'); + return false; + } + } + + if ('retry_ping' === error_type) { + data.action = slug + '_retry_connectivity_test'; + } + + $(this).css({'cursor': 'wait'}); + + // since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php + $.post(ajaxurl, data, function (response) { + if (1 == response) { + // Refresh page on success. + location.reload(); + } else if ('http' === response.substr(0, 4)) { + // Ping actually worked, redirect. + window.location = response; + } + }); + }); + }); </script> \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/templates/plugin-icon.php b/wp-content/plugins/nextgen-gallery/freemius/templates/plugin-icon.php index 9c910d08e98ace9701d23fe94a06af680469fac2..bdbd3f58e2c8deb000c22544a2b1630d4e998f38 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/templates/plugin-icon.php +++ b/wp-content/plugins/nextgen-gallery/freemius/templates/plugin-icon.php @@ -1,93 +1,93 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.1.4 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - $slug = $VARS['slug']; - $fs = freemius( $slug ); - - /** - * @since 1.1.7.5 - */ - $local_path = $fs->apply_filters( 'plugin_icon', false ); - - if ( is_string( $local_path ) ) { - $icons = array( $local_path ); - } else { - global $fs_active_plugins; - - $img_dir = WP_FS__DIR_IMG; - - if ( 1 < count( $fs_active_plugins->plugins ) ) { - foreach ( $fs_active_plugins->plugins as $sdk_path => &$data ) { - if ( $data->plugin_path == $fs->get_plugin_basename() ) { - $img_dir = WP_PLUGIN_DIR . '/' . $sdk_path . '/assets/img'; - break; - } - } - } - - $icons = glob( fs_normalize_path( $img_dir . '/' . $slug . '.*' ) ); - if ( ! is_array( $icons ) || 0 === count( $icons ) ) { - $icon_found = false; - $local_path = fs_normalize_path( $img_dir . '/' . $slug . '.png' ); - $have_write_permissions = is_writable( fs_normalize_path( $img_dir ) ); - - if ( WP_FS__IS_LOCALHOST && $fs->is_org_repo_compliant() && $have_write_permissions ) { - /** - * IMPORTANT: THIS CODE WILL NEVER RUN AFTER THE PLUGIN IS IN THE REPO. - * - * This code will only be executed once during the testing - * of the plugin in a local environment. The plugin icon file WILL - * already exist in the assets folder when the plugin is deployed to - * the repository. - */ - $suffixes = array( - '-128x128.png', - '-128x128.jpg', - '-256x256.png', - '-256x256.jpg', - '.svg', - ); - - $base_url = 'https://plugins.svn.wordpress.org/' . $slug . '/assets/icon'; - - foreach ( $suffixes as $s ) { - $headers = get_headers( $base_url . $s ); - if ( strpos( $headers[0], '200' ) ) { - $local_path = fs_normalize_path( $img_dir . '/' . $slug . '.' . substr( $s, strpos( $s, '.' ) + 1 ) ); - fs_download_image( $base_url . $s, $local_path ); - $icon_found = true; - break; - } - } - } - - if ( ! $icon_found ) { - // No icons found, fallback to default icon. - if ( $have_write_permissions ) { - // If have write permissions, copy default icon. - copy( fs_normalize_path( $img_dir . '/plugin-icon.png' ), $local_path ); - } else { - // If doesn't have write permissions, use default icon path. - $local_path = fs_normalize_path( $img_dir . '/plugin-icon.png' ); - } - } - - $icons = array( $local_path ); - } - } - - $icon_dir = dirname( $icons[0] ); - $relative_url = fs_img_url( substr( $icons[0], strlen( $icon_dir ) ), $icon_dir ); -?> -<div class="fs-plugin-icon"> - <img src="<?php echo $relative_url ?>"/> +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.1.4 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + $slug = $VARS['slug']; + $fs = freemius( $slug ); + + /** + * @since 1.1.7.5 + */ + $local_path = $fs->apply_filters( 'plugin_icon', false ); + + if ( is_string( $local_path ) ) { + $icons = array( $local_path ); + } else { + global $fs_active_plugins; + + $img_dir = WP_FS__DIR_IMG; + + if ( 1 < count( $fs_active_plugins->plugins ) ) { + foreach ( $fs_active_plugins->plugins as $sdk_path => &$data ) { + if ( $data->plugin_path == $fs->get_plugin_basename() ) { + $img_dir = WP_PLUGIN_DIR . '/' . $sdk_path . '/assets/img'; + break; + } + } + } + + $icons = glob( fs_normalize_path( $img_dir . '/' . $slug . '.*' ) ); + if ( ! is_array( $icons ) || 0 === count( $icons ) ) { + $icon_found = false; + $local_path = fs_normalize_path( $img_dir . '/' . $slug . '.png' ); + $have_write_permissions = is_writable( fs_normalize_path( $img_dir ) ); + + if ( WP_FS__IS_LOCALHOST && $fs->is_org_repo_compliant() && $have_write_permissions ) { + /** + * IMPORTANT: THIS CODE WILL NEVER RUN AFTER THE PLUGIN IS IN THE REPO. + * + * This code will only be executed once during the testing + * of the plugin in a local environment. The plugin icon file WILL + * already exist in the assets folder when the plugin is deployed to + * the repository. + */ + $suffixes = array( + '-128x128.png', + '-128x128.jpg', + '-256x256.png', + '-256x256.jpg', + '.svg', + ); + + $base_url = 'https://plugins.svn.wordpress.org/' . $slug . '/assets/icon'; + + foreach ( $suffixes as $s ) { + $headers = get_headers( $base_url . $s ); + if ( strpos( $headers[0], '200' ) ) { + $local_path = fs_normalize_path( $img_dir . '/' . $slug . '.' . substr( $s, strpos( $s, '.' ) + 1 ) ); + fs_download_image( $base_url . $s, $local_path ); + $icon_found = true; + break; + } + } + } + + if ( ! $icon_found ) { + // No icons found, fallback to default icon. + if ( $have_write_permissions ) { + // If have write permissions, copy default icon. + copy( fs_normalize_path( $img_dir . '/plugin-icon.png' ), $local_path ); + } else { + // If doesn't have write permissions, use default icon path. + $local_path = fs_normalize_path( $img_dir . '/plugin-icon.png' ); + } + } + + $icons = array( $local_path ); + } + } + + $icon_dir = dirname( $icons[0] ); + $relative_url = fs_img_url( substr( $icons[0], strlen( $icon_dir ) ), $icon_dir ); +?> +<div class="fs-plugin-icon"> + <img src="<?php echo $relative_url ?>"/> </div> \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/templates/plugin-info/description.php b/wp-content/plugins/nextgen-gallery/freemius/templates/plugin-info/description.php index 6aa7eda3f38b685b0148f9b59e86e7c4baf38213..bdcebbbf766b835ea309cfe301f6efefd1e760ee 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/templates/plugin-info/description.php +++ b/wp-content/plugins/nextgen-gallery/freemius/templates/plugin-info/description.php @@ -1,75 +1,75 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.6 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - /** - * @var FS_Plugin $plugin - */ - $plugin = $VARS['plugin']; - - if ( ! empty( $plugin->info->selling_point_0 ) || - ! empty( $plugin->info->selling_point_1 ) || - ! empty( $plugin->info->selling_point_2 ) - ) : ?> - <div class="fs-selling-points"> - <ul> - <?php for ( $i = 0; $i < 3; $i ++ ) : ?> - <?php if ( ! empty( $plugin->info->{'selling_point_' . $i} ) ) : ?> - <li><i class="dashicons dashicons-yes"></i> - - <h3><?php echo $plugin->info->{'selling_point_' . $i} ?></h3></li> - <?php endif ?> - <?php endfor ?> - </ul> - </div> - <?php endif ?> - <div> - <?php - echo wp_kses( $plugin->info->description, array( - 'a' => array( 'href' => array(), 'title' => array(), 'target' => array() ), - 'b' => array(), - 'i' => array(), - 'p' => array(), - 'blockquote' => array(), - 'h2' => array(), - 'h3' => array(), - 'ul' => array(), - 'ol' => array(), - 'li' => array() - ) ); - ?> - </div> -<?php if ( ! empty( $plugin->info->screenshots ) ) : ?> - <?php $screenshots = $plugin->info->screenshots ?> - <div class="fs-screenshots clearfix"> - <h2><?php _efs( 'screenshots', $plugin->slug ) ?></h2> - <ul> - <?php $i = 0; - foreach ( $screenshots as $s => $url ) : ?> - <?php - // Relative URLs are replaced with WordPress.org base URL - // therefore we need to set absolute URLs. - $url = 'http' . ( WP_FS__IS_HTTPS ? 's' : '' ) . ':' . $url; ?> - <li class="<?php echo ( 0 === $i % 2 ) ? 'odd' : 'even' ?>"> - <style> - #section-description .fs-screenshots <?php echo ".fs-screenshot-{$i}" ?> - { - background-image: url('<?php echo $url ?>'); - } - </style> - <a href="<?php echo $url ?>" - title="<?php printf( __fs( 'view-full-size-x', $plugin->slug ), $i ) ?>" - class="fs-screenshot-<?php echo $i ?>"></a> - </li> - <?php $i ++; endforeach ?> - </ul> - </div> +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.6 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + /** + * @var FS_Plugin $plugin + */ + $plugin = $VARS['plugin']; + + if ( ! empty( $plugin->info->selling_point_0 ) || + ! empty( $plugin->info->selling_point_1 ) || + ! empty( $plugin->info->selling_point_2 ) + ) : ?> + <div class="fs-selling-points"> + <ul> + <?php for ( $i = 0; $i < 3; $i ++ ) : ?> + <?php if ( ! empty( $plugin->info->{'selling_point_' . $i} ) ) : ?> + <li><i class="dashicons dashicons-yes"></i> + + <h3><?php echo $plugin->info->{'selling_point_' . $i} ?></h3></li> + <?php endif ?> + <?php endfor ?> + </ul> + </div> + <?php endif ?> + <div> + <?php + echo wp_kses( $plugin->info->description, array( + 'a' => array( 'href' => array(), 'title' => array(), 'target' => array() ), + 'b' => array(), + 'i' => array(), + 'p' => array(), + 'blockquote' => array(), + 'h2' => array(), + 'h3' => array(), + 'ul' => array(), + 'ol' => array(), + 'li' => array() + ) ); + ?> + </div> +<?php if ( ! empty( $plugin->info->screenshots ) ) : ?> + <?php $screenshots = $plugin->info->screenshots ?> + <div class="fs-screenshots clearfix"> + <h2><?php _efs( 'screenshots', $plugin->slug ) ?></h2> + <ul> + <?php $i = 0; + foreach ( $screenshots as $s => $url ) : ?> + <?php + // Relative URLs are replaced with WordPress.org base URL + // therefore we need to set absolute URLs. + $url = 'http' . ( WP_FS__IS_HTTPS ? 's' : '' ) . ':' . $url; ?> + <li class="<?php echo ( 0 === $i % 2 ) ? 'odd' : 'even' ?>"> + <style> + #section-description .fs-screenshots <?php echo ".fs-screenshot-{$i}" ?> + { + background-image: url('<?php echo $url ?>'); + } + </style> + <a href="<?php echo $url ?>" + title="<?php printf( __fs( 'view-full-size-x', $plugin->slug ), $i ) ?>" + class="fs-screenshot-<?php echo $i ?>"></a> + </li> + <?php $i ++; endforeach ?> + </ul> + </div> <?php endif ?> \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/templates/plugin-info/features.php b/wp-content/plugins/nextgen-gallery/freemius/templates/plugin-info/features.php index 6540ddf26f224d23546f5b04cf5452d240b7e0b8..daa5b2f0cd7d235bffbe2ef7a6f3a6edac604919 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/templates/plugin-info/features.php +++ b/wp-content/plugins/nextgen-gallery/freemius/templates/plugin-info/features.php @@ -1,97 +1,97 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.6 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - /** - * @var FS_Plugin $plugin - */ - $plugin = $VARS['plugin']; - - $plans = $VARS['plans']; - - $features_plan_map = array(); - foreach ( $plans as $plan ) { - foreach ( $plan->features as $feature ) { - if ( ! isset( $features_plan_map[ $feature->id ] ) ) { - $features_plan_map[ $feature->id ] = array( 'feature' => $feature, 'plans' => array() ); - } - - $features_plan_map[ $feature->id ]['plans'][ $plan->id ] = $feature; - } - - // Add support as a feature. - if ( ! empty( $plan->support_email ) || - ! empty( $plan->support_skype ) || - ! empty( $plan->support_phone ) || - true === $plan->is_success_manager - ) { - if ( ! isset( $features_plan_map['support'] ) ) { - $support_feature = new stdClass(); - $support_feature->id = 'support'; - $support_feature->title = __fs( 'Support', $plugin->slug ); - $features_plan_map[ $support_feature->id ] = array( 'feature' => $support_feature, 'plans' => array() ); - } else { - $support_feature = $features_plan_map['support']; - } - - $features_plan_map[ $support_feature->id ]['plans'][ $plan->id ] = $support_feature; - } - } - - // Add updates as a feature for all plans. - $updates_feature = new stdClass(); - $updates_feature->id = 'updates'; - $updates_feature->title = __fs( 'unlimited-updates', $plugin->slug ); - $features_plan_map[ $updates_feature->id ] = array( 'feature' => $updates_feature, 'plans' => array() ); - foreach ( $plans as $plan ) { - $features_plan_map[ $updates_feature->id ]['plans'][ $plan->id ] = $updates_feature; - } -?> -<div class="fs-features"> - <table> - <thead> - <tr> - <th></th> - <?php foreach ( $plans as $plan ) : ?> - <th> - <?php echo $plan->title ?> - <span class="fs-price"> - <?php foreach ( $plan->pricing as $pricing ) : ?> - <?php if ( 1 == $pricing->licenses ) : ?> - $<?php echo $pricing->annual_price ?> / year - <?php endif ?> - <?php endforeach ?> - </span> - </th> - <?php endforeach ?> - </tr> - </thead> - <tbody> - <?php $odd = true; - foreach ( $features_plan_map as $feature_id => $data ) : ?> - <tr class="fs-<?php echo $odd ? 'odd' : 'even' ?>"> - <td><?php echo ucfirst( $data['feature']->title ) ?></td> - <?php foreach ( $plans as $plan ) : ?> - <td> - <?php if ( isset( $data['plans'][ $plan->id ] ) ) : ?> - <?php if ( ! empty( $data['plans'][ $plan->id ]->value ) ) : ?> - <b><?php echo $data['plans'][ $plan->id ]->value ?></b> - <?php else : ?> - <i class="dashicons dashicons-yes"></i> - <?php endif ?> - <?php endif ?> - </td> - <?php endforeach ?> - </tr> - <?php $odd = ! $odd; endforeach ?> - </tbody> - </table> +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.6 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + /** + * @var FS_Plugin $plugin + */ + $plugin = $VARS['plugin']; + + $plans = $VARS['plans']; + + $features_plan_map = array(); + foreach ( $plans as $plan ) { + foreach ( $plan->features as $feature ) { + if ( ! isset( $features_plan_map[ $feature->id ] ) ) { + $features_plan_map[ $feature->id ] = array( 'feature' => $feature, 'plans' => array() ); + } + + $features_plan_map[ $feature->id ]['plans'][ $plan->id ] = $feature; + } + + // Add support as a feature. + if ( ! empty( $plan->support_email ) || + ! empty( $plan->support_skype ) || + ! empty( $plan->support_phone ) || + true === $plan->is_success_manager + ) { + if ( ! isset( $features_plan_map['support'] ) ) { + $support_feature = new stdClass(); + $support_feature->id = 'support'; + $support_feature->title = __fs( 'Support', $plugin->slug ); + $features_plan_map[ $support_feature->id ] = array( 'feature' => $support_feature, 'plans' => array() ); + } else { + $support_feature = $features_plan_map['support']; + } + + $features_plan_map[ $support_feature->id ]['plans'][ $plan->id ] = $support_feature; + } + } + + // Add updates as a feature for all plans. + $updates_feature = new stdClass(); + $updates_feature->id = 'updates'; + $updates_feature->title = __fs( 'unlimited-updates', $plugin->slug ); + $features_plan_map[ $updates_feature->id ] = array( 'feature' => $updates_feature, 'plans' => array() ); + foreach ( $plans as $plan ) { + $features_plan_map[ $updates_feature->id ]['plans'][ $plan->id ] = $updates_feature; + } +?> +<div class="fs-features"> + <table> + <thead> + <tr> + <th></th> + <?php foreach ( $plans as $plan ) : ?> + <th> + <?php echo $plan->title ?> + <span class="fs-price"> + <?php foreach ( $plan->pricing as $pricing ) : ?> + <?php if ( 1 == $pricing->licenses ) : ?> + $<?php echo $pricing->annual_price ?> / year + <?php endif ?> + <?php endforeach ?> + </span> + </th> + <?php endforeach ?> + </tr> + </thead> + <tbody> + <?php $odd = true; + foreach ( $features_plan_map as $feature_id => $data ) : ?> + <tr class="fs-<?php echo $odd ? 'odd' : 'even' ?>"> + <td><?php echo ucfirst( $data['feature']->title ) ?></td> + <?php foreach ( $plans as $plan ) : ?> + <td> + <?php if ( isset( $data['plans'][ $plan->id ] ) ) : ?> + <?php if ( ! empty( $data['plans'][ $plan->id ]->value ) ) : ?> + <b><?php echo $data['plans'][ $plan->id ]->value ?></b> + <?php else : ?> + <i class="dashicons dashicons-yes"></i> + <?php endif ?> + <?php endif ?> + </td> + <?php endforeach ?> + </tr> + <?php $odd = ! $odd; endforeach ?> + </tbody> + </table> </div> \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/templates/plugin-info/screenshots.php b/wp-content/plugins/nextgen-gallery/freemius/templates/plugin-info/screenshots.php index 25bfebc0f5bc34092feb90098146ccad7b5f7b85..ef025c188c9b91546ab4b83798649c72a284cb35 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/templates/plugin-info/screenshots.php +++ b/wp-content/plugins/nextgen-gallery/freemius/templates/plugin-info/screenshots.php @@ -1,33 +1,33 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.6 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - /** - * @var FS_Plugin $plugin - */ - $plugin = $VARS['plugin']; - - $screenshots = $VARS['screenshots']; -?> -<ol> - <?php $i = 0; - foreach ( $screenshots as $s => $url ) : ?> - <?php - // Relative URLs are replaced with WordPress.org base URL - // therefore we need to set absolute URLs. - $url = 'http' . ( WP_FS__IS_HTTPS ? 's' : '' ) . ':' . $url; ?> - <li> - <a href="<?php echo $url ?>" - title="<?php printf( __fs( 'view-full-size-x', $plugin->slug ), $i ) ?>"><img - src="<?php echo $url ?>"></a> - </li> - <?php $i ++; endforeach ?> -</ol> +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.6 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + /** + * @var FS_Plugin $plugin + */ + $plugin = $VARS['plugin']; + + $screenshots = $VARS['screenshots']; +?> +<ol> + <?php $i = 0; + foreach ( $screenshots as $s => $url ) : ?> + <?php + // Relative URLs are replaced with WordPress.org base URL + // therefore we need to set absolute URLs. + $url = 'http' . ( WP_FS__IS_HTTPS ? 's' : '' ) . ':' . $url; ?> + <li> + <a href="<?php echo $url ?>" + title="<?php printf( __fs( 'view-full-size-x', $plugin->slug ), $i ) ?>"><img + src="<?php echo $url ?>"></a> + </li> + <?php $i ++; endforeach ?> +</ol> diff --git a/wp-content/plugins/nextgen-gallery/freemius/templates/powered-by.php b/wp-content/plugins/nextgen-gallery/freemius/templates/powered-by.php index 45b39f44c2f817a5e99ee446bc9941e0b4485120..701653c8c94dbd2aab7827f86975366b0caa6a0e 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/templates/powered-by.php +++ b/wp-content/plugins/nextgen-gallery/freemius/templates/powered-by.php @@ -1,41 +1,41 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.5 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - /** - * KEEP THE POWERED BY TAB AND GET ADDITIONAL - 1% - OFF THE COMMISSION - */ - - wp_enqueue_script( 'jquery' ); - wp_enqueue_script( 'json2' ); - fs_enqueue_local_script( 'postmessage', 'nojquery.ba-postmessage.min.js' ); - fs_enqueue_local_script( 'fs-postmessage', 'postmessage.js' ); -?> - -<div id="piframe"></div> -<script type="text/javascript"> - (function ($) { - $(function () { - var - base_url = '<?php echo WP_FS__ADDRESS ?>', - piframe = $('<iframe id="fs_promo_tab" src="' + base_url + '/promotional-tab/?page=contact#' + encodeURIComponent(document.location.href) + '" height="350" width="60" frameborder="0" style=" background: transparent; position: fixed; top: 20%; right: 0;" scrolling="no"></iframe>') - .appendTo('#piframe'); - - FS.PostMessage.init(base_url); - FS.PostMessage.receive('state', function (state) { - if ('closed' === state) - $('#fs_promo_tab').css('width', '60px'); - else - $('#fs_promo_tab').css('width', '345px'); - }); - }); - })(jQuery); +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.5 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + /** + * KEEP THE POWERED BY TAB AND GET ADDITIONAL - 1% - OFF THE COMMISSION + */ + + wp_enqueue_script( 'jquery' ); + wp_enqueue_script( 'json2' ); + fs_enqueue_local_script( 'postmessage', 'nojquery.ba-postmessage.min.js' ); + fs_enqueue_local_script( 'fs-postmessage', 'postmessage.js' ); +?> + +<div id="piframe"></div> +<script type="text/javascript"> + (function ($) { + $(function () { + var + base_url = '<?php echo WP_FS__ADDRESS ?>', + piframe = $('<iframe id="fs_promo_tab" src="' + base_url + '/promotional-tab/?page=contact#' + encodeURIComponent(document.location.href) + '" height="350" width="60" frameborder="0" style=" background: transparent; position: fixed; top: 20%; right: 0;" scrolling="no"></iframe>') + .appendTo('#piframe'); + + FS.PostMessage.init(base_url); + FS.PostMessage.receive('state', function (state) { + if ('closed' === state) + $('#fs_promo_tab').css('width', '60px'); + else + $('#fs_promo_tab').css('width', '345px'); + }); + }); + })(jQuery); </script> \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/templates/pricing.php b/wp-content/plugins/nextgen-gallery/freemius/templates/pricing.php index 1e1c198cbb4c948d97ab74808d77a0bd27a14724..a5191e48b07868988b6eb084d1930588886534cf 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/templates/pricing.php +++ b/wp-content/plugins/nextgen-gallery/freemius/templates/pricing.php @@ -1,100 +1,100 @@ -<?php - /** - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.3 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } - - wp_enqueue_script( 'jquery' ); - wp_enqueue_script( 'json2' ); - fs_enqueue_local_script( 'postmessage', 'nojquery.ba-postmessage.min.js' ); - fs_enqueue_local_script( 'fs-postmessage', 'postmessage.js' ); - - $slug = $VARS['slug']; - $fs = freemius( $slug ); - $timestamp = time(); - - $context_params = array( - 'plugin_id' => $fs->get_id(), - 'plugin_public_key' => $fs->get_public_key(), - 'plugin_version' => $fs->get_plugin_version(), - ); - - // Get site context secure params. - if ( $fs->is_registered() ) { - $context_params = array_merge( $context_params, FS_Security::instance()->get_context_params( - $fs->get_site(), - $timestamp, - 'upgrade' - ) ); - } - - if ( $fs->is_payments_sandbox() ) // Append plugin secure token for sandbox mode authentication.) - { - $context_params['sandbox'] = FS_Security::instance()->get_secure_token( - $fs->get_plugin(), - $timestamp, - 'checkout' - ); - } - - $query_params = array_merge( $context_params, $_GET, array( - 'next' => $fs->_get_admin_page_url( 'account', array( 'fs_action' => $slug . '_sync_license' ) ), - 'plugin_version' => $fs->get_plugin_version(), - // Billing cycle. - 'billing_cycle' => fs_request_get( 'billing_cycle', WP_FS__PERIOD_ANNUALLY ), - ) ); -?> - - <div id="fs_pricing" class="wrap" style="margin: 0 0 -65px -20px;"> - <div id="iframe"></div> - <form action="" method="POST"> - <input type="hidden" name="user_id"/> - <input type="hidden" name="user_email"/> - <input type="hidden" name="site_id"/> - <input type="hidden" name="public_key"/> - <input type="hidden" name="secret_key"/> - <input type="hidden" name="action" value="account"/> - </form> - - <script type="text/javascript"> - (function ($, undef) { - $(function () { - var - // Keep track of the iframe height. - iframe_height = 800, - base_url = '<?php echo WP_FS__ADDRESS ?>', - // Pass the parent page URL into the Iframe in a meaningful way (this URL could be - // passed via query string or hard coded into the child page, it depends on your needs). - src = base_url + '/pricing/?<?php echo http_build_query($query_params) ?>#' + encodeURIComponent(document.location.href), - - // Append the Iframe into the DOM. - iframe = $('<iframe " src="' + src + '" width="100%" height="' + iframe_height + 'px" scrolling="no" frameborder="0" style="background: transparent;"><\/iframe>') - .appendTo('#iframe'); - - FS.PostMessage.init(base_url); - - FS.PostMessage.receive('height', function (data) { - var h = data.height; - if (!isNaN(h) && h > 0 && h != iframe_height) { - iframe_height = h; - $("#iframe iframe").height(iframe_height + 'px'); - } - }); - - FS.PostMessage.receive('get_dimensions', function (data) { - FS.PostMessage.post('dimensions', { - height : $(document.body).height(), - scrollTop: $(document).scrollTop() - }, iframe[0]); - }); - }); - })(jQuery); - </script> - </div> +<?php + /** + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.3 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } + + wp_enqueue_script( 'jquery' ); + wp_enqueue_script( 'json2' ); + fs_enqueue_local_script( 'postmessage', 'nojquery.ba-postmessage.min.js' ); + fs_enqueue_local_script( 'fs-postmessage', 'postmessage.js' ); + + $slug = $VARS['slug']; + $fs = freemius( $slug ); + $timestamp = time(); + + $context_params = array( + 'plugin_id' => $fs->get_id(), + 'plugin_public_key' => $fs->get_public_key(), + 'plugin_version' => $fs->get_plugin_version(), + ); + + // Get site context secure params. + if ( $fs->is_registered() ) { + $context_params = array_merge( $context_params, FS_Security::instance()->get_context_params( + $fs->get_site(), + $timestamp, + 'upgrade' + ) ); + } + + if ( $fs->is_payments_sandbox() ) // Append plugin secure token for sandbox mode authentication.) + { + $context_params['sandbox'] = FS_Security::instance()->get_secure_token( + $fs->get_plugin(), + $timestamp, + 'checkout' + ); + } + + $query_params = array_merge( $context_params, $_GET, array( + 'next' => $fs->_get_admin_page_url( 'account', array( 'fs_action' => $slug . '_sync_license' ) ), + 'plugin_version' => $fs->get_plugin_version(), + // Billing cycle. + 'billing_cycle' => fs_request_get( 'billing_cycle', WP_FS__PERIOD_ANNUALLY ), + ) ); +?> + + <div id="fs_pricing" class="wrap" style="margin: 0 0 -65px -20px;"> + <div id="iframe"></div> + <form action="" method="POST"> + <input type="hidden" name="user_id"/> + <input type="hidden" name="user_email"/> + <input type="hidden" name="site_id"/> + <input type="hidden" name="public_key"/> + <input type="hidden" name="secret_key"/> + <input type="hidden" name="action" value="account"/> + </form> + + <script type="text/javascript"> + (function ($, undef) { + $(function () { + var + // Keep track of the iframe height. + iframe_height = 800, + base_url = '<?php echo WP_FS__ADDRESS ?>', + // Pass the parent page URL into the Iframe in a meaningful way (this URL could be + // passed via query string or hard coded into the child page, it depends on your needs). + src = base_url + '/pricing/?<?php echo http_build_query($query_params) ?>#' + encodeURIComponent(document.location.href), + + // Append the Iframe into the DOM. + iframe = $('<iframe " src="' + src + '" width="100%" height="' + iframe_height + 'px" scrolling="no" frameborder="0" style="background: transparent;"><\/iframe>') + .appendTo('#iframe'); + + FS.PostMessage.init(base_url); + + FS.PostMessage.receive('height', function (data) { + var h = data.height; + if (!isNaN(h) && h > 0 && h != iframe_height) { + iframe_height = h; + $("#iframe iframe").height(iframe_height + 'px'); + } + }); + + FS.PostMessage.receive('get_dimensions', function (data) { + FS.PostMessage.post('dimensions', { + height : $(document.body).height(), + scrollTop: $(document).scrollTop() + }, iframe[0]); + }); + }); + })(jQuery); + </script> + </div> <?php fs_require_template( 'powered-by.php' ) ?> \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/freemius/templates/sticky-admin-notice-js.php b/wp-content/plugins/nextgen-gallery/freemius/templates/sticky-admin-notice-js.php index 987b1b287fb5ef2f10908124da920bd846608fcd..a6d194b76a0530bd71c798a09f2a61534889d963 100644 --- a/wp-content/plugins/nextgen-gallery/freemius/templates/sticky-admin-notice-js.php +++ b/wp-content/plugins/nextgen-gallery/freemius/templates/sticky-admin-notice-js.php @@ -1,40 +1,40 @@ -<?php - /** - * Sticky admin notices JavaScript handler for dismissing notice messages - * by sending AJAX call to the server in order to remove the message from the Database. - * - * @package Freemius - * @copyright Copyright (c) 2015, Freemius, Inc. - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License - * @since 1.0.7 - */ - - if ( ! defined( 'ABSPATH' ) ) { - exit; - } -?> -<script type="text/javascript" > - jQuery(document).ready(function($) { - $('.fs-notice.fs-sticky .fs-close').click(function(){ - var - notice = $(this).parents('.fs-notice'), - id = notice.attr('data-id'), - slug = notice.attr('data-slug'); - - notice.fadeOut('fast', function(){ - var data = { - action: slug + '_dismiss_notice_action', - slug: slug, - message_id: id - }; - - // since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php - $.post(ajaxurl, data, function(response) { - - }); - - notice.remove(); - }); - }); - }); +<?php + /** + * Sticky admin notices JavaScript handler for dismissing notice messages + * by sending AJAX call to the server in order to remove the message from the Database. + * + * @package Freemius + * @copyright Copyright (c) 2015, Freemius, Inc. + * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License + * @since 1.0.7 + */ + + if ( ! defined( 'ABSPATH' ) ) { + exit; + } +?> +<script type="text/javascript" > + jQuery(document).ready(function($) { + $('.fs-notice.fs-sticky .fs-close').click(function(){ + var + notice = $(this).parents('.fs-notice'), + id = notice.attr('data-id'), + slug = notice.attr('data-slug'); + + notice.fadeOut('fast', function(){ + var data = { + action: slug + '_dismiss_notice_action', + slug: slug, + message_id: id + }; + + // since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php + $.post(ajaxurl, data, function(response) { + + }); + + notice.remove(); + }); + }); + }); </script> \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/nggallery.php b/wp-content/plugins/nextgen-gallery/nggallery.php index dbc7769e65472fbbf78a779593efa6fdb8a0471e..77a8b0913c97194338051ae5ae4eee34d49050a4 100755 --- a/wp-content/plugins/nextgen-gallery/nggallery.php +++ b/wp-content/plugins/nextgen-gallery/nggallery.php @@ -3,8 +3,8 @@ if(preg_match('#' . basename(__FILE__) . '#', $_SERVER['PHP_SELF'])) { die('You /** * Plugin Name: NextGEN Gallery - * Description: The most popular gallery plugin for WordPress and one of the most popular plugins of all time with over 14 million downloads. - * Version: 2.1.43 + * Description: The most popular gallery plugin for WordPress and one of the most popular plugins of all time with over 15 million downloads. + * Version: 2.1.49 * Author: Imagely * Plugin URI: https://www.imagely.com/wordpress-gallery-plugin/nextgen-gallery/ * Author URI: https://www.imagely.com @@ -595,7 +595,7 @@ class C_NextGEN_Bootstrap define('NGG_PRODUCT_URL', path_join(str_replace("\\", '/', NGG_PLUGIN_URL), 'products')); define('NGG_MODULE_URL', path_join(str_replace("\\", '/', NGG_PRODUCT_URL), 'photocrati_nextgen/modules')); define('NGG_PLUGIN_STARTED_AT', microtime()); - define('NGG_PLUGIN_VERSION', '2.1.43'); + define('NGG_PLUGIN_VERSION', '2.1.49'); if (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) define('NGG_SCRIPT_VERSION', (string)mt_rand(0, mt_getrandmax())); @@ -853,7 +853,7 @@ function ngg_fs_custom_connect_message( ) { return sprintf( __fs( 'hey-x' ) . '<br>' . - __( 'Want to help make %2$s even more awesome? Allow %6$s to collect some diagnostic & usage data with %5$s. If you skip this, that\'s okay! %2$s will still work just fine.', 'nggallery' ), + __( 'Allow %6$s to collect some usage data with %5$s to make the plugin even more awesome. If you skip this, that\'s okay! %2$s will still work just fine.', 'nggallery' ), $user_first_name, '<b>' . __('NextGEN Gallery', 'nggallery') . '</b>', '<b>' . $user_login . '</b>', @@ -891,8 +891,9 @@ function ngg_fs() { // Always run Freemius in development mode for new plugin installs. $run_freemius = true; } else { - // Run Freemius code on 10% of the new installations. - $run_freemius = ( 1 == rand( 1, 10 ) ); + // Run Freemius code on 20% of the new installations. + $random = rand( 1, 10 ); + $run_freemius = ( 1 <= $random && $random <= 2 ); } update_option('ngg_run_freemius', $run_freemius); diff --git a/wp-content/plugins/nextgen-gallery/pope/lib/class.extensibleobject.php b/wp-content/plugins/nextgen-gallery/pope/lib/class.extensibleobject.php index e5eb51f72324e8fba01d6b3c102f4d37e8e941fa..6368d21e42b4d7efc6d483e433be3ac343431bd3 100755 --- a/wp-content/plugins/nextgen-gallery/pope/lib/class.extensibleobject.php +++ b/wp-content/plugins/nextgen-gallery/pope/lib/class.extensibleobject.php @@ -389,7 +389,7 @@ class ExtensibleObject extends PopeHelpers * @param string $property * @return mixed */ - function &__get($property) + function __get($property) { $retval = NULL; @@ -440,7 +440,7 @@ class ExtensibleObject extends PopeHelpers * @param mixed $value * @return mixed */ - function &__set($property, $value) + function __set($property, $value) { $retval = NULL; diff --git a/wp-content/plugins/nextgen-gallery/pope/run_tests.php b/wp-content/plugins/nextgen-gallery/pope/run_tests.php new file mode 100644 index 0000000000000000000000000000000000000000..c61fe13edacb985f9245d639b9b855013ce330e1 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/pope/run_tests.php @@ -0,0 +1,24 @@ +<?php + +/* + * Point this towards your own simpletest installation + */ +require_once(dirname(__FILE__) . '/../../simpletest-for-wordpress/lib/autorun.php'); + +require_once('lib/autoload.php'); + +$tests = array( + 'core', + 'pre_hooks', + 'post_hooks', + 'registry', + 'factories', + 'modules', + 'wrappers', + 'advanced', + 'method_properties' +); + +foreach ($tests as $test) { + require_once('tests/'.$test . '.php'); +} diff --git a/wp-content/plugins/nextgen-gallery/pope/tests/advanced.php b/wp-content/plugins/nextgen-gallery/pope/tests/advanced.php new file mode 100644 index 0000000000000000000000000000000000000000..dbeb83cd482702f3c4deab4e8c8f3435d04034ef --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/pope/tests/advanced.php @@ -0,0 +1,102 @@ +<?php + +class Mixin_Core_Replace_Method extends Mixin +{ + function run() + { + $this->object->Replaced_Method = True; + } +} + +class Test_Of_Core_Advanced extends UnitTestCase +{ + + public $str = 'test_string'; + + public function test_Core_Advanced() + { + $core = new C_Core($this->str); + + /* + * Pope internally caches some metadata about classes and which functions belong in those caches; including + * previous return values and names. + */ + $this->assertEqual( + False, + $core->is_cached('get_str'), + 'is_cached() returned True on a function not yet run' + ); + $core->get_str(); + $this->assertEqual( + True, $core->is_cached('get_str'), + 'is_cached() did not return True on an executed function' + ); + + /* + * Ensure remove_mixin() works + */ + $core->remove_mixin('Mixin_Core'); + $this->assertEqual( + False, + $core->get_mixin_providing('get_str'), + 'A mixin still provides get_str() after remove_mixin() was called' + ); + $core->add_mixin('Mixin_Core'); + + /* + * Make sure our classes are coming from the right places. + */ + $this->assertEqual( + 'core.php', + basename($core->get_class_definition_file()), + 'get_class_definition_file() did not return core.php' + ); + $this->assertEqual( + 'class.extensibleobject.php', + basename($core->get_class_definition_file(True)), + 'get_class_definition_file(True) did not return class.extensibleobject.php' + ); + $this->assertEqual( + 'tests', + basename($core->get_class_definition_dir()), + 'get_class_definition_dir() did not return this "tests" directory' + ); + $this->assertEqual( + 'lib', + basename($core->get_class_definition_dir(True)), + 'get_class_definition_dir(True) did not return the parent "lib" directory' + ); + + /* + * replace_method isn't quite what you would imagine; it prevents the original method from running + * and adds a new pre-hook to that method. While your new method will run the results from your method are + * not returned. Here we check for an object variable that shouldn't exist, swap out our method for a new one, + * and make sure it created that variable. + */ + $this->assertEqual( + False, + isset($core->object->Replaced_Method), + '$this->Replaced_Method was true before it should not have been' + ); + $core->replace_method('get_str', 'Mixin_Core_Replace_Method', 'run'); + $this->assertEqual( + null, + $core->get_str(), + 'replace_method() did not work' + ); + $this->assertEqual( + True, + $core->object->Replaced_Method, + '$this->Replaced_Method was not true when it should have been (run() was not called)' + ); + + // restore_method() reverts us back to a normal state + $core->restore_method('get_str'); + $this->assertEqual( + $this->str, + $core->get_str(), + 'restore_method() did not work' + ); + } + +} diff --git a/wp-content/plugins/nextgen-gallery/pope/tests/core.php b/wp-content/plugins/nextgen-gallery/pope/tests/core.php new file mode 100644 index 0000000000000000000000000000000000000000..3923555559a6db01d26d3e1eb6575a1d6965eef5 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/pope/tests/core.php @@ -0,0 +1,227 @@ +<?php + +/* + * This is a brief tutorial on how to use Pope through some unit test demonstrations. + * + * We begin by creating a simple class with a couple of functions. + * + * To help keep some of our classes separated (and to later demonstrate how to use the autoloader and factories) + * we're going to use the same naming scheme as Pope and prefix our classes with their class type. + * We start with our core class. + */ +class C_Core extends ExtensibleObject +{ + /* + * PHP imposes some limits that means our class variables and functions should ALL be public. "Private" variables + * should be named with a prefixed underscore. + */ + + /* + * This class exists to save and retrieve this string variable. We change our get/set functions with Mixins + * which we'll cover soon. + */ + public $_str; + + public function set_str($str) + { + $this->object->_str = $str; + } + + /* + * add_mixin() links the functions defined in Mixin_Core to this C_Core class. By assigning Mixin_Core we can + * call the "get_str" function on a C_Core instance even though this C_Core definition doesn't include a get_str + * function. You can even later add more Mixins that provide the same function; Pope tracks them by priority + * to determine name conflicts. + * + * define() is run when your class is created and can be used to automatically attach mixins or hooks. + */ + public function define() + { + $this->add_mixin('Mixin_Core'); + } + + /* + * This function is called at the end of __construct + */ + public function initialize($str) + { + $this->set_str($str); + } +} + +/* + * Now about mixins: they're like small plugins that can be assigned to give other classes their functions + * or to override their existing functions. They can access their parent data and can be added or removed + * and then added & removed again at any time. Let's demonstrate. + */ +class Mixin_Core extends Mixin +{ + public function get_str() + { + /* + * We can access the parent data with $this->object. When we attach this Mixin_Core to C_Core above this + * function returns C_Core's _str. If we attached this Mixin to any other class this Mixin would return that + * classes' _str variable. + */ + return $this->object->_str; + } +} + +/* + * We may need more than one way to retrieve that same string. This function returns our string inside of an HTML + * comment. The same C_Core instance can use both this and Mixin_Core's get_str() functions as you need them. + */ +class Mixin_Core_Override extends Mixin +{ + public function get_str($parent = False) + { + if (True == $parent) + { + return $this->call_parent('get_str'); + } else { + return '<!-- ' . $this->object->_str . ' -->'; + } + } +} + +/* + * This tutorial also doubles as a valid unit test with SimpleTest. The parameters for simpleTest's assert functions + * are (thing to compare one, thing to compare two, error message) + */ +class Test_Of_Core extends UnitTestCase +{ + + public $str = 'test_string'; + + /* + * We start with the simplest test possible. We create a C_Core class then we ask whether the string it has + * stored is the same as the string we gave it. Because we used add_mixin() in C_Core->define() we don't have + * to do it for every new C_Core we instantiate. + */ + public function test_Core() + { + $core = new C_Core($this->str); + + /* + * First we'll make sure that the get_str() method has been assigned + */ + $this->assertEqual( + True, + $core->has_method('get_str'), + 'has_method() did not return True on a method that exists' + ); + + /* + * Just in case has_method() is lying we ask about a method that doesnt exist + */ + $this->assertEqual( + False, + $core->has_method('does_not_exist'), + 'has_method() did not return False on a method that does not exist' + ); + + /* + * Finally we'll call get_str() + */ + $this->assertEqual( + $this->str, + $core->get_str(), + 'Simplest test did not work, probably add_mixin()' + ); + + /* + * We can ask pope what functions exist for our objects. Here we limit our results to functions provided by + * Mixin_Core. If you want every function available just remove the name parameter. + */ + $this->assertEqual( + array( + 0 => 'get_str' + ), + $core->get_instance_methods('Mixin_Core'), + 'get_instance_methods() did not return a correct list' + ); + + /* + * We can also ask which mixin provides our functions + */ + $this->assertEqual( + 'Mixin_Core', + $core->get_mixin_providing('get_str'), + 'get_mixin_providing() returned a wrong result' + ); + + $this->assertEqual( + $this->str, + $core->call_method('get_str'), + 'call_method() returned a wrong result' + ); + + /* + * Try calling a method for the object that doesn't exist + */ + $this->expectException('Exception', "ExtensibleObject did not throw an exception when an undefined method was called"); + $core->this_method_does_not_exist(); + } + + /* + * That's it! We created a C_Core class, assigned it a Mixin, and then called a function from the Mixin that the + * C_Core class didn't have. You now have a very simple and easily modifiable plugin system. + * + * Now we demonstrate how to work with other Mixins. + */ + public function test_Override() + { + /* + * By assigning Mixin_Core_Override it is given higher priority than Mixin_Core (first in, last out). Because + * our override returns the string as an HTML comment, we ask whether the override function ran. + */ + $core = new C_Core($this->str); + $core->add_mixin('Mixin_Core_Override'); + $this->assertEqual( + "<!-- {$this->str} -->", + $core->get_str(), + 'add_mixin() with an override did not render correctly' + ); + + /* + * Testing call_method() with our override + */ + $this->assertEqual( + "<!-- {$this->str} -->", + $core->call_method('get_str'), + 'call_method() returned a wrong result' + ); + + /* + * Our override will use it's call_parent() method when given a True parameter. Mixins and classes in Pope + * don't really have parents but it does maintain priority for each mixin added. If more than one mixin + * implements the same function they can call the mixins that are above them in priority. We demonstrate that + * by telling our override function to call it's parent -- the Mixin_Core->get_str() + */ + $this->assertEqual( + $this->str, + $core->get_str(True), + 'call_parent() did not function correctly' + ); + + /* + * Again we test call_method, this time while passing a parameter + */ + $this->assertEqual( + $this->str, + $core->call_method('get_str', array(True)), + 'call_method() returned a wrong result (with parameters)' + ); + + /* + * Just as easily as it was added we remove it and go back to our plain-old Mixin_Core. + */ + $core->del_mixin('Mixin_Core_Override'); + $this->assertEqual( + $this->str, + $core->get_str(), + 'del_mixin() did not remove the override mixin correctly' + ); + } + +} diff --git a/wp-content/plugins/nextgen-gallery/pope/tests/factories.php b/wp-content/plugins/nextgen-gallery/pope/tests/factories.php new file mode 100644 index 0000000000000000000000000000000000000000..7a3b92922aba3e4f1cfff3be1805140cec88957a --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/pope/tests/factories.php @@ -0,0 +1,209 @@ +<?php + +/* + * In this example we introduce interfaces, factories and the registry. We're going to create a "Simple Template" + * service and this means we an interface to implement, a class to implement it with, and a couple of mixins to attach + * to it. In the core unit test we created a service that returned a string wrapped in code comments. We do that again + * here. + * + * Start by creating the interface + */ +interface I_Simple_Template +{ + function render($arg); +} + +/* + * This is the default render() implementation. You may use your own default, but here we're going to requrie users + * to supply their own render() implementation. + */ +class Mixin_Simple_Template_Default +{ + function render($arg) + { + throw new Exception('Expected adapter to override this method'); + } +} + +/* + * Our main class. We now extend C_Component instead of ExtensibleObject and we use $this->implement() to implement + * the I_Simple_Template interface above. The context that initialize() asks for is used to juggle what kind of object + * our factories should create; you'll see soon. + */ +class C_Simple_Template extends C_Component +{ + function define() + { + parent::define(); + $this->add_mixin('Mixin_Simple_Template_Default'); + $this->implement('I_Simple_Template'); + } + + function initialize($context = False) + { + parent::initialize($context); + } +} + +class C_Simple_Template_Two extends C_Component +{ + function define() + { + parent::define(); + $this->add_mixin('Mixin_Simple_Template_Normal'); + } +} + +/* + * Let's create two implementations of render(). One will just return our string as is, and the other will be filtered + * through strip_tags() + */ +class A_Simple_Template_Normal extends Mixin +{ + function render($arg) + { + return $arg; + } +} + +class A_Simple_Template_Alternate extends Mixin +{ + function render($arg) + { + return strip_tags($arg); + } +} + +/* + * This is our factory; it's functions are called by name when calling the I_Component_Factory->create(). So here we + * name this function 'photocrati_simple_template' and use that same name again when doing $factory->create(). + */ +class A_Simple_Template_Factory extends Mixin +{ + function photocrati_simple_template($context = False) + { + return new C_Simple_Template($context); + } +} + +/** + * The SimpleTest class + */ +class Test_Of_Simple_Template extends UnitTestCase +{ + + public $str = 'test_string'; + + public function test_simple_template() + { + /* + * We first setup Pope, and then tell I_Component_Factory that our Simple_Template factory exists. + */ + $registry = C_Component_Registry::get_instance(); + $registry->add_utility('I_Component_Factory', 'C_Component_Factory'); + $registry->add_adapter('I_Component_Factory', 'A_Simple_Template_Factory'); + + /* + * Now we assign the Normal and Alternate implementations to the interface. + */ + $registry->add_adapter('I_Simple_Template', 'A_Simple_Template_Normal', 'Normal'); + $registry->add_adapter('I_Simple_Template', 'A_Simple_Template_Alternate', 'Alternate'); + + /* + * Now we create our objects. By providing the context "normal" we are asking Pope to use our "normal" render + * implementation. If we leave out the context parameter here our factory provides us with our default + * implementation which will throw an exception. + */ + $factory = $registry->get_utility('I_Component_Factory'); + $obj = $factory->create('photocrati_simple_template', 'Normal'); + $this->assertEqual( + $this->str, + $obj->render($this->str), + 'The normal context did not render correctly' + ); + + /* + * Because our default handler throws an exception when called, let's make certain it works as the fallback + */ + $obj = $factory->create('photocrati_simple_template', 'Test'); + $error = False; + try + { + $obj->render($this->str); + } catch (Exception $exception) + { + $error = True; + } + $this->assertEqual( + True, + $error, + 'The default throwback handler did not throw an exception (did not run)' + ); + + /* + * Now let's add it and test it again + */ + $registry->add_adapter('I_Simple_Template', 'A_Simple_Template_Normal', 'Test'); + $factory = $registry->get_utility('I_Component_Factory'); + + $obj = $factory->create('photocrati_simple_template', 'Test'); + $this->assertEqual( + $this->str, + $obj->render($this->str), + 'The test context did not render correctly after add_adapter()' + ); + + /* + * That worked! Let's delete it and make sure it again throws an exception + */ + $error = False; + $registry->del_adapter('I_Simple_Template', 'A_Simple_Template_Normal', 'Test'); + $factory = $registry->get_utility('I_Component_Factory'); + $obj = $factory->create('photocrati_simple_template', 'Test'); + try + { + $obj->render($this->str); + } catch (Exception $exception) + { + $error = True; + } + $this->assertEqual( + True, + $error, + 'Factory creation of a context after calling del_adapter() did not throw an exception' + ); + + /* + * We now swap out to the Alternate context where we ask for our text to be free of markup + */ + $obj = $factory->create('photocrati_simple_template', 'Alternate'); + $this->assertEqual( + $this->str, + $obj->render('<p>' . $this->str . '</p>'), + 'The alternative context did not render correctly' + ); + + /* + * We can of course still create our objects outside of the factory generator. Here we moved the implement() + * call outside of the class definition so that we can test it. + */ + $obj = new C_Simple_Template_Two(); + $this->assertEqual( + False, + $obj->implements_interface('I_Simple_Template'), + 'C_Simple_Template implemented I_Simple_Template_Two when it should not have' + ); + $obj->implement('I_Simple_Template'); + $this->assertEqual( + True, + $obj->implements_interface('I_Simple_Template'), + 'C_Simple_Template_Two did not implement I_Simple_Template when it should have' + ); + + /* + * That's it. We've created an interface and a couple of implementations of it. We can switch between those + * implementations based on context, and our factory maker provides the correct implementation. + */ + } + +} diff --git a/wp-content/plugins/nextgen-gallery/pope/tests/method_properties.php b/wp-content/plugins/nextgen-gallery/pope/tests/method_properties.php new file mode 100644 index 0000000000000000000000000000000000000000..cc8803a3d1ab4eee78212f56ea9fe5809b32a64f --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/pope/tests/method_properties.php @@ -0,0 +1,175 @@ +<?php + +/* + * We can make some significant changes to the Pope internals through the set_method_properties() function. + * + * Here we'll create two classes that capitalize & rot13 our string, each with a post and pre function. The capitalize + * class will also check an object variable. + * + * Because Pope caches the return values from executed functions we can also override that return value in our post + * hooks before it makes it is returned. We can also have one hook disable execution of other hooks and even the + * original function called. + */ +class Hook_MP_Capitalize extends Hook +{ + public function capitalize() + { + $prop = ExtensibleObject::METHOD_PROPERTY_RETURN_VALUE; + + // method, property, value + $this->object->set_method_property( + 'get_str', + $prop, + strtoupper($this->object->get_method_property('get_str', $prop)) + ); + + /* + * The object variables are set later as a manual trigger + */ + if (True == $this->object->disable_run_post_hooks) + { + $this->object->set_method_property('get_str', ExtensibleObject::METHOD_PROPERTY_RUN_POST_HOOKS, False); + } + } + + public function pre_capitalize() + { + $this->object->_str = strtoupper($this->object->_str); + + if (True == $this->object->disable_run_pre_hooks) + { + $this->object->set_method_property('get_str', ExtensibleObject::METHOD_PROPERTY_RUN_PRE_HOOKS, False); + } + + if (True == $this->object->disable_run) + { + $this->object->set_method_property('get_str', ExtensibleObject::METHOD_PROPERTY_RUN, False); + } + } +} + +/* + * Now we repeat ourselves, but simpler as this class exists just to be disabled + */ +class Hook_MP_Rot13 extends Hook +{ + public function rot13() + { + $prop = ExtensibleObject::METHOD_PROPERTY_RETURN_VALUE; + + // method, property, value + $this->object->set_method_property( + 'get_str', + $prop, + str_rot13($this->object->get_method_property('get_str', $prop)) + ); + } + + public function pre_rot13() + { + $this->object->_str = str_rot13($this->object->_str); + } +} + +class Test_Of_Method_Properties extends UnitTestCase +{ + public $str = 'test_string'; + + public function test_Method_Properties() + { + $core = new C_Core($this->str); + $core->add_mixin('Mixin_Core_Post'); + + /* + * This hook modifies the original return value to instead return its results directly through get_str() + */ + $core->add_post_hook('get_str', 'Method Properties Capitalize', 'Hook_MP_Capitalize', 'capitalize'); + $this->assertEqual( + strtoupper($this->str), + $core->get_str(), + 'set_method_property(return_value) did not capitalize our string' + ); + + /* + * We need at least two hooks to test + */ + $core->add_post_hook('get_str', 'Method Properties Rot13', 'Hook_MP_Rot13', 'rot13'); + $this->assertEqual( + str_rot13(strtoupper($this->str)), + $core->get_str(), + 'set_method_property(return_value) did not capitalize and rot13 our string across two hooks' + ); + + /* + * Our capitalize() function will check for this variable and disable other post hooks through + * set_method_property() + */ + $core->object->disable_run_post_hooks = True; + $this->assertEqual( + strtoupper($this->str), + $core->get_str(), + 'set_method_property(run_post_hooks) did not disable the rot13 hook' + ); + + $core->disable_post_hooks('get_str'); + $core->set_str($this->str); + + /* + * Now we add our pre-hooks and test them + */ + $core->add_pre_hook('get_str', 'Method Properties Pre-Capitalize', 'Hook_MP_Capitalize', 'pre_capitalize'); + $core->add_pre_hook('get_str', 'Method Properties Pre-Rot13', 'Hook_MP_Rot13', 'pre_rot13'); + $this->assertEqual( + str_rot13(strtoupper($this->str)), + $core->get_str(), + 'Something stopped the two pre-hooks from running' + ); + + /* + * Again our first pre-hook should disable the second from running + */ + $core->object->disable_run_pre_hooks = True; + $core->set_str($this->str); + $this->assertEqual( + strtoupper($this->str), + $core->get_str(), + 'set_method_property(run_pre_hooks) did not disable the rot13 hook' + ); + + /* + * When run == False get_str() should not run and should return null + */ + $core->set_str($this->str); + $core->disable_run = True; + $this->assertEqual( + Null, + $core->get_str(), + 'set_method_properties(run) did not stop get_str() from running' + ); + + /* + * And one last sanity check + */ + $this->assertEqual( + strtoupper($this->str), + $core->object->_str, + 'Something stopped the pre-hook from running' + ); + + /* + * clear_method_properties() resets the entire method properties array + */ + $core->reset_method_properties('get_str');; + $this->assertEqual( + array( + ExtensibleObject::METHOD_PROPERTY_RUN => True, + ExtensibleObject::METHOD_PROPERTY_RUN_PRE_HOOKS => True, + ExtensibleObject::METHOD_PROPERTY_RUN_POST_HOOKS => True + ), + $core->_method_properties['get_str'], + 'clear_method_properties() did not reset the method properties correctly' + ); + + + } +} diff --git a/wp-content/plugins/nextgen-gallery/pope/tests/modules.php b/wp-content/plugins/nextgen-gallery/pope/tests/modules.php new file mode 100644 index 0000000000000000000000000000000000000000..c9f45765a15a75b428e6e77497bc41ceef028465 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/pope/tests/modules.php @@ -0,0 +1,30 @@ +<?php + +class Test_Of_Modules extends UnitTestCase +{ + public $str = 'test_string'; + + public function test_Modules() + { + $registry = C_Component_Registry::get_instance(); + $factory = $registry->get_utility('I_Component_Factory'); + + /* + * photocrati_template is a continuation of the Simple_Template class, now reborn as "Template" that we have + * put into a product called "Pope". We test it the same way we did our Simple_Template class. + */ + $obj = $factory->create('photocrati_template', 'Normal'); + $this->assertEqual( + $this->str, + $obj->render($this->str), + 'Factory creation of a normal context template did not render correctly' + ); + + $obj = $factory->create('photocrati_template', 'Alternate'); + $this->assertEqual( + $this->str, + $obj->render('<p>' . $this->str . '</p>'), + 'Factory creation of an alternate context template did not render correctly' + ); + } +} diff --git a/wp-content/plugins/nextgen-gallery/pope/tests/post_hooks.php b/wp-content/plugins/nextgen-gallery/pope/tests/post_hooks.php new file mode 100644 index 0000000000000000000000000000000000000000..99a9f44ae7fcc58e2a88e89aa575e0f779d26a87 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/pope/tests/post_hooks.php @@ -0,0 +1,165 @@ +<?php + +/* + * Continuing on we now have post-hooks. + * + * With our pre-hooks we just modified our string before it was sent, but post-hooks run after get_str() so they won't + * help much. Instead we make a simple function for triggering our post-hooks, it doesn't do anything but trigger them. + */ +class Mixin_Core_Post extends Mixin +{ + public function do_nothing() + { + return null; + } +} + +/* + * In an alternate reality we need to change our string into a Ruby comment, but only after we've seen the original. + * We can do that as a post-hook. Again we create two for our tests and a global hook function. + */ +class Hook_Core_Post extends Hook +{ + public function change_str() + { + $this->object->_str = '=begin ' . $this->object->_str . ' =end'; + } + public function global_change_str() + { + $this->object->_str = '; ' . $this->object->_str; + } +} + +class Hook_Core_Post_Second extends Hook +{ + public function change_str() + { + $this->object->_str = '-- ' . $this->object->_str; + } +} + +class Test_Of_Post_Hooks extends UnitTestCase +{ + + public $str = 'test_string'; + + public function test_Post_Hooks() + { + $core = new C_Core($this->str); + $core->add_mixin('Mixin_Core_Post'); + $this->assertEqual( + True, + $core->has_method('do_nothing'), + 'has_method() did not return True on a method that does exist' + ); + + $core->add_post_hook('do_nothing', 'Post-Hook Test', 'Hook_Core_Post', 'change_str'); + $core->do_nothing(); + $this->assertEqual( + "=begin {$this->str} =end", + $core->get_str(), + 'add_post_hook() did not run correctly' + ); + + // make sure a posthook is registered for do_nothing() + $this->assertEqual( + True, + $core->have_posthook_for('do_nothing'), + 'have_posthook_for() did not return True on a function with a post-hook (one parameter)' + ); + + // and that we have one from "Post-Hook Test" and do_nothing() + $this->assertEqual( + True, + $core->have_posthook_for('do_nothing', 'Post-Hook Test'), + 'have_posthook_for() did not return True on a function with a post-hook (two parameter)' + ); + + // just to be safe, ensure we don't have posthooks that don't exist + $this->assertEqual( + False, + $core->have_posthook_for('do_nothing', 'Does Not Exist'), + 'have_posthook_for() did not return False on a post-hook label that does not exist' + ); + + // del_post_hook + $core->del_post_hook('do_nothing', 'Post-Hook Test'); + $core->set_str($this->str); + $this->assertEqual( + $this->str, + $core->get_str(), + 'del_post_hook() did not run correctly' + ); + $this->assertEqual( + False, + $core->have_posthook_for('do_nothing', 'Post-Hook Test'), + 'have_posthook_for() did not return False after calling del_post_hook()' + ); + + // re-add to continue testing + $core->add_post_hook('do_nothing', 'Post-Hook Test', 'Hook_Core_Post', 'change_str'); + + // disable_post_hooks + $core->disable_post_hooks('do_nothing'); + $this->assertEqual( + $this->str, + $core->get_str(), + 'disable_post_hooks() did not run correctly' + ); + + // enable_post_hooks + $core->enable_post_hooks('do_nothing'); + $core->do_nothing(); + $this->assertEqual( + "=begin {$this->str} =end", + $core->get_str(), + 'enable_post_hooks() did not run correctly' + ); + + // are_post_hooks_enabled + $this->assertEqual( + True, + $core->are_post_hooks_enabled('do_nothing'), + 'are_post_hooks_enabled() did not return True on a function with post-hooks' + ); + + // are_post_hooks_enabled + $core->disable_post_hooks('do_nothing'); + $this->assertEqual( + False, + $core->are_post_hooks_enabled('do_nothing'), + 'are_post_hooks_enabled() did not return False after calling disable_post_hooks()' + ); + + // two post hooks + $core->enable_post_hooks('do_nothing'); + $core->set_str($this->str); + $core->add_post_hook('do_nothing', 'Post-Hook Test Two', 'Hook_Core_Post_Second', 'change_str'); + $core->do_nothing(); + $this->assertEqual( + "-- =begin {$this->str} =end", + $core->get_str(), + 'enable_post_hooks() did not run correctly' + ); + + // del_post_hooks + $core->del_post_hooks('do_nothing'); + $core->set_str($this->str); + $this->assertEqual( + $this->str, + $core->get_str(), + 'del_post_hooks() did not run correctly' + ); + + // add_global_post_hook + $core->add_post_hook('do_nothing', 'Post-Hook Test Two', 'Hook_Core_Post_Second', 'change_str'); + $core->add_global_post_hook('Global Post-Hook', 'Hook_Core_Post', 'global_change_str'); + $core->add_post_hook('do_nothing', 'Post-Hook Test', 'Hook_Core_Post', 'change_str'); + $core->do_nothing(); + $this->assertEqual( + True, + "; =begin -- ; {$this->str} =end", + 'add_global_post_hook() did not run correctly' + ); + } +} diff --git a/wp-content/plugins/nextgen-gallery/pope/tests/pre_hooks.php b/wp-content/plugins/nextgen-gallery/pope/tests/pre_hooks.php new file mode 100644 index 0000000000000000000000000000000000000000..c09bc188528637850676cf702f19ffcec393d030 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/pope/tests/pre_hooks.php @@ -0,0 +1,197 @@ +<?php + +/* + * Now we are going to introduce hooks. Hooks extend the Mixin type and work in a similiar way. + * + * Like our previous Mixin override we put our string inside a C comment. With this we can filter our string through any + * number of hooks and not just rely on manually assigning Mixins. We eventually want to test our ability to remove + * both at once, so we setup hooks two. We also have global hooks (hooks that are assigned to ALL functions) so we + * create a special method for that also. + */ +class Hook_Core_Pre extends Hook +{ + public function change_str() + { + $this->object->_str = '/* ' . $this->object->_str . ' */'; + } + + public function global_change_str() + { + $this->object->_str = '// ' . $this->object->_str; + } +} +class Hook_Core_Pre_Second extends Hook +{ + public function change_str() + { + $this->object->_str = '## ' . $this->object->_str; + } + + /* + * We can tell our hook functions to call the function they are anchored to. + */ + public function test_call_anchor() + { + $this->object->_str = 'not the test string'; + return $this->call_anchor(); + } +} + +/* + * On to our unit tests + */ +class Test_Of_Pre_Hooks extends UnitTestCase +{ + + public $str = 'test_string'; + + public function test_Pre_Hooks() + { + /* + * We assign Hook_Core_Pre->change_str to run before the $core->get_str function. Hooks are grouped by + * name. You'll see when we get to del_pre_hook() + */ + $core = new C_Core($this->str); + $core->add_pre_hook('get_str', 'Pre-Hook Test', 'Hook_Core_Pre', 'change_str'); + $this->assertEqual( + "/* {$this->str} */", + $core->get_str(), + 'add_pre_hook() did not change our var correctly' + ); + + /* + * Just to be safe we're going to make sure the hook we just applied really is registered. We're being very + * cautious today so we'll also make sure there isn't a hook group that shouldn't be there. The first check + * is true if there's *any* hooks for get_str, the second only if there's a hook in the "Pre-Hook Test" group + * for get_str. + */ + $this->assertEqual( + True, + $core->have_prehook_for('get_str'), + 'have_prehook_for() with one parameter did not return True when it should have' + ); + $this->assertEqual( + True, + $core->have_prehook_for('get_str','Pre-Hook Test'), + 'have_prehook_for() with both parameters did not return True when it should have' + ); + $this->assertEqual( + False, + $core->have_prehook_for('get_str', 'Does Not Exist'), + 'have_prehook_for() did not return False on a non-existent pre-hook' + ); + + /* + * We don't actually NEED our string stored as a C comment, let's undo all that. Our filter up above + * changed the string variable itself, so after deleting our hook we reset the string and then test ourselves + * again. + */ + $core->del_pre_hook('get_str', 'Pre-Hook Test'); + $core->set_str($this->str); + $this->assertEqual( + $this->str, + $core->get_str(), + 'del_pre_hook() did not run correctly' + ); + $this->assertEqual( + False, + $core->have_prehook_for('get_str', 'Pre-Hook Test'), + 'have_prehook_for() did not return False for a deleted hook' + ); + + /* + * Wait, I've changed my mind. We need that hook back, but we're going to leave it disabled. + */ + $core->add_pre_hook('get_str', 'Pre-Hook Test', 'Hook_Core_Pre', 'change_str'); + $core->disable_pre_hooks('get_str'); + $this->assertEqual( + $this->str, + $core->get_str(), + 'disable_pre_hooks() did not run correctly' + ); + + /* + * We've proven the hook isn't a renegade robot, so we turn it back on and run another systems check. + */ + $core->enable_pre_hooks('get_str'); + $this->assertEqual( + "/* {$this->str} */", + $core->get_str(), + 'enable_pre_hooks() did not run correctly' + ); + + /* + * Like proper scientists we check our ability to check our ability to turn our hooks on and off + */ + $this->assertEqual( + True, + $core->are_pre_hooks_enabled('get_str'), + 'are_pre_hooks_enabled() did not return True after enable_pre_hooks() ran' + + ); + $core->disable_pre_hooks('get_str'); + $this->assertEqual( + False, + $core->are_pre_hooks_enabled('get_str'), + 'are_pre_hooks_enabled() did not return False after disable_pre_hooks() ran' + ); + + /* + * Now let's test our abilities to run more than one hook and to turn them all off at once + */ + $core->enable_pre_hooks('get_str'); + $core->set_str($this->str); + $core->add_pre_hook('get_str', 'Pre-Hook Test Two', 'Hook_Core_Pre_Second', 'change_str'); + $this->assertEqual( + "## /* {$this->str} */", + $core->get_str(), + 'enable_pre_hooks() did not run correctly' + ); + + /* + * Both hooks ran in the order we wanted, so we turn them both off. + */ + $core->del_pre_hooks('get_str'); + $core->set_str($this->str); + $this->assertEqual( + $this->str, + $core->get_str(), + 'del_pre_hooks() did not run correctly' + ); + + /* + * Let's add our global pre-hook. Just to demonstrate something, we'll add our "Second" hook first, then + * our global hook, and then the original pre-hook. Global hooks are run first, and then regular hooks are + * run in order they are attached. + */ + $core->add_pre_hook('get_str', 'Pre-Hook Test Two', 'Hook_Core_Pre_Second', 'change_str'); + $core->add_global_pre_hook('Global Pre-Hook', 'Hook_Core_Pre', 'global_change_str'); + $core->add_pre_hook('get_str', 'Pre-Hook Test', 'Hook_Core_Pre', 'change_str'); + $this->assertEqual( + "/* ## // {$this->str} */", + $core->get_str(), + 'add_global_pre_hook() did not run correctly' + ); + } + + public function test_Pre_Hook_Anchor() + { + /* + * Here we call a pre-hook that uses call_anchor() to invoke get_str() itself-after changing the set + * string to something entirely different. + */ + $core = new C_Core($this->str); + $core->add_mixin('Mixin_Core_Override'); + $core->add_pre_hook('get_str', 'Pre-Hook Anchor Test', 'Hook_Core_Pre_Second', 'test_call_anchor'); + + $this->assertEqual( + '<!-- not the test string -->', + $core->get_str(), + 'A hooks call_anchor() did not run correctly' + ); + } + + /* + * That's all for pre-hooks. Post-hooks work identically so readers may want to skip that file. + */ +} diff --git a/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_animal/pope_modules/animal_farm/adapter.animal_cow.php b/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_animal/pope_modules/animal_farm/adapter.animal_cow.php new file mode 100644 index 0000000000000000000000000000000000000000..a72028d40e8c5cb785b5570f5072a125802e16df --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_animal/pope_modules/animal_farm/adapter.animal_cow.php @@ -0,0 +1,9 @@ +<?php + +class A_Animal_Cow extends Mixin +{ + function speak($arg) + { + return 'The cow moos: ' . $arg; + } +} diff --git a/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_animal/pope_modules/animal_farm/adapter.animal_dog.php b/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_animal/pope_modules/animal_farm/adapter.animal_dog.php new file mode 100644 index 0000000000000000000000000000000000000000..56a3c46d83a96e8340a871ed3b6a07b8216810e4 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_animal/pope_modules/animal_farm/adapter.animal_dog.php @@ -0,0 +1,9 @@ +<?php + +class A_Animal_Dog extends Mixin +{ + function speak($arg) + { + return 'The dog barks: ' . $arg; + } +} diff --git a/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_animal/pope_modules/animal_farm/adapter.animal_factory.php b/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_animal/pope_modules/animal_farm/adapter.animal_factory.php new file mode 100644 index 0000000000000000000000000000000000000000..3ee484530fd3a3a2737d91b51c30007a954ec357 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_animal/pope_modules/animal_farm/adapter.animal_factory.php @@ -0,0 +1,9 @@ +<?php + +class A_Animal_Factory extends Mixin +{ + function animal_farm($context = False) + { + return new C_Animal_Library($context); + } +} diff --git a/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_animal/pope_modules/animal_farm/class.animal_empty.php b/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_animal/pope_modules/animal_farm/class.animal_empty.php new file mode 100644 index 0000000000000000000000000000000000000000..fe215f204dd80b95ed03c040d46786a221aa9bb3 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_animal/pope_modules/animal_farm/class.animal_empty.php @@ -0,0 +1,5 @@ +<?php + +class C_Animal_Empty extends C_Component +{ +} diff --git a/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_animal/pope_modules/animal_farm/class.animal_library.php b/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_animal/pope_modules/animal_farm/class.animal_library.php new file mode 100644 index 0000000000000000000000000000000000000000..b5ceee86f1c1a3a0743818d8d5c4ad8377b97ffe --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_animal/pope_modules/animal_farm/class.animal_library.php @@ -0,0 +1,19 @@ +<?php + +class C_Animal_Library extends C_Component +{ + function define() + { + parent::define(); + $this->add_mixin('Mixin_Animal_Default_Speak'); + $this->implement('I_Animal_Library'); + } +} + +class Mixin_Animal_Default_Speak +{ + function speak($arg) + { + throw new Exception('Expected adapter to override this method'); + } +} diff --git a/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_animal/pope_modules/animal_farm/interface.animal_library.php b/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_animal/pope_modules/animal_farm/interface.animal_library.php new file mode 100644 index 0000000000000000000000000000000000000000..f4651998bcdd7e9240ebdcc3d98199b037ea480d --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_animal/pope_modules/animal_farm/interface.animal_library.php @@ -0,0 +1,6 @@ +<?php + +interface I_Animal_Library +{ + function speak($arg); +} diff --git a/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_animal/pope_modules/animal_farm/module.animal_farm.php b/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_animal/pope_modules/animal_farm/module.animal_farm.php new file mode 100644 index 0000000000000000000000000000000000000000..240cc3c52cb363cb1a01ecc0229d4eb231a18e0e --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_animal/pope_modules/animal_farm/module.animal_farm.php @@ -0,0 +1,39 @@ +<?php + +/*** +{ +Module: photocrati-animal-farm +} + ***/ + +class M_Animal_Farm extends C_Base_Module +{ + public $is_initialized = False; + + public function define() + { + parent::define( + 'photocrati-animal-farm', + 'Photocrati Animal Farm', + 'An extremely simple animal-based "Hello World"', + '0.1', + 'https://www.imagely.com', + 'Photocrati Media', + 'https://www.imagely.com' + ); + } + + public function _register_adapters() + { + $this->get_registry()->add_adapter('I_Component_Factory', 'A_Animal_Factory'); + $this->get_registry()->add_adapter('I_Animal_Library', 'A_Animal_Cow', 'Cow'); + $this->get_registry()->add_adapter('I_Animal_Library', 'A_Animal_Dog', 'Dog'); + } + + public function initialize() + { + $this->is_initialized = True; + } +} + +new M_Animal_Farm(); diff --git a/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_animal/product.photocrati_animal.php b/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_animal/product.photocrati_animal.php new file mode 100644 index 0000000000000000000000000000000000000000..8e8b5d3f7da684ce24b118a78ff31e876ef39719 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_animal/product.photocrati_animal.php @@ -0,0 +1,31 @@ +<?php + +/*** +{ +Product: photocrati-animal +} + ***/ + +class P_Photocrati_Animal extends C_Base_Product +{ + public function define() + { + // id, name, description, version, uri, author, author_uri + parent::define( + 'photocrati-animal', + 'Photocrati Animal', + 'An extremely simple animal-based "Hello World"', + '0.1', + 'https://www.imagely.com', + 'Photocrati Media', + 'https://www.imagely.com' + ); + + $dir = dirname(__FILE__) . '/pope_modules/'; + $registry = $this->get_registry(); + $registry->set_product_module_path($this->module_id, $dir); + $registry->add_module_path($dir, True, False); + } +} + +new P_Photocrati_Animal(); diff --git a/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_pope/modules/template/adapter.template_alternate.php b/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_pope/modules/template/adapter.template_alternate.php new file mode 100644 index 0000000000000000000000000000000000000000..098f35c6c0d9aa365a854e3e20cfd3e37fcab183 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_pope/modules/template/adapter.template_alternate.php @@ -0,0 +1,9 @@ +<?php + +class A_Template_Alternate extends Mixin +{ + function render($arg) + { + return strip_tags($arg); + } +} diff --git a/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_pope/modules/template/adapter.template_factory.php b/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_pope/modules/template/adapter.template_factory.php new file mode 100644 index 0000000000000000000000000000000000000000..6b9f81b22d77e3935a14ed3301c49743a4da947d --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_pope/modules/template/adapter.template_factory.php @@ -0,0 +1,9 @@ +<?php + +class A_Template_Factory extends Mixin +{ + function photocrati_template($context = False) + { + return new C_Template_Library($context); + } +} diff --git a/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_pope/modules/template/adapter.template_normal.php b/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_pope/modules/template/adapter.template_normal.php new file mode 100644 index 0000000000000000000000000000000000000000..bfdbf9c3819ac90e66dce3c965cfa9a5ff82fd78 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_pope/modules/template/adapter.template_normal.php @@ -0,0 +1,9 @@ +<?php + +class A_Template_Normal extends Mixin +{ + function render($arg) + { + return $arg; + } +} diff --git a/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_pope/modules/template/class.template_library.php b/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_pope/modules/template/class.template_library.php new file mode 100644 index 0000000000000000000000000000000000000000..5294d11981484a734ea54aa8cd8e06ff18009a03 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_pope/modules/template/class.template_library.php @@ -0,0 +1,19 @@ +<?php + +class C_Template_Library extends C_Component +{ + function define() + { + parent::define(); + $this->add_mixin('Mixin_Template_Default_Render'); + $this->implement('I_Template_Library'); + } +} + +class Mixin_Template_Default_Render +{ + function render($arg) + { + throw new Exception('Expected adapter to override this method'); + } +} diff --git a/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_pope/modules/template/interface.template_library.php b/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_pope/modules/template/interface.template_library.php new file mode 100644 index 0000000000000000000000000000000000000000..eea2b7d644f70a8b86d77246e4dd5c9dcbf7c16f --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_pope/modules/template/interface.template_library.php @@ -0,0 +1,6 @@ +<?php + +interface I_Template_Library +{ + function render($arg); +} diff --git a/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_pope/modules/template/module.template.php b/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_pope/modules/template/module.template.php new file mode 100644 index 0000000000000000000000000000000000000000..943f83342aebe554d9353f930610a2a2e05bd953 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_pope/modules/template/module.template.php @@ -0,0 +1,54 @@ +<?php + +/*** +{ +Module: photocrati-template +} + ***/ + +class M_Template extends C_Base_Module +{ + public $is_initialized = False; + + public function define() + { + parent::define( + 'photocrati-template', + 'Photocrati Template', + 'An extremely simple template system', + '0.1', + 'https://www.imagely.com', + 'Photocrati Media', + 'https://www.imagely.com' + ); + } + + /* + * _registery_adapters, _register_hooks(), and _register_utilities are run at the end of parent::define() + */ + public function _register_adapters() + { + $this->get_registry()->add_adapter('I_Component_Factory', 'A_Template_Factory'); + $this->get_registry()->add_adapter('I_Template_Library', 'A_Template_Normal', 'Normal'); + $this->get_registry()->add_adapter('I_Template_Library', 'A_Template_Alternate', 'Alternate'); + } + + public function _register_hooks() + { + } + + public function _register_utilities() + { + } + + /* + * You can use initialize() here to act as soon as initialize_module() has been called on it. That way modules + * can be loaded but only started when desired. The initialize() function is only called once per object. + */ + public function initialize() + { + $this->is_initialized = True; + } +} + +new M_Template(); diff --git a/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_pope/product.photocrati_pope.php b/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_pope/product.photocrati_pope.php new file mode 100644 index 0000000000000000000000000000000000000000..5e7cb27b3a2bf7da549277946672e1e6a9badbbf --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/pope/tests/products/photocrati_pope/product.photocrati_pope.php @@ -0,0 +1,35 @@ +<?php + +/*** +{ +Product: photocrati-pope +} + ***/ + +class P_Photocrati_Pope extends C_Base_Product +{ + public function define() + { + // id, name, description, version, uri, author, author_uri + parent::define( + 'photocrati-pope', + 'Photocrati Pope', + 'Photocrati Pope', + '0.1', + 'https://bitbucket.org/photocrati/pope-framework', + 'Photocrati Media', + 'https://www.imagely.com' + ); + + /* + * The modules can be stored anywhere under this project. In the Animal product the modules are kept in a dir + * called "pope_modules" + */ + $dir = dirname(__FILE__) . '/modules/'; + $registry = $this->get_registry(); + $registry->set_product_module_path($this->module_id, $dir); + $registry->add_module_path($dir, True, False); + } +} + +new P_Photocrati_Pope(); diff --git a/wp-content/plugins/nextgen-gallery/pope/tests/registry.php b/wp-content/plugins/nextgen-gallery/pope/tests/registry.php new file mode 100644 index 0000000000000000000000000000000000000000..e32c0b405d86740c02eaa5a3016e0d9419772ee7 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/pope/tests/registry.php @@ -0,0 +1,454 @@ +<?php + +/* + * This is just an empty module to be used for testing later + */ +class C_Test_Autoload extends C_Base_Module +{ + function define() + { + parent::define( + 'C_Test_Autoload', + 'C_Test_Autoload Empty Class', + 'An empty shell to test the base modules autoload()', + '0.1', + 'https://www.imagely.com/', + 'Photocrati', + 'https://www.imagely.com/' + ); + } +} + + +/*** +{ +Product: photocrati-empty +} + ***/ + +class P_Photocrati_Empty extends C_Base_Product +{ + public function define() + { + // id, name, description, version, uri, author, author_uri + parent::define( + 'photocrati-empty', + 'Photocrati Empty', + 'AN empty shell used for unit testing', + '0.1', + 'https://bitbucket.org/photocrati/pope-framework', + 'Photocrati Media', + 'https://www.imagely.com' + ); + } +} + + +class Test_Of_Registry extends UnitTestCase +{ + /** @var string $path Path to the Pope products directory */ + public $path; + + public $registry; + + public function __construct() + { + $this->path = dirname(__FILE__) . '/products/'; + } + + /** + * Tests the registration setup for Pope + */ + public function test_Registry_Setup() + { + // Ensure we're working with an entirely new instance + C_Component_Registry::$_instance = Null; + $this->registry = C_Component_Registry::get_instance(); + + // We *want* to cause an exception for once. This should come without any utilities; we'll check for them again + // after we've added one + $factory = false; + try + { + $factory = $this->registry->get_utility('I_Component_Factory'); + } catch (Exception $exception) { } + $this->assertEqual( + False, + $factory, + 'A utility was registered to I_Component_Factory when it should be empty' + ); + + // Make sure we can set and retrieve utilities + $this->registry->add_utility('I_Component_Factory', 'C_Component_Factory'); + $factory = $this->registry->get_utility('I_Component_Factory'); + $this->assertEqual( + 'C_Component_Factory', + get_class($factory), + 'add_utility() followed by get_utility() did not return a C_Component_Factory utility' + ); + + // Pope can also handle singleton generation, just provide a get_instance() function for your class + $factory = $this->registry->get_utility('I_Component_Factory'); + $this->assertEqual( + 'C_Component_Factory', + get_class($factory), + 'get_utility did not return C_Component_Factory utility' + ); + + // We've just started so our product & module lists should be completely empty + $this->assertEqual( + array(), + $this->registry->get_known_product_list(), + 'No products should be known yet' + ); + $this->assertEqual( + array(), + $this->registry->get_known_module_list(), + 'No modules should be known yet' + ); + $this->assertEqual( + array(), + $this->registry->get_product_list(), + 'The product list should be empty' + ); + $this->assertEqual( + array(), + $this->registry->get_module_list(), + 'The module list should be empty' + ); + } + + /** + * Tests path setup and initial module loading + */ + public function test_Registry_Add_Module_Path() + { + /* + * Not every module has to set its own modules directory, add_module_path() will call set_default_module_path() + * the first time it runs so that all of your modules will come from the same place. + */ + $this->assertEqual( + Null, + $this->registry->get_default_module_path(), + 'get_default_module_path() returned !null before add_module_path() or set_default_module_path() were called' + ); + + $this->registry->add_module_path($this->path, True, False); + + $this->assertEqual( + $this->path, + $this->registry->get_default_module_path(), + 'add_module_path() did not call set_default_module_path() correctly' + ); + + /* + * get_known_module_list and get_known_product_list return ALL registered objects, even + * if they haven't been loaded yet (through load_all_products() or load_module() or such. + * get_product_list & get_module_list returns only loaded objects. + * + * Make sure we know of but haven't loaded any products yet + */ + $this->assertEqual( + array( + 0 => 'photocrati-animal', + 1 => 'photocrati-pope' + ), + $this->registry->get_known_product_list(), + 'Only the Pope and Animal-Farm products should be known' + ); + $this->assertEqual( + array(), + $this->registry->get_product_list(), + 'The product list should be empty' + ); + + // make sure we know about but haven't yet loaded any modules + $this->assertEqual( + array( + 0 => 'photocrati-animal', + 1 => 'photocrati-pope' + ), + $this->registry->get_known_module_list(), + 'Only the pope product should be known' + ); + $this->assertEqual( + array(), + $this->registry->get_module_list(), + 'The module should should be empty' + ); + } + + /** + * Tests loading of (product|module)s + */ + public function test_Registry_Load() + { + // test our ability to load & retrieve products + $this->registry->load_product('photocrati-pope'); + $this->assertEqual( + array( + 0 => 'photocrati-pope' + ), + $this->registry->get_product_list(), + 'get_product_list() did not return a correct list (see load_product() / add_product()?)' + ); + + // and then our ability to load & retrieve modules from products + $this->registry->load_module('photocrati-template'); + $this->assertEqual( + array( + 0 => 'photocrati-pope', + 1 => 'photocrati-template' + ), + $this->registry->get_module_list(), + 'get_module_list() did not retrieve a correct list (see load_module() / add_module()?)' + ); + + // make sure we're loading from the correct path + $this->assertEqual( + $this->path . 'photocrati_pope/modules/', + $this->registry->get_product_module_path('photocrati-pope'), + 'get_product_module_path() did not return the correct product-module path' + ); + + // and that the module is also in the right place + $this->assertEqual( + $this->path . 'photocrati_pope/modules/template/module.template.php', + $this->registry->get_module_path('photocrati-template'), + 'get_module_path() did not return the correct module path' + ); + $this->assertEqual( + $this->path . 'photocrati_pope/modules/template', + $this->registry->get_module_dir('photocrati-template'), + 'get_module_dir() did not return the correct module directory' + ); + } + + /** + * Tests retrieval of product metadata + */ + public function test_Registry_Get_Product() + { + // do we have the right product? + $obj = $this->registry->get_product('photocrati-pope'); + $this->assertEqual( + 'P_Photocrati_Pope', + get_class($obj), + 'get_product() did not return a P_Photocrati_Pope object (check add_product())' + ); + $this->assertEqual( + 'photocrati-pope', + $this->registry->get_product_meta('photocrati-pope', 'id'), + 'get_product_meta() did not return the correct product ID meta-information' + ); + $this->assertEqual( + array( + 'type' => 'product', + 'id' => 'photocrati-pope', + 'path' => $this->path . 'photocrati_pope/product.photocrati_pope.php', + 'product-module-path' => $this->path . 'photocrati_pope/modules/'), + $this->registry->get_product_meta_list('photocrati-pope'), + 'get_product_meta_list() did not return the correct product meta-information' + ); + } + + /** + * Tests retrieval of module metadata + */ + public function test_Registry_Get_Module() + { + // do we have the right module? + $obj = $this->registry->get_module('photocrati-template'); + $this->assertEqual( + 'M_Template', + get_class($obj), + 'get_module did not return a M_Template object' + ); + $this->assertEqual( + 'photocrati-template', + $this->registry->get_module_meta('photocrati-template', 'id'), + 'get_module_meta() did not return the correct module ID meta-information' + ); + $this->assertEqual( + array( + 'type' => 'module', + 'id' => 'photocrati-template', + 'path' => $this->path . 'photocrati_pope/modules/template/module.template.php'), + $this->registry->get_module_meta_list('photocrati-template'), + 'get_module_meta_list did not return the correct module meta-information' + ); + } + + /** + * Tests module initialization + */ + public function test_Registry_Initialization() + { + $obj = $this->registry->get_module('photocrati-template'); + + // we're looking at the correct product and module, let's initialize() it + $this->assertEqual( + False, + (isset($obj->is_initialized) && True == $obj->is_initialized), + 'Module was initialized prematurely' + ); + + $this->registry->initialize_module('photocrati-template'); + + $this->assertEqual( + True, + (isset($obj->is_initialized) && True == $obj->is_initialized), + 'initialize_module() did not run correctly' + ); + } + + /** + * Tests get_utility and factory creation + */ + public function test_Registry_Get_Utility() + { + /* + * We must again retrieve the factory class after having loaded our products & module. + */ + $factory = $this->registry->get_utility('I_Component_Factory'); + try + { + $obj = $factory->create('photocrati_template', 'Normal'); + } catch (Exception $exception) { } + $this->assertEqual( + 'C_Template_Library', + (isset($obj) && get_class($obj)), + 'create() did not return a C_Template_Library object' + ); + } + + /** + * Some sanity checks + */ + public function test_Registry_Paranoid_Check() + { + // Just to be paranoid we check to make sure we still have ONLY loaded the Pope product / Template module + $this->assertEqual( + array( + 0 => 'photocrati-pope' + ), + $this->registry->get_product_list(), + 'A product was loaded that should not have been' + ); + $this->assertEqual( + array( + 0 => 'photocrati-pope', + 1 => 'photocrati-template' + ), + $this->registry->get_module_list(), + 'A module was loaded that should not have been' + ); + } + + /** + * Tests loading of all remaining modules + */ + public function test_Registry_Load_All() + { + // load the remaining (Animal/AnimalFarm) products & modules + $this->registry->load_all_products(); + $this->registry->load_all_modules(); + + $this->assertEqual( + array( + 0 => 'photocrati-pope', + 1 => 'photocrati-animal' + ), + $this->registry->get_product_list(), + 'load_all_products() did not run correctly (Animal product was not loaded)' + ); + $this->assertEqual( + array( + 0 => 'photocrati-pope', + 1 => 'photocrati-template', + 2 => 'photocrati-animal', + 3 => 'photocrati-animal-farm' + ), + $this->registry->get_module_list(), + 'load_all_modules() did not run correctly (The Animal Farm module was not loaded)' + ); + + $obj = $this->registry->get_module('photocrati-animal-farm'); + $this->assertEqual( + False, + (isset($obj->is_initialized) && True == $obj->is_initialized), + 'Module was initialized prematurely' + ); + + $this->registry->initialize_all_modules(); + + $obj = $this->registry->get_module('photocrati-animal-farm'); + $this->assertEqual( + True, + (isset($obj->is_initialized) && True == $obj->is_initialized), + 'initialize_all_modules() did not run correctly (Animal Farm module was not initialized)' + ); + } + + /** + * Tests SPL autoloader + */ + public function test_Registry_Autoload() + { + /* + * The C_Animal_Empty class exists but is never referenced elsewhere in the code. We call class_exists() + * on it here to trigger the autoload() function which should have been automatically registered with the SPL. + */ + $this->assertEqual( + True, + class_exists('C_Animal_Empty'), + 'C_Animal_Empty was not found by autoload()' + ); + } + + /** + * Tests registry (add|del)_(module|product) functions + */ + public function test_Registry_CD() + { + $tmp = new C_Test_Autoload(); + + /* + * We add our empty module created above and dynamically add it to to our registry + */ + $this->assertEqual( + True, + in_array('C_Test_Autoload', $this->registry->get_module_list()), + 'add_module() did not run correctly for C_Test_Autoload' + ); + + /* + * We remove it just as easily + */ + $this->registry->del_module('C_Test_Autoload'); + $this->assertEqual( + False, + in_array('C_Test_Autoload', $this->registry->get_module_list()), + 'del_module() did not remove C_Test_Autoload from get_module_list()' + ); + + /* + * We can also instantiate our products manually and then pass them to Pope + */ + $this->registry->add_product('photocrati-empty', new P_Photocrati_Empty()); + + $this->assertEqual( + True, + in_array('photocrati-empty', $this->registry->get_product_list()), + 'add_product() did not add to the get_product_list() results' + ); + + $this->registry->del_product('photocrati-empty'); + + $this->assertEqual( + False, + in_array('photocrati-empty', $this->registry->get_product_list()), + 'del_product() did not remove from the get_product_list() results' + ); + } +} diff --git a/wp-content/plugins/nextgen-gallery/pope/tests/wrappers.php b/wp-content/plugins/nextgen-gallery/pope/tests/wrappers.php new file mode 100644 index 0000000000000000000000000000000000000000..a274a054864e47f75f33e2d6e2f34f3ea076539f --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/pope/tests/wrappers.php @@ -0,0 +1,106 @@ +<?php + +/* + * Pope will let us extend it's reach to classes we normally wouldn't be able to. In this case we've created a shell + * called "ThirdPartyLibrary". We're going to extend it to add our own functions; in this case we'll pretend to be + * adding a newsletter on top of a forum library. + */ +class ThirdPartyLibrary +{ + public $forum_setup = False; + + public function setup_forum() + { + $this->forum_setup = True; + } +} + +class Mixin_Third_Party_Lib extends Mixin +{ + function setup_newsletter() + { + $this->object->newsletter_setup = True; + } +} + +/* + * Now that we have our library and our mixin we bring them together. We wrap our mixin to this class and then we wrap + * our class to the third party library. Here we tell wrap() to use the _create_new() function as it returns + * ThirdPartyLibrary instances. + */ +class C_Third_Party_Lib_Wrapper extends ExtensibleObject +{ + public function define() + { + $this->add_mixin('Mixin_Third_Party_Lib'); + $this->wrap('ThirdPartyLibrary', array(&$this, '_create_new')); + } + + function _create_new() + { + return new ThirdPartyLibrary(); + } +} + +class Test_Of_Wrappers extends UnitTestCase +{ + public $str = 'test_string'; + + public function test_Wrappers() + { + $obj = new C_Third_Party_Lib_Wrapper(); + + $obj->setup_forum(); + $obj->setup_newsletter(); + + $this->assertEqual( + True, + $obj->object->forum_setup, + 'The wrapped class forum_setup() did not run' + ); + + $this->assertEqual( + True, + $obj->object->newsletter_setup, + 'The mixin class setup_newsletter() did not run' + ); + + /* + * Sometimes you need to know if you're dealing with a wrapper + */ + $core = new C_Core('test_string'); + $this->assertEqual( + True, + $obj->is_wrapper(), + 'is_wrapper() returned false on a wrapper' + ); + $this->assertEqual( + False, + $core->is_wrapper(), + 'is_wrapper() returned true on a non-wrapper' + ); + + /* + * wrapped_class_provides() lets us determine if the function we are calling is from the original class + * (ThirdPartyLib). + */ + $this->assertEqual( + True, + $obj->wrapped_class_provides('setup_forum'), + 'wrapped_class_provides() did not return True when it should have' + ); + + $this->assertEqual( + False, + $obj->wrapped_class_provides('setup_newsletter'), + 'wrapped_class_provides() did not return False when it should have' + ); + + $this->assertEqual( + False, + $obj->wrapped_class_provides('does_not_exist'), + 'wrapped_class_provides() did not return False on a non-existent method' + ); + } + +} diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ajax/module.ajax.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ajax/module.ajax.php index 05a022b0312ba0abec59de2976c1ef4471240717..2483e2eb9223323fa2757e237e36a5980b53c675 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ajax/module.ajax.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ajax/module.ajax.php @@ -16,7 +16,7 @@ class M_Ajax extends C_Base_Module 'photocrati-ajax', 'AJAX', 'Provides AJAX functionality', - '0.8', + '0.9', 'https://www.imagely.com', 'Photocrati Media', 'https://www.imagely.com' @@ -55,7 +55,8 @@ class M_Ajax extends C_Base_Module if (isset($_REQUEST[NGG_AJAX_SLUG])) { $controller = C_Ajax_Controller::get_instance(); $controller->index_action(); - throw new E_Clean_Exit; + // E_Clean_Exit may cause a warning to be appended to our response, spoiling any JSON sent + exit; } } diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/module.attach_to_post.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/module.attach_to_post.php index 3d5ba1bba32d4248e8872026966c448e9acdce54..bc790396bf800b3274a21f2d92c153f4b0c08347 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/module.attach_to_post.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/module.attach_to_post.php @@ -24,7 +24,7 @@ class M_Attach_To_Post extends C_Base_Module 'photocrati-attach_to_post', 'Attach To Post', 'Provides the "Attach to Post" interface for displaying galleries and albums', - '0.11', + '0.12', 'https://www.imagely.com/wordpress-gallery-plugin/nextgen-gallery/', 'Photocrati Media', 'https://www.imagely.com', @@ -115,6 +115,8 @@ class M_Attach_To_Post extends C_Base_Module add_action('admin_init', array(&$this, 'fix_ie11'), PHP_INT_MAX-1); add_action('admin_enqueue_scripts', array(&$this, 'fix_ie11'), 1); add_action('admin_enqueue_scripts', array(&$this, 'fix_ie11'), PHP_INT_MAX-1); + add_filter('wpseo_pre_analysis_post_content', array(&$this, 'remove_preview_images_from_yoast_opengraph')); + add_filter('wpseo_sitemap_urlimages', array(&$this, 'remove_preview_images_from_yoast_sitemap'), NULL, 2); // Emit frame communication events if ($this->does_request_require_frame_communication()) { @@ -124,7 +126,7 @@ class M_Attach_To_Post extends C_Base_Module add_action('ngg_manage_tags', array(&$this, 'manage_tags_event')); } - // Admin-only hooks + // Admin-only hooks if (is_admin()) { add_action( 'admin_enqueue_scripts', @@ -132,20 +134,79 @@ class M_Attach_To_Post extends C_Base_Module 1 ); - add_action('admin_init', array(&$this, 'route_insert_gallery_window')); + add_action('admin_init', array(&$this, 'route_insert_gallery_window')); // TODO: In 2.0.69, we're going to change the ATP placeholder urls if (FALSE) { - add_filter('the_editor_content', array(&$this, 'fix_preview_images')); + add_filter('the_editor_content', array($this, 'fix_preview_images')); } + + add_action('media_buttons', array($this, 'add_media_button'), 15); + } + // Frontend-only hooks + if (!is_admin()) { + // Add hook to subsitute displayed gallery placeholders + add_filter('the_content', array(&$this, 'substitute_placeholder_imgs'), PHP_INT_MAX, 1); } + } - // Frontend-only hooks - if (!is_admin()) { - // Add hook to subsitute displayed gallery placeholders - add_filter('the_content', array(&$this, 'substitute_placeholder_imgs'), PHP_INT_MAX, 1); - } + /** + * Removes IGW preview/placeholder images from Yoast OpenGraph analysis + * @param $content + * @return mixed + */ + function remove_preview_images_from_yoast_opengraph($content) + { + $content = $this->fix_preview_images($content); + $content = preg_replace('/http(s)?:\/\/(.*?)'.NGG_ATTACH_TO_POST_SLUG.'\/preview\/id--\d+/', "", $content); + $content = preg_replace('/http(s)?:\/\/(.*?)'.NGG_ATTACH_TO_POST_SLUG.'\/preview\/id\/\d+/', "", $content); + return $content; + } + + /** + * Removes IGW preview/placeholder images from Yoast's sitemap + * @param $images + * @param $post_id + * @return array + */ + function remove_preview_images_from_yoast_sitemap($images, $post_id) + { + $retval = array(); + + foreach ($images as $image) { + if (strpos($image['src'], NGG_ATTACH_TO_POST_SLUG) === FALSE) { + $retval[] = $image; + } + else { + // Lookup images for the displayed gallery + if (preg_match('/(\d+)$/', $image['src'], $match)) { + $displayed_gallery_id = $match[1]; + $mapper = C_Displayed_Gallery_Mapper::get_instance(); + $displayed_gallery = $mapper->find($displayed_gallery_id, TRUE); + if ($displayed_gallery) { + $gallery_storage = C_Gallery_Storage::get_instance(); + $settings = C_NextGen_Settings::get_instance(); + $source_obj = $displayed_gallery->get_source(); + if (in_array('image', $source_obj->returns)) { + foreach ($displayed_gallery->get_entities() as $image) { + $named_image_size = $settings->imgAutoResize ? 'full' : 'thumb'; + + $sitemap_image = array( + 'src' => $gallery_storage->get_image_url($image, $named_image_size), + 'alt' => $image->alttext, + 'title' => $image->description ? $image->description: $image->alttext + ); + $retval[] = $sitemap_image; + } + } + } + + } + } + } + + return $retval; } /** @@ -171,11 +232,18 @@ class M_Attach_To_Post extends C_Base_Module return $content; } + + function add_media_button() + { + $router = C_Router::get_instance(); - /** - * Route the IGW requests using wp-admin - * @throws E_Clean_Exit - */ + echo '<a href="#" data-editor="content" class="button ngg-add-gallery" id="ngg-media-button" class="button" onclick="tinymce.EditorManager.execCommand(\'ngg_attach_to_post\'); return false;"><img src="' . $router->get_static_url('photocrati-attach_to_post#atp_button.png') . '" style="padding:0; margin-top:-3px;"> ' . __('Add Gallery', 'nggallery') . '</a>'; + } + + /** + * Route the IGW requests using wp-admin + * @throws E_Clean_Exit + */ function route_insert_gallery_window() { if (isset($_REQUEST[NGG_ATTACH_TO_POST_SLUG])) { diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/package.module.attach_to_post.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/package.module.attach_to_post.php index 0a221bded4c49e74c76620d0f37b85a20a36b7ec..2741a3b257c8a0038f2135c7ffa677bdca94fc78 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/package.module.attach_to_post.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/package.module.attach_to_post.php @@ -145,8 +145,6 @@ class A_Attach_To_Post_Ajax extends Mixin // Get the thumbnail $entity->thumb_url = $storage->get_image_url($image, 'thumb', TRUE); $entity->thumb_html = $storage->get_image_html($image, 'thumb'); - $entity->max_width = $settings->thumbwidth; - $entity->max_height = $settings->thumbheight; } } else { $response['error'] = __('Missing parameters', 'nggallery'); @@ -223,7 +221,7 @@ class C_Attach_Controller extends C_NextGen_Admin_Page_Controller } return self::$_instances[$context]; } - public function define($context) + public function define($context = FALSE) { if (!is_array($context)) { $context = array($context); @@ -316,6 +314,7 @@ class Mixin_Attach_To_Post extends Mixin $this->object->mark_script('jquery-ui-sortable'); $this->object->mark_script('jquery-ui-tooltip'); $this->object->mark_script('ngg_tabs'); + wp_enqueue_style('buttons'); // Ensure select2 wp_enqueue_style('ngg_select2'); wp_enqueue_script('ngg_select2'); @@ -372,7 +371,8 @@ class Mixin_Attach_To_Post extends Mixin $image_mapper = C_Image_Mapper::get_instance(); // Get the first entity from the displayed gallery. We will use this // for a preview pic - $entity = array_pop($this->object->_displayed_gallery->get_included_entities(1)); + $results = $this->object->_displayed_gallery->get_included_entities(1); + $entity = array_pop($results); $image = FALSE; if ($entity) { // This is an album or gallery @@ -389,8 +389,10 @@ class Mixin_Attach_To_Post extends Mixin } } // Were we able to find a preview pic? If so, then render it - $image_size = $dyn_thumbs->get_size_name(array('width' => 200, 'height' => 200, 'quality' => 90, 'type' => 'jpg')); + $image_size = $dyn_thumbs->get_size_name(array('width' => 300, 'height' => 200, 'quality' => 90, 'type' => 'jpg', 'watermark' => FALSE, 'crop' => TRUE)); + add_filter('ngg_before_save_thumbnail', array(&$this, 'set_igw_placeholder_text')); $found_preview_pic = $storage->render_image($image, $image_size, TRUE); + remove_filter('ngg_before_save_thumbnail', array(&$this, 'set_igw_placeholder_text')); // Render invalid image if no preview pic is found if (!$found_preview_pic) { $filename = $this->object->get_static_abspath('photocrati-attach_to_post#invalid_image.png'); @@ -399,6 +401,27 @@ class Mixin_Attach_To_Post extends Mixin $this->render(); } } + /** + * Filter for ngg_before_save_thumbnail + */ + public function set_igw_placeholder_text($thumbnail) + { + $settings = C_NextGen_Settings::get_instance(); + $thumbnail->applyFilter(IMG_FILTER_BRIGHTNESS, -25); + $watermark_settings = apply_filters('ngg_igw_placeholder_line_1_settings', array('text' => __('NextGEN Gallery', 'nggallery'), 'font_color' => 'ffffff', 'font' => 'YanoneKaffeesatz-Bold.ttf', 'font_size' => 32)); + if ($watermark_settings) { + $thumbnail->watermarkText = $watermark_settings['text']; + $thumbnail->watermarkCreateText($watermark_settings['font_color'], $watermark_settings['font'], $watermark_settings['font_size'], 100); + $thumbnail->watermarkImage('topCenter', 0, 72); + } + $watermark_settings = apply_filters('ngg_igw_placeholder_line_2_settings', array('text' => __('Click to edit', 'nggallery'), 'font_color' => 'ffffff', 'font' => 'YanoneKaffeesatz-Bold.ttf', 'font_size' => 15)); + if ($watermark_settings) { + $thumbnail->watermarkText = $watermark_settings['text']; + $thumbnail->watermarkCreateText($watermark_settings['font_color'], $watermark_settings['font'], $watermark_settings['font_size'], 100); + $thumbnail->watermarkImage('topCenter', 0, 108); + } + return $thumbnail; + } /** * Returns the page title of the Attach to Post interface * @return string @@ -455,7 +478,7 @@ class Mixin_Attach_To_Post extends Mixin */ public function _render_display_tab() { - return $this->object->render_partial('photocrati-attach_to_post#display_tab', array('messages' => array(), 'tabs' => $this->object->_get_display_tabs()), TRUE); + return $this->object->render_partial('photocrati-attach_to_post#display_tab', array('messages' => array(), 'displayed_gallery' => $this->object->_displayed_gallery, 'tabs' => $this->object->_get_display_tabs()), TRUE); } /** * Renders the tab used primarily for Gallery and Image creation diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/static/attach_to_post.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/static/attach_to_post.css index 9dc74e6f0cbf1930d8885682486a5632d37e343f..d9b02dbb79f1daf0401f0862571b1351d2c3b814 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/static/attach_to_post.css +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/static/attach_to_post.css @@ -98,6 +98,10 @@ iframe { } /** Display Tab **/ +#preview_tab_content { + padding: 0.8em 1em; +} + #preview_tab_content .previewed_entity { width: 100%; border-bottom: solid 1px #E0E0D6; @@ -139,19 +143,27 @@ iframe { float: left; } -#preview_tab_content .image_container { +#preview_tab_content .preview_item { background-color: white; - background-repeat: no-repeat; - background-position: center center; - padding: 19px; - margin: 7px; - border: solid 1px black; + width: 100px; + padding: 6px 6px 1.4em 6px; + margin: 4px; + border: solid 1px #333; display: block; vertical-align: middle; text-align: center; position: relative; } +#preview_tab_content .image_container { + background-repeat: no-repeat; + background-position: center; + background-size: cover; + display: block; + width: 100%; + height: 75px; +} + #preview_tab_content .image_container img { border: 0px; } @@ -171,17 +183,27 @@ iframe { } #preview_tab_content #entity_list .exclude_container { + background: white; display: block; text-align: center; margin: 0 auto; color: black; font-weight: normal; + height: 1.4em; + line-height: 1.1em; + font-size: 0.8em; position: absolute; - bottom: 2px; + bottom: 0.2em; left: 0px; width: 100%; } +#preview_tab_content #entity_list .exclude_container input { + vertical-align: middle; + line-height: 1.2em; + margin: 0 0.5em; +} + #preview_tab_content .header_row { margin-bottom: 5px; } diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/static/attach_to_post.min.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/static/attach_to_post.min.css index 57597ea332e0404a9a2a0f4e92fca56ccf3c6671..aa67d174432a52eeea8e35909f16323938201f21 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/static/attach_to_post.min.css +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/static/attach_to_post.min.css @@ -1 +1 @@ -html,body{width:100%;min-height:100%;padding:0;margin:0;font-size:13px}body{position:absolute;visibility:hidden;-ms-filter:"alpha(opacity=0)";filter:alpha(opacity=0);opacity:0;height:100%}.entity_errors{color:red}.entity_errors ul{margin-left:30px}.entity_errors ul li{list-style-type:disc}.ui-helper-reset{font-size:13px}#attach_to_post_tabs{border:0;background:none;min-height:100%;overflow:hidden}#attach_to_post_tabs div.main_menu_tab{overflow:hidden}.ui-tabs-panel{min-height:100%}.ui-widget-header{border:0;border-bottom:1px solid #dfdfdf;background:none}iframe{width:100%;min-height:100%;border:0;padding:0;margin:0;background:transparent}#displayed_gallery_source{width:400px}#source_configuration td{vertical-align:top}#source_configuration .chzn-choices input[type=text]{height:auto !important}#slug_configuration #slug_label{width:52px}#slug_configuration #slug_column input[type=text]{width:498px}.display_type_preview{float:left;width:25%}.display_type_preview .image_container{width:100%;vertical-align:middle;text-align:center;font-size:12px;font-weight:600}.display_type_preview .image_container p{display:inline-block}#preview_tab_content .previewed_entity{width:100%;border-bottom:solid 1px #e0e0d6;background-color:#fafaf0}#preview_tab_content .previewed_entity .container{padding-top:15px}#preview_tab_content .previewed_entity.header{background-color:#f0f0e6;padding-bottom:5px;padding-top:5px}#preview_tab_content .header label{font-size:12px;color:#649664;font-weight:600}#preview_tab_content .ui-sortable-helper{background:none}#preview_tab_content ul{list-style-type:none;display:block;border:solid 2px #e0e0d6;padding:0;position:relative}#preview_tab_content .inclusion_checkbox{margin-right:7px;display:block;float:left}#preview_tab_content .image_container{background-color:white;background-repeat:no-repeat;background-position:center center;padding:19px;margin:7px;border:solid 1px black;display:block;vertical-align:middle;text-align:center;position:relative}#preview_tab_content .image_container img{border:0}#preview_tab_content #entity_list li{float:left}#preview_tab_content #entity_list .ui-state-default{background:none;border:0}#preview_tab_content .placeholder{background-color:#e0ddc1;position:relative}#preview_tab_content #entity_list .exclude_container{display:block;text-align:center;margin:0 auto;color:black;font-weight:normal;position:absolute;bottom:2px;left:0;width:100%}#preview_tab_content .header_row{margin-bottom:5px}#preview_tab_content .header_row strong{width:70px;display:inline-block}#preview_tab_content .header_row .separator{display:inline-block;margin:0 5px}#preview_tab_content .header_row .selected{font-weight:bold}#preview_tab_content #entity_list li.clear{float:none;clear:both}.clear{clear:both;float:none}table{font-size:13px}#display_settings_form table tr td:first-child{vertical-align:top;text-align:right;padding-right:7px;width:180px}#display_settings_form table td{text-align:left}#display_settings_form table textarea{height:60px}#display_settings_form textarea,#display_settings_form input[type=text],#display_settings_form input[type=number],#display_settings_form select{width:157px}#display_settings_form .ngg_slideshow_gallery_width,#display_settings_form .ngg_slideshow_gallery_height,#display_settings_form .ngg_thumbnail_dimension_width,#display_settings_form .ngg_thumbnail_dimension_height{width:65px !important}#display_settings_form .nextgen_settings_colorpicker{width:85px !important;text-align:center}.ui-tabs{visibility:visible;position:relative}.ui-tabs .ui-tabs-hide{display:block !important;visibility:hidden;position:absolute;top:-5000px}.ui-tabs .main_menu_tab{overflow:visible}.ui-tabs .ui-tabs-nav li.ui-tabs-active a,.ui-tabs .ui-tabs-nav li.ui-state-disabled a,.ui-tabs .ui-tabs-nav li.ui-tabs-loading a{cursor:pointer}.select2-result-label{white-space:nowrap}.select2-results{font-family:'segoe ui',Arial,sans-serif;font-size:13px}.refresh_button{float:right} \ No newline at end of file +html,body{width:100%;min-height:100%;padding:0;margin:0;font-size:13px}body{position:absolute;visibility:hidden;-ms-filter:"alpha(opacity=0)";filter:alpha(opacity=0);opacity:0;height:100%}.entity_errors{color:red}.entity_errors ul{margin-left:30px}.entity_errors ul li{list-style-type:disc}.ui-helper-reset{font-size:13px}#attach_to_post_tabs{border:0;background:none;min-height:100%;overflow:hidden}#attach_to_post_tabs div.main_menu_tab{overflow:hidden}.ui-tabs-panel{min-height:100%}.ui-widget-header{border:0;border-bottom:1px solid #dfdfdf;background:none}iframe{width:100%;min-height:100%;border:0;padding:0;margin:0;background:transparent}#displayed_gallery_source{width:400px}#source_configuration td{vertical-align:top}#source_configuration .chzn-choices input[type=text]{height:auto !important}#slug_configuration #slug_label{width:52px}#slug_configuration #slug_column input[type=text]{width:498px}.display_type_preview{float:left;width:25%}.display_type_preview .image_container{width:100%;vertical-align:middle;text-align:center;font-size:12px;font-weight:600}.display_type_preview .image_container p{display:inline-block}#preview_tab_content{padding:.8em 1em}#preview_tab_content .previewed_entity{width:100%;border-bottom:solid 1px #e0e0d6;background-color:#fafaf0}#preview_tab_content .previewed_entity .container{padding-top:15px}#preview_tab_content .previewed_entity.header{background-color:#f0f0e6;padding-bottom:5px;padding-top:5px}#preview_tab_content .header label{font-size:12px;color:#649664;font-weight:600}#preview_tab_content .ui-sortable-helper{background:none}#preview_tab_content ul{list-style-type:none;display:block;border:solid 2px #e0e0d6;padding:0;position:relative}#preview_tab_content .inclusion_checkbox{margin-right:7px;display:block;float:left}#preview_tab_content .preview_item{background-color:white;width:100px;padding:6px 6px 1.4em 6px;margin:4px;border:solid 1px #333;display:block;vertical-align:middle;text-align:center;position:relative}#preview_tab_content .image_container{background-repeat:no-repeat;background-position:center;background-size:cover;display:block;width:100%;height:75px}#preview_tab_content .image_container img{border:0}#preview_tab_content #entity_list li{float:left}#preview_tab_content #entity_list .ui-state-default{background:none;border:0}#preview_tab_content .placeholder{background-color:#e0ddc1;position:relative}#preview_tab_content #entity_list .exclude_container{background:white;display:block;text-align:center;margin:0 auto;color:black;font-weight:normal;height:1.4em;line-height:1.1em;font-size:.8em;position:absolute;bottom:.2em;left:0;width:100%}#preview_tab_content #entity_list .exclude_container input{vertical-align:middle;line-height:1.2em;margin:0 .5em}#preview_tab_content .header_row{margin-bottom:5px}#preview_tab_content .header_row strong{width:70px;display:inline-block}#preview_tab_content .header_row .separator{display:inline-block;margin:0 5px}#preview_tab_content .header_row .selected{font-weight:bold}#preview_tab_content #entity_list li.clear{float:none;clear:both}.clear{clear:both;float:none}table{font-size:13px}#display_settings_form table tr td:first-child{vertical-align:top;text-align:right;padding-right:7px;width:180px}#display_settings_form table td{text-align:left}#display_settings_form table textarea{height:60px}#display_settings_form textarea,#display_settings_form input[type=text],#display_settings_form input[type=number],#display_settings_form select{width:157px}#display_settings_form .ngg_slideshow_gallery_width,#display_settings_form .ngg_slideshow_gallery_height,#display_settings_form .ngg_thumbnail_dimension_width,#display_settings_form .ngg_thumbnail_dimension_height{width:65px !important}#display_settings_form .nextgen_settings_colorpicker{width:85px !important;text-align:center}.ui-tabs{visibility:visible;position:relative}.ui-tabs .ui-tabs-hide{display:block !important;visibility:hidden;position:absolute;top:-5000px}.ui-tabs .main_menu_tab{overflow:visible}.ui-tabs .ui-tabs-nav li.ui-tabs-active a,.ui-tabs .ui-tabs-nav li.ui-state-disabled a,.ui-tabs .ui-tabs-nav li.ui-tabs-loading a{cursor:pointer}.select2-result-label{white-space:nowrap}.select2-results{font-family:'segoe ui',Arial,sans-serif;font-size:13px}.refresh_button{float:right} \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/static/attach_to_post_dialog.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/static/attach_to_post_dialog.css index 5053082cc188fa84c5b3a6006bf31f10be7fe1ef..5751e08005569ffd3ae669a6dcbecf0d94d5e6c2 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/static/attach_to_post_dialog.css +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/static/attach_to_post_dialog.css @@ -61,3 +61,8 @@ background: rgba(255, 255, 255, 0.6); border-top: none; } + +/** "Add Gallery" button */ +#ngg-media-button { + display: none; +} diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/static/attach_to_post_dialog.min.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/static/attach_to_post_dialog.min.css index 381d62ec54f8c7796060e381d8f545b47659d47f..be24ca4dcca60c1f01ac2e51cab5371e711feb72 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/static/attach_to_post_dialog.min.css +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/static/attach_to_post_dialog.min.css @@ -1 +1 @@ -#ngg_attach_to_post_dialog-title{display:none}#ngg_attach_to_post_dialog-head{min-height:0;height:0}#ngg_attach_to_post_dialog-head .mce-close{position:absolute;top:6px !important;right:20px !important;z-index:2}.ngg_attach_to_post_window{position:relative;border:0 !important}.ngg_attach_to_post_window .mceResize,.ngg_attach_to_post_window .mceTop,.ngg_attach_to_post_window .mceBottom,.ngg_attach_to_post_window .mceLeft,.ngg_attach_to_post_window .mceRight,.ngg_attach_to_post_window .mceCenter{background:transparent !important;border:0 !important}.ngg_attach_to_post_window .mceMiddle span{padding-top:6px !important}.ngg_attach_to_post_window .mceTop{display:block !important;height:0 !important;font-size:0 !important}.ngg_attach_to_post_window .mceClose{background:url('uploader-icons.png') !important;display:block !important;margin:0 !important;padding:0 !important;width:15px !important;height:15px !important;background-position:-100px 0 !important;position:absolute !important;top:44px !important;right:30px !important}#ngg_attach_to_post_dialog-body{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;background:rgba(255,255,255,.6);border-top:0} \ No newline at end of file +#ngg_attach_to_post_dialog-title{display:none}#ngg_attach_to_post_dialog-head{min-height:0;height:0}#ngg_attach_to_post_dialog-head .mce-close{position:absolute;top:6px !important;right:20px !important;z-index:2}.ngg_attach_to_post_window{position:relative;border:0 !important}.ngg_attach_to_post_window .mceResize,.ngg_attach_to_post_window .mceTop,.ngg_attach_to_post_window .mceBottom,.ngg_attach_to_post_window .mceLeft,.ngg_attach_to_post_window .mceRight,.ngg_attach_to_post_window .mceCenter{background:transparent !important;border:0 !important}.ngg_attach_to_post_window .mceMiddle span{padding-top:6px !important}.ngg_attach_to_post_window .mceTop{display:block !important;height:0 !important;font-size:0 !important}.ngg_attach_to_post_window .mceClose{background:url('uploader-icons.png') !important;display:block !important;margin:0 !important;padding:0 !important;width:15px !important;height:15px !important;background-position:-100px 0 !important;position:absolute !important;top:44px !important;right:30px !important}#ngg_attach_to_post_dialog-body{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;background:rgba(255,255,255,.6);border-top:0}#ngg-media-button{display:none} \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/static/ngg_attach_to_post_tinymce_plugin.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/static/ngg_attach_to_post_tinymce_plugin.js index 59048f6c5332c55e848f74b863a4c160fa34d581..91c78da2ba4dd85e11c2b39d8661affd53c5bc38 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/static/ngg_attach_to_post_tinymce_plugin.js +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/static/ngg_attach_to_post_tinymce_plugin.js @@ -141,4 +141,15 @@ // Register plugin tinymce.PluginManager.add('NextGEN_AttachToPost', tinymce.plugins.NextGEN_AttachToPost); + + // Hide this button by default + var $button = jQuery('#ngg-media-button'); + $button.css('display', 'inline-block'); + jQuery('#content-html').on('click', function() { + $button.hide(); + }); + jQuery('#content-tmce').on('click', function() { + $button.css('display', 'inline-block'); + }); + })(photocrati_ajax.wp_site_url); diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/static/ngg_attach_to_post_tinymce_plugin.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/static/ngg_attach_to_post_tinymce_plugin.min.js index 3839b447e22c9568523fd8b7dc94132b6d296b02..f3636933460bd83e8beec7ac7ea048cddbd6e4b2 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/static/ngg_attach_to_post_tinymce_plugin.min.js +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/static/ngg_attach_to_post_tinymce_plugin.min.js @@ -1 +1 @@ -eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('(7(w){1j.4=\'K-1C-1B\';o.1A(\'1y.v\',{m:\'1a F D 1z 1b\'});b.1D(\'b.q.8\',{w:w,1J:7(){n{1I:\'F D\',1H:\'1F\',1G:\'O://Q.N.J\',1x:\'O://Q.N.J/K-L-C/1k-L/\',1p:\'0.1\'}},1q:7(2,X){3 f=u;2.c.13=2.c.E;2.c.E=7(T,11){3 G=2.c.13(T,11);G.V(\'1u\',f.R);n G};2.1r(\'v\',u.H,{2:2,C:2.q.8});2.1s(\'8\',{m:\'v.m\',1L:\'v\',1P:X+\'/22.21\'});2.W.1Z+=",Z";2.W.25="Z";2.V(\'1Y\',7(e){5(e.9.1X==\'1Q\'){5(f.U(e.9).1O(\'1M\')>=0){2.M.1N.1R(e);3 4=e.9.1S.1W(/\\d+$/);5(4)4=4.1V();3 1U=b.1T(f,{2:2,C:2.q.8,4:4});f.H(4)}}})},U:7(t){3 B=t.Y(\'12\')?t.Y(\'12\'):t.1w;5(B){n B}28{n""}},R:7(e){5(e&&e.9&&e.9.14&&e.9.14==\'15\'){a(\'1g,1f\').s(\'r\',\'1e\');o.z.P.S(o.z.M.S(\'p\')[0]);o.z.P.20(0)}},H:7(4){3 I=1n;5(1m(4)!=\'1l\'){I+="&4="+u.4}3 6=1j;1t(6.A!=26&&6.A!=6){6=6.A}6=a(6);3 l=6.16();3 i=6.1i();3 k=27;3 j=1h;3 18=29;3 17=1h;3 g=l-(l*0.19);3 h=i-(i*0.19);5(g<18){g=l-10}5(h<17){h=i-10}5(k>g){k=g}5(j>h){j=h}u.2.c.E({24:I,4:\'15\',16:k,1i:j,m:"F D - 1a 1K 1b"});a(\'1g,1f\').s(\'r\',\'1d\');a(\'#1c\').s(\'r-y\',\'1e\');a(\'#1c\').s(\'r-x\',\'1d\')}});b.1o.1v(\'8\',b.q.8)})(1E.23);',62,134,'||editor|var|id|if|win|function|NextGEN_AttachToPost|target|jQuery|tinymce|windowManager|||self|maxWidth|maxHeight|winHeight|popupHeight|popupWidth|winWidth|title|return|tinyMCE||plugins|overflow|css|node|this|ngg_attach_to_post|siteurl|||activeEditor|parent|class_name|plugin|Gallery|open|NextGEN|modal|render_attach_to_post_interface|attach_to_post_url|com|wordpress|gallery|dom|imagely|https|selection|www|wm_close_event|select|one|get_class_name|on|settings|plugin_url|getAttribute|shortcode||two|class|nggOldOpen|_id|ngg_attach_to_post_dialog|width|minHeight|minWidth|05|Attach|Post|ngg_attach_to_post_dialog_ifr|hidden|auto|body|html|600|height|window|nextgen|undefined|typeof|nextgen_gallery_attach_to_post_url|PluginManager|version|init|addCommand|addButton|while|close|add|className|infourl|en|to|addI18n|page|post|create|photocrati_ajax|Imagely|authorurl|author|longname|getInfo|To|cmd|ngg_displayed_gallery|events|indexOf|image|IMG|cancel|src|extend|obj|pop|match|tagName|mouseup|extended_valid_elements|collapse|png|atp_button|wp_site_url|url|custom_elements|null|1200|else|800'.split('|'),0,{})) +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('(7(F){N.4=\'R-1y-1A\';z.1R(\'1O.s\',{q:\'18 H L 1P 1e\'});h.1Q(\'h.w.9\',{F:F,1K:7(){m{1F:\'H L\',1H:\'1N\',1J:\'V://W.U.T\',1I:\'V://W.U.T/R-S-J/1E-S/\',1B:\'0.1\'}},1u:7(2,15){3 g=r;2.f.X=2.f.E;2.f.E=7(Y,14){3 K=2.f.X(Y,14);K.u(\'1q\',g.16);m K};2.1D(\'s\',r.C,{2:2,J:2.w.9});2.1w(\'9\',{q:\'s.q\',1C:\'s\',1x:15+\'/1G.1Y\'});2.13.2g+=",12";2.13.2e="12";2.u(\'29\',7(e){5(e.a.1S==\'2c\'){5(g.Z(e.a).2h(\'2d\')>=0){2.M.2a.2f(e);3 4=e.a.2j.2i(/\\d+$/);5(4)4=4.27();3 1X=h.28(g,{2:2,J:2.w.9,4:4});g.C(4)}}})},Z:7(l){3 B=l.Q(\'11\')?l.Q(\'11\'):l.1V;5(B){m B}1T{m""}},16:7(e){5(e&&e.a&&e.a.P&&e.a.P==\'1c\'){8(\'I,1f\').b(\'k\',\'1j\');z.A.17.O(z.A.M.O(\'p\')[0]);z.A.17.20(0)}},C:7(4){3 D=25;5(26(4)!=\'24\'){D+="&4="+r.4}3 6=N;21(6.G!=22&&6.G!=6){6=6.G}6=8(6);3 v=6.1d();3 t=6.1a();3 n=2b;3 o=1n;3 1p=23;3 1l=1n;3 j=v-(v*0.1o);3 c=t-(t*0.1o);5(j<1p){j=v-10}5(c<1l){c=t-10}5(n>j){n=j}5(o>c){o=c}r.2.f.E({1U:D,4:\'1c\',1d:n,1a:o,q:"H L - 18 1W 1e"});8(\'I,1f\').b(\'k\',\'1h\');8(\'#1g\').b(\'k-y\',\'1j\');8(\'#1g\').b(\'k-x\',\'1h\')}});h.1z.1r(\'9\',h.w.9);3 $i=8(\'#1s-1t-i\');$i.b(\'19\',\'1m-1b\');8(\'#1i-I\').u(\'1k\',7(){$i.1v()});8(\'#1i-1M\').u(\'1k\',7(){$i.b(\'19\',\'1m-1b\')})})(1L.1Z);',62,144,'||editor|var|id|if|win|function|jQuery|NextGEN_AttachToPost|target|css|maxHeight|||windowManager|self|tinymce|button|maxWidth|overflow|node|return|popupWidth|popupHeight||title|this|ngg_attach_to_post|winHeight|on|winWidth|plugins|||tinyMCE|activeEditor|class_name|render_attach_to_post_interface|attach_to_post_url|open|siteurl|parent|NextGEN|html|plugin|modal|Gallery|dom|window|select|_id|getAttribute|wordpress|gallery|com|imagely|https|www|nggOldOpen|one|get_class_name||class|shortcode|settings|two|plugin_url|wm_close_event|selection|Attach|display|height|block|ngg_attach_to_post_dialog|width|Post|body|ngg_attach_to_post_dialog_ifr|hidden|content|auto|click|minHeight|inline|600|05|minWidth|close|add|ngg|media|init|hide|addButton|image|post|PluginManager|page|version|cmd|addCommand|nextgen|longname|atp_button|author|infourl|authorurl|getInfo|photocrati_ajax|tmce|Imagely|en|to|create|addI18n|tagName|else|url|className|To|obj|png|wp_site_url|collapse|while|null|800|undefined|nextgen_gallery_attach_to_post_url|typeof|pop|extend|mouseup|events|1200|IMG|ngg_displayed_gallery|custom_elements|cancel|extended_valid_elements|indexOf|match|src'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/static/underscore.string.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/static/underscore.string.min.js index d8864bbd1f4485a34c2778b820328ff7feff06e2..2254c3b52c56f3f8c1da905652214067c6c64e8c 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/static/underscore.string.min.js +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/static/underscore.string.min.js @@ -1 +1 @@ -eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('!r(1G,y){\'3A 3I\';E 2h=y.21.1h;E 2v=y.21.3v;E 2g=y.21.3r;E 2j=r(24){l 24*1||0};E 1f=r(h,R){p(R<1)l\'\';E 1m=\'\';2r(R>0){p(R&1)1m+=h;R>>=1,h+=h}l 1m};E K=[].K;E 1D=r(J){p(J==v)l\'\\\\s\';I p(J.24)l J.24;I l\'[\'+C.2J(J)+\']\'};E 1C={3n:\'<\',3K:\'>\',3F:\'"\',3E:"\'",3M:\'&\'};E 2c={};1g(E 2k 2e 1C){2c[1C[2k]]=2k}E P=(r(){r 1T(2D){l 3G.21.1y.1j(2D).K(8,-1).1p()}E 3i=1f;E 11=r(){p(!11.1M.2f(1e[0])){11.1M[1e[0]]=11.3c(1e[0])}l 11.2T.1j(v,11.1M[1e[0]],1e)};11.2T=r(U,1i){E 25=1,2Y=U.t,23=\'\',D,1N=[],i,k,B,13,27,2d;1g(i=0;i<2Y;i++){23=1T(U[i]);p(23===\'2A\'){1N.1c(U[i])}I p(23===\'1U\'){B=U[i];p(B[2]){D=1i[25];1g(k=0;k<B[2].t;k++){p(!D.2f(B[2][k])){1s T 1w(P(\'[M.P] 3z "%s" 3p 2Q 3x\',B[2][k]))}D=D[B[2][k]]}}I p(B[1]){D=1i[B[1]]}I{D=1i[25++]}p(/[^s]/.2a(B[8])&&(1T(D)!=\'1a\')){1s T 1w(P(\'[M.P] 3q 1a 3j 3l %s\',1T(D)))}3f(B[8]){N\'b\':D=D.1y(2);V;N\'c\':D=y.1V(D);V;N\'d\':D=2L(D,10);V;N\'e\':D=B[7]?D.31(B[7]):D.31();V;N\'f\':D=B[7]?30(D).28(B[7]):30(D);V;N\'o\':D=D.1y(8);V;N\'s\':D=((D=y(D))&&B[7]?D.2s(0,B[7]):D);V;N\'u\':D=20.3L(D);V;N\'x\':D=D.1y(16);V;N\'X\':D=D.1y(16).1d();V}D=(/[3t]/.2a(B[8])&&B[3]&&D>=0?\'+\'+D:D);27=B[4]?B[4]==\'0\'?\'0\':B[4].1r(1):\' \';2d=B[6]-y(D).t;13=B[6]?3i(27,2d):\'\';1N.1c(B[5]?D+13:13+D)}}l 1N.17(\'\')};11.1M={};11.3c=r(1S){E 1l=1S,B=[],U=[],1P=0;2r(1l){p((B=/^[^\\2b]+/.1v(1l))!==v){U.1c(B[0])}I p((B=/^\\2b{2}/.1v(1l))!==v){U.1c(\'%\')}I p((B=/^\\2b(?:([1-9]\\d*)\\$|\\(([^\\)]+)\\))?(\\+)?(0|\'[^$])?(-)?(\\d+)?(?:\\.(\\d+))?([b-3N])/.1v(1l))!==v){p(B[2]){1P|=1;E 1I=[],1u=B[2],14=[];p((14=/^([a-1Q][a-1Q\\d]*)/i.1v(1u))!==v){1I.1c(14[1]);2r((1u=1u.2s(14[0].t))!==\'\'){p((14=/^\\.([a-1Q][a-1Q\\d]*)/i.1v(1u))!==v){1I.1c(14[1])}I p((14=/^\\[(\\d+)\\]/.1v(1u))!==v){1I.1c(14[1])}I{1s T 1w(\'[M.P] 2B?\')}}}I{1s T 1w(\'[M.P] 2B?\')}B[2]=1I}I{1P|=2}p(1P===3){1s T 1w(\'[M.P] 3k 3m 37 3H 3J 3B 2Q (3D) 3C\')}U.1c(B)}I{1s T 1w(\'[M.P] 2B?\')}1l=1l.2s(B[0].t)}l U};l 11})();E C={3o:\'2.3.0\',3e:r(h){p(h==v)h=\'\';l(/^\\s*$/).2a(h)},3w:r(h){p(h==v)l\'\';l y(h).H(/<\\/?[^>]+>/g,\'\')},2G:r(h){h=h==v?\'\':y(h);l h.1r(0).1d()+h.K(1)},3u:r(h,1B){p(h==v)l[];h=y(h);1B=~~1B;l 1B>0?h.B(T 1A(\'.{1,\'+1B+\'}\',\'g\')):[h]},3s:r(h){l C.2M(h).H(/\\s+/g,\' \')},3y:r(h,1k){p(h==v||1k==v)l 0;l y(h).1E(1k).t-1},2y:r(h){p(h==v)l[];l y(h).1E(\'\')},49:r(h){p(h==v)l\'\';l y(h).H(/\\S/g,r(c){l c===c.1d()?c.1p():c.1d()})},4j:r(h){p(h==v)l\'\';l y(h).H(/[&<>"\']/g,r(m){l\'&\'+2c[m]+\';\'})},4l:r(h){p(h==v)l\'\';l y(h).H(/\\&([^;]+);/g,r(2K,1H){E B;p(1H 2e 1C){l 1C[1H]}I p(B=1H.B(/^#x([\\4i-4h-F]+)$/)){l y.1V(2L(B[1],16))}I p(B=1H.B(/^#(\\d+)$/)){l y.1V(~~B[1])}I{l 2K}})},2J:r(h){p(h==v)l\'\';l y(h).H(/([.*+?^=!:${}()|[\\]\\/\\\\])/g,\'\\\\$1\')},2w:r(h,i,2H,1k){E 2p=C.2y(h);2p.2w(~~i,~~2H,1k);l 2p.17(\'\')},4f:r(h,i,1k){l C.2w(h,i,0,1k)},2n:r(h,2x){p(2x===\'\')l 1L;p(h==v)l 2m;l y(h).22(2x)!==-1},17:r(){E 1n=K.1j(1e),O=1n.4g();p(O==v)O=\'\';l 1n.17(O)},4n:r(h){p(h==v)l[];l y(h).1E("\\n")},29:r(h){l C.2y(h).29().17(\'\')},4v:r(h,1b){p(1b===\'\')l 1L;p(h==v||1b==v)l 2m;h=y(h);1b=y(1b);l h.t>=1b.t&&h.K(0,1b.t)===1b},4x:r(h,18){p(18===\'\')l 1L;p(h==v||18==v)l 2m;h=y(h);18=y(18);l h.t>=18.t&&h.K(h.t-18.t)===18},4w:r(h){p(h==v)l\'\';h=y(h);l h.K(0,-1)+y.1V(h.4y(h.t-1)+1)},2P:r(h){p(h==v)l\'\';l y(h).H(/(?:^|\\s)\\S/g,r(c){l c.1d()})},4u:r(h){l C.1h(h).H(/[-M\\s]+(.)?/g,r(B,c){l c.1d()})},2S:r(h){l C.1h(h).H(/([a-z\\d])([A-Z]+)/g,\'$4p$2\').H(/[-\\s]+/g,\'M\').1p()},2U:r(h){l C.1h(h).H(/([A-Z])/g,\'-$1\').H(/[-M\\s]+/g,\'-\').1p()},4r:r(h){l C.2P(y(h).H(/M/g,\' \')).H(/\\s/g,\'\')},4s:r(h){l C.2G(C.2S(h).H(/4b$/,\'\').H(/M/g,\' \'))},1h:r(h,J){p(h==v)l\'\';p(!J&&2h)l 2h.1j(h);J=1D(J);l y(h).H(T 1A(\'\\^\'+J+\'+|\'+J+\'+$\',\'g\'),\'\')},2I:r(h,J){p(h==v)l\'\';p(!J&&2g)l 2g.1j(h);J=1D(J);l y(h).H(T 1A(\'^\'+J+\'+\'),\'\')},1Y:r(h,J){p(h==v)l\'\';p(!J&&2v)l 2v.1j(h);J=1D(J);l y(h).H(T 1A(J+\'+$\'),\'\')},4c:r(h,t,1K){p(h==v)l\'\';h=y(h);1K=1K||\'...\';t=~~t;l h.t>t?h.K(0,t)+1K:h},3V:r(h,t,1q){p(h==v)l\'\';h=y(h);t=~~t;1q=1q!=v?y(1q):\'...\';p(h.t<=t)l h;E 2E=r(c){l c.1d()!==c.1p()?\'A\':\' \'},Y=h.K(0,t+1).H(/.(?=\\W*\\w*$)/g,2E);p(Y.K(Y.t-2).B(/\\w\\w/))Y=Y.H(/\\s*\\S+$/,\'\');I Y=C.1Y(Y.K(0,Y.t-1));l(Y+1q).t>h.t?h:h.K(0,Y.t)+1q},3O:r(h,2o){p(C.3e(h))l[];l C.1h(h,2o).1E(2o||/\\s+/)},13:r(h,t,L,3d){h=h==v?\'\':y(h);t=~~t;E 12=0;p(!L)L=\' \';I p(L.t>1)L=L.1r(0);3f(3d){N\'3a\':12=t-h.t;l h+1f(L,12);N\'3b\':12=t-h.t;l 1f(L,20.3Y(12/2))+h+1f(L,20.3P(12/2));3Q:12=t-h.t;l 1f(L,12)+h}},2R:r(h,t,L){l C.13(h,t,L)},39:r(h,t,L){l C.13(h,t,L,\'3a\')},2O:r(h,t,L){l C.13(h,t,L,\'3b\')},P:P,3R:r(1S,1i){1i.3S(1S);l P.2X(v,1i)},3Z:r(h,1R){p(h==v||h==\'\')l 0;h=y(h);E 26=2j(2j(h).28(~~1R));l 26===0&&!h.B(/^0+$/)?40.47:26},48:r(1a,38,2Z,1O){p(45(1a)||1a==v)l\'\';1a=1a.28(~~38);1O=1O||\',\';E 1W=1a.1E(\'.\'),2W=1W[0],1R=1W[1]?(2Z||\'.\')+1W[1]:\'\';l 2W.H(/(\\d)(?=(?:\\d{3})+$)/g,\'$1\'+1O)+1R},42:r(h,G){p(h==v)l\'\';h=y(h);G=G!=v?y(G):G;E Q=!G?-1:h.22(G);l~Q?h.K(Q+G.t,h.t):h},44:r(h,G){p(h==v)l\'\';h=y(h);G=G!=v?y(G):G;E Q=!G?-1:h.36(G);l~Q?h.K(Q+G.t,h.t):h},41:r(h,G){p(h==v)l\'\';h=y(h);G=G!=v?y(G):G;E Q=!G?-1:h.22(G);l~Q?h.K(0,Q):h},3U:r(h,G){p(h==v)l\'\';h+=\'\';G=G!=v?\'\'+G:G;E Q=h.36(G);l~Q?h.K(0,Q):h},33:r(1U,O,1o,34){O=O||\', \';1o=1o||\' 37 \';E a=1U.K(),2t=a.2N();p(1U.t>2&&34)1o=C.1Y(O)+1o;l a.t?a.17(O)+1o+2t:2t},4d:r(){E 1n=K.1j(1e);1n[3]=1L;l C.33.2X(C,1n)},3X:r(h){p(h==v)l\'\';E 2u="ąà áäâãåæćęèéëêìÃïîłńòóöôõøùúüûñçżź",35="43",32=T 1A(1D(2u),\'g\');h=y(h).1p().H(32,r(c){E 2V=2u.22(c);l 35.1r(2V)||\'-\'});l C.2U(h.H(/[^\\w\\s-]/g,\'\'))},3g:r(h,2l){l[2l,h,2l].17(\'\')},2C:r(h){l C.3g(h,\'"\')},1x:r(){E 1m={};1g(E 1F 2e 1J){p(!1J.2f(1F)||1F.B(/^(?:2n|2F|29)$/))46;1m[1F]=1J[1F]}l 1m},1Z:r(h,R,O){p(h==v)l\'\';R=~~R;p(O==v)l 1f(y(h),R);1g(E 1Z=[];R>0;1Z[--R]=h){}l 1Z.17(O)},4a:r(15,19){p(15==v&&19==v)l 0;p(15==v)l y(19).t;p(19==v)l y(15).t;15=y(15);19=y(19);E 1t=[],1X,1z;1g(E i=0;i<=19.t;i++)1g(E j=0;j<=15.t;j++){p(i&&j)p(15.1r(j-1)===19.1r(i-1))1z=1X;I 1z=20.3T(1t[j],1t[j-1],1X)+1;I 1z=i+j;1X=1t[j];1t[j]=1z}l 1t.2N()}};C.2M=C.1h;C.3W=C.2I;C.4q=C.1Y;C.4t=C.2O;C.4o=C.2R;C.4e=C.39;C.2F=C.2n;C.q=C.2C;p(2q 1x!==\'3h\'){p(2q 2z!==\'3h\'&&2z.1x){2z.1x=C}1x.C=C}I p(2q 2i===\'r\'&&2i.4m){2i(\'4k.2A\',[],r(){l C})}I{1G.M=1G.M||{};1G.M.2A=1G.M.h=C}}(1J,y);',62,283,'|||||||||||||||||str||||return||||if||function||length||null|||String|||match|_s|arg|var||sep|replace|else|characters|slice|padStr|_|case|separator|sprintf|pos|qty||new|parse_tree|break|||template|||str_format|padlen|pad|field_match|str1||join|ends|str2|number|starts|push|toUpperCase|arguments|strRepeat|for|trim|argv|call|substr|_fmt|result|args|lastSeparator|toLowerCase|pruneStr|charAt|throw|current|replacement_field|exec|Error|exports|toString|value|RegExp|step|escapeChars|defaultToWhiteSpace|split|prop|root|entityCode|field_list|this|truncateStr|true|cache|output|tsep|arg_names|z_|decimals|fmt|get_type|array|fromCharCode|parts|prev|rtrim|repeat|Math|prototype|indexOf|node_type|source|cursor|num|pad_character|toFixed|reverse|test|x25|reversedEscapeChars|pad_length|in|hasOwnProperty|nativeTrimLeft|nativeTrim|define|parseNumber|key|wrapper|false|include|delimiter|arr|typeof|while|substring|lastMember|from|nativeTrimRight|splice|needle|chars|module|string|huh|quote|variable|tmpl|contains|capitalize|howmany|ltrim|escapeRegExp|entity|parseInt|strip|pop|lrpad|titleize|not|lpad|underscored|format|dasherize|index|fnums|apply|tree_length|dsep|parseFloat|toExponential|regex|toSentence|serial|to|lastIndexOf|and|dec|rpad|right|both|parse|type|isBlank|switch|surround|undefined|str_repeat|but|mixing|found|positional|lt|VERSION|does|expecting|trimLeft|clean|def|chop|trimRight|stripTags|exist|count|property|use|is|supported|yet|apos|quot|Object|named|strict|placeholders|gt|abs|amp|fosuxX|words|floor|default|vsprintf|unshift|min|strLeftBack|prune|lstrip|slugify|ceil|toNumber|Number|strLeft|strRight|aaaaaaaaceeeeeiiiilnoooooouuuunczz|strRightBack|isNaN|continue|NaN|numberFormat|swapCase|levenshtein|_id|truncate|toSentenceSerial|ljust|insert|shift|fA|da|escapeHTML|underscore|unescapeHTML|amd|lines|rjust|1_|rstrip|classify|humanize|center|camelize|startsWith|succ|endsWith|charCodeAt'.split('|'),0,{})) +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('!r(1E,y){\'3O 3P\';E 2l=y.1M.1l;E 2d=y.1M.3Q;E 2a=y.1M.3R;E 2e=r(1X){l 1X*1||0};E 1f=r(h,U){p(U<1)l\'\';E 1q=\'\';2f(U>0){p(U&1)1q+=h;U>>=1,h+=h}l 1q};E M=[].M;E 1z=r(K){p(K==v)l\'\\\\s\';L p(K.1X)l K.1X;L l\'[\'+C.2O(K)+\']\'};E 1K={3M:\'<\',3I:\'>\',3J:\'"\',3K:"\'",3L:\'&\'};E 2s={};1g(E 2E 2g 1K){2s[1K[2E]]=2E}E T=(r(){r 1U(2V){l 3T.1M.1L.1j(2V).M(8,-1).1r()}E 2L=1f;E 11=r(){p(!11.1Z.2n(1h[0])){11.1Z[1h[0]]=11.2N(1h[0])}l 11.2T.1j(v,11.1Z[1h[0]],1h)};11.2T=r(12,1i){E 2o=1,2U=12.t,1V=\'\',D,27=[],i,k,B,1b,2z,2u;1g(i=0;i<2U;i++){1V=1U(12[i]);p(1V===\'2p\'){27.14(12[i])}L p(1V===\'1O\'){B=12[i];p(B[2]){D=1i[2o];1g(k=0;k<B[2].t;k++){p(!D.2n(B[2][k])){1w V 1u(T(\'[O.T] 3Z "%s" 3Y 2M 3U\',B[2][k]))}D=D[B[2][k]]}}L p(B[1]){D=1i[B[1]]}L{D=1i[2o++]}p(/[^s]/.2v(B[8])&&(1U(D)!=\'1e\')){1w V 1u(T(\'[O.T] 3W 1e 3H 44 %s\',1U(D)))}2Y(B[8]){P\'b\':D=D.1L(2);Y;P\'c\':D=y.1P(D);Y;P\'d\':D=2K(D,10);Y;P\'e\':D=B[7]?D.2J(B[7]):D.2J();Y;P\'f\':D=B[7]?2I(D).2j(B[7]):2I(D);Y;P\'o\':D=D.1L(8);Y;P\'s\':D=((D=y(D))&&B[7]?D.2t(0,B[7]):D);Y;P\'u\':D=23.3r(D);Y;P\'x\':D=D.1L(16);Y;P\'X\':D=D.1L(16).1k();Y}D=(/[3q]/.2v(B[8])&&B[3]&&D>=0?\'+\'+D:D);2z=B[4]?B[4]==\'0\'?\'0\':B[4].1y(1):\' \';2u=B[6]-y(D).t;1b=B[6]?2L(2z,2u):\'\';27.14(B[5]?D+1b:1b+D)}}l 27.1c(\'\')};11.1Z={};11.2N=r(1R){E 1m=1R,B=[],12=[],24=0;2f(1m){p((B=/^[^\\2C]+/.1p(1m))!==v){12.14(B[0])}L p((B=/^\\2C{2}/.1p(1m))!==v){12.14(\'%\')}L p((B=/^\\2C(?:([1-9]\\d*)\\$|\\(([^\\)]+)\\))?(\\+)?(0|\'[^$])?(-)?(\\d+)?(?:\\.(\\d+))?([b-3n])/.1p(1m))!==v){p(B[2]){24|=1;E 1G=[],1s=B[2],18=[];p((18=/^([a-21][a-21\\d]*)/i.1p(1s))!==v){1G.14(18[1]);2f((1s=1s.2t(18[0].t))!==\'\'){p((18=/^\\.([a-21][a-21\\d]*)/i.1p(1s))!==v){1G.14(18[1])}L p((18=/^\\[(\\d+)\\]/.1p(1s))!==v){1G.14(18[1])}L{1w V 1u(\'[O.T] 2q?\')}}}L{1w V 1u(\'[O.T] 2q?\')}B[2]=1G}L{24|=2}p(24===3){1w V 1u(\'[O.T] 45 3D 35 3E 3F 3B 2M (3w) 3x\')}12.14(B)}L{1w V 1u(\'[O.T] 2q?\')}1m=1m.2t(B[0].t)}l 12};l 11})();E C={4v:\'2.3.0\',2F:r(h){p(h==v)h=\'\';l(/^\\s*$/).2v(h)},4q:r(h){p(h==v)l\'\';l y(h).J(/<\\/?[^>]+>/g,\'\')},2Q:r(h){h=h==v?\'\':y(h);l h.1y(0).1k()+h.M(1)},4r:r(h,1J){p(h==v)l[];h=y(h);1J=~~1J;l 1J>0?h.B(V 1A(\'.{1,\'+1J+\'}\',\'g\')):[h]},4A:r(h){l C.3f(h).J(/\\s+/g,\' \')},4z:r(h,1n){p(h==v||1n==v)l 0;l y(h).1H(1n).t-1},2k:r(h){p(h==v)l[];l y(h).1H(\'\')},4B:r(h){p(h==v)l\'\';l y(h).J(/\\S/g,r(c){l c===c.1k()?c.1r():c.1k()})},4C:r(h){p(h==v)l\'\';l y(h).J(/[&<>"\']/g,r(m){l\'&\'+2s[m]+\';\'})},4p:r(h){p(h==v)l\'\';l y(h).J(/\\&([^;]+);/g,r(2H,1D){E B;p(1D 2g 1K){l 1K[1D]}L p(B=1D.B(/^#x([\\4l-4m-F]+)$/)){l y.1P(2K(B[1],16))}L p(B=1D.B(/^#(\\d+)$/)){l y.1P(~~B[1])}L{l 2H}})},2O:r(h){p(h==v)l\'\';l y(h).J(/([.*+?^=!:${}()|[\\]\\/\\\\])/g,\'\\\\$1\')},2A:r(h,i,2P,1n){E 2y=C.2k(h);2y.2A(~~i,~~2P,1n);l 2y.1c(\'\')},4j:r(h,i,1n){l C.2A(h,i,0,1n)},29:r(h,2B){p(2B===\'\')l 1Y;p(h==v)l 28;l y(h).26(2B)!==-1},1c:r(){E 1t=M.1j(1h),Q=1t.48();p(Q==v)Q=\'\';l 1t.1c(Q)},47:r(h){p(h==v)l[];l y(h).1H("\\n")},2m:r(h){l C.2k(h).2m().1c(\'\')},4a:r(h,1d){p(1d===\'\')l 1Y;p(h==v||1d==v)l 28;h=y(h);1d=y(1d);l h.t>=1d.t&&h.M(0,1d.t)===1d},4c:r(h,19){p(19===\'\')l 1Y;p(h==v||19==v)l 28;h=y(h);19=y(19);l h.t>=19.t&&h.M(h.t-19.t)===19},4o:r(h){p(h==v)l\'\';h=y(h);l h.M(0,-1)+y.1P(h.4t(h.t-1)+1)},2S:r(h){p(h==v)l\'\';l y(h).J(/(?:^|\\s)\\S/g,r(c){l c.1k()})},4D:r(h){l C.1l(h).J(/[-O\\s]+(.)?/g,r(B,c){l c.1k()})},2R:r(h){l C.1l(h).J(/([a-z\\d])([A-Z]+)/g,\'$4F$2\').J(/[-\\s]+/g,\'O\').1r()},36:r(h){l C.1l(h).J(/([A-Z])/g,\'-$1\').J(/[-O\\s]+/g,\'-\').1r()},3v:r(h){l C.2S(y(h).J(/O/g,\' \')).J(/\\s/g,\'\')},4b:r(h){l C.2Q(C.2R(h).J(/4h$/,\'\').J(/O/g,\' \'))},1l:r(h,K){p(h==v)l\'\';p(!K&&2l)l 2l.1j(h);K=1z(K);l y(h).J(V 1A(\'\\^\'+K+\'+|\'+K+\'+$\',\'g\'),\'\')},3g:r(h,K){p(h==v)l\'\';p(!K&&2a)l 2a.1j(h);K=1z(K);l y(h).J(V 1A(\'^\'+K+\'+\'),\'\')},1N:r(h,K){p(h==v)l\'\';p(!K&&2d)l 2d.1j(h);K=1z(K);l y(h).J(V 1A(K+\'+$\'),\'\')},3y:r(h,t,1Q){p(h==v)l\'\';h=y(h);1Q=1Q||\'...\';t=~~t;l h.t>t?h.M(0,t)+1Q:h},3G:r(h,t,1o){p(h==v)l\'\';h=y(h);t=~~t;1o=1o!=v?y(1o):\'...\';p(h.t<=t)l h;E 2G=r(c){l c.1k()!==c.1r()?\'A\':\' \'},13=h.M(0,t+1).J(/.(?=\\W*\\w*$)/g,2G);p(13.M(13.t-2).B(/\\w\\w/))13=13.J(/\\s*\\S+$/,\'\');L 13=C.1N(13.M(0,13.t-1));l(13+1o).t>h.t?h:h.M(0,13.t)+1o},41:r(h,2D){p(C.2F(h))l[];l C.1l(h,2D).1H(2D||/\\s+/)},1b:r(h,t,N,2W){h=h==v?\'\':y(h);t=~~t;E 1a=0;p(!N)N=\' \';L p(N.t>1)N=N.1y(0);2Y(2W){P\'3l\':1a=t-h.t;l h+1f(N,1a);P\'3j\':1a=t-h.t;l 1f(N,23.40(1a/2))+h+1f(N,23.42(1a/2));43:1a=t-h.t;l 1f(N,1a)+h}},3c:r(h,t,N){l C.1b(h,t,N)},38:r(h,t,N){l C.1b(h,t,N,\'3l\')},3d:r(h,t,N){l C.1b(h,t,N,\'3j\')},T:T,3A:r(1R,1i){1i.3z(1R);l T.2X(v,1i)},3X:r(h,1W){p(h==v||h==\'\')l 0;h=y(h);E 2i=2e(2e(h).2j(~~1W));l 2i===0&&!h.B(/^0+$/)?4E.49:2i},4g:r(1e,3k,3h,1T){p(4k(1e)||1e==v)l\'\';1e=1e.2j(~~3k);1T=1T||\',\';E 1S=1e.1H(\'.\'),33=1S[0],1W=1S[1]?(3h||\'.\')+1S[1]:\'\';l 33.J(/(\\d)(?=(?:\\d{3})+$)/g,\'$1\'+1T)+1W},4d:r(h,H){p(h==v)l\'\';h=y(h);H=H!=v?y(H):H;E R=!H?-1:h.26(H);l~R?h.M(R+H.t,h.t):h},46:r(h,H){p(h==v)l\'\';h=y(h);H=H!=v?y(H):H;E R=!H?-1:h.34(H);l~R?h.M(R+H.t,h.t):h},4e:r(h,H){p(h==v)l\'\';h=y(h);H=H!=v?y(H):H;E R=!H?-1:h.26(H);l~R?h.M(0,R):h},4f:r(h,H){p(h==v)l\'\';h+=\'\';H=H!=v?\'\'+H:H;E R=h.34(H);l~R?h.M(0,R):h},31:r(1O,Q,1v,32){Q=Q||\', \';1v=1v||\' 35 \';E a=1O.M(),2w=a.3e();p(1O.t>2&&32)1v=C.1N(Q)+1v;l a.t?a.1c(Q)+1v+2w:2w},4i:r(){E 1t=M.1j(1h);1t[3]=1Y;l C.31.2X(C,1t)},4s:r(h){p(h==v)l\'\';E 2r="G�1B��G� G�I�G�I�G�I�G�I�G�I�G�I�G�1B��G�1B��G�I�G�I�G�I�G�4u�I�G�I�G�I�G�I�G�1B��G�1B��G�I�G�I�G�I�G�I�G�4y�I�G�I�G�4x�I�G�I�G�I�G�I�G�I�G�4w",2Z="4n",3i=V 1A(1z(2r),\'g\');h=y(h).1r().J(3i,r(c){E 30=2r.26(c);l 2Z.1y(30)||\'-\'});l C.36(h.J(/[^\\w\\s-]/g,\'\'))},37:r(h,2b){l[2b,h,2b].1c(\'\')},3a:r(h){l C.37(h,\'"\')},1I:r(){E 1q={};1g(E 1C 2g 22){p(!22.2n(1C)||1C.B(/^(?:29|39|2m)$/))3u;1q[1C]=22[1C]}l 1q},20:r(h,U,Q){p(h==v)l\'\';U=~~U;p(Q==v)l 1f(y(h),U);1g(E 20=[];U>0;20[--U]=h){}l 20.1c(Q)},3o:r(17,15){p(17==v&&15==v)l 0;p(17==v)l y(15).t;p(15==v)l y(17).t;17=y(17);15=y(15);E 1x=[],25,1F;1g(E i=0;i<=15.t;i++)1g(E j=0;j<=17.t;j++){p(i&&j)p(17.1y(j-1)===15.1y(i-1))1F=25;L 1F=23.3m(1x[j],1x[j-1],25)+1;L 1F=i+j;25=1x[j];1x[j]=1F}l 1x.3e()}};C.3f=C.1l;C.3p=C.3g;C.3t=C.1N;C.3s=C.3d;C.3C=C.3c;C.3V=C.38;C.39=C.29;C.q=C.3a;p(2c 1I!==\'3b\'){p(2c 2h!==\'3b\'&&2h.1I){2h.1I=C}1I.C=C}L p(2c 2x===\'r\'&&2x.3S){2x(\'3N.2p\',[],r(){l C})}L{1E.O=1E.O||{};1E.O.2p=1E.O.h=C}}(22,y);',62,290,'|||||||||||||||||str||||return||||if||function||length||null|||String|||match|_s|arg|var||�|sep|�|replace|characters|else|slice|padStr|_|case|separator|pos||sprintf|qty|new|||break|||str_format|parse_tree|template|push|str2||str1|field_match|ends|padlen|pad|join|starts|number|strRepeat|for|arguments|argv|call|toUpperCase|trim|_fmt|substr|pruneStr|exec|result|toLowerCase|replacement_field|args|Error|lastSeparator|throw|current|charAt|defaultToWhiteSpace|RegExp|�|prop|entityCode|root|value|field_list|split|exports|step|escapeChars|toString|prototype|rtrim|array|fromCharCode|truncateStr|fmt|parts|tsep|get_type|node_type|decimals|source|true|cache|repeat|z_|this|Math|arg_names|prev|indexOf|output|false|include|nativeTrimLeft|wrapper|typeof|nativeTrimRight|parseNumber|while|in|module|num|toFixed|chars|nativeTrim|reverse|hasOwnProperty|cursor|string|huh|from|reversedEscapeChars|substring|pad_length|test|lastMember|define|arr|pad_character|splice|needle|x25|delimiter|key|isBlank|tmpl|entity|parseFloat|toExponential|parseInt|str_repeat|not|parse|escapeRegExp|howmany|capitalize|underscored|titleize|format|tree_length|variable|type|apply|switch|to|index|toSentence|serial|fnums|lastIndexOf|and|dasherize|surround|rpad|contains|quote|undefined|lpad|lrpad|pop|strip|ltrim|dsep|regex|both|dec|right|min|fosuxX|levenshtein|lstrip|def|abs|center|rstrip|continue|classify|yet|supported|truncate|unshift|vsprintf|is|rjust|positional|named|placeholders|prune|but|gt|quot|apos|amp|lt|underscore|use|strict|trimRight|trimLeft|amd|Object|exist|ljust|expecting|toNumber|does|property|ceil|words|floor|default|found|mixing|strRightBack|lines|shift|NaN|startsWith|humanize|endsWith|strRight|strLeft|strLeftBack|numberFormat|_id|toSentenceSerial|insert|isNaN|da|fA|aaaaaaaaceeeeeiiiilnoooooouuuunczz|succ|unescapeHTML|stripTags|chop|slugify|charCodeAt|ª�|VERSION|º|º�|µ�|count|clean|swapCase|escapeHTML|camelize|Number|1_'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/templates/display_tab.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/templates/display_tab.php index cdbd4eeae5b66ee2cc169758ad662560306f05b9..9d6ba31bd36aa5ab7bf81d03b9cb051c2bd341a7 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/templates/display_tab.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/templates/display_tab.php @@ -6,6 +6,6 @@ <?php echo $tab ?> <?php endforeach ?> </div> -<p> - <input type="button" id="save_displayed_gallery" value="<?php _e('Save', 'nggallery'); ?>"/> -</p> \ No newline at end of file +<p class="wp-core-ui"> + <input type="button" class="button button-primary button-large" id="save_displayed_gallery" value="<?php if ($displayed_gallery->id()) { _e('Save Changes', 'nggallery'); } else { _e('Insert Displayed Gallery', 'nggallery'); } ?>"/> +</p> diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/templates/display_tab_js.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/templates/display_tab_js.php index 5736a5fc9633b2601609285d2935128b89a4dffa..8c3aa7df23c051fcc7f80cd3f26b61e2b2ccebef 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/templates/display_tab_js.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/attach_to_post/templates/display_tab_js.php @@ -1193,6 +1193,7 @@ jQuery(function($){ _.each(this.options, function(value, key){ this[key] = value; }, this); + this.initTime = new Date().getTime(); this.model.on('change', this.render, this); if (this.model.get('sortorder') == 0) { this.model.set('sortorder', -1, {silent: true}); @@ -1208,27 +1209,27 @@ jQuery(function($){ render: function(){ this.$el.empty(); + var preview_item = $('<div/>').addClass('preview_item'); var image_container = $('<div/>').addClass('image_container'); var alt_text = this.model.alttext().replace(/\\&/g, '&').replace(/\\'/g, "'"); - var timestamp = new Date().getTime(); + var timestamp = this.initTime; image_container.attr({ title: alt_text, style: "background-image: url('"+this.model.get('thumb_url')+"?timestamp"+timestamp+"')" - }).css({ - width: this.model.get('max_width'), - height: this.model.get('max_height'), - 'max-width': this.model.get('max_width'), - 'max-height': this.model.get('max_height') }); - this.$el.append(image_container).addClass('ui-state-default'); + this.$el.append(preview_item).addClass('ui-state-default'); + + preview_item.append(image_container); // Add exclude checkbox var exclude_container = $('<div/>').addClass('exclude_container'); - exclude_container.append('Exclude?'); + var exclude_label = $('<label/>'); + exclude_label.append('<?php _e('Exclude?', 'nggallery'); ?>'); var exclude_checkbox = new this.ExcludeCheckbox({model: this.model}); - exclude_container.append(exclude_checkbox.render().el); - image_container.append(exclude_container); + exclude_label.append(exclude_checkbox.render().el); + exclude_container.append(exclude_label); + preview_item.append(exclude_container); return this; }, diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/datamapper/package.module.datamapper.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/datamapper/package.module.datamapper.php index b3ff599a62fc6b3038db1a03adaea48d630a045f..70b3776212166f80dcdf704917b02891de2b9505 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/datamapper/package.module.datamapper.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/datamapper/package.module.datamapper.php @@ -368,6 +368,8 @@ class Mixin_CustomPost_DataMapper_Driver extends Mixin // Save properties as post meta $this->object->_flush_and_update_postmeta($post_id, $entity instanceof stdClass ? $entity : $entity->get_entity()); $entity->{$primary_key} = $post_id; + // Clean cache + $this->object->_cache = array(); } $entity->id_field = $primary_key; return $post_id; @@ -903,6 +905,10 @@ class C_CustomTable_DataMapper_Driver_Mixin extends Mixin } } $entity->id_field = $primary_key; + // Clean cache + if ($retval) { + $this->object->_cache = array(); + } return $retval; } /** diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/fs/module.fs.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/fs/module.fs.php index 0025f97088f7e01df3c948632b8aad7fa022d1e6..175f827b508e302fccbb0fb6190c7be071c41da3 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/fs/module.fs.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/fs/module.fs.php @@ -12,7 +12,7 @@ class M_Fs extends C_Base_Module 'photocrati-fs', 'Filesystem', 'Provides a filesystem abstraction layer for Pope modules', - '0.4', + '0.5', 'https://www.imagely.com', 'Photocrati Media', 'https://www.imagely.com' diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/fs/package.module.fs.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/fs/package.module.fs.php index e68cc7aa312dc54c927aea94a5be4ad0b649d22b..ad23fb512665204c990de1bd4a03938800d43bbc 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/fs/package.module.fs.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/fs/package.module.fs.php @@ -274,6 +274,10 @@ class Mixin_Fs_Instance_Methods extends Mixin if (strpos($retval, $this->get_document_root()) !== 0 && strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') { $retval = DIRECTORY_SEPARATOR . trim($retval, '/\\'); } + // Check for and adjust Windows UNC paths (\\server\share\) for network mounted sites + if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN' && substr($this->get_document_root(), 0, 2) === '\\\\') { + $retval = '\\\\' . $retval; + } return $retval; } public function _flatten_array($obj, &$arr) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/lightbox/static/fancybox/jquery.fancybox-1.3.4.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/lightbox/static/fancybox/jquery.fancybox-1.3.4.css index bc0f15fd1631c27f675a4fe77c46ad12d9b7d0b6..e59be37cf4f9bd1d20b5d45fd96ef06ea7ca7acc 100755 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/lightbox/static/fancybox/jquery.fancybox-1.3.4.css +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/lightbox/static/fancybox/jquery.fancybox-1.3.4.css @@ -1,366 +1,366 @@ -/* - * FancyBox - jQuery Plugin - * Simple and fancy lightbox alternative - * - * Examples and documentation at: http://fancybox.net - * - * Copyright (c) 2008 - 2010 Janis Skarnelis - * That said, it is hardly a one-person project. Many people have submitted bugs, code, and offered their advice freely. Their support is greatly appreciated. - * - * Version: 1.3.4 (11/11/2010) - * Requires: jQuery v1.3+ - * - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html - */ - -#fancybox-loading { - position: fixed; - top: 50%; - left: 50%; - width: 40px; - height: 40px; - margin-top: -20px; - margin-left: -20px; - cursor: pointer; - overflow: hidden; - z-index: 1104; - display: none; -} - -#fancybox-loading div { - position: absolute; - top: 0; - left: 0; - width: 40px; - height: 480px; - background-image: url('fancybox.png'); -} - -#fancybox-overlay { - position: absolute; - top: 0; - left: 0; - width: 100%; - z-index: 1100; - display: none; -} - -#fancybox-tmp { - padding: 0; - margin: 0; - border: 0; - overflow: auto; - display: none; -} - -#fancybox-wrap { - position: absolute; - top: 0; - left: 0; - padding: 20px; - z-index: 1101; - outline: none; - display: none; -} - -#fancybox-outer { - position: relative; - width: 100%; - height: 100%; - background: #fff; -} - -#fancybox-content { - width: 0; - height: 0; - padding: 0; - outline: none; - position: relative; - overflow: hidden; - z-index: 1102; - border: 0px solid #fff; -} - -#fancybox-hide-sel-frame { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: transparent; - z-index: 1101; -} - -#fancybox-close { - position: absolute; - top: -15px; - right: -15px; - width: 30px; - height: 30px; - background: transparent url('fancybox.png') -40px 0px; - cursor: pointer; - z-index: 1103; - display: none; -} - -#fancybox-error { - color: #444; - font: normal 12px/20px Arial; - padding: 14px; - margin: 0; -} - -#fancybox-img { - width: 100%; - height: 100%; - padding: 0; - margin: 0; - border: none; - outline: none; - line-height: 0; - vertical-align: top; -} - -#fancybox-frame { - width: 100%; - height: 100%; - border: none; - display: block; -} - -#fancybox-left, #fancybox-right { - position: absolute; - bottom: 0px; - height: 100%; - width: 35%; - cursor: pointer; - outline: none; - background: transparent url('blank.gif'); - z-index: 1102; - display: none; -} - -#fancybox-left { - left: 0px; -} - -#fancybox-right { - right: 0px; -} - -#fancybox-left-ico, #fancybox-right-ico { - position: absolute; - top: 50%; - left: -9999px; - width: 30px; - height: 30px; - margin-top: -15px; - cursor: pointer; - z-index: 1102; - display: block; -} - -#fancybox-left-ico { - background-image: url('fancybox.png'); - background-position: -40px -30px; -} - -#fancybox-right-ico { - background-image: url('fancybox.png'); - background-position: -40px -60px; -} - -#fancybox-left:hover, #fancybox-right:hover { - visibility: visible; /* IE6 */ -} - -#fancybox-left:hover span { - left: 20px; -} - -#fancybox-right:hover span { - left: auto; - right: 20px; -} - -.fancybox-bg { - position: absolute; - padding: 0; - margin: 0; - border: 0; - width: 20px; - height: 20px; - z-index: 1001; -} - -#fancybox-bg-n { - top: -20px; - left: 0; - width: 100%; - background-image: url('fancybox-x.png'); -} - -#fancybox-bg-ne { - top: -20px; - right: -20px; - background-image: url('fancybox.png'); - background-position: -40px -162px; -} - -#fancybox-bg-e { - top: 0; - right: -20px; - height: 100%; - background-image: url('fancybox-y.png'); - background-position: -20px 0px; -} - -#fancybox-bg-se { - bottom: -20px; - right: -20px; - background-image: url('fancybox.png'); - background-position: -40px -182px; -} - -#fancybox-bg-s { - bottom: -20px; - left: 0; - width: 100%; - background-image: url('fancybox-x.png'); - background-position: 0px -20px; -} - -#fancybox-bg-sw { - bottom: -20px; - left: -20px; - background-image: url('fancybox.png'); - background-position: -40px -142px; -} - -#fancybox-bg-w { - top: 0; - left: -20px; - height: 100%; - background-image: url('fancybox-y.png'); -} - -#fancybox-bg-nw { - top: -20px; - left: -20px; - background-image: url('fancybox.png'); - background-position: -40px -122px; -} - -#fancybox-title { - font-family: Helvetica; - font-size: 12px; - z-index: 1102; -} - -.fancybox-title-inside { - padding-bottom: 10px; - text-align: center; - color: #333; - background: #fff; - position: relative; -} - -.fancybox-title-outside { - padding-top: 10px; - color: #fff; -} - -.fancybox-title-over { - position: absolute; - bottom: 0; - left: 0; - color: #FFF; - text-align: left; -} - -#fancybox-title-over { - padding: 10px; - background-image: url('fancy_title_over.png'); - display: block; -} - -.fancybox-title-float { - position: absolute; - left: 0; - bottom: -20px; - height: 32px; -} - -#fancybox-title-float-wrap { - border: none; - border-collapse: collapse; - width: auto; -} - -#fancybox-title-float-wrap td { - border: none; - white-space: nowrap; -} - -#fancybox-title-float-left { - padding: 0 0 0 15px; - background: url('fancybox.png') -40px -90px no-repeat; -} - -#fancybox-title-float-main { - color: #FFF; - line-height: 29px; - font-weight: bold; - padding: 0 0 3px 0; - background: url('fancybox-x.png') 0px -40px; -} - -#fancybox-title-float-right { - padding: 0 0 0 15px; - background: url('fancybox.png') -55px -90px no-repeat; -} - -/* IE6 */ - -.fancybox-ie6 #fancybox-close { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_close.png', sizingMethod='scale'); } - -.fancybox-ie6 #fancybox-left-ico { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_nav_left.png', sizingMethod='scale'); } -.fancybox-ie6 #fancybox-right-ico { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_nav_right.png', sizingMethod='scale'); } - -.fancybox-ie6 #fancybox-title-over { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_over.png', sizingMethod='scale'); zoom: 1; } -.fancybox-ie6 #fancybox-title-float-left { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_left.png', sizingMethod='scale'); } -.fancybox-ie6 #fancybox-title-float-main { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_main.png', sizingMethod='scale'); } -.fancybox-ie6 #fancybox-title-float-right { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_right.png', sizingMethod='scale'); } - -.fancybox-ie6 #fancybox-bg-w, .fancybox-ie6 #fancybox-bg-e, .fancybox-ie6 #fancybox-left, .fancybox-ie6 #fancybox-right, #fancybox-hide-sel-frame { - height: expression(this.parentNode.clientHeight + "px"); -} - -#fancybox-loading.fancybox-ie6 { - position: absolute; margin-top: 0; - top: expression( (-20 + (document.documentElement.clientHeight ? document.documentElement.clientHeight/2 : document.body.clientHeight/2 ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop )) + 'px'); -} - -#fancybox-loading.fancybox-ie6 div { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_loading.png', sizingMethod='scale'); } - -/* IE6, IE7, IE8 */ - -.fancybox-ie .fancybox-bg { background: transparent !important; } - -.fancybox-ie #fancybox-bg-n { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_n.png', sizingMethod='scale'); } -.fancybox-ie #fancybox-bg-ne { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_ne.png', sizingMethod='scale'); } -.fancybox-ie #fancybox-bg-e { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_e.png', sizingMethod='scale'); } -.fancybox-ie #fancybox-bg-se { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_se.png', sizingMethod='scale'); } -.fancybox-ie #fancybox-bg-s { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_s.png', sizingMethod='scale'); } -.fancybox-ie #fancybox-bg-sw { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_sw.png', sizingMethod='scale'); } -.fancybox-ie #fancybox-bg-w { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_w.png', sizingMethod='scale'); } -.fancybox-ie #fancybox-bg-nw { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_nw.png', sizingMethod='scale'); } - -/* Note: Prevents issues with "style resets" or themes that apply 'box-sizing: border-box' to everything */ -#fancybox-wrap, #fancybox-content, #fancybox-outer { - box-sizing: content-box; - -moz-box-sizing: content-box; - -webkit-box-sizing: content-box; +/* + * FancyBox - jQuery Plugin + * Simple and fancy lightbox alternative + * + * Examples and documentation at: http://fancybox.net + * + * Copyright (c) 2008 - 2010 Janis Skarnelis + * That said, it is hardly a one-person project. Many people have submitted bugs, code, and offered their advice freely. Their support is greatly appreciated. + * + * Version: 1.3.4 (11/11/2010) + * Requires: jQuery v1.3+ + * + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + */ + +#fancybox-loading { + position: fixed; + top: 50%; + left: 50%; + width: 40px; + height: 40px; + margin-top: -20px; + margin-left: -20px; + cursor: pointer; + overflow: hidden; + z-index: 1104; + display: none; +} + +#fancybox-loading div { + position: absolute; + top: 0; + left: 0; + width: 40px; + height: 480px; + background-image: url('fancybox.png'); +} + +#fancybox-overlay { + position: absolute; + top: 0; + left: 0; + width: 100%; + z-index: 1100; + display: none; +} + +#fancybox-tmp { + padding: 0; + margin: 0; + border: 0; + overflow: auto; + display: none; +} + +#fancybox-wrap { + position: absolute; + top: 0; + left: 0; + padding: 20px; + z-index: 1101; + outline: none; + display: none; +} + +#fancybox-outer { + position: relative; + width: 100%; + height: 100%; + background: #fff; +} + +#fancybox-content { + width: 0; + height: 0; + padding: 0; + outline: none; + position: relative; + overflow: hidden; + z-index: 1102; + border: 0px solid #fff; +} + +#fancybox-hide-sel-frame { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: transparent; + z-index: 1101; +} + +#fancybox-close { + position: absolute; + top: -15px; + right: -15px; + width: 30px; + height: 30px; + background: transparent url('fancybox.png') -40px 0px; + cursor: pointer; + z-index: 1103; + display: none; +} + +#fancybox-error { + color: #444; + font: normal 12px/20px Arial; + padding: 14px; + margin: 0; +} + +#fancybox-img { + width: 100%; + height: 100%; + padding: 0; + margin: 0; + border: none; + outline: none; + line-height: 0; + vertical-align: top; +} + +#fancybox-frame { + width: 100%; + height: 100%; + border: none; + display: block; +} + +#fancybox-left, #fancybox-right { + position: absolute; + bottom: 0px; + height: 100%; + width: 35%; + cursor: pointer; + outline: none; + background: transparent url('blank.gif'); + z-index: 1102; + display: none; +} + +#fancybox-left { + left: 0px; +} + +#fancybox-right { + right: 0px; +} + +#fancybox-left-ico, #fancybox-right-ico { + position: absolute; + top: 50%; + left: -9999px; + width: 30px; + height: 30px; + margin-top: -15px; + cursor: pointer; + z-index: 1102; + display: block; +} + +#fancybox-left-ico { + background-image: url('fancybox.png'); + background-position: -40px -30px; +} + +#fancybox-right-ico { + background-image: url('fancybox.png'); + background-position: -40px -60px; +} + +#fancybox-left:hover, #fancybox-right:hover { + visibility: visible; /* IE6 */ +} + +#fancybox-left:hover span { + left: 20px; +} + +#fancybox-right:hover span { + left: auto; + right: 20px; +} + +.fancybox-bg { + position: absolute; + padding: 0; + margin: 0; + border: 0; + width: 20px; + height: 20px; + z-index: 1001; +} + +#fancybox-bg-n { + top: -20px; + left: 0; + width: 100%; + background-image: url('fancybox-x.png'); +} + +#fancybox-bg-ne { + top: -20px; + right: -20px; + background-image: url('fancybox.png'); + background-position: -40px -162px; +} + +#fancybox-bg-e { + top: 0; + right: -20px; + height: 100%; + background-image: url('fancybox-y.png'); + background-position: -20px 0px; +} + +#fancybox-bg-se { + bottom: -20px; + right: -20px; + background-image: url('fancybox.png'); + background-position: -40px -182px; +} + +#fancybox-bg-s { + bottom: -20px; + left: 0; + width: 100%; + background-image: url('fancybox-x.png'); + background-position: 0px -20px; +} + +#fancybox-bg-sw { + bottom: -20px; + left: -20px; + background-image: url('fancybox.png'); + background-position: -40px -142px; +} + +#fancybox-bg-w { + top: 0; + left: -20px; + height: 100%; + background-image: url('fancybox-y.png'); +} + +#fancybox-bg-nw { + top: -20px; + left: -20px; + background-image: url('fancybox.png'); + background-position: -40px -122px; +} + +#fancybox-title { + font-family: Helvetica; + font-size: 12px; + z-index: 1102; +} + +.fancybox-title-inside { + padding-bottom: 10px; + text-align: center; + color: #333; + background: #fff; + position: relative; +} + +.fancybox-title-outside { + padding-top: 10px; + color: #fff; +} + +.fancybox-title-over { + position: absolute; + bottom: 0; + left: 0; + color: #FFF; + text-align: left; +} + +#fancybox-title-over { + padding: 10px; + background-image: url('fancy_title_over.png'); + display: block; +} + +.fancybox-title-float { + position: absolute; + left: 0; + bottom: -20px; + height: 32px; +} + +#fancybox-title-float-wrap { + border: none; + border-collapse: collapse; + width: auto; +} + +#fancybox-title-float-wrap td { + border: none; + white-space: nowrap; +} + +#fancybox-title-float-left { + padding: 0 0 0 15px; + background: url('fancybox.png') -40px -90px no-repeat; +} + +#fancybox-title-float-main { + color: #FFF; + line-height: 29px; + font-weight: bold; + padding: 0 0 3px 0; + background: url('fancybox-x.png') 0px -40px; +} + +#fancybox-title-float-right { + padding: 0 0 0 15px; + background: url('fancybox.png') -55px -90px no-repeat; +} + +/* IE6 */ + +.fancybox-ie6 #fancybox-close { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_close.png', sizingMethod='scale'); } + +.fancybox-ie6 #fancybox-left-ico { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_nav_left.png', sizingMethod='scale'); } +.fancybox-ie6 #fancybox-right-ico { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_nav_right.png', sizingMethod='scale'); } + +.fancybox-ie6 #fancybox-title-over { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_over.png', sizingMethod='scale'); zoom: 1; } +.fancybox-ie6 #fancybox-title-float-left { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_left.png', sizingMethod='scale'); } +.fancybox-ie6 #fancybox-title-float-main { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_main.png', sizingMethod='scale'); } +.fancybox-ie6 #fancybox-title-float-right { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_right.png', sizingMethod='scale'); } + +.fancybox-ie6 #fancybox-bg-w, .fancybox-ie6 #fancybox-bg-e, .fancybox-ie6 #fancybox-left, .fancybox-ie6 #fancybox-right, #fancybox-hide-sel-frame { + height: expression(this.parentNode.clientHeight + "px"); +} + +#fancybox-loading.fancybox-ie6 { + position: absolute; margin-top: 0; + top: expression( (-20 + (document.documentElement.clientHeight ? document.documentElement.clientHeight/2 : document.body.clientHeight/2 ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop )) + 'px'); +} + +#fancybox-loading.fancybox-ie6 div { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_loading.png', sizingMethod='scale'); } + +/* IE6, IE7, IE8 */ + +.fancybox-ie .fancybox-bg { background: transparent !important; } + +.fancybox-ie #fancybox-bg-n { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_n.png', sizingMethod='scale'); } +.fancybox-ie #fancybox-bg-ne { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_ne.png', sizingMethod='scale'); } +.fancybox-ie #fancybox-bg-e { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_e.png', sizingMethod='scale'); } +.fancybox-ie #fancybox-bg-se { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_se.png', sizingMethod='scale'); } +.fancybox-ie #fancybox-bg-s { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_s.png', sizingMethod='scale'); } +.fancybox-ie #fancybox-bg-sw { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_sw.png', sizingMethod='scale'); } +.fancybox-ie #fancybox-bg-w { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_w.png', sizingMethod='scale'); } +.fancybox-ie #fancybox-bg-nw { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_nw.png', sizingMethod='scale'); } + +/* Note: Prevents issues with "style resets" or themes that apply 'box-sizing: border-box' to everything */ +#fancybox-wrap, #fancybox-content, #fancybox-outer { + box-sizing: content-box; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/lightbox/static/fancybox/jquery.fancybox-1.3.4.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/lightbox/static/fancybox/jquery.fancybox-1.3.4.js index a8520051dc780846e034c9c5ef7a72ce107e9c6c..be77275376b7083d0df61b1ebe93a101ed52bebf 100755 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/lightbox/static/fancybox/jquery.fancybox-1.3.4.js +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/lightbox/static/fancybox/jquery.fancybox-1.3.4.js @@ -1,1156 +1,1156 @@ -/* - * FancyBox - jQuery Plugin - * Simple and fancy lightbox alternative - * - * Examples and documentation at: http://fancybox.net - * - * Copyright (c) 2008 - 2010 Janis Skarnelis - * That said, it is hardly a one-person project. Many people have submitted bugs, code, and offered their advice freely. Their support is greatly appreciated. - * - * Version: 1.3.4 (11/11/2010) - * Requires: jQuery v1.3+ - * - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html - */ - -;(function($) { - var tmp, loading, overlay, wrap, outer, content, close, title, nav_left, nav_right, - - selectedIndex = 0, selectedOpts = {}, selectedArray = [], currentIndex = 0, currentOpts = {}, currentArray = [], - - ajaxLoader = null, imgPreloader = new Image(), imgRegExp = /\.(jpg|gif|png|bmp|jpeg)(.*)?$/i, swfRegExp = /[^\.]\.(swf)\s*$/i, - - loadingTimer, loadingFrame = 1, - - titleHeight = 0, titleStr = '', start_pos, final_pos, busy = false, fx = $.extend($('<div/>')[0], { prop: 0 }), - - isIE6 = $.browser.msie && $.browser.version < 7 && !window.XMLHttpRequest, - - /* - * Private methods - */ - - _abort = function() { - loading.hide(); - - imgPreloader.onerror = imgPreloader.onload = null; - - if (ajaxLoader) { - ajaxLoader.abort(); - } - - tmp.empty(); - }, - - _error = function() { - if (false === selectedOpts.onError(selectedArray, selectedIndex, selectedOpts)) { - loading.hide(); - busy = false; - return; - } - - selectedOpts.titleShow = false; - - selectedOpts.width = 'auto'; - selectedOpts.height = 'auto'; - - tmp.html( '<p id="fancybox-error">The requested content cannot be loaded.<br />Please try again later.</p>' ); - - _process_inline(); - }, - - _start = function() { - var obj = selectedArray[ selectedIndex ], - href, - type, - title, - str, - emb, - ret; - - _abort(); - - selectedOpts = $.extend({}, $.fn.fancybox.defaults, (typeof $(obj).data('fancybox') == 'undefined' ? selectedOpts : $(obj).data('fancybox'))); - - ret = selectedOpts.onStart(selectedArray, selectedIndex, selectedOpts); - - if (ret === false) { - busy = false; - return; - } else if (typeof ret == 'object') { - selectedOpts = $.extend(selectedOpts, ret); - } - - title = selectedOpts.title || (obj.nodeName ? $(obj).attr('title') : obj.title) || ''; - - if (obj.nodeName && !selectedOpts.orig) { - selectedOpts.orig = $(obj).children("img:first").length ? $(obj).children("img:first") : $(obj); - } - - if (title === '' && selectedOpts.orig && selectedOpts.titleFromAlt) { - title = selectedOpts.orig.attr('alt'); - } - - href = selectedOpts.href || (obj.nodeName ? $(obj).attr('href') : obj.href) || null; - - if ((/^(?:javascript)/i).test(href) || href == '#') { - href = null; - } - - if (selectedOpts.type) { - type = selectedOpts.type; - - if (!href) { - href = selectedOpts.content; - } - - } else if (selectedOpts.content) { - type = 'html'; - - } else if (href) { - if (href.match(imgRegExp)) { - type = 'image'; - - } else if (href.match(swfRegExp)) { - type = 'swf'; - - } else if ($(obj).hasClass("iframe")) { - type = 'iframe'; - - } else if (href.indexOf("#") === 0) { - type = 'inline'; - - } else { - type = 'ajax'; - } - } - - if (!type) { - _error(); - return; - } - - if (type == 'inline') { - obj = href.substr(href.indexOf("#")); - type = $(obj).length > 0 ? 'inline' : 'ajax'; - } - - selectedOpts.type = type; - selectedOpts.href = href; - selectedOpts.title = title; - - if (selectedOpts.autoDimensions) { - if (selectedOpts.type == 'html' || selectedOpts.type == 'inline' || selectedOpts.type == 'ajax') { - selectedOpts.width = 'auto'; - selectedOpts.height = 'auto'; - } else { - selectedOpts.autoDimensions = false; - } - } - - if (selectedOpts.modal) { - selectedOpts.overlayShow = true; - selectedOpts.hideOnOverlayClick = false; - selectedOpts.hideOnContentClick = false; - selectedOpts.enableEscapeButton = false; - selectedOpts.showCloseButton = false; - } - - selectedOpts.padding = parseInt(selectedOpts.padding, 10); - selectedOpts.margin = parseInt(selectedOpts.margin, 10); - - tmp.css('padding', (selectedOpts.padding + selectedOpts.margin)); - - $('.fancybox-inline-tmp').unbind('fancybox-cancel').bind('fancybox-change', function() { - $(this).replaceWith(content.children()); - }); - - switch (type) { - case 'html' : - tmp.html( selectedOpts.content ); - _process_inline(); - break; - - case 'inline' : - if ( $(obj).parent().is('#fancybox-content') === true) { - busy = false; - return; - } - - $('<div class="fancybox-inline-tmp" />') - .hide() - .insertBefore( $(obj) ) - .bind('fancybox-cleanup', function() { - $(this).replaceWith(content.children()); - }).bind('fancybox-cancel', function() { - $(this).replaceWith(tmp.children()); - }); - - $(obj).appendTo(tmp); - - _process_inline(); - break; - - case 'image': - busy = false; - - $.fancybox.showActivity(); - - imgPreloader = new Image(); - - imgPreloader.onerror = function() { - _error(); - }; - - imgPreloader.onload = function() { - busy = true; - - imgPreloader.onerror = imgPreloader.onload = null; - - _process_image(); - }; - - imgPreloader.src = href; - break; - - case 'swf': - selectedOpts.scrolling = 'no'; - - str = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="' + selectedOpts.width + '" height="' + selectedOpts.height + '"><param name="movie" value="' + href + '"></param>'; - emb = ''; - - $.each(selectedOpts.swf, function(name, val) { - str += '<param name="' + name + '" value="' + val + '"></param>'; - emb += ' ' + name + '="' + val + '"'; - }); - - str += '<embed src="' + href + '" type="application/x-shockwave-flash" width="' + selectedOpts.width + '" height="' + selectedOpts.height + '"' + emb + '></embed></object>'; - - tmp.html(str); - - _process_inline(); - break; - - case 'ajax': - busy = false; - - $.fancybox.showActivity(); - - selectedOpts.ajax.win = selectedOpts.ajax.success; - - ajaxLoader = $.ajax($.extend({}, selectedOpts.ajax, { - url : href, - data : selectedOpts.ajax.data || {}, - error : function(XMLHttpRequest, textStatus, errorThrown) { - if ( XMLHttpRequest.status > 0 ) { - _error(); - } - }, - success : function(data, textStatus, XMLHttpRequest) { - var o = typeof XMLHttpRequest == 'object' ? XMLHttpRequest : ajaxLoader; - if (o.status == 200) { - if ( typeof selectedOpts.ajax.win == 'function' ) { - ret = selectedOpts.ajax.win(href, data, textStatus, XMLHttpRequest); - - if (ret === false) { - loading.hide(); - return; - } else if (typeof ret == 'string' || typeof ret == 'object') { - data = ret; - } - } - - tmp.html( data ); - _process_inline(); - } - } - })); - - break; - - case 'iframe': - _show(); - break; - } - }, - - _process_inline = function() { - var - w = selectedOpts.width, - h = selectedOpts.height; - - if (w.toString().indexOf('%') > -1) { - w = parseInt( ($(window).width() - (selectedOpts.margin * 2)) * parseFloat(w) / 100, 10) + 'px'; - - } else { - w = w == 'auto' ? 'auto' : w + 'px'; - } - - if (h.toString().indexOf('%') > -1) { - h = parseInt( ($(window).height() - (selectedOpts.margin * 2)) * parseFloat(h) / 100, 10) + 'px'; - - } else { - h = h == 'auto' ? 'auto' : h + 'px'; - } - - tmp.wrapInner('<div style="width:' + w + ';height:' + h + ';overflow: ' + (selectedOpts.scrolling == 'auto' ? 'auto' : (selectedOpts.scrolling == 'yes' ? 'scroll' : 'hidden')) + ';position:relative;"></div>'); - - selectedOpts.width = tmp.width(); - selectedOpts.height = tmp.height(); - - _show(); - }, - - _process_image = function() { - selectedOpts.width = imgPreloader.width; - selectedOpts.height = imgPreloader.height; - - $("<img />").attr({ - 'id' : 'fancybox-img', - 'src' : imgPreloader.src, - 'alt' : selectedOpts.title - }).appendTo( tmp ); - - _show(); - }, - - _show = function() { - var pos, equal; - - loading.hide(); - - if (wrap.is(":visible") && false === currentOpts.onCleanup(currentArray, currentIndex, currentOpts)) { - $.event.trigger('fancybox-cancel'); - - busy = false; - return; - } - - busy = true; - - $(content.add( overlay )).unbind(); - - $(window).unbind("resize.fb scroll.fb"); - $(document).unbind('keydown.fb'); - - if (wrap.is(":visible") && currentOpts.titlePosition !== 'outside') { - wrap.css('height', wrap.height()); - } - - currentArray = selectedArray; - currentIndex = selectedIndex; - currentOpts = selectedOpts; - - if (currentOpts.overlayShow) { - overlay.css({ - 'background-color' : currentOpts.overlayColor, - 'opacity' : currentOpts.overlayOpacity, - 'cursor' : currentOpts.hideOnOverlayClick ? 'pointer' : 'auto', - 'height' : $(document).height() - }); - - if (!overlay.is(':visible')) { - if (isIE6) { - $('select:not(#fancybox-tmp select)').filter(function() { - return this.style.visibility !== 'hidden'; - }).css({'visibility' : 'hidden'}).one('fancybox-cleanup', function() { - this.style.visibility = 'inherit'; - }); - } - - overlay.show(); - } - } else { - overlay.hide(); - } - - final_pos = _get_zoom_to(); - - _process_title(); - - if (wrap.is(":visible")) { - $( close.add( nav_left ).add( nav_right ) ).hide(); - - pos = wrap.position(), - - start_pos = { - top : pos.top, - left : pos.left, - width : wrap.width(), - height : wrap.height() - }; - - equal = (start_pos.width == final_pos.width && start_pos.height == final_pos.height); - - content.fadeTo(currentOpts.changeFade, 0.3, function() { - var finish_resizing = function() { - content.html( tmp.contents() ).fadeTo(currentOpts.changeFade, 1, _finish); - }; - - $.event.trigger('fancybox-change'); - - content - .empty() - .removeAttr('filter') - .css({ - 'border-width' : currentOpts.padding, - 'width' : final_pos.width - currentOpts.padding * 2, - 'height' : selectedOpts.autoDimensions ? 'auto' : final_pos.height - titleHeight - currentOpts.padding * 2 - }); - - if (equal) { - finish_resizing(); - - } else { - fx.prop = 0; - - $(fx).animate({prop: 1}, { - duration : currentOpts.changeSpeed, - easing : currentOpts.easingChange, - step : _draw, - complete : finish_resizing - }); - } - }); - - return; - } - - wrap.removeAttr("style"); - - content.css('border-width', currentOpts.padding); - - if (currentOpts.transitionIn == 'elastic') { - start_pos = _get_zoom_from(); - - content.html( tmp.contents() ); - - wrap.show(); - - if (currentOpts.opacity) { - final_pos.opacity = 0; - } - - fx.prop = 0; - - $(fx).animate({prop: 1}, { - duration : currentOpts.speedIn, - easing : currentOpts.easingIn, - step : _draw, - complete : _finish - }); - - return; - } - - if (currentOpts.titlePosition == 'inside' && titleHeight > 0) { - title.show(); - } - - content - .css({ - 'width' : final_pos.width - currentOpts.padding * 2, - 'height' : selectedOpts.autoDimensions ? 'auto' : final_pos.height - titleHeight - currentOpts.padding * 2 - }) - .html( tmp.contents() ); - - wrap - .css(final_pos) - .fadeIn( currentOpts.transitionIn == 'none' ? 0 : currentOpts.speedIn, _finish ); - }, - - _format_title = function(title) { - if (title && title.length) { - if (currentOpts.titlePosition == 'float') { - return '<table id="fancybox-title-float-wrap" cellpadding="0" cellspacing="0"><tr><td id="fancybox-title-float-left"></td><td id="fancybox-title-float-main">' + title + '</td><td id="fancybox-title-float-right"></td></tr></table>'; - } - - return '<div id="fancybox-title-' + currentOpts.titlePosition + '">' + title + '</div>'; - } - - return false; - }, - - _process_title = function() { - titleStr = currentOpts.title || ''; - titleHeight = 0; - - title - .empty() - .removeAttr('style') - .removeClass(); - - if (currentOpts.titleShow === false) { - title.hide(); - return; - } - - titleStr = $.isFunction(currentOpts.titleFormat) ? currentOpts.titleFormat(titleStr, currentArray, currentIndex, currentOpts) : _format_title(titleStr); - - if (!titleStr || titleStr === '') { - title.hide(); - return; - } - - title - .addClass('fancybox-title-' + currentOpts.titlePosition) - .html( titleStr ) - .appendTo( 'body' ) - .show(); - - switch (currentOpts.titlePosition) { - case 'inside': - title - .css({ - 'width' : final_pos.width - (currentOpts.padding * 2), - 'marginLeft' : currentOpts.padding, - 'marginRight' : currentOpts.padding - }); - - titleHeight = title.outerHeight(true); - - title.appendTo( outer ); - - final_pos.height += titleHeight; - break; - - case 'over': - title - .css({ - 'marginLeft' : currentOpts.padding, - 'width' : final_pos.width - (currentOpts.padding * 2), - 'bottom' : currentOpts.padding - }) - .appendTo( outer ); - break; - - case 'float': - title - .css('left', parseInt((title.width() - final_pos.width - 40)/ 2, 10) * -1) - .appendTo( wrap ); - break; - - default: - title - .css({ - 'width' : final_pos.width - (currentOpts.padding * 2), - 'paddingLeft' : currentOpts.padding, - 'paddingRight' : currentOpts.padding - }) - .appendTo( wrap ); - break; - } - - title.hide(); - }, - - _set_navigation = function() { - if (currentOpts.enableEscapeButton || currentOpts.enableKeyboardNav) { - $(document).bind('keydown.fb', function(e) { - if (e.keyCode == 27 && currentOpts.enableEscapeButton) { - e.preventDefault(); - $.fancybox.close(); - - } else if ((e.keyCode == 37 || e.keyCode == 39) && currentOpts.enableKeyboardNav && e.target.tagName !== 'INPUT' && e.target.tagName !== 'TEXTAREA' && e.target.tagName !== 'SELECT') { - e.preventDefault(); - $.fancybox[ e.keyCode == 37 ? 'prev' : 'next'](); - } - }); - } - - if (!currentOpts.showNavArrows) { - nav_left.hide(); - nav_right.hide(); - return; - } - - if ((currentOpts.cyclic && currentArray.length > 1) || currentIndex !== 0) { - nav_left.show(); - } - - if ((currentOpts.cyclic && currentArray.length > 1) || currentIndex != (currentArray.length -1)) { - nav_right.show(); - } - }, - - _finish = function () { - if (!$.support.opacity) { - content.get(0).style.removeAttribute('filter'); - wrap.get(0).style.removeAttribute('filter'); - } - - if (selectedOpts.autoDimensions) { - content.css('height', 'auto'); - } - - wrap.css('height', 'auto'); - - if (titleStr && titleStr.length) { - title.show(); - } - - if (currentOpts.showCloseButton) { - close.show(); - } - - _set_navigation(); - - if (currentOpts.hideOnContentClick) { - content.bind('click', $.fancybox.close); - } - - if (currentOpts.hideOnOverlayClick) { - overlay.bind('click', $.fancybox.close); - } - - $(window).bind("resize.fb", $.fancybox.resize); - - if (currentOpts.centerOnScroll) { - $(window).bind("scroll.fb", $.fancybox.center); - } - - if (currentOpts.type == 'iframe') { - $('<iframe id="fancybox-frame" name="fancybox-frame' + new Date().getTime() + '" frameborder="0" hspace="0" ' + ($.browser.msie ? 'allowtransparency="true""' : '') + ' scrolling="' + selectedOpts.scrolling + '" src="' + currentOpts.href + '"></iframe>').appendTo(content); - } - - wrap.show(); - - busy = false; - - $.fancybox.center(); - - currentOpts.onComplete(currentArray, currentIndex, currentOpts); - - _preload_images(); - }, - - _preload_images = function() { - var href, - objNext; - - if ((currentArray.length -1) > currentIndex) { - href = currentArray[ currentIndex + 1 ].href; - - if (typeof href !== 'undefined' && href.match(imgRegExp)) { - objNext = new Image(); - objNext.src = href; - } - } - - if (currentIndex > 0) { - href = currentArray[ currentIndex - 1 ].href; - - if (typeof href !== 'undefined' && href.match(imgRegExp)) { - objNext = new Image(); - objNext.src = href; - } - } - }, - - _draw = function(pos) { - var dim = { - width : parseInt(start_pos.width + (final_pos.width - start_pos.width) * pos, 10), - height : parseInt(start_pos.height + (final_pos.height - start_pos.height) * pos, 10), - - top : parseInt(start_pos.top + (final_pos.top - start_pos.top) * pos, 10), - left : parseInt(start_pos.left + (final_pos.left - start_pos.left) * pos, 10) - }; - - if (typeof final_pos.opacity !== 'undefined') { - dim.opacity = pos < 0.5 ? 0.5 : pos; - } - - wrap.css(dim); - - content.css({ - 'width' : dim.width - currentOpts.padding * 2, - 'height' : dim.height - (titleHeight * pos) - currentOpts.padding * 2 - }); - }, - - _get_viewport = function() { - return [ - $(window).width() - (currentOpts.margin * 2), - $(window).height() - (currentOpts.margin * 2), - $(document).scrollLeft() + currentOpts.margin, - $(document).scrollTop() + currentOpts.margin - ]; - }, - - _get_zoom_to = function () { - var view = _get_viewport(), - to = {}, - resize = currentOpts.autoScale, - double_padding = currentOpts.padding * 2, - ratio; - - if (currentOpts.width.toString().indexOf('%') > -1) { - to.width = parseInt((view[0] * parseFloat(currentOpts.width)) / 100, 10); - } else { - to.width = currentOpts.width + double_padding; - } - - if (currentOpts.height.toString().indexOf('%') > -1) { - to.height = parseInt((view[1] * parseFloat(currentOpts.height)) / 100, 10); - } else { - to.height = currentOpts.height + double_padding; - } - - if (resize && (to.width > view[0] || to.height > view[1])) { - if (selectedOpts.type == 'image' || selectedOpts.type == 'swf') { - ratio = (currentOpts.width ) / (currentOpts.height ); - - if ((to.width ) > view[0]) { - to.width = view[0]; - to.height = parseInt(((to.width - double_padding) / ratio) + double_padding, 10); - } - - if ((to.height) > view[1]) { - to.height = view[1]; - to.width = parseInt(((to.height - double_padding) * ratio) + double_padding, 10); - } - - } else { - to.width = Math.min(to.width, view[0]); - to.height = Math.min(to.height, view[1]); - } - } - - to.top = parseInt(Math.max(view[3] - 20, view[3] + ((view[1] - to.height - 40) * 0.5)), 10); - to.left = parseInt(Math.max(view[2] - 20, view[2] + ((view[0] - to.width - 40) * 0.5)), 10); - - return to; - }, - - _get_obj_pos = function(obj) { - var pos = obj.offset(); - - pos.top += parseInt( obj.css('paddingTop'), 10 ) || 0; - pos.left += parseInt( obj.css('paddingLeft'), 10 ) || 0; - - pos.top += parseInt( obj.css('border-top-width'), 10 ) || 0; - pos.left += parseInt( obj.css('border-left-width'), 10 ) || 0; - - pos.width = obj.width(); - pos.height = obj.height(); - - return pos; - }, - - _get_zoom_from = function() { - var orig = selectedOpts.orig ? $(selectedOpts.orig) : false, - from = {}, - pos, - view; - - if (orig && orig.length) { - pos = _get_obj_pos(orig); - - from = { - width : pos.width + (currentOpts.padding * 2), - height : pos.height + (currentOpts.padding * 2), - top : pos.top - currentOpts.padding - 20, - left : pos.left - currentOpts.padding - 20 - }; - - } else { - view = _get_viewport(); - - from = { - width : currentOpts.padding * 2, - height : currentOpts.padding * 2, - top : parseInt(view[3] + view[1] * 0.5, 10), - left : parseInt(view[2] + view[0] * 0.5, 10) - }; - } - - return from; - }, - - _animate_loading = function() { - if (!loading.is(':visible')){ - clearInterval(loadingTimer); - return; - } - - $('div', loading).css('top', (loadingFrame * -40) + 'px'); - - loadingFrame = (loadingFrame + 1) % 12; - }; - - /* - * Public methods - */ - - $.fn.fancybox = function(options) { - if (!$(this).length) { - return this; - } - - $(this) - .data('fancybox', $.extend({}, options, ($.metadata ? $(this).metadata() : {}))) - .unbind('click.fb') - .bind('click.fb', function(e) { - e.preventDefault(); - - if (busy) { - return; - } - - busy = true; - - $(this).blur(); - - selectedArray = []; - selectedIndex = 0; - - var rel = $(this).attr('rel') || ''; - - if (!rel || rel == '' || rel === 'nofollow') { - selectedArray.push(this); - - } else { - selectedArray = $("a[rel=" + rel + "], area[rel=" + rel + "]"); - selectedIndex = selectedArray.index( this ); - } - - _start(); - - return; - }); - - return this; - }; - - $.fancybox = function(obj) { - var opts; - - if (busy) { - return; - } - - busy = true; - opts = typeof arguments[1] !== 'undefined' ? arguments[1] : {}; - - selectedArray = []; - selectedIndex = parseInt(opts.index, 10) || 0; - - if ($.isArray(obj)) { - for (var i = 0, j = obj.length; i < j; i++) { - if (typeof obj[i] == 'object') { - $(obj[i]).data('fancybox', $.extend({}, opts, obj[i])); - } else { - obj[i] = $({}).data('fancybox', $.extend({content : obj[i]}, opts)); - } - } - - selectedArray = jQuery.merge(selectedArray, obj); - - } else { - if (typeof obj == 'object') { - $(obj).data('fancybox', $.extend({}, opts, obj)); - } else { - obj = $({}).data('fancybox', $.extend({content : obj}, opts)); - } - - selectedArray.push(obj); - } - - if (selectedIndex > selectedArray.length || selectedIndex < 0) { - selectedIndex = 0; - } - - _start(); - }; - - $.fancybox.showActivity = function() { - clearInterval(loadingTimer); - - loading.show(); - loadingTimer = setInterval(_animate_loading, 66); - }; - - $.fancybox.hideActivity = function() { - loading.hide(); - }; - - $.fancybox.next = function() { - return $.fancybox.pos( currentIndex + 1); - }; - - $.fancybox.prev = function() { - return $.fancybox.pos( currentIndex - 1); - }; - - $.fancybox.pos = function(pos) { - if (busy) { - return; - } - - pos = parseInt(pos); - - selectedArray = currentArray; - - if (pos > -1 && pos < currentArray.length) { - selectedIndex = pos; - _start(); - - } else if (currentOpts.cyclic && currentArray.length > 1) { - selectedIndex = pos >= currentArray.length ? 0 : currentArray.length - 1; - _start(); - } - - return; - }; - - $.fancybox.cancel = function() { - if (busy) { - return; - } - - busy = true; - - $.event.trigger('fancybox-cancel'); - - _abort(); - - selectedOpts.onCancel(selectedArray, selectedIndex, selectedOpts); - - busy = false; - }; - - // Note: within an iframe use - parent.$.fancybox.close(); - $.fancybox.close = function() { - if (busy || wrap.is(':hidden')) { - return; - } - - busy = true; - - if (currentOpts && false === currentOpts.onCleanup(currentArray, currentIndex, currentOpts)) { - busy = false; - return; - } - - _abort(); - - $(close.add( nav_left ).add( nav_right )).hide(); - - $(content.add( overlay )).unbind(); - - $(window).unbind("resize.fb scroll.fb"); - $(document).unbind('keydown.fb'); - - content.find('iframe').attr('src', isIE6 && /^https/i.test(window.location.href || '') ? 'javascript:void(false)' : 'about:blank'); - - if (currentOpts.titlePosition !== 'inside') { - title.empty(); - } - - wrap.stop(); - - function _cleanup() { - overlay.fadeOut('fast'); - - title.empty().hide(); - wrap.hide(); - - $.event.trigger('fancybox-cleanup'); - - content.empty(); - - currentOpts.onClosed(currentArray, currentIndex, currentOpts); - - currentArray = selectedOpts = []; - currentIndex = selectedIndex = 0; - currentOpts = selectedOpts = {}; - - busy = false; - } - - if (currentOpts.transitionOut == 'elastic') { - start_pos = _get_zoom_from(); - - var pos = wrap.position(); - - final_pos = { - top : pos.top , - left : pos.left, - width : wrap.width(), - height : wrap.height() - }; - - if (currentOpts.opacity) { - final_pos.opacity = 1; - } - - title.empty().hide(); - - fx.prop = 1; - - $(fx).animate({ prop: 0 }, { - duration : currentOpts.speedOut, - easing : currentOpts.easingOut, - step : _draw, - complete : _cleanup - }); - - } else { - wrap.fadeOut( currentOpts.transitionOut == 'none' ? 0 : currentOpts.speedOut, _cleanup); - } - }; - - $.fancybox.resize = function() { - if (overlay.is(':visible')) { - overlay.css('height', $(document).height()); - } - - $.fancybox.center(true); - }; - - $.fancybox.center = function() { - var view, align; - - if (busy) { - return; - } - - align = arguments[0] === true ? 1 : 0; - view = _get_viewport(); - - if (!align && (wrap.width() > view[0] || wrap.height() > view[1])) { - return; - } - - wrap - .stop() - .animate({ - 'top' : parseInt(Math.max(view[3] - 20, view[3] + ((view[1] - content.height() - 40) * 0.5) - currentOpts.padding)), - 'left' : parseInt(Math.max(view[2] - 20, view[2] + ((view[0] - content.width() - 40) * 0.5) - currentOpts.padding)) - }, typeof arguments[0] == 'number' ? arguments[0] : 200); - }; - - $.fancybox.init = function() { - if ($("#fancybox-wrap").length) { - return; - } - - $('body').append( - tmp = $('<div id="fancybox-tmp"></div>'), - loading = $('<div id="fancybox-loading"><div></div></div>'), - overlay = $('<div id="fancybox-overlay"></div>'), - wrap = $('<div id="fancybox-wrap"></div>') - ); - - outer = $('<div id="fancybox-outer"></div>') - .append('<div class="fancybox-bg" id="fancybox-bg-n"></div><div class="fancybox-bg" id="fancybox-bg-ne"></div><div class="fancybox-bg" id="fancybox-bg-e"></div><div class="fancybox-bg" id="fancybox-bg-se"></div><div class="fancybox-bg" id="fancybox-bg-s"></div><div class="fancybox-bg" id="fancybox-bg-sw"></div><div class="fancybox-bg" id="fancybox-bg-w"></div><div class="fancybox-bg" id="fancybox-bg-nw"></div>') - .appendTo( wrap ); - - outer.append( - content = $('<div id="fancybox-content"></div>'), - close = $('<a id="fancybox-close"></a>'), - title = $('<div id="fancybox-title"></div>'), - - nav_left = $('<a href="javascript:;" id="fancybox-left"><span class="fancy-ico" id="fancybox-left-ico"></span></a>'), - nav_right = $('<a href="javascript:;" id="fancybox-right"><span class="fancy-ico" id="fancybox-right-ico"></span></a>') - ); - - close.click($.fancybox.close); - loading.click($.fancybox.cancel); - - nav_left.click(function(e) { - e.preventDefault(); - $.fancybox.prev(); - }); - - nav_right.click(function(e) { - e.preventDefault(); - $.fancybox.next(); - }); - - if ($.fn.mousewheel) { - wrap.bind('mousewheel.fb', function(e, delta) { - if (busy) { - e.preventDefault(); - - } else if ($(e.target).get(0).clientHeight == 0 || $(e.target).get(0).scrollHeight === $(e.target).get(0).clientHeight) { - e.preventDefault(); - $.fancybox[ delta > 0 ? 'prev' : 'next'](); - } - }); - } - - if (!$.support.opacity) { - wrap.addClass('fancybox-ie'); - } - - if (isIE6) { - loading.addClass('fancybox-ie6'); - wrap.addClass('fancybox-ie6'); - - $('<iframe id="fancybox-hide-sel-frame" src="' + (/^https/i.test(window.location.href || '') ? 'javascript:void(false)' : 'about:blank' ) + '" scrolling="no" border="0" frameborder="0" tabindex="-1"></iframe>').prependTo(outer); - } - }; - - $.fn.fancybox.defaults = { - padding : 10, - margin : 40, - opacity : false, - modal : false, - cyclic : false, - scrolling : 'auto', // 'auto', 'yes' or 'no' - - width : 560, - height : 340, - - autoScale : true, - autoDimensions : true, - centerOnScroll : false, - - ajax : {}, - swf : { wmode: 'transparent' }, - - hideOnOverlayClick : true, - hideOnContentClick : false, - - overlayShow : true, - overlayOpacity : 0.7, - overlayColor : '#777', - - titleShow : true, - titlePosition : 'float', // 'float', 'outside', 'inside' or 'over' - titleFormat : null, - titleFromAlt : false, - - transitionIn : 'fade', // 'elastic', 'fade' or 'none' - transitionOut : 'fade', // 'elastic', 'fade' or 'none' - - speedIn : 300, - speedOut : 300, - - changeSpeed : 300, - changeFade : 'fast', - - easingIn : 'swing', - easingOut : 'swing', - - showCloseButton : true, - showNavArrows : true, - enableEscapeButton : true, - enableKeyboardNav : true, - - onStart : function(){}, - onCancel : function(){}, - onComplete : function(){}, - onCleanup : function(){}, - onClosed : function(){}, - onError : function(){} - }; - - $(document).ready(function() { - $.fancybox.init(); - }); - +/* + * FancyBox - jQuery Plugin + * Simple and fancy lightbox alternative + * + * Examples and documentation at: http://fancybox.net + * + * Copyright (c) 2008 - 2010 Janis Skarnelis + * That said, it is hardly a one-person project. Many people have submitted bugs, code, and offered their advice freely. Their support is greatly appreciated. + * + * Version: 1.3.4 (11/11/2010) + * Requires: jQuery v1.3+ + * + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + */ + +;(function($) { + var tmp, loading, overlay, wrap, outer, content, close, title, nav_left, nav_right, + + selectedIndex = 0, selectedOpts = {}, selectedArray = [], currentIndex = 0, currentOpts = {}, currentArray = [], + + ajaxLoader = null, imgPreloader = new Image(), imgRegExp = /\.(jpg|gif|png|bmp|jpeg)(.*)?$/i, swfRegExp = /[^\.]\.(swf)\s*$/i, + + loadingTimer, loadingFrame = 1, + + titleHeight = 0, titleStr = '', start_pos, final_pos, busy = false, fx = $.extend($('<div/>')[0], { prop: 0 }), + + isIE6 = $.browser.msie && $.browser.version < 7 && !window.XMLHttpRequest, + + /* + * Private methods + */ + + _abort = function() { + loading.hide(); + + imgPreloader.onerror = imgPreloader.onload = null; + + if (ajaxLoader) { + ajaxLoader.abort(); + } + + tmp.empty(); + }, + + _error = function() { + if (false === selectedOpts.onError(selectedArray, selectedIndex, selectedOpts)) { + loading.hide(); + busy = false; + return; + } + + selectedOpts.titleShow = false; + + selectedOpts.width = 'auto'; + selectedOpts.height = 'auto'; + + tmp.html( '<p id="fancybox-error">The requested content cannot be loaded.<br />Please try again later.</p>' ); + + _process_inline(); + }, + + _start = function() { + var obj = selectedArray[ selectedIndex ], + href, + type, + title, + str, + emb, + ret; + + _abort(); + + selectedOpts = $.extend({}, $.fn.fancybox.defaults, (typeof $(obj).data('fancybox') == 'undefined' ? selectedOpts : $(obj).data('fancybox'))); + + ret = selectedOpts.onStart(selectedArray, selectedIndex, selectedOpts); + + if (ret === false) { + busy = false; + return; + } else if (typeof ret == 'object') { + selectedOpts = $.extend(selectedOpts, ret); + } + + title = selectedOpts.title || (obj.nodeName ? $(obj).attr('title') : obj.title) || ''; + + if (obj.nodeName && !selectedOpts.orig) { + selectedOpts.orig = $(obj).children("img:first").length ? $(obj).children("img:first") : $(obj); + } + + if (title === '' && selectedOpts.orig && selectedOpts.titleFromAlt) { + title = selectedOpts.orig.attr('alt'); + } + + href = selectedOpts.href || (obj.nodeName ? $(obj).attr('href') : obj.href) || null; + + if ((/^(?:javascript)/i).test(href) || href == '#') { + href = null; + } + + if (selectedOpts.type) { + type = selectedOpts.type; + + if (!href) { + href = selectedOpts.content; + } + + } else if (selectedOpts.content) { + type = 'html'; + + } else if (href) { + if (href.match(imgRegExp)) { + type = 'image'; + + } else if (href.match(swfRegExp)) { + type = 'swf'; + + } else if ($(obj).hasClass("iframe")) { + type = 'iframe'; + + } else if (href.indexOf("#") === 0) { + type = 'inline'; + + } else { + type = 'ajax'; + } + } + + if (!type) { + _error(); + return; + } + + if (type == 'inline') { + obj = href.substr(href.indexOf("#")); + type = $(obj).length > 0 ? 'inline' : 'ajax'; + } + + selectedOpts.type = type; + selectedOpts.href = href; + selectedOpts.title = title; + + if (selectedOpts.autoDimensions) { + if (selectedOpts.type == 'html' || selectedOpts.type == 'inline' || selectedOpts.type == 'ajax') { + selectedOpts.width = 'auto'; + selectedOpts.height = 'auto'; + } else { + selectedOpts.autoDimensions = false; + } + } + + if (selectedOpts.modal) { + selectedOpts.overlayShow = true; + selectedOpts.hideOnOverlayClick = false; + selectedOpts.hideOnContentClick = false; + selectedOpts.enableEscapeButton = false; + selectedOpts.showCloseButton = false; + } + + selectedOpts.padding = parseInt(selectedOpts.padding, 10); + selectedOpts.margin = parseInt(selectedOpts.margin, 10); + + tmp.css('padding', (selectedOpts.padding + selectedOpts.margin)); + + $('.fancybox-inline-tmp').unbind('fancybox-cancel').bind('fancybox-change', function() { + $(this).replaceWith(content.children()); + }); + + switch (type) { + case 'html' : + tmp.html( selectedOpts.content ); + _process_inline(); + break; + + case 'inline' : + if ( $(obj).parent().is('#fancybox-content') === true) { + busy = false; + return; + } + + $('<div class="fancybox-inline-tmp" />') + .hide() + .insertBefore( $(obj) ) + .bind('fancybox-cleanup', function() { + $(this).replaceWith(content.children()); + }).bind('fancybox-cancel', function() { + $(this).replaceWith(tmp.children()); + }); + + $(obj).appendTo(tmp); + + _process_inline(); + break; + + case 'image': + busy = false; + + $.fancybox.showActivity(); + + imgPreloader = new Image(); + + imgPreloader.onerror = function() { + _error(); + }; + + imgPreloader.onload = function() { + busy = true; + + imgPreloader.onerror = imgPreloader.onload = null; + + _process_image(); + }; + + imgPreloader.src = href; + break; + + case 'swf': + selectedOpts.scrolling = 'no'; + + str = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="' + selectedOpts.width + '" height="' + selectedOpts.height + '"><param name="movie" value="' + href + '"></param>'; + emb = ''; + + $.each(selectedOpts.swf, function(name, val) { + str += '<param name="' + name + '" value="' + val + '"></param>'; + emb += ' ' + name + '="' + val + '"'; + }); + + str += '<embed src="' + href + '" type="application/x-shockwave-flash" width="' + selectedOpts.width + '" height="' + selectedOpts.height + '"' + emb + '></embed></object>'; + + tmp.html(str); + + _process_inline(); + break; + + case 'ajax': + busy = false; + + $.fancybox.showActivity(); + + selectedOpts.ajax.win = selectedOpts.ajax.success; + + ajaxLoader = $.ajax($.extend({}, selectedOpts.ajax, { + url : href, + data : selectedOpts.ajax.data || {}, + error : function(XMLHttpRequest, textStatus, errorThrown) { + if ( XMLHttpRequest.status > 0 ) { + _error(); + } + }, + success : function(data, textStatus, XMLHttpRequest) { + var o = typeof XMLHttpRequest == 'object' ? XMLHttpRequest : ajaxLoader; + if (o.status == 200) { + if ( typeof selectedOpts.ajax.win == 'function' ) { + ret = selectedOpts.ajax.win(href, data, textStatus, XMLHttpRequest); + + if (ret === false) { + loading.hide(); + return; + } else if (typeof ret == 'string' || typeof ret == 'object') { + data = ret; + } + } + + tmp.html( data ); + _process_inline(); + } + } + })); + + break; + + case 'iframe': + _show(); + break; + } + }, + + _process_inline = function() { + var + w = selectedOpts.width, + h = selectedOpts.height; + + if (w.toString().indexOf('%') > -1) { + w = parseInt( ($(window).width() - (selectedOpts.margin * 2)) * parseFloat(w) / 100, 10) + 'px'; + + } else { + w = w == 'auto' ? 'auto' : w + 'px'; + } + + if (h.toString().indexOf('%') > -1) { + h = parseInt( ($(window).height() - (selectedOpts.margin * 2)) * parseFloat(h) / 100, 10) + 'px'; + + } else { + h = h == 'auto' ? 'auto' : h + 'px'; + } + + tmp.wrapInner('<div style="width:' + w + ';height:' + h + ';overflow: ' + (selectedOpts.scrolling == 'auto' ? 'auto' : (selectedOpts.scrolling == 'yes' ? 'scroll' : 'hidden')) + ';position:relative;"></div>'); + + selectedOpts.width = tmp.width(); + selectedOpts.height = tmp.height(); + + _show(); + }, + + _process_image = function() { + selectedOpts.width = imgPreloader.width; + selectedOpts.height = imgPreloader.height; + + $("<img />").attr({ + 'id' : 'fancybox-img', + 'src' : imgPreloader.src, + 'alt' : selectedOpts.title + }).appendTo( tmp ); + + _show(); + }, + + _show = function() { + var pos, equal; + + loading.hide(); + + if (wrap.is(":visible") && false === currentOpts.onCleanup(currentArray, currentIndex, currentOpts)) { + $.event.trigger('fancybox-cancel'); + + busy = false; + return; + } + + busy = true; + + $(content.add( overlay )).unbind(); + + $(window).unbind("resize.fb scroll.fb"); + $(document).unbind('keydown.fb'); + + if (wrap.is(":visible") && currentOpts.titlePosition !== 'outside') { + wrap.css('height', wrap.height()); + } + + currentArray = selectedArray; + currentIndex = selectedIndex; + currentOpts = selectedOpts; + + if (currentOpts.overlayShow) { + overlay.css({ + 'background-color' : currentOpts.overlayColor, + 'opacity' : currentOpts.overlayOpacity, + 'cursor' : currentOpts.hideOnOverlayClick ? 'pointer' : 'auto', + 'height' : $(document).height() + }); + + if (!overlay.is(':visible')) { + if (isIE6) { + $('select:not(#fancybox-tmp select)').filter(function() { + return this.style.visibility !== 'hidden'; + }).css({'visibility' : 'hidden'}).one('fancybox-cleanup', function() { + this.style.visibility = 'inherit'; + }); + } + + overlay.show(); + } + } else { + overlay.hide(); + } + + final_pos = _get_zoom_to(); + + _process_title(); + + if (wrap.is(":visible")) { + $( close.add( nav_left ).add( nav_right ) ).hide(); + + pos = wrap.position(), + + start_pos = { + top : pos.top, + left : pos.left, + width : wrap.width(), + height : wrap.height() + }; + + equal = (start_pos.width == final_pos.width && start_pos.height == final_pos.height); + + content.fadeTo(currentOpts.changeFade, 0.3, function() { + var finish_resizing = function() { + content.html( tmp.contents() ).fadeTo(currentOpts.changeFade, 1, _finish); + }; + + $.event.trigger('fancybox-change'); + + content + .empty() + .removeAttr('filter') + .css({ + 'border-width' : currentOpts.padding, + 'width' : final_pos.width - currentOpts.padding * 2, + 'height' : selectedOpts.autoDimensions ? 'auto' : final_pos.height - titleHeight - currentOpts.padding * 2 + }); + + if (equal) { + finish_resizing(); + + } else { + fx.prop = 0; + + $(fx).animate({prop: 1}, { + duration : currentOpts.changeSpeed, + easing : currentOpts.easingChange, + step : _draw, + complete : finish_resizing + }); + } + }); + + return; + } + + wrap.removeAttr("style"); + + content.css('border-width', currentOpts.padding); + + if (currentOpts.transitionIn == 'elastic') { + start_pos = _get_zoom_from(); + + content.html( tmp.contents() ); + + wrap.show(); + + if (currentOpts.opacity) { + final_pos.opacity = 0; + } + + fx.prop = 0; + + $(fx).animate({prop: 1}, { + duration : currentOpts.speedIn, + easing : currentOpts.easingIn, + step : _draw, + complete : _finish + }); + + return; + } + + if (currentOpts.titlePosition == 'inside' && titleHeight > 0) { + title.show(); + } + + content + .css({ + 'width' : final_pos.width - currentOpts.padding * 2, + 'height' : selectedOpts.autoDimensions ? 'auto' : final_pos.height - titleHeight - currentOpts.padding * 2 + }) + .html( tmp.contents() ); + + wrap + .css(final_pos) + .fadeIn( currentOpts.transitionIn == 'none' ? 0 : currentOpts.speedIn, _finish ); + }, + + _format_title = function(title) { + if (title && title.length) { + if (currentOpts.titlePosition == 'float') { + return '<table id="fancybox-title-float-wrap" cellpadding="0" cellspacing="0"><tr><td id="fancybox-title-float-left"></td><td id="fancybox-title-float-main">' + title + '</td><td id="fancybox-title-float-right"></td></tr></table>'; + } + + return '<div id="fancybox-title-' + currentOpts.titlePosition + '">' + title + '</div>'; + } + + return false; + }, + + _process_title = function() { + titleStr = currentOpts.title || ''; + titleHeight = 0; + + title + .empty() + .removeAttr('style') + .removeClass(); + + if (currentOpts.titleShow === false) { + title.hide(); + return; + } + + titleStr = $.isFunction(currentOpts.titleFormat) ? currentOpts.titleFormat(titleStr, currentArray, currentIndex, currentOpts) : _format_title(titleStr); + + if (!titleStr || titleStr === '') { + title.hide(); + return; + } + + title + .addClass('fancybox-title-' + currentOpts.titlePosition) + .html( titleStr ) + .appendTo( 'body' ) + .show(); + + switch (currentOpts.titlePosition) { + case 'inside': + title + .css({ + 'width' : final_pos.width - (currentOpts.padding * 2), + 'marginLeft' : currentOpts.padding, + 'marginRight' : currentOpts.padding + }); + + titleHeight = title.outerHeight(true); + + title.appendTo( outer ); + + final_pos.height += titleHeight; + break; + + case 'over': + title + .css({ + 'marginLeft' : currentOpts.padding, + 'width' : final_pos.width - (currentOpts.padding * 2), + 'bottom' : currentOpts.padding + }) + .appendTo( outer ); + break; + + case 'float': + title + .css('left', parseInt((title.width() - final_pos.width - 40)/ 2, 10) * -1) + .appendTo( wrap ); + break; + + default: + title + .css({ + 'width' : final_pos.width - (currentOpts.padding * 2), + 'paddingLeft' : currentOpts.padding, + 'paddingRight' : currentOpts.padding + }) + .appendTo( wrap ); + break; + } + + title.hide(); + }, + + _set_navigation = function() { + if (currentOpts.enableEscapeButton || currentOpts.enableKeyboardNav) { + $(document).bind('keydown.fb', function(e) { + if (e.keyCode == 27 && currentOpts.enableEscapeButton) { + e.preventDefault(); + $.fancybox.close(); + + } else if ((e.keyCode == 37 || e.keyCode == 39) && currentOpts.enableKeyboardNav && e.target.tagName !== 'INPUT' && e.target.tagName !== 'TEXTAREA' && e.target.tagName !== 'SELECT') { + e.preventDefault(); + $.fancybox[ e.keyCode == 37 ? 'prev' : 'next'](); + } + }); + } + + if (!currentOpts.showNavArrows) { + nav_left.hide(); + nav_right.hide(); + return; + } + + if ((currentOpts.cyclic && currentArray.length > 1) || currentIndex !== 0) { + nav_left.show(); + } + + if ((currentOpts.cyclic && currentArray.length > 1) || currentIndex != (currentArray.length -1)) { + nav_right.show(); + } + }, + + _finish = function () { + if (!$.support.opacity) { + content.get(0).style.removeAttribute('filter'); + wrap.get(0).style.removeAttribute('filter'); + } + + if (selectedOpts.autoDimensions) { + content.css('height', 'auto'); + } + + wrap.css('height', 'auto'); + + if (titleStr && titleStr.length) { + title.show(); + } + + if (currentOpts.showCloseButton) { + close.show(); + } + + _set_navigation(); + + if (currentOpts.hideOnContentClick) { + content.bind('click', $.fancybox.close); + } + + if (currentOpts.hideOnOverlayClick) { + overlay.bind('click', $.fancybox.close); + } + + $(window).bind("resize.fb", $.fancybox.resize); + + if (currentOpts.centerOnScroll) { + $(window).bind("scroll.fb", $.fancybox.center); + } + + if (currentOpts.type == 'iframe') { + $('<iframe id="fancybox-frame" name="fancybox-frame' + new Date().getTime() + '" frameborder="0" hspace="0" ' + ($.browser.msie ? 'allowtransparency="true""' : '') + ' scrolling="' + selectedOpts.scrolling + '" src="' + currentOpts.href + '"></iframe>').appendTo(content); + } + + wrap.show(); + + busy = false; + + $.fancybox.center(); + + currentOpts.onComplete(currentArray, currentIndex, currentOpts); + + _preload_images(); + }, + + _preload_images = function() { + var href, + objNext; + + if ((currentArray.length -1) > currentIndex) { + href = currentArray[ currentIndex + 1 ].href; + + if (typeof href !== 'undefined' && href.match(imgRegExp)) { + objNext = new Image(); + objNext.src = href; + } + } + + if (currentIndex > 0) { + href = currentArray[ currentIndex - 1 ].href; + + if (typeof href !== 'undefined' && href.match(imgRegExp)) { + objNext = new Image(); + objNext.src = href; + } + } + }, + + _draw = function(pos) { + var dim = { + width : parseInt(start_pos.width + (final_pos.width - start_pos.width) * pos, 10), + height : parseInt(start_pos.height + (final_pos.height - start_pos.height) * pos, 10), + + top : parseInt(start_pos.top + (final_pos.top - start_pos.top) * pos, 10), + left : parseInt(start_pos.left + (final_pos.left - start_pos.left) * pos, 10) + }; + + if (typeof final_pos.opacity !== 'undefined') { + dim.opacity = pos < 0.5 ? 0.5 : pos; + } + + wrap.css(dim); + + content.css({ + 'width' : dim.width - currentOpts.padding * 2, + 'height' : dim.height - (titleHeight * pos) - currentOpts.padding * 2 + }); + }, + + _get_viewport = function() { + return [ + $(window).width() - (currentOpts.margin * 2), + $(window).height() - (currentOpts.margin * 2), + $(document).scrollLeft() + currentOpts.margin, + $(document).scrollTop() + currentOpts.margin + ]; + }, + + _get_zoom_to = function () { + var view = _get_viewport(), + to = {}, + resize = currentOpts.autoScale, + double_padding = currentOpts.padding * 2, + ratio; + + if (currentOpts.width.toString().indexOf('%') > -1) { + to.width = parseInt((view[0] * parseFloat(currentOpts.width)) / 100, 10); + } else { + to.width = currentOpts.width + double_padding; + } + + if (currentOpts.height.toString().indexOf('%') > -1) { + to.height = parseInt((view[1] * parseFloat(currentOpts.height)) / 100, 10); + } else { + to.height = currentOpts.height + double_padding; + } + + if (resize && (to.width > view[0] || to.height > view[1])) { + if (selectedOpts.type == 'image' || selectedOpts.type == 'swf') { + ratio = (currentOpts.width ) / (currentOpts.height ); + + if ((to.width ) > view[0]) { + to.width = view[0]; + to.height = parseInt(((to.width - double_padding) / ratio) + double_padding, 10); + } + + if ((to.height) > view[1]) { + to.height = view[1]; + to.width = parseInt(((to.height - double_padding) * ratio) + double_padding, 10); + } + + } else { + to.width = Math.min(to.width, view[0]); + to.height = Math.min(to.height, view[1]); + } + } + + to.top = parseInt(Math.max(view[3] - 20, view[3] + ((view[1] - to.height - 40) * 0.5)), 10); + to.left = parseInt(Math.max(view[2] - 20, view[2] + ((view[0] - to.width - 40) * 0.5)), 10); + + return to; + }, + + _get_obj_pos = function(obj) { + var pos = obj.offset(); + + pos.top += parseInt( obj.css('paddingTop'), 10 ) || 0; + pos.left += parseInt( obj.css('paddingLeft'), 10 ) || 0; + + pos.top += parseInt( obj.css('border-top-width'), 10 ) || 0; + pos.left += parseInt( obj.css('border-left-width'), 10 ) || 0; + + pos.width = obj.width(); + pos.height = obj.height(); + + return pos; + }, + + _get_zoom_from = function() { + var orig = selectedOpts.orig ? $(selectedOpts.orig) : false, + from = {}, + pos, + view; + + if (orig && orig.length) { + pos = _get_obj_pos(orig); + + from = { + width : pos.width + (currentOpts.padding * 2), + height : pos.height + (currentOpts.padding * 2), + top : pos.top - currentOpts.padding - 20, + left : pos.left - currentOpts.padding - 20 + }; + + } else { + view = _get_viewport(); + + from = { + width : currentOpts.padding * 2, + height : currentOpts.padding * 2, + top : parseInt(view[3] + view[1] * 0.5, 10), + left : parseInt(view[2] + view[0] * 0.5, 10) + }; + } + + return from; + }, + + _animate_loading = function() { + if (!loading.is(':visible')){ + clearInterval(loadingTimer); + return; + } + + $('div', loading).css('top', (loadingFrame * -40) + 'px'); + + loadingFrame = (loadingFrame + 1) % 12; + }; + + /* + * Public methods + */ + + $.fn.fancybox = function(options) { + if (!$(this).length) { + return this; + } + + $(this) + .data('fancybox', $.extend({}, options, ($.metadata ? $(this).metadata() : {}))) + .unbind('click.fb') + .bind('click.fb', function(e) { + e.preventDefault(); + + if (busy) { + return; + } + + busy = true; + + $(this).blur(); + + selectedArray = []; + selectedIndex = 0; + + var rel = $(this).attr('rel') || ''; + + if (!rel || rel == '' || rel === 'nofollow') { + selectedArray.push(this); + + } else { + selectedArray = $("a[rel=" + rel + "], area[rel=" + rel + "]"); + selectedIndex = selectedArray.index( this ); + } + + _start(); + + return; + }); + + return this; + }; + + $.fancybox = function(obj) { + var opts; + + if (busy) { + return; + } + + busy = true; + opts = typeof arguments[1] !== 'undefined' ? arguments[1] : {}; + + selectedArray = []; + selectedIndex = parseInt(opts.index, 10) || 0; + + if ($.isArray(obj)) { + for (var i = 0, j = obj.length; i < j; i++) { + if (typeof obj[i] == 'object') { + $(obj[i]).data('fancybox', $.extend({}, opts, obj[i])); + } else { + obj[i] = $({}).data('fancybox', $.extend({content : obj[i]}, opts)); + } + } + + selectedArray = jQuery.merge(selectedArray, obj); + + } else { + if (typeof obj == 'object') { + $(obj).data('fancybox', $.extend({}, opts, obj)); + } else { + obj = $({}).data('fancybox', $.extend({content : obj}, opts)); + } + + selectedArray.push(obj); + } + + if (selectedIndex > selectedArray.length || selectedIndex < 0) { + selectedIndex = 0; + } + + _start(); + }; + + $.fancybox.showActivity = function() { + clearInterval(loadingTimer); + + loading.show(); + loadingTimer = setInterval(_animate_loading, 66); + }; + + $.fancybox.hideActivity = function() { + loading.hide(); + }; + + $.fancybox.next = function() { + return $.fancybox.pos( currentIndex + 1); + }; + + $.fancybox.prev = function() { + return $.fancybox.pos( currentIndex - 1); + }; + + $.fancybox.pos = function(pos) { + if (busy) { + return; + } + + pos = parseInt(pos); + + selectedArray = currentArray; + + if (pos > -1 && pos < currentArray.length) { + selectedIndex = pos; + _start(); + + } else if (currentOpts.cyclic && currentArray.length > 1) { + selectedIndex = pos >= currentArray.length ? 0 : currentArray.length - 1; + _start(); + } + + return; + }; + + $.fancybox.cancel = function() { + if (busy) { + return; + } + + busy = true; + + $.event.trigger('fancybox-cancel'); + + _abort(); + + selectedOpts.onCancel(selectedArray, selectedIndex, selectedOpts); + + busy = false; + }; + + // Note: within an iframe use - parent.$.fancybox.close(); + $.fancybox.close = function() { + if (busy || wrap.is(':hidden')) { + return; + } + + busy = true; + + if (currentOpts && false === currentOpts.onCleanup(currentArray, currentIndex, currentOpts)) { + busy = false; + return; + } + + _abort(); + + $(close.add( nav_left ).add( nav_right )).hide(); + + $(content.add( overlay )).unbind(); + + $(window).unbind("resize.fb scroll.fb"); + $(document).unbind('keydown.fb'); + + content.find('iframe').attr('src', isIE6 && /^https/i.test(window.location.href || '') ? 'javascript:void(false)' : 'about:blank'); + + if (currentOpts.titlePosition !== 'inside') { + title.empty(); + } + + wrap.stop(); + + function _cleanup() { + overlay.fadeOut('fast'); + + title.empty().hide(); + wrap.hide(); + + $.event.trigger('fancybox-cleanup'); + + content.empty(); + + currentOpts.onClosed(currentArray, currentIndex, currentOpts); + + currentArray = selectedOpts = []; + currentIndex = selectedIndex = 0; + currentOpts = selectedOpts = {}; + + busy = false; + } + + if (currentOpts.transitionOut == 'elastic') { + start_pos = _get_zoom_from(); + + var pos = wrap.position(); + + final_pos = { + top : pos.top , + left : pos.left, + width : wrap.width(), + height : wrap.height() + }; + + if (currentOpts.opacity) { + final_pos.opacity = 1; + } + + title.empty().hide(); + + fx.prop = 1; + + $(fx).animate({ prop: 0 }, { + duration : currentOpts.speedOut, + easing : currentOpts.easingOut, + step : _draw, + complete : _cleanup + }); + + } else { + wrap.fadeOut( currentOpts.transitionOut == 'none' ? 0 : currentOpts.speedOut, _cleanup); + } + }; + + $.fancybox.resize = function() { + if (overlay.is(':visible')) { + overlay.css('height', $(document).height()); + } + + $.fancybox.center(true); + }; + + $.fancybox.center = function() { + var view, align; + + if (busy) { + return; + } + + align = arguments[0] === true ? 1 : 0; + view = _get_viewport(); + + if (!align && (wrap.width() > view[0] || wrap.height() > view[1])) { + return; + } + + wrap + .stop() + .animate({ + 'top' : parseInt(Math.max(view[3] - 20, view[3] + ((view[1] - content.height() - 40) * 0.5) - currentOpts.padding)), + 'left' : parseInt(Math.max(view[2] - 20, view[2] + ((view[0] - content.width() - 40) * 0.5) - currentOpts.padding)) + }, typeof arguments[0] == 'number' ? arguments[0] : 200); + }; + + $.fancybox.init = function() { + if ($("#fancybox-wrap").length) { + return; + } + + $('body').append( + tmp = $('<div id="fancybox-tmp"></div>'), + loading = $('<div id="fancybox-loading"><div></div></div>'), + overlay = $('<div id="fancybox-overlay"></div>'), + wrap = $('<div id="fancybox-wrap"></div>') + ); + + outer = $('<div id="fancybox-outer"></div>') + .append('<div class="fancybox-bg" id="fancybox-bg-n"></div><div class="fancybox-bg" id="fancybox-bg-ne"></div><div class="fancybox-bg" id="fancybox-bg-e"></div><div class="fancybox-bg" id="fancybox-bg-se"></div><div class="fancybox-bg" id="fancybox-bg-s"></div><div class="fancybox-bg" id="fancybox-bg-sw"></div><div class="fancybox-bg" id="fancybox-bg-w"></div><div class="fancybox-bg" id="fancybox-bg-nw"></div>') + .appendTo( wrap ); + + outer.append( + content = $('<div id="fancybox-content"></div>'), + close = $('<a id="fancybox-close"></a>'), + title = $('<div id="fancybox-title"></div>'), + + nav_left = $('<a href="javascript:;" id="fancybox-left"><span class="fancy-ico" id="fancybox-left-ico"></span></a>'), + nav_right = $('<a href="javascript:;" id="fancybox-right"><span class="fancy-ico" id="fancybox-right-ico"></span></a>') + ); + + close.click($.fancybox.close); + loading.click($.fancybox.cancel); + + nav_left.click(function(e) { + e.preventDefault(); + $.fancybox.prev(); + }); + + nav_right.click(function(e) { + e.preventDefault(); + $.fancybox.next(); + }); + + if ($.fn.mousewheel) { + wrap.bind('mousewheel.fb', function(e, delta) { + if (busy) { + e.preventDefault(); + + } else if ($(e.target).get(0).clientHeight == 0 || $(e.target).get(0).scrollHeight === $(e.target).get(0).clientHeight) { + e.preventDefault(); + $.fancybox[ delta > 0 ? 'prev' : 'next'](); + } + }); + } + + if (!$.support.opacity) { + wrap.addClass('fancybox-ie'); + } + + if (isIE6) { + loading.addClass('fancybox-ie6'); + wrap.addClass('fancybox-ie6'); + + $('<iframe id="fancybox-hide-sel-frame" src="' + (/^https/i.test(window.location.href || '') ? 'javascript:void(false)' : 'about:blank' ) + '" scrolling="no" border="0" frameborder="0" tabindex="-1"></iframe>').prependTo(outer); + } + }; + + $.fn.fancybox.defaults = { + padding : 10, + margin : 40, + opacity : false, + modal : false, + cyclic : false, + scrolling : 'auto', // 'auto', 'yes' or 'no' + + width : 560, + height : 340, + + autoScale : true, + autoDimensions : true, + centerOnScroll : false, + + ajax : {}, + swf : { wmode: 'transparent' }, + + hideOnOverlayClick : true, + hideOnContentClick : false, + + overlayShow : true, + overlayOpacity : 0.7, + overlayColor : '#777', + + titleShow : true, + titlePosition : 'float', // 'float', 'outside', 'inside' or 'over' + titleFormat : null, + titleFromAlt : false, + + transitionIn : 'fade', // 'elastic', 'fade' or 'none' + transitionOut : 'fade', // 'elastic', 'fade' or 'none' + + speedIn : 300, + speedOut : 300, + + changeSpeed : 300, + changeFade : 'fast', + + easingIn : 'swing', + easingOut : 'swing', + + showCloseButton : true, + showNavArrows : true, + enableEscapeButton : true, + enableKeyboardNav : true, + + onStart : function(){}, + onCancel : function(){}, + onComplete : function(){}, + onCleanup : function(){}, + onClosed : function(){}, + onError : function(){} + }; + + $(document).ready(function() { + $.fancybox.init(); + }); + })(jQuery); \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/mvc/module.mvc.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/mvc/module.mvc.php index 92c748549cb04ddce0bfa2682cf2627cc781837c..ba9cdd1a799f5095cfcfdb6f88758e82946d3f3e 100755 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/mvc/module.mvc.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/mvc/module.mvc.php @@ -20,7 +20,7 @@ class M_MVC extends C_Base_Module "photocrati-mvc", "MVC Framework", "Provides an MVC architecture for the plugin to use", - "0.6", + "0.7", "https://www.imagely.com", "Photocrati Media", "https://www.imagely.com" diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/mvc/package.module.mvc.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/mvc/package.module.mvc.php index ab50e3c2325b43a4d08986a3105d127ecc28a936..7295bd43313756f5c5a697a9f486e02bd0d3f477 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/mvc/package.module.mvc.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/mvc/package.module.mvc.php @@ -17,7 +17,7 @@ class A_MVC_Fs extends Mixin public function initialize() { register_shutdown_function(array(&$this, 'cache_lookups')); - self::$_lookups = C_Photocrati_Transient_Manager::fetch($this->_get_cache_key(), array()); + //self::$_lookups = C_Photocrati_Transient_Manager::fetch($this->_get_cache_key(), array()); self::$_non_minified_modules = apply_filters('ngg_non_minified_modules', array()); } public function cache_lookups() @@ -441,23 +441,18 @@ class C_MVC_View extends C_Component public $_engine = ''; public $_params = array(); public $_queue = array(); - public function define($template, $params = array(), $engine = 'php', $context = FALSE) - { - parent::define($context); - $this->implement('I_MVC_View'); - $this->add_mixin('Mixin_Mvc_View_Instance_Methods'); - } - /** - * Initialize the view with some parameters - * @param array $params - * @param context $context - */ - public function initialize($template, $params = array(), $engine = 'php', $context = FALSE) + public function __construct($template, $params = array(), $engine = 'php', $context = FALSE) { - parent::initialize($context); $this->_template = $template; $this->_params = (array) $params; $this->_engine = $engine; + parent::__construct(); + } + public function define($context = FALSE) + { + parent::define($context); + $this->implement('I_MVC_View'); + $this->add_mixin('Mixin_Mvc_View_Instance_Methods'); } } class Mixin_Mvc_View_Instance_Methods extends Mixin diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/module.nextgen_addgallery_page.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/module.nextgen_addgallery_page.php index 16090e6bb4d989b8713021f1574e2c3067bb332b..15d6eabd004b6e495420a2b5f29ba6bebfbf1761 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/module.nextgen_addgallery_page.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/module.nextgen_addgallery_page.php @@ -15,7 +15,7 @@ class M_NextGen_AddGallery_Page extends C_Base_Module 'photocrati-nextgen_addgallery_page', 'NextGEN Add Gallery Page', 'Provides admin page for adding a gallery and uploading images', - '0.6', + '0.7', 'https://www.imagely.com/wordpress-gallery-plugin/nextgen-gallery/', 'Photocrati Media', 'https://www.imagely.com' diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/package.module.nextgen_addgallery_page.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/package.module.nextgen_addgallery_page.php index a9c02e8ab8380c77abb6b8b93469dad47c909216..5c42acb154454c16d43ba5ef3aa5eb10953d8e31 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/package.module.nextgen_addgallery_page.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/package.module.nextgen_addgallery_page.php @@ -99,6 +99,7 @@ class A_NextGen_AddGallery_Ajax extends Mixin // Upload the image to the gallery if (!$error) { $retval['gallery_id'] = $gallery_id; + $settings = C_NextGen_Settings::get_instance(); $storage = C_Gallery_Storage::get_instance(); try { if ($storage->is_zip()) { @@ -109,6 +110,21 @@ class A_NextGen_AddGallery_Ajax extends Mixin } } elseif ($image = $storage->upload_image($gallery_id)) { $retval['image_ids'] = array($image->id()); + $retval['image_errors'] = array(); + // check if image was resized correctly + if ($settings->imgAutoResize) { + $image_path = $storage->get_full_abspath($image); + $image_thumb = new C_NggLegacy_Thumbnail($image_path, true); + if ($image_thumb->error) { + $retval['image_errors'][] = array('id' => $image->id(), 'error' => sprintf(__('Automatic image resizing failed [%1$s].', 'nggallery'), $image_thumb->errmsg)); + $image_thumb = null; + } + } + // check if thumb was generated correctly + $thumb_path = $storage->get_thumb_abspath($image); + if (!file_exists($thumb_path)) { + $retval['image_errors'][] = array('id' => $image->id(), 'error' => __('Thumbnail generation failed.', 'nggallery')); + } } else { $retval['error'] = __('Image generation failed', 'nggallery'); $error = TRUE; @@ -334,6 +350,10 @@ class A_Upload_Images_Form extends Mixin { return __('Upload Images', 'nggallery'); } + public function get_i18n_strings() + { + return array('no_image_uploaded' => __('No images were uploaded successfully.', 'nggallery'), 'one_image_uploaded' => __('1 image was uploaded successfully.', 'nggallery'), 'x_images_uploaded' => __('{count} images were uploaded successfully.', 'nggallery'), 'image_errors' => __('The following errors occured:', 'nggallery'), 'manage_gallery' => __('Manage gallery', 'nggallery')); + } /** * Plupload stores its i18n JS *mostly* as "en.js" or "ar.js" - but some as zh_CN.js so we must check both if the * first does not match. @@ -365,6 +385,7 @@ class A_Upload_Images_Form extends Mixin wp_enqueue_style('ngg.plupload.queue'); wp_enqueue_script('browserplus'); wp_enqueue_script('ngg.plupload.queue'); + wp_localize_script('ngg.plupload.queue', 'NggUploadImages_i18n', $this->object->get_i18n_strings()); $i18n = $this->_find_plupload_i18n(); if (!empty($i18n)) { wp_enqueue_script('ngg.plupload.i18n', $i18n, array('ngg.plupload.full'), NGG_SCRIPT_VERSION); diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/jquery.filetree/jquery.filetree.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/jquery.filetree/jquery.filetree.css index db969e2de0ec5399af3375e93bc7d818eaeb8a53..aaed0443c1a4e65a6e4311ab0fe92d96db7195bf 100755 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/jquery.filetree/jquery.filetree.css +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/jquery.filetree/jquery.filetree.css @@ -1,95 +1,95 @@ -UL.jqueryFileTree { - font-family: Verdana, sans-serif; - font-size: 11px; - line-height: 18px; - padding: 0px; - margin: 0px; -} - -UL.jqueryFileTree LI { - list-style: none; - padding: 0px; - padding-left: 20px; - margin: 0px; - white-space: nowrap; -} - -UL.jqueryFileTree A { - color: #333; - text-decoration: none; - display: block; - padding: 0px 2px; -} - -UL.jqueryFileTree A:hover { - background: #BDF; -} - -UL.jqueryFileTree A.selected_folder { - background-color: #EEEEEE; -} - -/* Core Styles */ -.jqueryFileTree LI.directory { background: url(images/directory.png) left top no-repeat; } -.jqueryFileTree LI.expanded { background: url(images/folder_open.png) left top no-repeat; } -.jqueryFileTree LI.file { background: url(images/file.png) left top no-repeat; } -.jqueryFileTree LI.wait { background: url(images/spinner.gif) left top no-repeat; } -/* File Extensions*/ -.jqueryFileTree LI.ext_3gp { background: url(images/film.png) left top no-repeat; } -.jqueryFileTree LI.ext_afp { background: url(images/code.png) left top no-repeat; } -.jqueryFileTree LI.ext_afpa { background: url(images/code.png) left top no-repeat; } -.jqueryFileTree LI.ext_asp { background: url(images/code.png) left top no-repeat; } -.jqueryFileTree LI.ext_aspx { background: url(images/code.png) left top no-repeat; } -.jqueryFileTree LI.ext_avi { background: url(images/film.png) left top no-repeat; } -.jqueryFileTree LI.ext_bat { background: url(images/application.png) left top no-repeat; } -.jqueryFileTree LI.ext_bmp { background: url(images/picture.png) left top no-repeat; } -.jqueryFileTree LI.ext_c { background: url(images/code.png) left top no-repeat; } -.jqueryFileTree LI.ext_cfm { background: url(images/code.png) left top no-repeat; } -.jqueryFileTree LI.ext_cgi { background: url(images/code.png) left top no-repeat; } -.jqueryFileTree LI.ext_com { background: url(images/application.png) left top no-repeat; } -.jqueryFileTree LI.ext_cpp { background: url(images/code.png) left top no-repeat; } -.jqueryFileTree LI.ext_css { background: url(images/css.png) left top no-repeat; } -.jqueryFileTree LI.ext_doc { background: url(images/doc.png) left top no-repeat; } -.jqueryFileTree LI.ext_exe { background: url(images/application.png) left top no-repeat; } -.jqueryFileTree LI.ext_gif { background: url(images/picture.png) left top no-repeat; } -.jqueryFileTree LI.ext_fla { background: url(images/flash.png) left top no-repeat; } -.jqueryFileTree LI.ext_h { background: url(images/code.png) left top no-repeat; } -.jqueryFileTree LI.ext_htm { background: url(images/html.png) left top no-repeat; } -.jqueryFileTree LI.ext_html { background: url(images/html.png) left top no-repeat; } -.jqueryFileTree LI.ext_jar { background: url(images/java.png) left top no-repeat; } -.jqueryFileTree LI.ext_jpg { background: url(images/picture.png) left top no-repeat; } -.jqueryFileTree LI.ext_jpeg { background: url(images/picture.png) left top no-repeat; } -.jqueryFileTree LI.ext_js { background: url(images/script.png) left top no-repeat; } -.jqueryFileTree LI.ext_lasso { background: url(images/code.png) left top no-repeat; } -.jqueryFileTree LI.ext_log { background: url(images/txt.png) left top no-repeat; } -.jqueryFileTree LI.ext_m4p { background: url(images/music.png) left top no-repeat; } -.jqueryFileTree LI.ext_mov { background: url(images/film.png) left top no-repeat; } -.jqueryFileTree LI.ext_mp3 { background: url(images/music.png) left top no-repeat; } -.jqueryFileTree LI.ext_mp4 { background: url(images/film.png) left top no-repeat; } -.jqueryFileTree LI.ext_mpg { background: url(images/film.png) left top no-repeat; } -.jqueryFileTree LI.ext_mpeg { background: url(images/film.png) left top no-repeat; } -.jqueryFileTree LI.ext_ogg { background: url(images/music.png) left top no-repeat; } -.jqueryFileTree LI.ext_pcx { background: url(images/picture.png) left top no-repeat; } -.jqueryFileTree LI.ext_pdf { background: url(images/pdf.png) left top no-repeat; } -.jqueryFileTree LI.ext_php { background: url(images/php.png) left top no-repeat; } -.jqueryFileTree LI.ext_png { background: url(images/picture.png) left top no-repeat; } -.jqueryFileTree LI.ext_ppt { background: url(images/ppt.png) left top no-repeat; } -.jqueryFileTree LI.ext_psd { background: url(images/psd.png) left top no-repeat; } -.jqueryFileTree LI.ext_pl { background: url(images/script.png) left top no-repeat; } -.jqueryFileTree LI.ext_py { background: url(images/script.png) left top no-repeat; } -.jqueryFileTree LI.ext_rb { background: url(images/ruby.png) left top no-repeat; } -.jqueryFileTree LI.ext_rbx { background: url(images/ruby.png) left top no-repeat; } -.jqueryFileTree LI.ext_rhtml { background: url(images/ruby.png) left top no-repeat; } -.jqueryFileTree LI.ext_rpm { background: url(images/linux.png) left top no-repeat; } -.jqueryFileTree LI.ext_ruby { background: url(images/ruby.png) left top no-repeat; } -.jqueryFileTree LI.ext_sql { background: url(images/db.png) left top no-repeat; } -.jqueryFileTree LI.ext_swf { background: url(images/flash.png) left top no-repeat; } -.jqueryFileTree LI.ext_tif { background: url(images/picture.png) left top no-repeat; } -.jqueryFileTree LI.ext_tiff { background: url(images/picture.png) left top no-repeat; } -.jqueryFileTree LI.ext_txt { background: url(images/txt.png) left top no-repeat; } -.jqueryFileTree LI.ext_vb { background: url(images/code.png) left top no-repeat; } -.jqueryFileTree LI.ext_wav { background: url(images/music.png) left top no-repeat; } -.jqueryFileTree LI.ext_wmv { background: url(images/film.png) left top no-repeat; } -.jqueryFileTree LI.ext_xls { background: url(images/xls.png) left top no-repeat; } -.jqueryFileTree LI.ext_xml { background: url(images/code.png) left top no-repeat; } +UL.jqueryFileTree { + font-family: Verdana, sans-serif; + font-size: 11px; + line-height: 18px; + padding: 0px; + margin: 0px; +} + +UL.jqueryFileTree LI { + list-style: none; + padding: 0px; + padding-left: 20px; + margin: 0px; + white-space: nowrap; +} + +UL.jqueryFileTree A { + color: #333; + text-decoration: none; + display: block; + padding: 0px 2px; +} + +UL.jqueryFileTree A:hover { + background: #BDF; +} + +UL.jqueryFileTree A.selected_folder { + background-color: #EEEEEE; +} + +/* Core Styles */ +.jqueryFileTree LI.directory { background: url(images/directory.png) left top no-repeat; } +.jqueryFileTree LI.expanded { background: url(images/folder_open.png) left top no-repeat; } +.jqueryFileTree LI.file { background: url(images/file.png) left top no-repeat; } +.jqueryFileTree LI.wait { background: url(images/spinner.gif) left top no-repeat; } +/* File Extensions*/ +.jqueryFileTree LI.ext_3gp { background: url(images/film.png) left top no-repeat; } +.jqueryFileTree LI.ext_afp { background: url(images/code.png) left top no-repeat; } +.jqueryFileTree LI.ext_afpa { background: url(images/code.png) left top no-repeat; } +.jqueryFileTree LI.ext_asp { background: url(images/code.png) left top no-repeat; } +.jqueryFileTree LI.ext_aspx { background: url(images/code.png) left top no-repeat; } +.jqueryFileTree LI.ext_avi { background: url(images/film.png) left top no-repeat; } +.jqueryFileTree LI.ext_bat { background: url(images/application.png) left top no-repeat; } +.jqueryFileTree LI.ext_bmp { background: url(images/picture.png) left top no-repeat; } +.jqueryFileTree LI.ext_c { background: url(images/code.png) left top no-repeat; } +.jqueryFileTree LI.ext_cfm { background: url(images/code.png) left top no-repeat; } +.jqueryFileTree LI.ext_cgi { background: url(images/code.png) left top no-repeat; } +.jqueryFileTree LI.ext_com { background: url(images/application.png) left top no-repeat; } +.jqueryFileTree LI.ext_cpp { background: url(images/code.png) left top no-repeat; } +.jqueryFileTree LI.ext_css { background: url(images/css.png) left top no-repeat; } +.jqueryFileTree LI.ext_doc { background: url(images/doc.png) left top no-repeat; } +.jqueryFileTree LI.ext_exe { background: url(images/application.png) left top no-repeat; } +.jqueryFileTree LI.ext_gif { background: url(images/picture.png) left top no-repeat; } +.jqueryFileTree LI.ext_fla { background: url(images/flash.png) left top no-repeat; } +.jqueryFileTree LI.ext_h { background: url(images/code.png) left top no-repeat; } +.jqueryFileTree LI.ext_htm { background: url(images/html.png) left top no-repeat; } +.jqueryFileTree LI.ext_html { background: url(images/html.png) left top no-repeat; } +.jqueryFileTree LI.ext_jar { background: url(images/java.png) left top no-repeat; } +.jqueryFileTree LI.ext_jpg { background: url(images/picture.png) left top no-repeat; } +.jqueryFileTree LI.ext_jpeg { background: url(images/picture.png) left top no-repeat; } +.jqueryFileTree LI.ext_js { background: url(images/script.png) left top no-repeat; } +.jqueryFileTree LI.ext_lasso { background: url(images/code.png) left top no-repeat; } +.jqueryFileTree LI.ext_log { background: url(images/txt.png) left top no-repeat; } +.jqueryFileTree LI.ext_m4p { background: url(images/music.png) left top no-repeat; } +.jqueryFileTree LI.ext_mov { background: url(images/film.png) left top no-repeat; } +.jqueryFileTree LI.ext_mp3 { background: url(images/music.png) left top no-repeat; } +.jqueryFileTree LI.ext_mp4 { background: url(images/film.png) left top no-repeat; } +.jqueryFileTree LI.ext_mpg { background: url(images/film.png) left top no-repeat; } +.jqueryFileTree LI.ext_mpeg { background: url(images/film.png) left top no-repeat; } +.jqueryFileTree LI.ext_ogg { background: url(images/music.png) left top no-repeat; } +.jqueryFileTree LI.ext_pcx { background: url(images/picture.png) left top no-repeat; } +.jqueryFileTree LI.ext_pdf { background: url(images/pdf.png) left top no-repeat; } +.jqueryFileTree LI.ext_php { background: url(images/php.png) left top no-repeat; } +.jqueryFileTree LI.ext_png { background: url(images/picture.png) left top no-repeat; } +.jqueryFileTree LI.ext_ppt { background: url(images/ppt.png) left top no-repeat; } +.jqueryFileTree LI.ext_psd { background: url(images/psd.png) left top no-repeat; } +.jqueryFileTree LI.ext_pl { background: url(images/script.png) left top no-repeat; } +.jqueryFileTree LI.ext_py { background: url(images/script.png) left top no-repeat; } +.jqueryFileTree LI.ext_rb { background: url(images/ruby.png) left top no-repeat; } +.jqueryFileTree LI.ext_rbx { background: url(images/ruby.png) left top no-repeat; } +.jqueryFileTree LI.ext_rhtml { background: url(images/ruby.png) left top no-repeat; } +.jqueryFileTree LI.ext_rpm { background: url(images/linux.png) left top no-repeat; } +.jqueryFileTree LI.ext_ruby { background: url(images/ruby.png) left top no-repeat; } +.jqueryFileTree LI.ext_sql { background: url(images/db.png) left top no-repeat; } +.jqueryFileTree LI.ext_swf { background: url(images/flash.png) left top no-repeat; } +.jqueryFileTree LI.ext_tif { background: url(images/picture.png) left top no-repeat; } +.jqueryFileTree LI.ext_tiff { background: url(images/picture.png) left top no-repeat; } +.jqueryFileTree LI.ext_txt { background: url(images/txt.png) left top no-repeat; } +.jqueryFileTree LI.ext_vb { background: url(images/code.png) left top no-repeat; } +.jqueryFileTree LI.ext_wav { background: url(images/music.png) left top no-repeat; } +.jqueryFileTree LI.ext_wmv { background: url(images/film.png) left top no-repeat; } +.jqueryFileTree LI.ext_xls { background: url(images/xls.png) left top no-repeat; } +.jqueryFileTree LI.ext_xml { background: url(images/code.png) left top no-repeat; } .jqueryFileTree LI.ext_zip { background: url(images/zip.png) left top no-repeat; } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ar.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ar.min.js new file mode 100644 index 0000000000000000000000000000000000000000..b2150e3d1411f00e3ab39103887e9b7d76091233 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ar.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('11.10({"1o c":"1�0�0�1�0� 1�0�3�0�0�0�","c q v J i o 1c\'t K.":"1�0�0�1�0� 1�0�3�0�0�0� 1�1�0�1� 0�0�0�0� 1�1�1�1� 1�0� 8�1� 0�4�0�1�","I":"4�1�1�1�1�0�2","H":"1�0�1�1�0�","E":"1�8�1�0�","F 7.":"1�1�1� 0�0� 4�0�1�1�","n 6 G e L l M S e T R.":"1�1�0� 0�0�0�1�2 1�0�0� 1�0�0�1�1�0�1� 1�0�3�1�1� 1�0�3�0�0�0� 1�0� 1�1�k� 1�0�0� 1�1� 1�0�1�1�1�0�1�","D":"1�1�0� 1�0�0�0�0�","O P U i o u r.":"g�k� 1�0�g�1�1� 1�0�1� 1�1�1�1� 1�0� 8�1� 0�1�1�0�0�0�","B":"1�0�1�1�0�1�","z f.":"1�1�1� 0�0� 1�1�4�0�0�0� 0�0�0� 1�0�0�0�0�1�2","y c":"1�1�1�1� 1�0�3�0�0�0�","x":"0�0�1�1�1�1�0�2","C":"0�0�0�0�1�1�0�2","w 9 7.":"1�1�1�1� 0�0� 4�1�1�1� 1�0�0�0�0�","5 h 7.":"1�1�1� 0�0� 1�1�0� 1�0�0�0�0�","N/A":"0�1� 1�0�","p":"1�0�1�1�1�1�0�2","f: Q 9 m:":"1�1�1�1� : 1�0�3�1�1� 1�0�0�0�0� 8�1� j�0�1� :","1p 6":"1�1�3� 1�0�0�0�0�1�2","%s 1g 1h 1f e l.":"%s 1�0�0�0�0� 0�0�1�0�1� 1�1�0�0�1�0� 0�0� 0�1�1�0�1� 1�0�1�0�3�1�1�","5: %s":"0�0�0�: %s","b":"1�1�0�2","1e %d/%d 6":"3�0�0�0� %d/%d 0�0�0�","c V 1d 1i %d 9(s) 1j a 1n. 1m 6 1k 1l.":"1�0�1�0�1�j� 1�0�0�0�1�0�0�0� 0�3�0�0�0� 0�0� %d 0�0�0� 0�0� 0�1�1� 1�0�0�0�2. 1�0�0�0�0�1�2 1�0�1�1�1�0�0�1� 1�1�0�0�1�.","%d 6 1b":"%d 1�0�0�0�0�1�2 0�0� 0�1�1�0�1� 1�0�1�0�3�1�1�","5: %s, h: %d, 1a 9 h: %d":"0�0�0�: %s, 1�0�g� 1�1�0� 0�0�0�0�0�: %d, 1�1�0�: %d","Z 6 Y.":"1�1�1� 1�0�0�0�0� 0�0�1�","W X 12 13 18 19.":"1�0�1�1�0�1�1� 1�0�0�4�0�1�0� 1�0�4�2 0�0�1�1� 1�0�3�8�0�","5 17 7.":"1�1�1�1� 0�0� 1�1� 1�0�0�0�0�1�2","5 m 7.":"1�1�1� 0�0� 1�0�3�1�1� 1�0�0�0�0�","f: 5 16 14:":" 1�1�1�1� : 1�1�0� 1�0�0�0�0� 0�1�0�1� :","n 15":"1�1�0� 0�0�0�1�2"});',62,88,'�|�|ت|ت�|ت�|File|files|error|غ�|file|||Upload||the|Error|ص�|size|wrong|ص�|غ�|queue|extension|Add|or|gb|URL|supported|||not|might|Duplicate|mb|Start|HTTP||Status|kb|Filename|Close|Init|to|Size|tb|be|exist|upload|and||Image|format|Invalid|button|click|start|either|element|Runtime|ran|here|Drag|addI18n|plupload|out|of|large|Files|too|count|available|memory|max|queued|doesn|accepts|Uploaded|in|already|present|only|at|were|stripped|Extra|time|Stop|Select'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/bs.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/bs.min.js new file mode 100644 index 0000000000000000000000000000000000000000..660de7c7d02ac9f710ffefcaf3b4bf67384215eb --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/bs.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('1g.1f({"1h 6":"1i f","6 v 1j 1e p w 1d\'t 19.":"v q f k x B 1a 1b.","r":"r","1k":"1l�9","1u":"1t","1v 4.":"1w y�1.","F 2 1x c 1s D 1r 1n c 1m 1o.":"1p 0 u 1q i 17 12 O q M.","P":"Q 0","L S G p w I J.":"R 16 k x B 13 14�15.","o":"o","z l.":"z y�1.","Z 6":"V�U f","C":"C","m":"m","1z 8 4.":"1I 7.","3 h 4.":"5�1 u g�28 0.","N/A":"N/A","n":"n","l: 2a 8 E:":"5�1! 2b 27 0:","26 2":"22 0","%s 23 24 2d c D.":"%s 2c 2f� 2l u 2k.","3: %s":"j: %s","b":"b","2j %d/%d 2":"2e %d/%d 7","6 2h 2i 2m %d 8(s) 20 a 21. 1H 2 1J 1K.":"1L 1G 1F 1B %d 7 1A. 1C 0 1D 1E.","%d 2 1M":"%d 7 1W�1V","3: %s, h: %d, 1X 8 h: %d":"j: %s, g�9: %d, 1U g�9: %d","1O 2 1R.":"1S 0 1y.","1Q 1P 1T 1Z 1Y 1N.":"2g 25�e 29 Y.","3 X 4.":"5�1 u W 10.","3 E 4.":"5�1 u 11 0.","l: 3 T K:":"5�1! j k H:","F 1c":"18 0"});',62,147,'datoteke|ka|files|File|error|Gre�|Upload|datoteka|file|ina|||the|||dodavanje|veli�|size||Datoteka|je|Error|kb|gb|Status|wrong|za|tb||||URL|or|neispravan|gre�|HTTP||ili|mb|queue|extension|Add|either|prevelika|not|supported|large|Image|pokretanje||dugme|Filename|Naziv|Format|format|too|ni|Zapo�|brojanju|count|memorije|Start|datoeka|ekstenziji|na|nije|podr�|an|slike|kliknite|Dodaj|exist|ne|postoji|Files|doesn|be|addI18n|plupload|Stop|Prekini|might|Size|Veli�|start|click|button|Dodajte|red|and|upload|Zatvori|Close|Init|Inicijalizacijska|to|ovdje|Duplicate|istovremeno|samo|Dodatne|su|uklonjene|dozvoljava|trenutno|Extra|Dupla|were|stripped|Dodavanje|queued|memory|Drag|ran|Runtime|here|Dovucite|out|maksimalna|eka|�|max|available|of|at|time|Odaberite|already|present|vi�|Select|ekstenzija|ini|dostupne|Invalid|Neispravan|se|in|Dodano|ve�|Nema|element|accepts|Uploaded|redu|nalazi|only'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ca.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ca.min.js new file mode 100644 index 0000000000000000000000000000000000000000..c77fb6e079a865c4421dfd970ecaff5fcf4acb82 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ca.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('B.C({"z 4":"","4 y v w 8 9 x\'t D.":"","E":"","K":"","L":"","J 2.":"","e 0 u 6 F c G H 6 M h.":"","k":"","j i g 8 9 n r.":"","q":"","o 5.":"","p 4":"","m":"","l":"","I 3 2.":"","1 7 2.":"","N/A":"","1a":"","5: 1b 3 f:":"","19 0":"","%s 18 O 16 6 c.":"","1: %s":"","b":"","1d %d/%d 0":"","4 1c 1f 1g %d 3(s) 1e a 17. 13 0 14 T.":"","%d 0 U":"","1: %s, 7: %d, S 3 7: %d":"","R 0 P.":"","Q V W 11 12 10.":"","1 Z 2.":"","1 f 2.":"","5: 1 X Y:":"","e 15":""});',62,79,'files|File|error|file|Upload|Error|the|size|wrong|or|||queue||Add|extension|either|button|format|Image|Filename|kb|mb|not|HTTP|Start|Status|supported|||to|might|be|doesn|URL|Stop||plupload|addI18n|exist|tb|upload|and|click|Duplicate|Init|Size|Close|start||present|here|Runtime|Drag|max|stripped|queued|ran|out|too|large|count|memory|of|available|Extra|were|Files|in|time|already|Select|gb|Invalid|element|Uploaded|at|accepts|only'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/cs.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/cs.min.js new file mode 100644 index 0000000000000000000000000000000000000000..bc5425ed5e4baf32eb9e25a9d80f1dba7fbf8781 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/cs.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('Z.10({"F 3":"F 3","3 V X T 7 c U\'t Q.":"3 V X T 7 c U\'t Q.","17":"","19":"18","C":"C","m 1.":"m 1.","W 2 16 e 14 B 15 1a e 1b 1g.":"R�13 8 1f 1e a 1c 1d�E z�y�n�.","1h":"11�Y 12","v i r 7 c q p.":"v i r 7 c q p.","o":"o","u 5.":"u 5.","1n 3":"1A z�y�n�","1z":"","1y":"","1x 4 1.":"","0 6 1.":"0 6 1.","N/A":"N/A","1B":"","5: w 4 9:":"5: w 4 9:","1C 2":"1D 8","%s 1i 1E 1F e B.":"","0: %s":"0: %s","b":"","1v %d/%d 2":"1w�1m %d/%d 1l�","3 f h l %d 4(s) k a g. j 2 x I.":"3 f h l %d 4(s) k a g. j 2 x I.","%d 2 S":"%d 2 S","0: %s, 6: %d, 1j 4 6: %d":"","1k 2 1o.":"1p 1u�1t�1s�E 8.","H L J K M D.":"H L J K M D.","0 G 1.":"0 G 1.","0 9 1.":"0 9 1.","5: 0 P O:":"5: 0 P O:","W 1q":"R�1r 8"});',62,104,'File|error|files|Upload|file|Error|size|wrong|soubory|extension|||or||the|element|time|accepts|format|Extra|at|only|Init|n�|Status|supported|not|either|||HTTP|Image|Invalid|were|v�|nahr�||queue|Close|memory|te|Stop|count|Runtime|stripped|out|of|ran|available||large|too|exist|P�|queued|be|doesn|URL|Add|might|zev|plupload|addI18n|N�|souboru|idejte|upload|and|to|tb|Velikost|Size|click|start|pak|spus�|fronty|do|button|Filename|already|max|Drag|soubor�|no|Start|here|Sem|Files|idat|hn�|et�|p�|Uploaded|Nahr�|Duplicate|kb|mb|Spustit|gb|Select|Vyberte|present|in'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/cy.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/cy.min.js new file mode 100644 index 0000000000000000000000000000000000000000..5a12d57ab4129036419406ed5fb731d4e455b7b2 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/cy.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('1d.1c({"1e 7":"1f x","7 v 1g 1b q z 1a\'t 16.":"v y 17 18 w p 19 3 1h.","u":"u","1r":"1q","1s":"1t","1u 6.":"1 1p.","C 4 1o c 1k B 1j 1l c 1m 1n.":"14 5 i\'r h k a Z\'r L M.","O":"K\'r 0","Q J F q z I G.":"P 13 3 w p 11 12 Y.","X":"T","n e.":"1 n.","U 7":"V x","m":"m","l":"l","1w 8 6.":"1 0 1C.","2 g 6.":"1 f 0.","N/A":"22/A","j":"j","e: 20 8 D:":"1: E 0 1Z:","1V 4":"1W 5","%s 1X 1Y 25 c B.":"%s 3 y h 3 2e.","2: %s":"9: %s","b":"b","2g %d/%d 4":"2b %d/%d 0","7 28 29 2a %d 8(s) 2c a 1D. 1E 4 1F 1G.":"1B\'r 1x k 3 1z %d 0 1A y 1I. 1P 5 1Q 1R 1S.","%d 4 1O":"%d 0 1N h","2: %s, g: %d, 1K 8 g: %d":"9: %s, f: %d, f 1H 0: %d","1U 4 2f.":"23 5 21.","1v 27 1T 1M 1L 1J.":"1y o 26.","2 24 6.":"1 W 5.","2 D 6.":"1 E 0.","e: 2 S 10:":"1: 9 3 R H:","C 1i":"15 2d"});',62,141,'ffeil|Gwall|File|yn|files|ffeiliau|error|Upload|file|Ffeil|||the||Error|maint|size|ciw||gb|lanlwytho|kb|mb|HTTP||neu|wrong||||tb|URL|anghywir|Lanlwytho||or||queue|Add|extension|estyniad|either|supported|fawr|not|format|Enw|botwm|dechrau||Filename|Fformat|Image|rhy|too|Statws|Start|Dechrau|cyfri|Status|gynnal|chlicio|large|heb|ei|delwedd|Ychwanegwch|Ychwanegu|exist|lanlwythiad|ynb|ddim|doesn|be|addI18n|plupload|Stop|Atal|might|bodoli|Files|and|upload|click|start|button|to|cych|Maint|Size|Close|Cau|Init|Runtime|Duplicate|elfen|Allan|derbyn|ar|Mae|ddyblyg|time|Extra|were|stripped|mwyaf|tro|memory|max|available|of|mewn|queued|Caiff|ychwanegol|eu|tynnu|out|Drag|Select|Dewis|already|present|annilys|Invalid|yma|Dd|Llusgwch|count|in|gof|ran|element|accepts|only|Lanlwythwyd|at|Ffeiliau|barod|here|Uploaded'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/da.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/da.min.js new file mode 100644 index 0000000000000000000000000000000000000000..c4860e50fd3ddd8d19e7cbb75c3cdafe440919ae --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/da.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('10.17({"F 3":"F 3","3 G H W 8 6 X\'t V.":"3 G H W 8 6 X\'t V.","18":"","15":"14�12","g":"g","C 1.":"C 1.","e 2 13 c 11 h 1c 1b c 1a 19.":"1d�j f Z Y�16","1g":"1s","u r q 8 6 p v.":"u r q 8 6 p v.","w":"w","B 5.":"B 5.","o 3":"o 3","1q":"","1u":"","1r 4 1.":"","0 7 1.":"0 7 1.","N/A":"N/A","1t":"","5: y 4 9:":"5: y 4 9:","1p 2":"1e�1n f","%s 1h 1o 1f c h.":"","0: %s":"0: %s","b":"","l %d/%d 2":"l %d/%d 2","3 m i n %d 4(s) D a z. T 2 S R.":"3 m i n %d 4(s) D a z. T 2 S R.","%d 2 U":"%d 2 U","0: %s, 7: %d, 1i 4 7: %d":"","1j 2 1m.":"1l�k f 1k.","K L M O J I.":"K L M O J I.","0 E 1.":"0 E 1.","0 9 1.":"0 9 1.","5: 0 P Q:":"5: 0 P Q:","e x":"e x"});',62,93,'File|error|files|Upload|file|Error|or|size|wrong|extension|||the||Add|filer|Close|queue|accepts|||Uploaded|element|only|Start|not|either|format|||Image|supported|Status|Files|Invalid|time||HTTP|Init|at|count|Stop|URL|might|memory|available|Runtime|ran|out||of|too|large|stripped|were|Extra|queued|exist|be|doesn|k�|til|plupload|upload|rrelse|to|St�|Size|en|addI18n|tb|button|start|click|and|Tilf�|V�|in|Filename|already|max|Drag|her|Tr�|here|lg|present|Select|mb|Duplicate|Filnavn|gb|kb'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/de.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/de.min.js new file mode 100644 index 0000000000000000000000000000000000000000..d957f9659152af852fe5dea04480b98d62572529 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/de.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('1d.1c({"1e 4":"q 1f","4 l 1g 1b r u 1a\'t 15.":"4-l 14 o n 16 i.","17":"19","18":"1h&G;&1i;e","1s":"1r�p","1t 2.":"1u","h 3 1v g 1q j 1p 1k g 13 1l.":"0 1m&c;k 1o 1n \'q\' 1w.","Z":"R","S O K r u T U.":"10 o n i X&c;12.","m":"m","x f.":"x-5","11 4":"4 M","P":"V","Q":"L","Y 7 2.":"","1 9 2.":"5 F W&G;8�e","N/A":"1j 2d&c;20","2a":"29","f: 2h 7 H:":"5: 1x�27 w:","28 3":"0 26","%s 25 21 v g j.":"","1: %s":"6: %s","b":"B","24 %d/%d 3":"%d/%d 0 2b 2c","4 2l 2m 2k %d 7(s) 2i a 2e. 2f 3 2g 22.":"1Y 1Z 1G 1F %d 6(p) 1H 1I. 8�1J�1E 0 1D 1z.","%d 3 1y":"%d 0 v 1A 1B","1: %s, 9: %d, 1C 7 9: %d":"6: %s, 1L�8�e: %d, 1U 1T�8�e: %d","1W 3 1S.":"1R 1N 1M 0 1O 1P","I C J z y D.":"I C J z y D.","1 E 2.":"1 E 2.","1 H 2.":"5 F w","f: 1 1Q 1X:":"5: 6 1V 1K�:","h 2j":"0 23�k"});',62,147,'Dateien|File|error|files|Upload|Fehler|Datei|file|�|size|||uuml|||Error|the|Add|nicht|queue|gen|URL|Status|oder|falsch|en|Hochladen|wrong|||or|in|Dateiendung|HTTP|available|of|||ran|memory|count|bei|ouml|extension|Runtime|out|either|kB|beginnen||format|mb|kb|Dateiname|Image|not|supported|MB|Dateigr|unterst|Duplicate|Filename|Bildformat|Start|tzt|start|ist|exist|existiert|tb|Size|TB|doesn|be|addI18n|plupload|Stop|stoppen|might|Gr|szlig|Nicht|click|button|hinzuf|auf|und|and|upload|Schlie�|Close|Init|Initialisierungsfehler|to|klicken|Ung�|queued|abgetrennt|der|Warteschlange|max|wurden|hlige|nur|akzeptiert|pro|Durchgang|berz�|gro�|Gr�|die|Sie|hier|hin|too|Ziehen|here|Dateigr�|maximale|zu|Drag|large|Der|Uploader|gbar|present|stripped|hinzuf�|Uploaded|already|hochladen|ltige|Select|GB|gb|sind|hochgeladen|verf|time|Extra|were|Invalid|at|Files|only|element|accepts'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/el.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/el.min.js new file mode 100644 index 0000000000000000000000000000000000000000..a76be16b11d3b77e8420cb7ce91755dba62966bf --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/el.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('15.1a({"w 6":"w 6","6 v u r 9 c x\'t y.":"6 v u r 9 c x\'t y.","16":"","17":"0�0�0�5�0�1�","D":"D","C 3.":"C 3.","J 4 12 i Y F X Z i 10 11.":"0�1�0�1�0�0�p� 0�1�1�5�1�0� 1�1�0�0� 0�1�1�0� 0�g�0�1�1�1�1�1�1�0�1�","19":"0�0�0�0�0� 0�1�1�5�0�1�","B q E 9 c l o.":"B q E 9 c l o.","1g":"0�0�1�0�1�1�0�1�0�","n 7.":"n 7.","1b 6":"0�1d�0�0�1�0� 0�g�0�1�1�1�1�1�1�0�1�","1e":"","1f":"","1n 8 3.":"","2 e 3.":"2 e 3.","N/A":"N/A","14":"","7: m 8 f:":"7: m 8 f:","1i 4":"0�1�0�0�0�0�1�h 0�1�1�5�0�","%s 1j 1c 1m i F.":"","2: %s":"2: %s","b":"","13 %d/%d 4":"0�0�0�0�0�p�0� %d/%d 0�1�1�5�0�","6 k j z %d 8(s) H a U. T 4 V W.":"6 k j z %d 8(s) H a U. T 4 V W.","%d 4 R":"%d 4 R","2: %s, e: %d, 1h 8 e: %d":"","1l 4 1k.":"0�1�1�g�h 0�1�1�5�0� 5�1�","G K L Q P O.":"G K L Q P O.","2 I 3.":"2 I 3.","2 f 3.":"2 f 3.","7: 2 M S:":"7: 2 M S:","J 18":"0�1�0�1�0�0�1�1�h 0�1�1�5�0�"});',62,86,'�|�|File|error|files|ε�|Upload|Error|file|wrong|||or||size|extension|ε�|ε|the|accepts|element|not|Invalid|HTTP|supported|κ�|format|be|||might|URL|Stop|doesn|exist|only||Image|Init|Close|either|queue|Runtime|at|count|Add|ran|out|too||memory|available|of|queued|large|Extra|time|were|stripped|and|upload|click|start|button|to|Uploaded|gb|plupload|tb|Size|Files|Filename|addI18n|Start|present|κκ�|mb|kb|Status|max|Select|already|here|Drag|in|Duplicate'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/en.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/en.min.js new file mode 100644 index 0000000000000000000000000000000000000000..3b00c5bf51f32006d4a4b86db2039e7e87278911 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/en.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('1f.1g({"J 3":"J 3","3 B C z f 9 y\'t v.":"3 B C z f 9 y\'t v.","w":"w","x":"x","D":"D","E 2.":"E 2.","e 0 K 5 I 8 F G 5 u L.":"e 0 K 5 I 8 F G 5 u L.","p":"p","h i g f 9 j r.":"h i g f 9 j r.","k":"k","q 7.":"q 7.","o 3":"o 3","n":"n","l":"l","m 4 2.":"m 4 2.","1 6 2.":"1 6 2.","N/A":"N/A","H":"H","7: S 4 c:":"7: S 4 c:","18 0":"18 0","%s 19 M 16 5 8.":"%s 19 M 16 5 8.","1: %s":"1: %s","b":"b","1b %d/%d 0":"1b %d/%d 0","3 15 1a 1c %d 4(s) 1e a 1d. 14 0 12 13.":"3 15 1a 1c %d 4(s) 1e a 1d. 14 0 12 13.","%d 0 T":"%d 0 T","1: %s, 6: %d, R 4 6: %d":"1: %s, 6: %d, R 4 6: %d","Q 0 O.":"Q 0 O.","P U V 10 11 Z.":"P U V 10 11 Z.","1 Y 2.":"1 Y 2.","1 c 2.":"1 c 2.","7: 1 W X:":"7: 1 W X:","e 17":"e 17"});',62,79,'files|File|error|Upload|file|the|size|Error|queue|or|||extension||Add|wrong|either|Image|format|not|Status|kb|Duplicate|mb|Start|Filename|HTTP|supported|||start|exist|tb|Size|doesn|be||URL|might|Close|Init|and|click|gb|upload|Stop|to|button|present||here|Runtime|Drag|max|Invalid|queued|ran|out|too|large|count|memory|of|available|were|stripped|Extra|element|in|Files|Select|already|accepts|Uploaded|only|time|at|plupload|addI18n'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/es.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/es.min.js new file mode 100644 index 0000000000000000000000000000000000000000..deb975a6073e735caf00b2b7509c4052551ab277 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/es.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('W.10({"G 9":"1q 18.","9 w 1a X j i 1k\'t Z.":"w 0 f E.","J":"1j","1i":"1v�o","1d":"1c","1e 7.":"1 0 1f�n.","m 5 1g c 1b p 15 14 c 16 17.":"19 3 a q r 0 1h y 1s 1t 6 1u 1p�n 0 l f","1o":"1l 0 2","1m 1n 13 j i I K.":"L 0 M k O.","H":"D","h 1.":"1 0 h.","F 9":"l f","12":"P","Y":"11","V 8 7.":"1, 2 R","4 g 7.":"1 0 e�o 0 2.","N/A":"C z","Q":"S","1: T 8 x:":"1: U�n 0 2 1r�1F:","28 5":"27 3","%s 29 2a 2b c p.":"%s 26 v 1w 6 q r.","4: %s":"u: %s","b":"B","25 %d/%d 5":"21 %d/%d 3","9 20 22 23 %d 8(s) 2d a 2c. 2f 5 2j 2l.":"2i 2h 2g�2e %d 2(s) 2m 2k. 24�s, k v 1Y 6 1G.","%d 5 1Z":"%d 3 6 1H.","4: %s, g: %d, 1I 8 g: %d":"u: %s, e�o: %d, e�o 1J�1E 0 2: %d","1D 5 1y.":"1x 3 1z�","1A 1C 1B 1K 1L 1U.":"C 1T 1V z.","4 1W 7.":"1 6 1X 0 3.","4 x 7.":"1 0 1S�n 0 2.","1: 4 1R 1N:":"1: 2 1M 1O:","m 1P":"1Q 3"});',62,147,'de|Error|archivo|archivos|File|files|en|error|file|Upload|||the||tama�|carga|size|HTTP|or|wrong|no|Iniciar|Add|||queue|la|lista|||Archivo|se|URL|extension||disponible|||No|Estado|inexistente|Start|Stop|Status|not|tb|supported|Formato|imagen||soportada|MB|gb|duplicado|GB|Invalid|Extensi�|Duplicate|plupload|be|kb|exist|addI18n|KB|mb|either|click|and|start|button|Subida|Agregue|might|upload|Cerrar|Close|Init|inicializaci�|to|subida|Size|TB|doesn|Nombre|Image|format|Filename|bot�|Detener|inv�|pulse|clic|el|Tama�|encuentra|Arrastre|here|aqu�|Runtime|out|ran|Drag|ximo|lida|cuenta|cola|max|m�|of|available|demasiado|large|grande|Files|Agregar|too|extensi�|hay|memory|memoria|count|contador|tienen|queued|element|Subidos|accepts|only|M�|Uploaded|ya|Elija|Select|already|present|in|time|at|lo|Extra|s�|aceptan|Se|were|tiempo|stripped|al'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/et.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/et.min.js new file mode 100644 index 0000000000000000000000000000000000000000..3a7b33f2d4bae73074f498113fb313f3e2f3ba1e --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/et.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('1d.1e({"q 2":"q 2","2 p 1c 1b e 8 17\'t 18.":"0�9 p 1a 1g 1h 1o 1p 1q.","1n":"","1m":"1i","1j":"1k","1l 4.":"16�15 7.","g 3 Q h R z S T h P O.":"J c 0�9 k�K L M U V.","12":"13","o n r e 8 m x.":"o n r e 8 m x.","1s":"1z","w 6.":"w 0�1S 7.","v 2":"v 2","1Q":"","1P":"","1M 5 4.":"","1 i 4.":"1N 7.","N/A":"N/A","1V":"","6: y 5 f:":"6: y 5 f:","22 3":"20 1Z","%s 1W 1X 1Y h z.":"","1: %s":"1y: %s","b":"","1A %d/%d 3":"0�1x 1w %d/%d","2 l 1u 1v %d 5(s) 1B a 1I. 1J 3 1H 1G.":"0�9 l 1F 23 1E 1C %d u 0�1U 1O. 0�1R�0�21 c k�Z Y.","%d 3 X":"19�1f 1T %d u","1: %s, i: %d, 1r 5 i: %d":"","1D 3 1t.":"1K c 1L.","H I C B D E.":"H I C B D E.","1 W 4.":"10 11 7.","1 f 4.":"14 7.","6: 1 G F:":"6: 1 G F:","g j":"g j"});',62,128,'�|File|Upload|files|error|file|Error|viga|or|leslaadimise|||failid||wrong|extension|Add|the|size|Files|j�|element|not|format|Image|URL|Stop|either|||faili|Start|HTTP|supported|Invalid|queue||of|out|available|memory|large|too|Runtime|ran|Lisa|rjekorda|ja|klõpsa||button|start|to|upload|and|click|alustamise|nupule|count|queued|laadimata|etakse|Failide|arvu|Filename|Failinimi|Faililaiendi|htestamise|L�|doesn|exist|J�|võib|be|might|plupload|addI18n|rjekorras|olla|vale|Suurus|Close|Sulge|Init|Size|tb|või|seda|pole|max|Status|here|accepts|only|laaditud|les|Fail|Olek|Uploaded|at|ainult|Drag|võtta|saab|stripped|were|time|Extra|Lohista|siia|Duplicate|Failisuuruse|korraga|kb|mb|lej�|henduse|on|he|gb|already|present|in|faile|Vali|nud|Select|vastu'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/fa.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/fa.min.js new file mode 100644 index 0000000000000000000000000000000000000000..a5fbea5d18ace8f06bda0dd0f3888233990c1455 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/fa.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('17.12({"1l 7":"5�1�1� 0�1�5�0�1�","7 G B n e f r\'t u.":"7 G B n e f r\'t u.","S":"","R":"0�0�2�0�","Q":"0�0�5�","P 9.":"0�0�0� 0�0� 0�0�j�0�g 0�0�3�0�2�1�g","z 6 O h U o Y X h W V.":"0�0�0�1�1� 3�1�2�0� 1�0�2�1� 1�0� 0�0� 0�1� F� 0�1�1�1�0� 1� 0�3�1�1� 0�0�1�0� 0�0� 3�1�2�3� 3�1�2�0�.","Z":"1�0�1� 1�0�2�1�","x q v e f m p.":"x q v e f m p.","L":"1�0�0�2�g","I c.":"I 0�0�0�2�","M 7":"0�0�1�0� 0�1�5�0�1�","T":"","1p":"","1i 8 9.":"","4 i 9.":"0�0�0�2� 0�0�2�0� 1�0�2�1�","N/A":"N/A","1h":"","c: H 8 k:":"c: H 8 k:","1g 6":"0�1�j�0�0� 1�0�2�1�","%s 1e 1f 1j h o.":"","4: %s":" 1�0�2�1� 1�0� : %s","b":"","1k %d/%d 6":"1�1�5�1� 0�0� %d/%d 0�0� 1�0�2�1�1�0�","7 10 1o 1n %d 8(s) 1m a 1d. 1c 6 15 14.":"0�1�13� 0�0�0�3�0�0�0� 1�1�0� %d 1�0�2�1� 0�1� 0�0� 2�3� 0�1�0�1� 1�2� 1�0�2�0�0�. 0�0�2�0� 1�0�2�1� 1�0� 1�0�0�0� 0�0� 0�2�1� 1�1�0�1�0� 1�0�5�0�.","%d 6 11":"%d 1�0�2�1� 0�0� F�","4: %s, i: %d, 16 8 i: %d":"","1b 6 1a.":"0�3�0�2�0� 1�0�2�1� 1�0� 0�1� 0�1� 0�2�1�0�0�","D E w K y l.":"D E w K y l.","4 19 9.":"0�0�0�2� j�0�0�0� 1�0�2�1�","4 k 9.":"0�0�0� 1�2�0�1�1�0� 1�0�2�1�","c: 4 J C:":"c: 4 J C:","z 18":"0�1�0�1�0�1� 1�0�2�1�"});',62,88,'�|�|�|�|File|ت�|files|Upload|file|error|||Error||wrong|or|ت|the|size|ت�|extension|memory|not|be|queue|supported|format|doesn|||exist|either|out|Image|available|Add||might|large|Runtime|ran|ص�|URL|Invalid|HTTP|too|of|Status|Start||to|Init|Close|Size|tb|mb|upload|button|start|click|and|Filename|element|queued|addI18n|ص�|stripped|were|max|plupload|Files|count|here|Drag|Extra|time|already|present|Select|gb|Duplicate|in|Uploaded|Stop|at|only|accepts|kb'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/fi.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/fi.min.js new file mode 100644 index 0000000000000000000000000000000000000000..4fd468c47cfbd2018fbe01fac480492fbea85a2d --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/fi.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('Z.10({"z 0":"z 0","0 y L J 7 6 F\'t u.":"0 y L J 7 6 F\'t u.","11":"","Y":"X","T":"U","h 4.":"h k.","c 2 S 9 W q 12 13 9 1a 1b.":"1c�8� i 19 18 14 15-16.","17":"1d","G n m 7 6 l o.":"G n m 7 6 l o.","Q":"R","r 3.":"r k.","j 0":"j 0","M":"","P":"","O 5 4.":"","1 e 4.":"V.","N/A":"N/A","1K":"","3: H 5 f:":"3: H 5 f:","1D 2":"1H i","%s 1G 1Q 1F 9 q.":"","1: %s":"1e: %s","b":"","1E %d/%d 2":"1A %d/%d g","0 1C 1I 1J %d 5(s) 1O a 1P. 1N 2 1M 1L.":"1B 1y 1l 1z %d 1m(a) 1n. 1k�8�1j�1f I 1g.","%d 2 1h":"%d g 1i","1: %s, e: %d, 1o 5 e: %d":"","1p 2 1v.":"1w I 1x�1u.","K D E x w v.":"K D E x w v.","1 1t 4.":"1q.","1 f 4.":"1r�8�1s.","3: 1 C B:":"3: 1 C B:","c p":"c p"});',62,115,'Upload|File|files|Error|error|file|or|wrong|�|the|||Add||size|extension|tiedostoa|Init|tiedostoja|Start|virhe|not|either|format|supported|Files|queue|HTTP|||exist|memory|available|of|URL|Stop||large|too|ran|out|doesn|Image|Invalid|tiedostot|be|Runtime|might|mb||Duplicate|kb|Status|Tila|to|Close|Sulje|Tiedostokokovirhe|upload|Koko|Size|plupload|addI18n|tb|and|click|klikkaa|aloita|nappia|Filename|ja|latausjonoon|start|button|Lis�|Tiedostonimi|Tiedosto|iset|ohitettiin|queued|jonossa|r�|Ylim�|ladata|tiedosto|kerrallaan|max|Drag|Tiedostolaskentavirhe|Tiedostop�|tevirhe|count|nne|here|Raahaa|t�|sallii|vain|Ladattu|Latauselementti|element|Select|Uploaded|in|already|Valitse|accepts|only|gb|stripped|were|Extra|at|time|present'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/fr.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/fr.min.js new file mode 100644 index 0000000000000000000000000000000000000000..a072e630768e9b060a78506e00e5096cd82192b0 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/fr.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('1l.1k({"1m g":"1n l\'f.","g O 1p 1o J P 1j\'t 1i.":"L\'O d\'f F c B�e c n\'1d D.","1c":"1b","1e":"1f","1h":"1g","1q 8.":"1 d\'1r.","w 6 1B q 1A v 1C 1D q 1F 1E.":"1z C 0 4� k 5 d\'p 2 j�1y�1t 1s 1u z 1a 1x \'m�G l\'f\'","1w":"1G 15 7","Q M R J P S T.":"I M d\'U F c B� c D 19�V�.","14":"4�16","x r.":"1 x.","17 g":"m�G l\'f","13":"12","X":"W","Y 5 8.":"1: 9 4� Z.","3 h 8.":"1 2 i 2 7.","N/A":"11 10","1v":"1S","r: 1H 5 u:":"1: 2m 2 7 2o 2p:","2q 6":"2l�2k y 0","%s 2f 2e 2g q v.":"%s 2j�2i� 2r�2A 2B k 5 d\'p.","3: %s":"9: %s","b":"o","2u %d/%d 6":"%d 0 z %d K 4�j� H�s","g 2v 2t 2y %d 5(s) 2x a 2C. 2w 6 2z 2h.":"2c %d 7(s) 1R 1Q H�(s) 4� k 1T. 1V 0 1U�1P K 4�j� 1I�s.","%d 6 1K":"%d 0 1L p","3: %s, h: %d, E 5 h: %d":"9: %s, i: %d, i E. d\'1M 7: %d","1W 6 27.":"m�28 y 0 29.","2b 2a 25 24 1Z 1Y.":"I 20 a 21� 2 23�22 2n.","3 26 8.":"1: 1X 2 0.","3 u 8.":"1 d\'u 2 7","r: 3 1N 1J:":"1: 9 1O 2d:","w 2s":"18 C 0"});',62,163,'fichiers|Erreur|de|File|�|file|files|fichier|error|Fichier|||soit|||envoi|Upload|size|taille|t�|la||D�|||attente|the|Error|||extension|queue|Add|HTTP|les|sur||erron�|des|pas|max|est|marrer|envoy�|Le|wrong|ont||format||URL|or|Image|either|not|supported|image|r�|Ko|kb|Duplicate|double|applicable|Non|Mo|mb|Status|du|tat|Start|Ajouter|g�|le|To|tb|existe|Size|Taille|Fermer|Close|exist|doesn|addI18n|plupload|Stop|Arrêter|be|might|Init|initialisation|et|chargement|appuyez|gb|Filename|bouton|l�|Ajoutez|upload|to|and|click|button|start|Nom|Invalid|ignor�|large|queued|en|un|too|trop|mentaires|être|peuvent|Go|fois|suppl�|Les|Drag|Nombre|memory|available|traitement|manqu�|moire|m�|of|out|count|here|posez|ici|ran|Runtime|Que|volumineux|present|already|in|stripped|j�|d�|lectionnez|S�|Extension|disponible|non|valide|Select|pr�|Files|accepts|Uploaded|element|Extra|at|only|were|sent|dans|time'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/he.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/he.min.js new file mode 100644 index 0000000000000000000000000000000000000000..1b37f58bb9b3abd466a928bd629aa7fd2887764b --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/he.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('H.F({"G 4":"בטל העלאה","4 h E D i 9 y\'t z.":"כ�0וב�0 h שגויה או לא קיימ�0.","g":"g","C":"גודל","I":"סגור","P 3.":"שגיא�0 אי�0חול","e 1 Q 8 M c J x 8 K L.":"הוסף קבצים לרשימה ולחץ על כפ�0ור שליחה לה�0חל�0 פעולו�0 העלאה","R":"שם קובץ","v j k i 9 m w.":"�0מונה פגומה או סוג �0מונה לא נ�0מך","n":"אחוז","r 6.":"שגיא�0 פרוטוקול","q 4":"שליחה","o":"p","u":"l","O 5 3.":"קובץ כפול","2 7 3.":"גודל קובץ חורג מהמו�0ר","N/A":"שגיאה","1g":"1f","6: 1a 5 f:":"שגיאה: סוג קובץ לא נ�0מך:","1c 1":"בחר קבצים","%s 1k S 1d 8 c.":"%sקובץ נמצא כבר ברשימ�0 הקבצים.","2: %s":"קובץ: %s","b":"B","1b %d/%d 1":"מעלה: %d/%d","4 1l 1j 1i %d 5(s) 1h a 18. 19 1 Y Z.":"אלמנטי ההעלאה מקבלים רק %d קובץ(ים) בפעם אח�0. קבצים נוספים הוסרו.","%d 1 X":"%d קבצים נו�0רו","2: %s, 7: %d, W 5 7: %d":"קובץ: %s, גודל: %d, גודל מקסימלי: %d","T 1 U.":"גרור קבצים לכאן","V 10 11 16 17 15.":"שגיא�0 מחסור בזיכרון","2 14 3.":"שגיא�0 מספר קבצים","2 f 3.":"קובץ זה לא נ�0מך","6: 2 12 13:":"שגיאה: קובץ חורג מהגודל המו�0ר:","e 1e":"הוסף קבצים"});',62,84,'�|files|File|error|Upload|file|Error|size|the|or|||queue||Add|extension|tb|URL|wrong|format|either|KB|not|Status|mb|MB|Start|HTTP|||kb|Image|supported|click|doesn|exist|||Size|be|might|addI18n|Stop|plupload|Close|and|start|button|upload||Duplicate|Init|to|Filename|present|Drag|here|Runtime|max|queued|were|stripped|ran|out|too|large|count|memory|of|available|time|Extra|Invalid|Uploaded|Select|in|Files|GB|gb|at|only|accepts|already|element'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/hr.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/hr.min.js new file mode 100644 index 0000000000000000000000000000000000000000..22f2c48424dfa1797d61ff8791072a551c21bd94 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/hr.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('18.19({"1a 3":"17 j.","3 Q S K 8 9 L\'t J.":"3 Q S K 8 9 L\'t J.","I":"I","16":"13�g","14":"15","1b 5.":"v�1 1c.","r 2 1i e j R 1j 1k e 1h 1g.":"1d 0 u 12 i 1e 3.","1f":"1l 0","B z U 8 9 o p.":"B z U 8 9 o p.","E":"E","P k.":"P W�1.","11 3":"10 j.","H":"H","G":"G","Z 7 5.":"6�1 Y 0.","4 f 5.":"v�1 h�X 0.","N/A":"N/A","q":"q","k: 1N 7 V:":"6�1: 1O�1L�i 1H 0:","1I 2":"1J 0:","%s 1P 1Q 1W e R.":"%s m 1Y� 1m u 1Z D�1V.","4: %s":"l: %s","b":"b","1R %d/%d 2":"1S %d/%d c","3 C n F %d 7(s) T a O. y 2 x w.":"3 C n F %d 7(s) T a O. y 2 x w.","%d 2 1G":"%d c 1F D�1s.","4: %s, f: %d, 1t 7 f: %d":"l: %s, h�g: %d, 1r h�g: %d","1n 2 1o.":"1p 0 1v","M 1w 1C 1D 1E 1B.":"M 1A m 1x 1y.","4 1z 5.":"6�1 u 1X c.","4 V 5.":"6�1 u 1q 0.","k: 4 1u 1T:":"6�1: l m 1U:","r 1K":"1M 0"});',62,124,'datoteke|ka|files|Upload|File|error|Pogre�|file|wrong|or|||datoteka||the|size|ina|veli�||upload|Error|Datoteka|je|accepts|not|supported|gb|Add||||Gre�|stripped|were|Extra|format||Image|element|�|Status|only|kb|mb|tb|exist|be|doesn|Runtime||time|HTTP|URL|queue|might|at|either|extension|gre�|ine|dvostruke|Duplicate|Pokreni|Start|listu|Veli�|Close|Zatvori|Size|Zaustavi|plupload|addI18n|Stop|Init|inicijalizacije|Dodajte|kliknite|Filename|button|start|to|and|click|Ime|prisutan|Drag|here|Dovucite|nastavku|maksimalna|ekanju|max|too|ovdje|ran|ponestalo|memorije|count|aplikaciji|memory|out|of|available|na|queued|nastavak|Select|Odaberite|Files|e�|Dodaj|Invalid|Neva�|already|present|Uploaded|Uploadano|large|prevelika|ekanja|in|broju|ve�|listi'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/hu.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/hu.min.js new file mode 100644 index 0000000000000000000000000000000000000000..e572a91c5f0cbc0f01fe4b524a51cceca49d0bb8 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/hu.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('1o.1n({"1m g":"p�5�s 1p�j�4�6","g E 1q 1s J I 1r\'t 1l.":"A h�1k� E 1f�s z k 1e�1d.","1g":"","1h":"1j�c","1i":"1t�1u�s","B 9.":"B f.","u 1 1F l 1E D 1G 1H l 1J 1I.":"A 0�7 h�5�1D 1C 1x� y�K�6 1w�n 1v 1y�4�s 1c 1B 1A.","1K":"8�17�v","M L Q J I O R.":"T z k 4�U P�S�1b.","16":"o�15","C q.":"C-f.","V g":"p�5�s 18�4�6","1a":"","19":"","14 e 9.":"13�Y�2-f.","3 m 9.":"H�s 0�w�c.","N/A":"X W�Z�","10":"","q: 12 e G:":"x: o�11�1z 0�F�s:","1W 1":"8�7 2s�2r�6","%s 1L 2t 2u l D.":"%s i�r 2w a 2v�2q.","3: %s":"8�2: %s","b":"b","2p %d/%d 1":"p�5�2k 0�7: %d/%d","g 2l 2m 2y %d e(s) 2o a 2n. 2x 1 2z 2J.":"A h�5�s 2G 2I %d 0�2H 2E 2A, a 4�2B 0�2 k 2D h�2h.","%d 1 2i":"%d 0�2 1V�j�1X","3: %s, m: %d, 1Y e m: %d":"8�2: %s, i�c: %d, 1Z 0�w�c: %d","1T 1 1O.":"1N 1M 1P a 0�1Q.","1S 1R 21 22 2c 2b.":"2d�2e�2g 2f a 2a�29 o�j� 24�23.","3 25 9.":"A 0�7 26�i�28 27 f.","3 G 9.":"H�s 0�F�s.","q: 3 1U 20:":"x: a 0�2 2C 2F:","u 2j":"8�7 y�K�6"});',62,170,'f�|files|jl|File|t�|lt�|sa|jlok|F�|error|||ret||file|hiba|Upload|felt�|m�|ll�|nem|the|size||�|Felt�|Error||||Add||jlm�|Hiba|hozz�|vagy||Init|HTTP|queue|URL|jlkiterjeszt�|extension|Hib�|or|wrong|ad�|format|Image||not|k�|either|supported|pform�|Rossz|mogatott|Start|el�|Nem|ltf�|rhet�|gb|rv�|Invalid|Duplik�|Duplicate|llapot|Status|jln�|ind�|kb|mb|tum|gombra|tezik|l�|hib�|tb|Size|Close|M�|lt�|exist|Stop|addI18n|plupload|le�|might|doesn|be|Bez�|r�|az|ut�|val�|Ind�|nytelen|kattintani|kell|sorhoz|si|upload|to|and|click|button|start|Filename|already|lehet|Ide|here|húzni|jlokat|ran|Runtime|Drag|too|sorba�|Select|tva|max|legnagyobb|large|out|of|ria|mem�|count|sz�|kapcsolatos|val|sre|rendelkez�|memory|available|Fut�|sid�|elfogyott|ben|ltve|queued|Files|tt|element|accepts|time|at|Uploaded|ban|laszt�|kiv�|present|in|list�|szerepel|Extra|only|were|el|bbi|túl|lesz|fogad|nagy|egyszerre|jlt|csak|stripped'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/hy.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/hy.min.js new file mode 100644 index 0000000000000000000000000000000000000000..a32b66b91c048b6f9f838acbe1515959a6018b6e --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/hy.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('G.H({"F 7":"6�0�0�0�0�0�1�0�0�0�","7 l E B k j C\'t D.":"6�0�0�1�0�0�0�0� l-0� 0�0�0�0� 0� 0�0�0� 0�0�2�1�0�2�1�0� 0�0�1�0�0�1�","I":"0�0�","J":"0�0�1�","P":"0�0�0�0�0�","Q 5.":"0�0�0�0�0�0�0�0� 0�0�0�0�","f 4 O c M g K z c R q.":"6�0�0�0�0�1�1�0�1� 1�0�2�0�1� 1�0�1�1�0�0�0�1�0� 1� 0�0�0�0�0�1� \\"0�0�1�0�0�0�0�0�0�\\"1�","n":"0�0�2�0� 0�0�0�1�0�","o p m k j y x.":"0�0�0�1�0� 1�0�1�0�0�0�0� 0�0�0�0� 0� 0�0�0� 0�0� 0�0�0�0�1�0�0�0�1�0�1�","w":"","h e.":"h 0�0�0�0�","v 7":"0�0�1�0�0�0�0�0�0�","r":"0�0�","u":"0�0�","L 8 5.":"0�0�2�0� 0�1�0�0�0�0�0� 0�0�0�0�","3 9 5.":"0�0�2�0� 0�0�1�0� 0�0�0�0�","N/A":"N/A","1d":"0�0�","e: S 8 i:":"0�0�0�0�1� 0�0�2�0� 0�0�0�0�0�2�0�1�0�0� 0�0�0�0� 0�1�","1e 4":"6�0�0�1�0�1� 1�0�2�0�1�0�","%s 1c 1b 19 c g.":"%s 1�0�2�0� 0�1�0�0�0� 0�0�0�0�0�1�0�0�0� 0� 1�0�1�1�0�0�0�1�0�.","3: %s":"0�0�2�: %s","b":"0�","1g %d/%d 4":"0�0�1�0�0�0�0�0�0�0� 0�0� %d/%d 1�0�2�0�1�0�","7 1j 1k 1h %d 8(s) 1i a 1f. 17 4 18 X.":"","%d 4 Y":"1�0�1�1�0�0�0�1�0� 0�0� %d 1�0�2�","3: %s, 9: %d, W 8 9: %d":"0�0�2�: %s, 0�0�1�: %d, 1�0�2�0� 0�0�1�0�0�0�0�1�0� 0�0�1�: %d","U 4 Z.":"0�0�0�0�1�0�0�0�1� 1�0�2�0�1�0� 0�2�0�0�0�","10 15 16 14 13 11.":"","3 12 5.":"0�0�2�0�1�0� 1�0�0�0�0�0� 0�0�0�0�","3 i 5.":"0�0�2�0� 0�0�0�0�0�2�0�0�0� 0�0�0�0�","e: 3 T V:":"0�0�0�0�1� 0�0�2�0� 0�0�1�0� 0�0�0� 0�1�","f 1a":"6�0�0�0�0�1�0�0�0� 1�0�2�0�1�"});',62,83,'�|�|յ�|File|files|error|�|Upload|file|size|||the||Error|Add|queue|HTTP|extension|or|wrong|URL|either|Filename|Image|format|button|mb|||kb|Start|Status|supported|not|click||be|doesn|exist|might|Stop|plupload|addI18n|tb|Size|and|Duplicate|upload||to|Close|Init|start|Invalid|too|Drag|large|max|stripped|queued|here|Runtime|memory|count|available|of|ran|out|Extra|were|in|Files|present|already|gb|Select|time|Uploaded|only|at|element|accepts'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/id.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/id.min.js new file mode 100644 index 0000000000000000000000000000000000000000..ab2593ddbacd1fb2223f05a89663411875d376be --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/id.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('17.18({"19 4":"1a 4","4 p 16 15 m q 11\'t 12.":"13 p j 7 8 1b r 8 z","o":"o","1j":"1k","1l":"1m","n 5.":"2 6 n","B 3 1i h 7 i 1h 1d h 1e 1f.":"10 0 1n e 7 V I J v","K":"L 1","H D G m q M Z.":"2 6 x O r x 0 8 Y","w":"w","l g.":"l T","P 4":"v 4","u":"u","y":"y","1g 0 5.":"1o 1T 0","1 c 5.":"2 6 9 0","N/A":"N/A","k":"k","g: 1V 0 C:":"2: 1S 0 8 1R","1N 3":"1O 0","%s 1P 1Q 1X h i.":"%s 24 z f 22 e","1: %s":"1: %s","b":"b","1Y %d/%d 3":"1 20 %d/%d","4 23 1L 1M %d 0(s) 1v a 1w. 1x 3 1y 1u.":"1t j 7 1q 1r %d 0(s) f 1s 7. 1 1A 8 1I 1J","%d 3 1K":"%d 0 f e","1: %s, c: %d, 1B 0 c: %d":"1: %s, 9: %d, 1D 9 0: %d","1E 3 1C.":"1F 0 1G","1H 1z 1p 21 25 1Z.":"1W 1U S","1 R 5.":"2 6 Q 0","1 C 5.":"2 6 U 0","g: 1 X W:":"2: 1 F E","B 1c":"14 1"});',62,130,'file|File|Kesalahan|files|Upload|error|pada|upload|tidak|ukuran|||size||antrian|dalam|Error|the|queue|untuk|gb|HTTP|wrong|Init|tb|URL|or|atau|||mb|Mulai|Status|jenis|kb|ada||Add|extension|format|besar|terlalu|either|Image|klik|tombol|Filename|Nama|not||gambar|Start|jumlah|count|memori|Bermasalah|ekstensi|dan|large|too|didukung|supported|Tambahkan|doesn|exist|Alamat|Tambah|be|might|plupload|addI18n|Stop|Hentikan|benar|Files|click|start|button|Duplicate|and|to|Size|Ukuran|Close|Tutup|kedalam|Terjadi|out|hanya|menerima|setiap|Tempat|stripped|at|time|Extra|were|ran|lainnya|max|here|maksimum|Drag|Tarik|kesini|Runtime|akan|disertakan|queued|accepts|only|Select|Pilih|already|present|dikenal|Ekstensi|duplikasi|cukup|Invalid|Tidak|in|Uploaded|memory|terupload|of|daftar|element|sudah|available'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/it.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/it.min.js new file mode 100644 index 0000000000000000000000000000000000000000..e014b8f0059ab2dba614cffab9b514ad44e46b38 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/it.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('V.10({"T 3":"Q 3","3 G M L z w 1k\'t 1m.":"G 7 3 1p o 9 1o","H":"H","1g":"1f","18":"15","19 5.":"4 1e.","E 2 1d 6 1j p 1b 1c 6 1a 17.":"J i 0 1n g 7 1l e 1h 1i 14 7 1q.","13":"P 0","O R S z w 11 12.":"Z Y U o 9 W.","X":"16","u 8.":"4 u.","1M 3":"1U 3","r":"r","q":"q","1V 0 5.":"4 0 1W.","1 c 5.":"4 f 0.","N/A":"N/D","v":"v","8: 1T 0 I:":"4: 1S 0 9 1r:","1O 2":"1P i 2","%s 1Q 1Y C 6 p.":"%s 1R� 1X 1Z g.","1: %s":"1: %s","b":"21","20 %d/%d 2":"22 %d/%d 0","3 x B n %d 0(s) j a h. k 2 l m.":"3 x B n %d 0(s) j a h. k 2 l m.","%d 2 1N":"%d 0 C g","1: %s, c: %d, y 0 c: %d":"1: %s, f: %d, f y 0: %d","1y 2 1z.":"1A i 2 1x.","F 1w 1s 1t 1u 1v.":"F 1B 1C 1J 1K 1L.","1 K 5.":"1 K 5.","1 I 5.":"4 1I 0.","8: 1 1H 1D:":"4: 1 1E 1F:","E 1G":"J 0"});',62,127,'file|File|files|Upload|Errore|error|the|di|Error|non|||size|||dimensione|coda|time||at|Extra|were|stripped|only||queue|kb|mb|||HTTP|gb|or|element|max|wrong||accepts|in||Add|Runtime|URL|tb|extension|Aggiungi|count|be|might||Image|Nome|Ferma|format|either|Stop|errato|plupload|supportato|Status|immagine|Formato|addI18n|not|supported|Filename|pulsante|Chiudi|Stato|button|Close|Init|start|and|click|to|inizializzazione|Dimensione|Size|clicca|il|upload|doesn|caricamento|exist|alla|esistente|errata|avvio|valida|out|of|available|memory|ran|qui|Drag|here|Trascina|ha|esaurito|large|troppo|grande|Files|too|estensione|la|memoria|disponibile|Start|queued|Select|Seleziona|already|gi�|Estensione|Invalid|Inizia|Duplicate|duplicato|presente|present|nella|Uploaded|byte|Caricati'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ja.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ja.min.js new file mode 100644 index 0000000000000000000000000000000000000000..98706186d1d193cb1abc332ef0e83876713d7cdc --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ja.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('V.W({"U 8":"0��0��0��0��0��0��1��4��","8 n T R h g S\'t X.":"0��0��0��0��0��0��1��0�� n 0��1��1��0��0��0��0��","13":"","14":"0�w��0�12","11":"j��0��0��","Z 5.":"0��0��0��0��0��0��0�q��0��0��","B 3 10 f Q x O J f I K.":"0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��9��1��0��0��0��0��0��0��0��0��0��0��0��0�c��0��0��0��0��0��0��0��","L":"0��0��0��0��1��","l k o h g u p.":"l k o h g u p.","15":"0��0��0��0��0��","v 6.":"v 0��0��0��","16 8":"0��0��0��0��0��0��","1l":"","1k":"","1j 7 5.":"","2 e 5.":"0��0��0��0��0�w��0�q��0��0��","N/A":"N/A","1n":"","6: r 7 i:":"6: r 7 i:","1q 3":"0��0��0��0��j��4��","%s 1p 1o 1i f x.":"","2: %s":"0��0��0��0��: %s","b":"","18 %d/%d 3":"0��0��0��0��0��0��m�� %d/%d 0��0��0��0��","8 1b 1c 1g %d 7(s) 1f a 1r. 1d 3 1e 17.":"0��0��0��0��0��0��1��9��0�c��0��0��0��4��0�� %d 0��0��0��m��1��0�c��0��0��0��0��1��j��0��0��0��0��0��","%d 3 19":"%d 0��0��0��0��0��9��1��0��0��0��0��0��","2: %s, e: %d, 1m 7 e: %d":"","1a 3 1h.":"0��0��0��0��0��0��0��0��0��0��0��0��","C E D F H G.":"C E D F H G.","2 P 5.":"0��0��0��0��4��0��0��0��","2 i 5.":"0��0��0��0��4��1�M��0��0��0��","6: 2 y z:":"6: 2 y z:","B Y":"0��0��0��0��0��9��1��"});',62,90,'�|�|File|files|�|error|Error|file|Upload|�|||��||size|the|or|wrong|extension|�|format|Image|�|URL|either|supported|��|Invalid|||not|HTTP|��|queue|too|large||Add|Runtime|out|ran|of|memory|available|start|click|button|Filename|��||and|count|upload|be|doesn|might|Stop|plupload|addI18n|exist|Files|Init|to|Close|�|tb|Size|Status|Start|stripped|Uploaded|queued|Drag|element|accepts|Extra|were|at|only|here|in|Duplicate|kb|mb|max|gb|present|already|Select|time'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ka.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ka.min.js new file mode 100644 index 0000000000000000000000000000000000000000..e0959dab7d04a53ecd3a334ed158c035b21b98be --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ka.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('q.w({"K 6":"0��0��0��0��0��0��0��0��0�� 0��0��0��0��0��0��0��0��","6 E F D f h C\'t y.":"0��0��0��0��0��0��0��0��0�� 0��0��0��0��0��0��0��0��0�� 0��0��0��0��0��0��0��0��0�� 0��0�� 0��0�� 0��0��0��0��0��0��0��0��.","z":"0��0��","B":"0��0��0��0��","G":"0��0��0��0��0��0��0��0��","H 4.":"0��0��0��0�3��0��0��0��0��0��0�3��0��0�� 0��0��0�3��0��0��0��.","c 1 M 7 O e I J 7 x P.":"0��0��0��0��0��0��0��0�� 0��0��0��0��0��0��0�� 0��0�� 0��0��0��0��0��0��0��0�� 0��0��0��0��0��0�� - 0��0��0��0��0��0��0��0��.","n":"0��0��0��0��0��0�� 0��0��0��0��0��0��","l k j f h m u.":"0��0��0��0��0��0�� 0��0��0��0��0��0��0�� 0��0�� 0��0��0��0�� 0��0��0��0��0��0��0��0��0��0��0��0�� 0��0�� 0��0��0��0��0��0��0��0��0��.","r":"0��0��0��0��0��0��0��","g 9.":"g 0��0��0�3��0��0��0��.","o 6":"0��0��0��0��0��0��0��0��","p":"0��0��","v":"0��0��","L 5 4.":"0��0��0��0��0�� 0��0��0��0��0�� 0��0��0��0�� 0��0��0��0��0��0��0��0��0��0��0��.","2 8 4.":"0��0��0��0��0��0�� 0��0��0��0�� 0��0��0��0��0��0��0��0��0��0�� 0��0��0��0��0��.","N/A":"N/A","1c":"0��0��","9: 1d 5 i:":"0��0��0�3��0��0��0��: 0��0��0��0��0�� 0��0��0��0�� 0��0��0��0��0��0��0��0�� 0��0��0��0��0��0��0��0��0��0��.","1b 1":"0��0��0��0��0��0��0��0�� 0��0��0��0��0��0��0��0��","%s 1a 17 Q 7 e.":"%s 0��0��0��0�� 0��0��0��0��0��0��0��0��0��0��0��.","2: %s":"0��0��0��0��0��: %s","b":"0��","18 %d/%d 1":"0��0��0��0��0��0��0��0��0��0�� %d/%d 0��0��0��0��0��","6 1f 1e 1i %d 5(s) 1h a 1g. 19 1 15 16.":"0��0��0��0��0��0��0��0��0��0�� 0��0��0��0��0��0��0��0��0��0�� 0��0��0��0��0��0�� %d 0��0��0��0��0��0�� 0��0��0��0��0��0��0��0��.","%d 1 V":"0��0��0��0��0��0�� %d 0��0��0��0��0��","2: %s, 8: %d, W 5 8: %d":"0��0��0��0��0��: %s, 0��0��0��0��: %d, 0��0��0��0��0��0��0��0��0��0��0�� 0��0��0��0��0��0��0��0��0�� 0��0��0��0��: %d","U 1 T.":"0��0��0��0��0��0��0�� 0��0��0��0��0��0��0�� 0��0��.","R S X Y 13 14.":"0��0��0��0��0��0��0��0��0��0��0��0��0�� 0��0��0��0��0��0��0��0��0��0�� 0��0��0��0��0��0��0��0��.","2 12 4.":"0��0��0��0��0��0��0��0��0��0��0�� 0��0��0��0��0��0��0�� 0��0��0��0��0��0��0��.","2 i 4.":"0��0��0��0��0��0�� 0��0��0��0��0��0��0�� 0��0��0��0��0��0��0��0��0�� 0��0�� 0��0��0��0��.","9: 2 11 Z:":"0��0��0�3��0��0��0��: 0��0��0��0��0�� 0��0��0��0��0��0��0��0�� 0��0��0��0��0��.","c 10":"0��0��0��0��0��0��0��0�� 0��0��0��0��0��0��0��"});',62,81,'�|files|File|��|error|file|Upload|the|size|Error|||Add||queue|wrong|HTTP|or|extension|either|format|Image|not|Filename|Start|mb|plupload|Status|||supported|kb|addI18n|start|exist|tb||Size|doesn|be|URL|might|Close|Init|and|click|Stop|Duplicate|to||upload|button|in|Runtime|ran|here|Drag|queued|max|out|of|large|Files|too|count|available|memory|were|stripped|present|Uploaded|Extra|already|Select|gb|Invalid|accepts|element|time|at|only'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/kk.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/kk.min.js new file mode 100644 index 0000000000000000000000000000000000000000..5ef602e642a33011195c23678810a1ddfb94f117 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/kk.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('13.15({"1t f":"0�2�6�4�0�1� 1�0�2�1�0�1�1�","f u z y n r 1m\'t M.":"0�2�6�4�0�1� 2�0�0�1�0�0�0�1�1�1� u 2�0�1�5 0�5 0�2�0�0�3� O�1�1�4�1�0�0�3�3�.","L":"1�0�","K":"e�0�1�3�1�","H":"0�0�0�1�","I c.":"0�0�0�1�0�0�0�0�0�0�1�0�1� 2�0�1�4�1�.","o 9 J h P l Q V h G U.":"0�2�6�4� 7�3�1�0�5 1�0�0�0�0�0�1� 2�0�1�1�0�, 0�0�1�1�0�1� j�0�0�j�1�1�0� 0�0�1�1�2�1�0�.","T":"0�0�0�0� 0�1�1�","R S X n r x w.":"0�1�1�4� 1�0�1�0�0�1�1� 2�0�1�5 0�3�4�5 0�0�1�2� 2�0�0�0�0�1�1� 0�0�2�.","v":"0�2�0�1�","p k.":"p 2�0�1�4�1�.","F f":"0�2�6�4�0�1� 0�0�1�1�0�1�","E":"0�0�","D":"j�","C g c.":"0�0�0�0� 2�0�0�1�0�0�0�0�0�1�1�0�1�2� 2�0�1�4�1�.","8 i c.":"0�0�0�0� e�0�1�3�1�0�1�2� 2�0�1�4�1�.","N/A":"2�/0�","B":"0�0�","k: W g q:":"2�0�1�5: 0�0�0�0� m�3�1�1�0�1�1� 2�0�1�5:","1u 9":"0�0�0�0�0�0�1� 1�0�2�0�0�2�1�0�","%s 1k 1l 1j h l.":"%s 1�0�0�0�1� 7�1i�5 0�2�1�1�0�0�0�0� 0�0�1�.","8: %s":"0�0�0�0�: %s","b":"0�","1g %d/%d 9":"0�2�6�3�0�3�: %d/%d 1�0�0�0�","f 1h Y 1n %d g(s) 1s a 1r. 1q 9 1o 1p.":"0�2�6�4� 1�0�3�3�1�1� 0�1�1� 7�0�5 %d 1�0�0�0� 2�0�0�0� 0�2�6�3� 0�0�0�0�1�. 0�1�1�1�2� 1�0�0�0�0�0�1� 0�2�6�3�0�3�0�1�.","%d 9 1f":"%d 1�0�0�0� 7�1e 2�0�0�1�0�0�1�","8: %s, i: %d, 14 g i: %d":"0�0�0�0�: %s, e�0�1�3�1�: %d, 0�0�6�. 1�0�0�0� e�0�1�3�1�: %d","12 9 Z.":"0�0�0�0�0�0�1�0�1� 0�1�0�0� 0�4�0�5 1�0�1�1�0�2�1�0�.","10 11 16 17 1c 1d.":"0�1�1�0�0�0�1� 7�1�0�0�5 0�0�0�1� 0�4�0�3� 2�0�0�0�1�.","8 1b c.":"0�0�0�0� 1�0�0�1�0�1�2� 2�0�1�4�1�.","8 q c.":"0�0�0�0� m�3�1�1�0�1�1�0�1�2� 2�0�1�4�1�.","k: 8 1a 18:":"2�0�1�5: 0�0�0�0� 0�e�0�1�4�1� 1�1�0� 2�0�7�:","o 19":"0�0�0�0� 2�0�1�1�"});',62,93,'�|�|�|е�|е�|е|к�|ке�|File|files|||error||�|Upload|file|the|size|к�|Error|queue|ке�|wrong|Add|HTTP|extension|or|||URL|Status|supported|not|be|might||gb|Duplicate|kb|mb|Start|start|Close|Init|to|Size|tb|exist||к�|upload|and|Image|format|Filename|button|click|Invalid|either|accepts|here|Runtime|ran|Drag|plupload|max|addI18n|out|of|large|Files|too|count|available|memory|екке|queued|Uploaded|element|ек�|in|already|present|doesn|only|were|stripped|Extra|time|at|Stop|Select'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ko.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ko.min.js new file mode 100644 index 0000000000000000000000000000000000000000..6a15a914dba75ac5b1503e5dc5939168086c8651 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ko.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('Q.R({"P 7":"0��1��1�� 0��0��","7 O L M e f S\'t T.":"0��1��1��2�� Y�� 0��0��2��0�� 0��0�9��1��","X":"","W":"2��3��","U":"1��3��","V 6.":"0��3��2�� 0��1��","w 5 Z c K o G C c D E.":"2��0��0�� 0��1��1�� 2��0�� 0��3��2��0�� 0��0�� 1��2��0�� 2��1��2��0��0��0��.","I":"2��0�� 0��1��","i n k e f l j.":"i n k e f l j.","z":"0��2��","m h.":"m 0��1��","1d 7":"0��1��1��","1i":"","10":"","1h 8 6.":"","4 g 6.":"2��0�� 2��3�� 0��1��","N/A":"N/A","1g":"","h: 1k 8 x:":"0��1�� : 2��0��0��3�� 2��0��1��0�� 0��0�9��1�� :","1j 5":"2��0�� 0��2��","%s 1l 1n 1m c o.":"","4: %s":"2��0�� % s","b":"","1f %d/%d 5":"0��1��1�� 0�� % d / % d 2��0��","7 1e 15 14 %d 8(s) 13 a 11. 12 5 16 17.":"0��1��1�� 3��1��2�� 2��0��0�� 0��1�� % 1c��1��1��. 1��2��0��2�� 2��0��0�� 0��0��1��0��0�9��1��","%d 5 1b":"% d 2��0��0�� 0��3��1��0��0�9��1��","4: %s, g: %d, 1a 8 g: %d":"","19 5 18.":"0��3��0�� 2��0��0�� 1��1��3��","v u q p r y.":"v u q p r y.","4 B 6.":"0��1��0�� : 0��1��","4 x 6.":"2��0�� 2��0��0�� 0��1��","h: 4 J F:":"0��1�� : 2��3��3�� 1��1�� 2��1��1��","w H":"2��0�� 0��3��"});',62,86,'�|�|�|�|File|files|error|Upload|file|��|||the||wrong|or|size|Error|Image|supported|either|not|HTTP|format|queue|of|out|available|||ran|Runtime|Add|extension|memory|Status||count|click|start|button|large|and|Files|Filename|too|upload|might|be||URL|Stop|plupload|addI18n|doesn|exist|Close|Init|Size|tb|URL�|to|kb|time|Extra|at|only|accepts|were|stripped|here|Drag|max|queued|d�|Start|element|Uploaded|gb|Duplicate|mb|Select|Invalid|already|in|present'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/lt.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/lt.min.js new file mode 100644 index 0000000000000000000000000000000000000000..0e8fc1e5b0e45a8235bb8f742b9ed3fc7bf3d27d --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/lt.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('1f.1e({"1g 8":"1h 0�5�v�","8 1i 1d 1c u w 18\'t 17.":"19 r 1a 0�5�y 1b.","m":"m","1j":"1k","1s":"1t�1u","1v 4.":"0�1r p.","D 1 1q g 1m B 1l 1n g 1o 1p.":"E�16 3 0� 0�5�y c� 11 M L O�.","P":"K R","J G I u w Q 15.":"S 10 12 r 14.","Z":"Y","q h.":"q p.","T 8":"V�9 0�5�v�","x":"x","o":"o","26 6 4.":"27 28.","2 k 4.":"7 e i.","N/A":"N/A","z":"z","h: 25 6 F:":"C: 7 e 24�20:","1Z 1":"l�21�9 3","%s 22 2b 23 g B.":"%s 2j 2k c�n.","2: %s":"j: %s","b":"b","2h %d/%d 1":"0�2g f�: %d/%d","8 2e 2f 2l %d 6(s) 2i a 1Y. 1G 1 1F 1H.":"1I 1J 1E 0�1D 1z %d 3(l�). 1A e 1C 1K�1L.","%d 1 1T":"%d f� c�n","2: %s, k: %d, 1W 6 k: %d":"j: %s, i: %d, 1N i: %d","1O 1 1Q.":"1X�9 3 0�1P.","1M 1R 1S 1V 1U 1B.":"1y�2c 2d� 2a.","2 29 4.":"7 f� 1x.","2 F 4.":"7 X.","h: 2 W U:":"C: j 13 H�:","D 1w":"E�9 3"});',62,146,'�|files|File|bylas|error|k�|file|Netinkamas|Upload|ti|||eil�||bylos|byl�|the|Error|dydis|Byla|size|�|tb|je|kb|klaida|HTTP|arba|||wrong|lim�|or|mb|limo|gb||queue|Klaida|Add|Prid�|extension|format|didel�|either|Image|Bylos|starto|paspauskite||mygtuk�|Filename|not|pavadinimas|Paveiksliuko|Start|large|Prad�|too|pletinys|Statusas|Status|formatas|ir|klaidingas|per|nebepalaikomas|supported|kite|exist|doesn|Klaidinga|neegzistuojanti|nuoroda|be|might|addI18n|plupload|Stop|Stabdyti|URL|Size|Dydis|and|upload|click|start|button|to|krovimo|Close|U�|daryti|Init|Files|kiekis|I�|tik|Papildomos|memory|buvo|kelti|galima|were|Extra|stripped|Vienu|metu|pa�|alintos|Runtime|galimas|Drag|ia|here|ran|out|queued|available|of|max|Pad�|time|Select|tinys|ym�|already|in|pl�|Invalid|Duplicate|Pasikartojanti|byla|count|atmintis|present|eikvota|darbin�|element|accepts|kelta|Uploaded|at|jau|yra|only'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/lv.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/lv.min.js new file mode 100644 index 0000000000000000000000000000000000000000..38929691d9ccf09fe067358a018864f8bcec6bc2 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/lv.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('1e.1f({"z 1":"z 1","1 o u P c 9 G\'t M.":"1 o u P c 9 G\'t M.","1g":"1h","1d":"1c�l","16":"17�19","1a 7.":"1b�1i 5�0�4.","j 3 1j i 1q B 1r 1s i 1t 1p.":"1o e p 1k 1l�1m�1n 1u","10":"k V","O S C c 9 x H.":"O S C c 9 x H.","15":"12","D 6.":"D 5�0�4.","w 1":"w 1","13":"14","11":"W","X 8 7.":"Y�Z Q 5�0�4","2 f 7.":"k g�18 5�0�4.","N/A":"N/A","20":"21","6: U 8 m:":"6: U 8 m:","22 3":"23�1Z e","%s 1Y 1U 1V i B.":"%s 1W 1X 25 24�.","2: %s":"r: %s","b":"1v","2c %d/%d 3":"2a�26�y�28 %d/%d h","1 29 2d 27 %d 8(s) 2b a 1S. 1T 3 1C 1D.":"1E�1F 1B�y�t 1A %d e 1w� 1x�. 1y�1z h 1G n","%d 3 1H":"%d h n p","2: %s, f: %d, F 8 f: %d":"r: %s, g�l: %d, F Q g�l: %d","1O 3 1P.":"1Q e 0�1R","I J L K T R.":"I J L K T R.","2 1N 7.":"1M 1I 5�0�4","2 m 7.":"k 1J�1K�1L 5�0�4.","6: 2 q v:":"6: 2 q v:","j E":"j E"});',62,138,'�|Upload|File|files|da|k�|Error|error|file|or|||wrong||failus|size|izm�|faili|the|Add|Faila|rs|extension|pievienoti|URL|rindai|too|Fails|||might|large|Start|not|d�|Stop||queue|either|HTTP|Files|max|doesn|supported|Runtime|ran|of|out|exist||Image|be|faila|memory|format|available|Invalid|nosaukums|kilobaiti|Duplicate|Atk�|rtota|Filename|kb|Statuss|mb|megabaiti|Status|Close|Aizv�|ra|rt|Init|Inicializ�|Izm�|Size|plupload|addI18n|tb|terrabaiti|cijas|to|un|klik�|�|iniet|Pieveinojiet|button|upload|and|click|start|uz|baiti|vien�|reiz�|Atliku�|ie|tikai|iel�|were|stripped|Iesp�|jams|netika|queued|skaita|papla�|in�|juma|Failu|count|Drag|here|Ievelciet|eit|time|Extra|present|in|jau|ir|already|lieties|gb|gigabaiti|Select|Izv�|rind�|atrodams|upiel�|only|ti|element|Aug�|at|Uploaded|accepts'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/nl.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/nl.min.js new file mode 100644 index 0000000000000000000000000000000000000000..5981433f021ba18aeb355761083035aa4e75364a --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/nl.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('10.11({"H 2":"H 2","2 C M L 7 6 V\'t U.":"2 C M L 7 6 V\'t U.","16":"","17":"15","j":"j","13 3.":"14 3.","g 1 19 9 l n 1a 1f 9 12 1e.":"1d c 1b 1c 1g Z x X W \'e\'.","Y":"18","k h p 7 6 y z.":"k h p 7 6 y z.","u":"u","r 4.":"r 4.","e 2":"e 2","1l":"","1x":"","1w 5 3.":"","0 8 3.":"1v 4.","N/A":"1u 1z","1C":"","4: v 5 f:":"4: v 5 f:","1B 1":"1h 1A(x):","%s 1y 1s 1t 9 n.":"","0: %s":"0: %s","b":"","1k %d/%d 1":"%d/%d c 1j-l","2 m o B %d 5(s) i a q. K 1 Q O.":"2 m o B %d 5(s) i a q. K 1 Q O.","%d 1 T":"%d 1 T","0: %s, 8: %d, 1i 5 8: %d":"","1m 1 1n.":"1r c 1q.","J I G D E F.":"J I G D E F.","0 S 3.":"0 S 3.","0 f 3.":"1p 1o.","4: 0 P R:":"4: 0 P R:","g w":"g w"});',62,101,'File|files|Upload|error|Error|file|or|wrong|size|the|||bestanden||Start|extension|Add|format|at|Close|Image|upload|element|queue|accepts|either|time|HTTP|||Status|Invalid|Files|en|not|supported||only|URL|of|available|memory|out|Stop|ran|Runtime|Extra|be|might||stripped|too|were|large|count|queued|exist|doesn|op|druk|Filename|wachtrij|plupload|addI18n|start|Init|Initialisatie|Grootte|tb|Size|Bestandsnaam|to|and|toe|aan|Voeg|button|click|de|Selecteer|max|ge|Uploaded|mb|Drag|here|bestandstype|Ongeldig|hierheen|Sleep|present|in|Niet|Bestandsgrootte|Duplicate|kb|already|beschikbaar|bestand|Select|gb'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/pl.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/pl.min.js new file mode 100644 index 0000000000000000000000000000000000000000..17ee721593b147e7a4d6f992de93a7dbe7d5619d --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/pl.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('18.19({"17 1":"16 q.","1 R S T 8 7 U\'t D.":"1 R S T 8 7 U\'t D.","14":"","15":"1a","l":"l","13 3.":"G�F�d 1b.","M 2 1g f 1h p 1f 1e f 1c 1d.":"K 6 i 1i \'10 q\'.","12":"11 E","o c u 8 7 B O.":"o c u 8 7 B O.","V":"V","L 5.":"G�F�d L.","m 1":"m 1","1m":"","1E":"","1F 4 3.":"","0 e 3.":"1D 1C 1A 1B�y.","N/A":"1L 1K�1I","1J":"","5: r 4 9:":"5: r 4 9:","1z 2":"1j 6:","%s 1y 1p 1n f p.":"","0: %s":"0: %s","b":"","1k %d/%d 2":"1l�1q %d/%d j�w","1 v n z %d 4(s) x a C. k 2 g h.":"1 v n z %d 4(s) x a C. k 2 g h.","%d 2 1w":"%d j�w w 1v.","0: %s, e: %d, 1s 4 e: %d":"","1t 2 1u.":"1x�1r 1o 6","Z Y X W Q P.":"Z Y X W Q P.","0 H 3.":"0 H 3.","0 9 3.":"1M�1H c E.","5: 0 I J:":"5: 0 I J:","M 1G":"K 6"});',62,111,'File|Upload|files|error|file|Error|pliki|or|wrong|extension|||format||size|the|were|stripped||plik�|Extra|Close|Start|accepts|Image|queue|transfer|Invalid|||either|element||at||only||not|time|exist|pliku|�|B�|count|too|large|Dodaj|HTTP|Add||supported|memory|available|URL|might|be|doesn|Status|of|out|ran|Runtime|Rozpocznij|Nazwa|Filename|Init|tb|Size|Przerwij|Stop|plupload|addI18n|Rozmiar|inicjalizacji|start|button|click|and|to|upload|kliknij|Wybierz|Uploaded|Wys�|mb|in|tu|present|ano|gnij|max|Drag|here|kolejce|queued|Przeci�|already|Select|zbyt|du�|jest|Plik|kb|Duplicate|Files|ugiwany|pne|gb|dost�|Nie|Nieobs�'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/pt_BR.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/pt_BR.min.js new file mode 100644 index 0000000000000000000000000000000000000000..e27391e4808d77248965a00955a3e694b29c305b --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/pt_BR.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('1z.1n({"1H 8":"23 o 7","8 y 1J P h i R\'t 1e.":"y c 7 14� 15 16 l�o 17","13":"","12":"C","Y":"Z","10 4.":"g 11.","G 1 18 j 19 I 1g X j 1h 1i.":"1j k 5 1f e 1a 1b 1c�o \\"n o 7\\".","1d":"1k W 2","r q u h i v x.":"r q u h i v x.","p":"p","w 3.":"g w.","V 8":"n o 7","T":"","S":"","U 6 4.":"","0 9 4.":"C c 2 l�o B.","N/A":"N/D","Q":"","3: m 6 f:":"3: m 6 f:","1Y 1":"1P k 5","%s 1Q 1R 1O j I.":"","0: %s":"1N: %s","b":"","1K %d/%d 1":"1L(s) %d/%d 2(s)","8 1M 1l 1S %d 6(s) 1T a 20. 22 1 21 1Z.":"1U� 1V�o 1W %d 5 1X 1I. O 1s 1t 1u 1v 1r.","%d 1 1q":"%d 2(s)","0: %s, 9: %d, 1m 6 9: %d":"","1o 1 1p.":"1w k 5 1x 1E�","J M L K z H.":"J M L K z H.","0 1F 4.":"g 1G 1D 1C 5","0 f 4.":"1y c 2 l�o B.","3: 0 E F:":"3: 0 E F:","G 1A":"1B 2(s)"});',62,128,'File|files|arquivo|Error|error|arquivos|file|envio|Upload|size|||de|||extension|Erro|wrong|or|the|os|n�|Invalid|Iniciar||Status|format|Image|||either|not|HTTP|supported|URL|available||permitido|Tamanho||too|large|Add|memory|queue|Runtime|of|out|ran|||be|gb|doesn|kb|mb|Duplicate|Start|do|click|Close|Fechar|Init|inicializando|Size|tb|est�|errada|ou|existe|to|upload|clique|no|bot�|Filename|exist|abaixo|and|start|button|Adicione|Nome|accepts|max|addI18n|Drag|here|queued|descartado|que|passou|disso|foi|Arraste|pra|Tipo|plupload|Files|Adicionar|dos|contagem|c�|count|na|Stop|vez|might|Uploaded|Enviado|element|Arquivo|in|Escolha|already|present|only|at|S�|s�|aceitos|por|Select|stripped|time|were|Extra|Parar'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ro.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ro.min.js new file mode 100644 index 0000000000000000000000000000000000000000..633893fe1e37d8d210291ce328460713256080c1 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ro.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('1l.1m({"1n 4":"1k�1j 1�c�j","4 V T Y h k U\'t H.":"4 V T Y h k U\'t H.","v":"v","1f":"1g�g","1h":"1�1i","1o 7.":"2 1e�1w.","X 3 1x l 1y C 1v 1u l 1q 1r.":"D� 0�9 1�n B 1s 1t� 1z \\"1�Z 1�c�j\\".","17":"12 0�6","13 14 10 h k 1b 15.":"1a z 19 I f 16�18 I 1c f 11.","1p":"1G","P m.":"2 P","20 4":"1�Z 1�c�j","w":"w","u":"u","21 8 7.":"2 22 0�6.","5 i 7.":"2 1Z 0�6.","N/A":"N/A","E":"E","m: 1A 8 W:":"2: 1V 0�1W f 24�:","1X 3":"23� 0�R","%s 2a 28 29 l C.":"%s 26� 27 1�n B z 1T�1U.","5: %s":"e�6: %s","b":"b","1H %d/%d 3":"e�9 1�c�1E %d/%d","4 G F y %d 8(s) x a q. p 3 o r.":"4 G F y %d 8(s) x a q. p 3 o r.","%d 3 1C":"%d 0�9 1D","5: %s, i: %d, 1J 8 i: %d":"e�6: %s, J�g: %d, J�g 1R�: %d","1S 3 1P.":"1O 1L 0�R.","L K S M O Q.":"L K S M O Q.","5 1M 7.":"2 1N�1Y 0�9.","5 W 7.":"2 1Q 0�6.","m: 5 1K 1B:":"2: e�1F f 1I 25:","X 1d":"D� 0�9"});',62,135,'fi�|�|Eroare|files|Upload|File|ier|error|file|iere|||nc�||Fi�|este|rime|wrong|size|rcarea|or|the|Error||were|Extra|time|stripped|||kb|tb|mb|at|only|de||lista|queue|Adaug�|gb|accepts|element|exist|ori|m�|ran|Runtime|of||available|HTTP|memory|ierele|out|might|doesn|URL|extension|Add|be|ncepe|either|suportat|Nume|Image|format|supported|gre�|Filename|it|imagine|Formatul|not|nu|Files|ini�|Size|M�|Close|nchide|te|Opre�|plupload|addI18n|Stop|Init|Status|start|button|apoi|apas�|click|and|ializare|to|upload|butonul|Invalid|large|queued|listate|rcate|ierul|Stare|Uploaded|prea|max|too|aici|count|num�|Trage|here|extensie|maxim�|Drag|a�|teptare|Extensia|ierului|Select|rare|dimensiune|Start|Duplicate|duplicat|Selecteaz�|invalid�|mare|exist�|deja|present|in|already'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ru.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ru.min.js new file mode 100644 index 0000000000000000000000000000000000000000..a4cf234d7cf80f97104b63e2981bf6d05a1d169c --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ru.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('Z.Y({"1m c":"0�1�1�0�0�0�0�0�1�1� 0�0�0�1�1�0�9�","c u w H k l 1a\'t I.":"0�0�1�2� 0�0�1�0�1�0�5� 0�3�1�0�0�0�0�1�0�1�0� 0�0�0� 0�0� 0�4 1�1�1�2�1�0�1�2�.","G":"1�0�","F":"0�0�0�0�2�","C":"0�0�9�1�1�1�","D 8.":"0�1�0�0�5� 0�0�0�1�0�0�0�0�0�0�1�0�0�.","n 7 E g J m K Q g R B.":"0�0�0�0�0�1�1�4 1�0�0�0�1� 0� 0�1�2�3�1� 0� 0�0�0�0�0�1�4 5�0�0�9� \\"0�0�0�1�1�0�0�1�1� 1�0�0�0�1�\\".","O":"0�0�1� 1�0�0�0�0�","L M S k l q p.":"0�0�1�0�0�1� 5�1�1�0�0�5� 0�3�1�0�0�0�0�1�0�1�0� 0�0�0� 0�0� 0�4 0�0�0�0�2�0�0�0�0�2�1�1�.","o":"0�1�0�1�1�1�","i h.":"0�1�0�0�5� i.","z c":"0�0�1�0�1�1� 0�0�0�1�1�0�9�","y":"0�0�","x":"5�","r e 8.":"0�0�5�0� 1�0�0�0� 1�0�4 0�1�0�1�1�1�1�1�0�1�2� 0� 0�1�2�3�0�.","6 f 8.":"0�3�1�0�0�0�0�1�0�1�0� 1�0�0�0�2� 1�0�0�0�0�.","N/A":"N/A","v":"0�0�","h: P e j:":"0�1�0�0�5�: 0� 1�0�0�0�0� 0�3�1�0�0�0�0�1�0�0�4 1�0�1�1�0�1�3�0�4:","1n 7":"0�1�0�2�0�1�4 1�0�0�0�1�","%s 1e 1f 1d g m.":"%s 1�0�4 0�1�0�1�1�1�1�1�0�1�2� 0� 0�1�2�3�0�.","6: %s":"0�0�0�0�: %s","b":"0�","1c %d/%d 7":"0�0�0�1�1�0�3�0� %d/%d 1�0�0�0�0�0�","c T 1b 1g %d e(s) 1h a 1l. 1k 7 1i 1j.":"0�0�0�1�1�0�0�1�0�1�0� 1�0�3�3�1� 0�0� 1�0�0� 0�1�0�0�0�0�0�2� 1�0�0�1�5� %d 1�0�0�0�(0�0�). 0�0�1�0�0�4 1�0�0�0�1� 0�1�0�0� 0�1�0�1�0�1�3�1�.","%d 7 19":"0� 0�1�2�3�0� %d 1�0�0�0�(0�0�)","6: %s, f: %d, 18 e f: %d":"0�0�0�0�: %s, 1�0�0�0�2�: %d, 0�0�9�. 1�0�0�0�2� 1�0�0�0�0�: %d","X 7 W.":"0�2�2�0�1�0�1�4 1�0�0�0�1� 1�1�0�0�.","U V 10 11 16 17.":"0�0�0�0�1�0�1� 1�1�3�0� 0�1�3�1�1�0�0�0� 0�0�0�0�1� 0�0�1�1�1�0�0�0� 0�0�0�1�1�0�.","6 15 8.":"0�0�0�1�5�0� 0�0�0�0�0� 1�0�0�0�0�0�.","6 j 8.":"0�3�1�0�0�0�0�1�0�0�4 1�0�1�1�0�1�3�0�4 1�0�0�0�0�.","h: 6 14 12:":"0�1�0�0�5�: 0�0�0�0� 1�0�0�1�5�0� 0�0�0�1�1�0�0�:","n 13":"0�0�0�0�0�1�1�4 1�0�0�0�1�"});',62,86,'�|�|е�|е�|е|к�|File|files|error|к�|||Upload||file|size|the|Error|HTTP|extension|wrong|or|queue|Add|Status|supported|not|Duplicate|||URL|gb|might|kb|mb|Start||button|Close|Init|to|Size|tb|be|exist|upload|and|Image|format||Filename|Invalid|click|start|either|element|Runtime|ran|here|Drag|addI18n|plupload|out|of|large|Files|too|count|available|memory|max|queued|doesn|accepts|Uploaded|in|already|present|only|at|were|stripped|Extra|time|Stop|Select'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/sk.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/sk.min.js new file mode 100644 index 0000000000000000000000000000000000000000..12b70f7d50260a9f2ff7bc2049632af3437ef7d7 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/sk.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('1d.1e({"1c 1":"1b� y�x","1 g j p 7 6 D\'t B.":"1 g j p 7 6 D\'t B.","1f":"","1g":"1l�1m�","C":"C","18 3.":"G 1k�1j.","e 2 1h 8 1i k 1n 14 8 11 10.":"Z c K J a 12 15 y�x.","17":"16�13 R","w u v 7 6 F E.":"w u v 7 6 F E.","1I":"1G","r 5.":"r G.","i 1":"i 1","1K":"","1J":"","1M 4 3.":"","0 9 3.":"1L 1N 1E�1B� 1t�1C�.","N/A":"N/A","1r":"","5: H 4 f:":"5: H 4 f:","1p 2":"1q c","%s 1u 1v 1A 8 k.":"","0: %s":"0: %s","b":"","1z %d/%d 2":"1y�Y %d/%d W","1 o n m %d 4(s) q a l. z 2 I T.":"1 o n m %d 4(s) q a l. z 2 I T.","%d 2 1x":"%d W 1w�Y K J","0: %s, 9: %d, 1D 4 9: %d":"","1F 2 1H.":"1o 1s c.","X S U O L M.":"X S U O L M.","0 P 3.":"0 P 3.","0 f 3.":"1a� 19 R.","5: 0 Q V:":"5: 0 Q V:","e h":"e h"});',62,112,'File|Upload|files|error|file|Error|or|wrong|the|size|||súbory||Add|extension|URL|Files|Start|might|queue|time|only|accepts|element|be|at|HTTP|||format|either|Image|vanie|nahr�|Extra||exist|Close|doesn|supported|not|Chyba|Invalid|were|zoznamu|do|available|memory||of|count|too|súboru|ran|stripped|out|large|súborov|Runtime|ch|Pridajte|button|start|potom|zov|click|spustite|N�|Filename|Init|typ|Chybn�|Zastavi�|Stop|plupload|addI18n|tb|Size|to|upload|cie|inicializ�|Ve�|kos�|and|Sem|Select|Vyberte|gb|pretiahnite|ve�|already|present|pridan�|queued|Nahran�|Uploaded|in|li�|k�|max|pr�|Drag|Stav|here|Status|kb|mb|Súbor|Duplicate|je'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/sr.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/sr.min.js new file mode 100644 index 0000000000000000000000000000000000000000..e35a3dcf84f47af47b9538b5e51c3344064f4d4a --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/sr.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('1a.19({"m 3":"m 3","3 l h j 9 8 B\'t E.":"3 l h j 9 8 B\'t E.","1c":"","1g":"1f�1e","x":"x","w 1.":"w 1.","M 2 13 e f n Z Y e X 10.":"11 7 u 15 i 12 14 1i g.","1m":"1x 1v","v r y 9 8 D C.":"v r y 9 8 D C.","q":"q","o 5.":"o 5.","g 3":"1t�1l f","1k":"","1j":"","1n 4 1.":"","0 6 1.":"0 6 1.","N/A":"N/A","1o":"","5: F 4 c:":"5: F 4 c:","1q 2":"1p 7","%s 1d 1r 1u e n.":"","0: %s":"0: %s","b":"","1h %d/%d 2":"16 %d/%d 1b","3 p k z %d 4(s) I a T. W 2 V U.":"3 p k z %d 4(s) I a T. W 2 V U.","%d 2 R":"%d 2 R","0: %s, 6: %d, 1s 4 6: %d":"","1y 2 1z.":"1A 7 1w.","J S H G K L.":"J S H G K L.","0 Q 1.":"0 Q 1.","0 c 1.":"0 c 1.","5: 0 P O:":"5: 0 P O:","M 17":"18 7"});',62,99,'File|error|files|Upload|file|Error|size|fajlove|or|wrong|||extension||the|upload|Start|might||be|accepts|URL|Stop|queue|HTTP|element|Status|format||||Image|Init|Close|either|only||doesn|supported|not|exist|Invalid|of|out|at|Runtime|available|memory|Add||large|too|count|queued|ran|time|stripped|were|Extra|start|click|and|button|Dodajte|kliknite|to|na|listu|Snimljeno|Files|Dodaj|addI18n|plupload|fajlova|tb|already|ina|Veli�|Size|Uploaded|dugme|kb|mb|ni|Filename|Duplicate|gb|Izaberite|Select|present|max|Po�|in|fajla|ovde|Naziv|Drag|here|Prevucite'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/sv.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/sv.min.js new file mode 100644 index 0000000000000000000000000000000000000000..f3e9caf87db3c6ce6aff13325d123f1eb76801f7 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/sv.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('11.1d({"L 3":"L 3","3 G H Q 6 7 W\'t T.":"3 G H Q 6 7 W\'t T.","16":"","15":"14","m":"m","g 2.":"g 2.","e 1 13 c 17 l 18 12 c u 1b.":"1a�19 r f r 10�n Z 1c 1h� u.","1v":"1s","q p v 6 7 w B.":"q p v 6 7 w B.","o":"o","y 5.":"y 5.","x 3":"x 3","1q":"","1u":"","1t 4 2.":"","0 8 2.":"0 8 2.","N/A":"N/A","1r":"","5: C 4 9:":"5: C 4 9:","1e 1":"1o�1i f","%s 1p 1g 1f c l.":"","0: %s":"0: %s","b":"","h %d/%d 1":"h %d/%d 1","3 j i D %d 4(s) z a S. R 1 U V.":"3 j i D %d 4(s) z a S. R 1 U V.","%d 1 Y":"%d 1 Y","0: %s, 8: %d, 1j 4 8: %d":"","1k 1 1n.":"1m f 1l","K M O J I E.":"K M O J I E.","0 F 2.":"0 F 2.","0 9 2.":"0 9 2.","5: 0 P X:":"5: 0 P X:","e k":"e k"});',62,94,'File|files|error|Upload|file|Error|wrong|or|size|extension|||the||Add|filer|Init|Uploaded|accepts|element|Files|queue|Close||Status|format|Image|till|||start|either|not|Start|HTTP|at||supported|Invalid|only|memory|count|URL|might|available|of|Runtime|Stop|ran||out|too|be|Extra|time|exist|were|stripped|doesn|large|queued|och|k�|plupload|click|to|Storlek|Size|tb|upload|and|gg|L�|button|tryck|addI18n|Select|in|present|p�|lj|max|Drag|hit|Dra|here|V�|already|mb|gb|Filnamn|Duplicate|kb|Filename'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/th_TH.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/th_TH.min.js new file mode 100644 index 0000000000000000000000000000000000000000..59827c38ee01cbdbdd68f771197c190107925733 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/th_TH.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('F.G({"E 7":"0��0��0��0��0��0��0��0��0��0��0��","7 k D B i e C\'t H.":"k 0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0�1��0��0��0��","I":"0��0��0��0��0��0��0��0��","O":"0��0��0��0��","P":"0��0��0��","h 5.":"h 0��0��0��0��0��0��0��0��0��0��0��0��0��0��","g 4 M 9 L f z K 9 Q y.":"0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0�1��0��0��0��0��0��0��0��0��0��","p":"0��0��0��0��0��0��0��0��","o n m i e v x.":"0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0�3��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��","w":"0�3��0��0��0��","l c.":"l 0��0��0��0��0��0��0��0��0��0��0��0��0��0��","r 7":"0��0��0��0��0��0��0��0��0��0��0��0��","q":"0��0��0��0��0��0��0��0��","u":"0��0��0��0��0��0��0��0��","J 6 5.":"0��0��0��0��0��0�1��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��","2 8 5.":"0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��","N/A":"N/A","1d":"0��0��0��0��0��0��0��0��","c: R 6 j:":"0��0��0��0��0��0��0��0��0��0��: 0��0��0��0�3��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��:","18 4":"0��0��0��0��0��0��0��0��0��","%s 1c 1i 1b 9 f.":"%s 0��0��0��0��0��0��0��0��0��0��0��0��0��","2: %s":"0��0��0��0��: %s","b":"0��0��0��0��","1e %d/%d 4":"0��0��0��0��0��0��0��0��0��0��0�� %d/%d 0��0��0��0��","7 1j 1h 1g %d 6(s) 1f a 16. 17 4 W X.":"0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0�� %d 0��0��0��0��(s) 0��0��0��0��0��0��0��0��0��0��0��0��0�1��0��0��0��0�� 0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��","%d 4 V":"%d 0��0��0��0��0��0�1��0��0��0��0��0��0��0��0��0��","2: %s, 8: %d, U 6 8: %d":"0��0��0��0��: %s, 0��0��0��0��: %d, 0��0��0��0��0��0��0��0��0�3��0��0�3��0��: %d","Y 4 Z.":"0��0��0��0��0��0��0��0��0��0��0�1��0��0�1��","14 15 13 12 10 11.":"0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��","2 19 5.":"0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��","2 j 5.":"0��0��0��0�3��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��0��","c: 2 T S:":"0��0��0��0��0��0��0��0��0��0��: 0��0��0��0��0��0��0��0��0��0��0��0��0��0��:","g 1a":"0��0��0��0��0��0��0��0��0��"});',62,82,'�|��|File|��|files|error|file|Upload|size|the|||Error||or|queue|Add|Init|wrong|extension|URL|HTTP|either|format|Image|Filename|mb|Start|||kb|not|Status|supported|button|and||be|doesn|might|Stop|plupload|addI18n|exist|tb|Duplicate|click|upload|to||Size|Close|start|Invalid|large|too|max|queued|were|stripped|Drag|here|available|memory|of|out|Runtime|ran|time|Extra|Select|count|Files|in|already|gb|Uploaded|at|only|accepts|present|element'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/tr.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/tr.min.js new file mode 100644 index 0000000000000000000000000000000000000000..692b9667f4d78ce494c14024f7be045f9f857c4b --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/tr.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('1N.1A({"1E 7":"8�p 1K","7 J 1F 26 i g 12\'t 2a.":"J D h o 13� S.","I":"I","O":"M","1k":"1l","1t 5.":"1a�1o�r� 1�.","j 2 1e e 1d l 1f 1g e 1h 1c.":"f� 1b�a 17 16 x�18 19 1i�1j�n.","1r":"0 1s�","1u 1q 1p i g 1m 1n.":"15 1v� 14�w� h o P.","Q":"L","y c.":"y 1�.","K 7":"8�p x�R","v":"v","u":"u","10 6 5.":"11 3 1�.","4 9 5.":"0 z 1�.","N/A":"-","q":"q","c: Z 6 E:":"H: Y�U 3 B�F�:","T 2":"f� V�","%s W X G e l.":"%s 2s 2c 2b.","4: %s":"0: %s","b":"2d","2e %d/%d 2":"%d/%d 3 C�2f","7 29 24 23 %d 6(s) 25 a 28. 27 2 2g 2h.":"8�2v 2r� 2q� 2t %d 3 2u 2p. 2o 2j 2i�2k 2l.","%d 2 2n":"2m %d 3 22.","4: %s, 9: %d, 21 6 9: %d":"0: %s, 1H: %d, 1I 3 z: %d","1J 2 1D.":"f� 1y 1x�1z�n.","1C 1B 1L 1M 1W 1V.":"1X�w�1Y 20�G 1Z 1U D.","4 1T 5.":"0 1O�m 1�.","4 E 5.":"0 B�F� 1�.","c: 4 1S 1R:":"H: 0 r�1Q 1P�C�k:","j 1G":"0 1w"});',62,156,'Dosya|hatas�|files|dosya|File|error|file|Upload|Y�|size|||Error||the|Dosyalar�|or|ya|wrong|Add||queue|||da|klemeyi|gb|�|||kb|mb|�|ba�|HTTP|boyutu||uzant�|y�|yok|extension|s�|in|Hata|tb|URL|Start|Durum|Boyut||Size|desteklenmiyor|Status|lat|olabilir|Select|ersiz|se�|already|present|Ge�|Invalid|Duplicate|Yinelenen|doesn|hatal�|yanl�|Resim|ve|ekleyin|latma|butonuna|Ba�|kuyru�|button|upload|to|and|click|start|t�|klay�|Close|Kapat|not|supported|lang�|either|format|Filename|ad�|Init|Image|format�|ekle|b�|buraya|rak�|addI18n|ran|Runtime|here|Stop|might|Files|boyut|maksimum|Drag|durdur|out|of|plupload|say�|b�|ok|large|too|count|bellek|memory|available|�|lem|yeterli|i�|max|var|only|accepts|at|be|Extra|time|element|exist|mevcut|zaten|bayt|Uploaded|klendi|were|stripped|i�|dosyalar|leme|konulmaz|Kuyrukta|queued|Ekstra|eder|ayn�|eleman�|kuyrukta|anda|kabul|kleme'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/uk_UA.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/uk_UA.min.js new file mode 100644 index 0000000000000000000000000000000000000000..b90682a7f3b8634306fdeced40b17e86e3c13572 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/uk_UA.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('L.M({"K c":"0�1�0�0�0�0�1�0� 0�0�0�0�0�1�0�0�2�0�1�","c J G H k h I\'t O.":"0�0�1�5�0� 0�0�0�0�0�1�0�0�2�0�1� 0�2�1�0�0�0�0�1�0�0� 0�0�0� 0�4 1�1�0�1�1�.","P":"","U":"0�0�0�0�1�1�","V":"0�0�j�0�1�0�","T 8.":"0�0�0�0�0�3� 1�0�1�1�1�0�0�1�0�0�1�1�1�.","m 6 S f Q l R F f E r.":"0�0�0�0�0�1�4 1�0�0�0�0� 0� 1�5�0�1� 1�0� 0�0�1�0�1�0�1�1�1� 3�0�0�j� \\"0�0�0�0�0�1�0�0�0�1�0� 1�0�0�0�0�\\".","q":"0�0�0�0�0� 1�0�0�0�1�","v o p k h C D.":"0�0�1�0�0�1� 3�1�1�0�0�3� 0�4 0�1�0�0�0�0�1�0�0�0� 0�0�0� 0�4 0�1�0�1�1�0�0�1�1�1�1�1�1�.","B":"0�1�0�1�1�1�","i g.":"0�0�0�0�0�3� i.","x c":"0�0�1�0�1�0� 0�0�0�0�0�1�0�0�2�0�1�","y":"","W":"","X 9 8.":"","7 e 8.":"0�2�1�0�0�0�0�1�0�0�0� 1�0�0�0�1�1� 1�0�0�0�1�.","N/A":"0�/0�","1f":"","g: 1n 9 n:":"0�0�0�0�0�3�: 0� 1�0�0�0�1� 0�2�1�0�0�0�0�1�0�4 1�0�0�1�0�1�2�0�1�:","1h 6":"0�0�5�1�1�1� 1�0�0�0�0�","%s 1g 1d 1i f l.":"","7: %s":"0�0�0�0�: %s","b":"","1m %d/%d 6":"0�0�0�0�0�1�0�0�2�0� %d/%d 1�0�0�0�1�0�","c 1k 1e 1b %d 9(s) 1c a 13. 11 6 10 Y.":"","%d 6 Z":"0� 1�5�0�1� %d 1�0�0�0�(1�0�)","7: %s, e: %d, 14 9 e: %d":"","19 6 16.":"0�5�5�1�0�0�1�1�1� 1�0�0�0�0� 1�1�0�0�.","17 12 18 1a 15 1l.":"0�0�0�0�1�4 1�5�2�0�0�0�1�4 0�5�2�0�1�0�0�0� 0�1�0�1�1� 0�0�1�1�1�0�0�0�1� 0�0�0�\'1�1�1�.","7 1j 8.":"0�0�0�0�0�1�0� 0�0�0�0�1�0� 1�0�0�0�1�0�.","7 n 8.":"0�2�1�0�0�0�0�1�0�4 1�0�0�1�0�1�2�0�1� 1�0�0�0�1�.","g: 7 z w:":"0�0�0�0�0�3�: 0�0�0�0� 0�0�0�0�0�1�0� 0�2�0�3�0�:","m u":"0�0�0�0�1�0� 1�0�0�0�0�"});',62,86,'�|�|е�|к�|е|е�|files|File|error|file|||Upload||size|the|Error|or|HTTP|к�|wrong|queue|Add|extension|format|either|Filename|button|||Files|Image|large|Start|mb|too||Status|not|supported|start|click|might|be|doesn|URL|Stop|plupload|addI18n||exist|tb|upload|and|to|Init|Size|Close|kb|Duplicate|stripped|queued|were|Extra|ran|time|max|available|here|Runtime|out|Drag|of|only|at|present|accepts|gb|already|Select|in|count|element|memory|Uploaded|Invalid'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/zh_CN.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/zh_CN.min.js new file mode 100644 index 0000000000000000000000000000000000000000..ab892e4c09b542b40dd46c9cb583512da00ff2f6 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/zh_CN.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('12.1c({"1q e":"0��1��2��2��","e E z L w n 1f\'t M.":"2��2��6��K��4��1��3��4��6��1��2��0��0��5��","o":"o","J":"0��0��","G":"0��3��","H 9.":"0��0��0��3��4��5��","l 8 I i O r P U i V F.":"0��1��2��1��0��0��2��2��3��0��g��6��0��6��0��k��0��0��2��2��k��1��3��5��","S":"1��2��0��","Q R W w n y x.":"0��6��1��0��3��4��1��4��2��1��1��5��","C":"6��1��","p j.":"p 3��4��5��","D e":"0��0��2��2��","v":"v","u":"u","B c 9.":"3��0��1��2��3��4��5��","7 h 9.":"1��2��0��0��3��4��5��","N/A":"N/A","m":"m","j: T c q:":"3��4��g��1��1��6��1��2��1��0��0��:","1s 8":"3��1��1��2��","%s 1i 1j 1h i r.":"%s 0��6��0��0��0��3��0��3��5��","7: %s":"1��2��: %s","b":"b","1g %d/%d 8":"0��2��2�� %d/%d 2�f��2��","e 1e X 1k %d c(s) 1l a 1r. 1p 8 1o 1m.":"1��1��0�f��0��0��1��2��2�� %d 2�f��2��g��0��2��6��1��2��0��2��4��0��3��5��","%d 8 1n":"%d 2�f��2��0��0��0��3��0��","7: %s, h: %d, 1d c h: %d":"1��2��: %s, 0��0��: %d, 1��0��1��2��0��0��: %d","13 8 11.":"1��1��2��1��0��4��3��5��","10 Y Z 14 15 1a.":"4��4��1��0��1��4��1��1��0��6��0��0��5��","7 1b 9.":"1��2��1��3��3��4��5��","7 q 9.":"1��2��1��0��0��3��4��5��","j: 7 19 18:":"3��4��: 1��2��0�16��:","l 17":"0��0��1��2��"});',62,91,'�|�|�|�|�|�|�|File|files|error|||file||Upload|��|�|size|the|Error|�|Add|gb|or|tb|HTTP|extension|queue|||kb|mb|wrong|supported|not|might||Duplicate|Status|Start|URL|button|Close|Init|to|Size|URL�|be|exist||upload|and|Image|format|Filename|Invalid|click|start|either|accepts|ran|out|Runtime|here|plupload|Drag|of|available|��|Files|large|too|memory|count|addI18n|max|element|doesn|Uploaded|in|already|present|only|at|stripped|queued|were|Extra|Stop|time|Select'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/zh_TW.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/zh_TW.min.js new file mode 100644 index 0000000000000000000000000000000000000000..327a76e7ed24a85786aef6c107e74b2f725232f7 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/zh_TW.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('Q.R({"P h":"0��1��8��0��","h O K L p o M\'t S.":"3�1��T��6��1��7�1��6��8��0��0��5��","m":"m","Z":"0��0��","10":"2��2��","Y e.":"0��0��0��2��7�5��","u c X k U y J V k W 11.":"0��3�1��0��0��8��0��j�0��f��4��0��2��2��r��2��0��8��0��r��1��2��5��","C":"3�1��0��4��","B z I p o H D.":"0��4��1��0��2��7�1��6��8��1��1��5��","G":"4��1��","x l.":"x 2��7�5��","F h":"2��0��8��0��","v":"v","w":"w","E g e.":"2��7�f��3�1��2��6��5��","9 i e.":"2��7�f��3�1��0��0��6��2��2��0��5��","N/A":"N/A","n":"n","l: 1p g q:":"2��7�f��8��1��0��4��3�1��1��0��:","1q c":"2��1��3�1��","%s 12 1n 1k k y.":"%s 0��4��0��0��4��0��4��3�1��j�0��5��","9: %s":"3�1��: %s","b":"b","1l %d/%d c":"0��8��0�� %d/%d 0��1��8��","h 1s 1w 1v %d g(s) 1u a 1t. 1r c 1i 1j.":"1��1��0�18��8��0�� %d 0��3�1��f��6��2��2��0��1��2��4��3�1��0��6��0��4��5��","%d c 17":"%d 0��3�1��0��0��0��j�0��","9: %s, i: %d, 16 g i: %d":"3�1��: %s, 0��0��: %d, 1��0��3�1��0��0��: %d","14 c 1a.":"1��3�1��1��1��0��2��6��5��","1b 1g 1h 1f 1e 1c.":"0��6��1��6��4��1d�1��1��0��4��4��6��1��2��5��","9 1o e.":"3�1��1��2��2��7�5��","9 q e.":"3�1��0��3�0��2��7�5��","l: 9 15 13:":"2��7�: 3�1��0��0��0�19��:","u 1m":"0��0��3�1��"});',62,95,'�|�|�|�|�|�|�|�|�|File|||files||error|�|file|Upload|size|�|the|Error|tb|gb|or|wrong|extension|�|||Add|mb|kb|HTTP|queue|format||Image|Filename|supported|Duplicate|Start|Status|not|either|and|might|be|doesn||URL|Stop|plupload|addI18n|exist|URL�|upload|click|start|to|Init|Size|Close|button|already|large|Drag|too|max|queued|��|��|here|Runtime|memory|�|available|of|ran|out|were|stripped|in|Uploaded|Files|present|count|Invalid|Select|Extra|element|time|at|only|accepts'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/templates/import_media_library.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/templates/import_media_library.php index ac157d51cf445ce28b87a2928ee855e1848f1425..7631fefc7c279b48a8a7dd1a71477950a7c99bfb 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/templates/import_media_library.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/templates/import_media_library.php @@ -13,4 +13,4 @@ <button id='ngg-importML-select-opener' class='button-primary hidden'><?php echo $i18n['select-opener']; ?></button> <button id='ngg-importML-selected-image-import' - class='button-primary hidden'><?php echo $i18n['import_singular']; ?></button> \ No newline at end of file + class='button-primary hidden'></button> \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/templates/upload_images.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/templates/upload_images.php index 039867852f5d6fc2e5b3bd8e8766a58e2b56c130..6cedb5581f918106db1bf47c6688356534b2b5f9 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/templates/upload_images.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_addgallery_page/templates/upload_images.php @@ -72,6 +72,7 @@ var $gallery_name = $('#gallery_name').show(); var $gallery_selection = $('#gallery_selection').detach(); window.uploaded_image_ids = []; + window.uploaded_image_errors = []; plupload.addFileFilter('xss_protection', function(enabled, file, cb){ var retval = true; @@ -164,19 +165,36 @@ // Determine appropriate message to display var upload_count = window.uploaded_image_ids.length; + var errors = window.uploaded_image_errors; var msg = ''; - - <?php $url = admin_url() . 'admin.php?page=nggallery-manage-gallery&mode=edit&gid={gid}'; ?> + var gallery_url = '<?php echo admin_url("/admin.php?page=nggallery-manage-gallery&mode=edit&gid=")?>' + $gallery_id.val(); if (upload_count == 0) { - msg = "<?php _e('0 images were uploaded', 'nggallery'); ?>"; - } else { - msg = '<?php printf(__('{count} images were uploaded successfully. <a href="%s" target="_blank">Manage gallery</a>', 'nggallery'), $url); ?>'; - if (upload_count == 1) { - msg = '<?php printf(__('1 image was uploaded successfully. <a href="%s" target="_blank">Manage gallery</a>', 'nggallery'), $url); ?>'; - } - msg = msg.replace('{gid}', $gallery_id.val()); + msg = NggUploadImages_i18n.no_images_uploaded; + } + else { + msg = upload_count == 1 ? NggUploadImages_i18n.one_image_uploaded : NggUploadImages_i18n.x_images_uploaded; msg = msg.replace('{count}', upload_count); + + if (errors.length > 0) { + msg = msg + '<br/>' + NggUploadImages_i18n.image_errors; + + for (var i = 0; i < errors.length; i++) { + msg = msg + '<br/>' + errors[i]; + } + + msg = msg + '<br/>'; + } + + // If we're outside of the IGW, we will then display a link to manage the gallery + if ($('#iframely').length == 0) { + var $link = $('<a/>').attr({ + href: gallery_url, + target: '_blank' + }); + $link.text(NggUploadImages_i18n.manage_gallery); + msg = msg + ' ' + $link[0].outerHTML; + } } // Display message/notification @@ -230,7 +248,15 @@ else { window.uploaded_image_ids = window.uploaded_image_ids.concat(response.image_ids); up.settings.url = window.set_plupload_url(response.gallery_id, $gallery_name.val()); - + + if (response.image_errors) { + for (var i = 0; i < response.image_errors.length; i++) { + var errMsg = response.image_errors[i].error; + if (window.uploaded_image_errors.indexOf(errMsg) == -1) + window.uploaded_image_errors.push(errMsg); + } + } + // If we created a new gallery, ensure it's now in the drop-down list, and select it if ($gallery_id.find('option[value="'+response.gallery_id+'"]').length == 0) { var option = $('<option/>').attr('value', response.gallery_id).html(response.gallery_name); diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_admin/module.nextgen_admin.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_admin/module.nextgen_admin.php index 265ee4ae656a39fdab3a32e122eab43ac39576f5..85d6bed829fa095951ca11baf70ff582b6e440c1 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_admin/module.nextgen_admin.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_admin/module.nextgen_admin.php @@ -19,7 +19,7 @@ class M_NextGen_Admin extends C_Base_Module 'photocrati-nextgen_admin', 'NextGEN Administration', 'Provides a framework for adding Administration pages', - '0.9', + '0.10', 'https://www.imagely.com/wordpress-gallery-plugin/nextgen-gallery/', 'Photocrati Media', 'https://www.imagely.com' @@ -93,19 +93,34 @@ class M_NextGen_Admin extends C_Base_Module function _register_hooks() { // Register scripts - add_action('init', array(&$this, 'register_scripts'), 9); + add_action('init', array($this, 'register_scripts'), 9); // Provides menu options for managing NextGEN Settings - add_action('admin_menu', array(&$this, 'add_menu_pages'), 999); + add_action('admin_menu', array($this, 'add_menu_pages'), 999); // Define routes - add_action('ngg_routes', array(&$this, 'define_routes')); + add_action('ngg_routes', array($this, 'define_routes')); // Provides admin notices $notices = C_Admin_Notification_Manager::get_instance(); add_action('init', array($notices, 'serve_ajax_request')); add_action('admin_footer', array($notices, 'enqueue_scripts')); add_action('all_admin_notices', array($notices, 'render')); + + $php_id = 0; + + if (defined('PHP_VERSION_ID')) { + $php_id = PHP_VERSION_ID; + } + else { + $version = explode('.', PHP_VERSION); + + $php_id = ($version[0] * 10000 + $version[1] * 100 + $version[2]); + } + + if ($php_id < 50300) { + $notices->add("ngg_php52_deprecation", array("message" => __('PHP 5.2 will be deprecated in a future version of NextGEN. Please upgrade your PHP installation to 5.3 or above.', 'nggallery'))); + } } function define_routes($router) @@ -219,7 +234,10 @@ class C_NextGen_Admin_Installer $cleanup = FALSE; foreach ($modules as $module) { if (strpos($module, $module_name) !== FALSE) { - if (version_compare(array_pop(explode('|', $module)), '0.3') == -1) { + // Leave $module as-is: inside version_compare() will warn about passing items by reference + $module = explode('|', $module); + $val = array_pop($module); + if (version_compare($val, '0.3') == -1) { $cleanup = TRUE; } break; diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_admin/package.module.nextgen_admin.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_admin/package.module.nextgen_admin.php index 50096bf8e3072e96aa39ee08a1407d13f6080edb..0af57519be95ac29784099a84c521c2427fd085e 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_admin/package.module.nextgen_admin.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_admin/package.module.nextgen_admin.php @@ -62,6 +62,28 @@ class A_NextGen_Admin_Default_Pages extends Mixin return $this->call_parent('setup'); } } +class C_Admin_Notification_Wrapper +{ + public $_name; + public $_data; + public function __construct($name, $data) + { + $this->_name = $name; + $this->_data = $data; + } + public function is_renderable() + { + return true; + } + public function is_dismissable() + { + return true; + } + public function render() + { + return $this->_data['message']; + } +} class C_Admin_Notification_Manager { public $_notifications = array(); @@ -144,8 +166,13 @@ class C_Admin_Notification_Manager public function get_handler_instance($name) { $retval = NULL; - if (isset($this->_notifications[$name]) && ($handler = $this->_notifications[$name])) { - if (class_exists($handler)) { + if (isset($this->_notifications[$name])) { + $handler = $this->_notifications[$name]; + if (is_object($handler)) { + $retval = $handler; + } elseif (is_array($handler)) { + $retval = new C_Admin_Notification_Wrapper($name, $handler); + } elseif (class_exists($handler)) { $retval = call_user_func(array($handler, 'get_instance'), $name); } } @@ -211,7 +238,7 @@ class C_Form extends C_MVC_Controller * Defines the form * @param string $context */ - public function define($context) + public function define($context = FALSE) { parent::define($context); $this->add_mixin('Mixin_Form_Instance_Methods'); diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_admin/static/select2/select2.modded.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_admin/static/select2/select2.modded.min.js index c1e98f9d79808262c9186d3262fd100fe52e087f..3e5adad15feaea34b4fcbc6a66af6defb4d60261 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_admin/static/select2/select2.modded.min.js +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_admin/static/select2/select2.modded.min.js @@ -1 +1 @@ -eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('(5($){if(3m $.fn.2E=="1h"){$.2Z($.fn,{2E:5(c){14 j=$([0]),i=-1,l=3.1d;6H(++i<l&&(j.24=j[0]=3[i])&&c.20(j[0],i,j)!==1e);11 3}})}})(8y);(5($,1h){"aA jn";if(1I.49!==1h){11}14 5e,7Q,7P,4J,3W,6s={x:0,y:0},$1W,67,1m={5x:9,3z:13,5l:27,jj:32,5q:37,4f:38,5M:39,5t:40,at:16,ak:17,al:18,8h:33,84:34,ix:36,iI:35,4L:8,6d:46,iT:5(k){k=k.1v?k.1v:k;6c(k){2d 1m.5q:2d 1m.5M:2d 1m.4f:2d 1m.5t:11 1l}11 1e},8m:5(e){14 k=e.1v;6c(k){2d 1m.at:2d 1m.ak:2d 1m.al:11 1l}if(e.85)11 1l;11 1e},8g:5(k){k=k.1v?k.1v:k;11 k>=iX&&k<=iW}},8J="<1X 1s=\'6-iR-iQ\'></1X>",8E={"\\iM":"A","\\iP":"A","\\hj":"A","\\fT":"A","\\fU":"A","\\fW":"A","\\fV":"A","\\fQ":"A","\\fJ":"A","\\fL":"A","\\fM":"A","\\fO":"A","\\fN":"A","\\fX":"A","\\g6":"A","\\g0":"A","\\fZ":"A","\\g1":"A","\\g2":"A","\\g3":"A","\\fI":"A","\\fH":"A","\\fk":"A","\\fo":"A","\\fj":"A","\\fe":"A","\\fC":"A","\\fB":"A","\\fG":"A","\\fA":"A","\\fy":"A","\\fx":"A","\\gd":"A","\\ge":"gW","\\gU":"8j","\\gT":"8j","\\gO":"8j","\\gN":"gP","\\gQ":"h1","\\hd":"9G","\\hc":"9G","\\he":"ha","\\h9":"B","\\h6":"B","\\h8":"B","\\h7":"B","\\gL":"B","\\go":"B","\\gr":"B","\\gu":"B","\\gs":"C","\\gn":"C","\\gm":"C","\\gh":"C","\\gg":"C","\\gf":"C","\\gi":"C","\\gj":"C","\\gl":"C","\\gk":"C","\\gv":"C","\\gw":"D","\\gG":"D","\\gF":"D","\\gH":"D","\\gI":"D","\\gK":"D","\\gJ":"D","\\gE":"D","\\gD":"D","\\gy":"D","\\gx":"D","\\gA":"D","\\gB":"D","\\gC":"9u","\\gz":"9u","\\gp":"9s","\\gM":"9s","\\h5":"E","\\h3":"E","\\h4":"E","\\hg":"E","\\hh":"E","\\hf":"E","\\h2":"E","\\gR":"E","\\gS":"E","\\gZ":"E","\\h0":"E","\\gY":"E","\\gX":"E","\\gV":"E","\\fw":"E","\\fv":"E","\\ft":"E","\\fu":"E","\\fz":"E","\\fF":"E","\\fE":"E","\\fD":"E","\\fs":"E","\\fr":"E","\\fg":"E","\\fh":"E","\\ff":"E","\\fb":"E","\\fc":"E","\\fd":"F","\\fi":"F","\\fp":"F","\\fq":"F","\\fm":"F","\\fl":"G","\\g4":"G","\\g5":"G","\\gb":"G","\\gc":"G","\\ga":"G","\\g9":"G","\\g7":"G","\\g8":"G","\\fY":"G","\\fK":"G","\\fP":"G","\\fR":"G","\\fS":"G","\\hi":"H","\\iO":"H","\\iN":"H","\\iK":"H","\\iL":"H","\\iV":"H","\\iU":"H","\\iS":"H","\\iJ":"H","\\iy":"H","\\iz":"H","\\iw":"H","\\ir":"H","\\iu":"I","\\iv":"I","\\iA":"I","\\iB":"I","\\iG":"I","\\iH":"I","\\iF":"I","\\iE":"I","\\iC":"I","\\iD":"I","\\iY":"I","\\iZ":"I","\\jk":"I","\\jl":"I","\\ji":"I","\\jg":"I","\\jh":"I","\\jm":"I","\\js":"I","\\jt":"J","\\jr":"J","\\jq":"J","\\jo":"J","\\jp":"K","\\jf":"K","\\je":"K","\\j4":"K","\\j5":"K","\\j3":"K","\\j2":"K","\\j0":"K","\\j1":"K","\\j6":"K","\\j7":"K","\\jc":"K","\\jd":"K","\\jb":"L","\\ja":"L","\\j8":"L","\\j9":"L","\\iq":"L","\\ip":"L","\\hG":"L","\\hH":"L","\\hF":"L","\\hE":"L","\\hC":"L","\\hD":"L","\\hI":"L","\\hJ":"L","\\hO":"L","\\hP":"L","\\hN":"L","\\hM":"hK","\\hL":"hB","\\hA":"M","\\hp":"M","\\hq":"M","\\ho":"M","\\hn":"M","\\hk":"M","\\hl":"M","\\hm":"N","\\hr":"N","\\hs":"N","\\hy":"N","\\hz":"N","\\fa":"N","\\hx":"N","\\hw":"N","\\ht":"N","\\hu":"N","\\hQ":"N","\\hR":"N","\\ic":"N","\\ie":"N","\\ib":"N","\\ia":"i8","\\i9":"ig","\\ih":"O","\\im":"O","\\io":"O","\\il":"O","\\ik":"O","\\ii":"O","\\ij":"O","\\i7":"O","\\i6":"O","\\hW":"O","\\hX":"O","\\hV":"O","\\hU":"O","\\hS":"O","\\hT":"O","\\hY":"O","\\hZ":"O","\\i4":"O","\\i5":"O","\\i3":"O","\\i2":"O","\\i0":"O","\\i1":"O","\\ju":"O","\\ef":"O","\\c1":"O","\\c2":"O","\\c3":"O","\\c0":"O","\\bZ":"O","\\bW":"O","\\bX":"O","\\bY":"O","\\c4":"O","\\c5":"O","\\cb":"O","\\cc":"O","\\cd":"O","\\ca":"O","\\c9":"O","\\c6":"O","\\c7":"O","\\c8":"bV","\\bU":"bH","\\bI":"bJ","\\bG":"P","\\bF":"P","\\bC":"P","\\bD":"P","\\bE":"P","\\bK":"P","\\bL":"P","\\bR":"P","\\bS":"P","\\bT":"Q","\\bQ":"Q","\\bP":"Q","\\bM":"Q","\\bN":"Q","\\bO":"R","\\ce":"R","\\cf":"R","\\cG":"R","\\cH":"R","\\cI":"R","\\cF":"R","\\cE":"R","\\cB":"R","\\cC":"R","\\cD":"R","\\cJ":"R","\\cK":"R","\\cQ":"R","\\cR":"R","\\cS":"R","\\cP":"S","\\cO":"S","\\cL":"S","\\cM":"S","\\cN":"S","\\cA":"S","\\cz":"S","\\cl":"S","\\cn":"S","\\co":"S","\\ck":"S","\\bB":"S","\\cg":"S","\\ch":"S","\\ci":"S","\\cp":"S","\\cq":"T","\\cw":"T","\\cx":"T","\\cy":"T","\\cv":"T","\\cu":"T","\\cr":"T","\\cs":"T","\\ct":"T","\\cT":"T","\\aZ":"T","\\aY":"T","\\aX":"T","\\aW":"T","\\b1":"b2","\\b5":"U","\\b4":"U","\\aV":"U","\\bA":"U","\\bs":"U","\\br":"U","\\bq":"U","\\b7":"U","\\bu":"U","\\bz":"U","\\by":"U","\\bx":"U","\\bv":"U","\\bw":"U","\\bn":"U","\\bm":"U","\\bc":"U","\\b8":"U","\\bh":"U","\\bi":"U","\\bo":"U","\\bj":"U","\\bk":"U","\\bl":"U","\\bg":"U","\\bf":"U","\\b9":"U","\\ba":"U","\\bb":"U","\\bd":"U","\\bt":"U","\\bp":"U","\\aS":"U","\\aU":"V","\\aT":"V","\\b6":"V","\\b3":"V","\\b0":"V","\\cj":"V","\\f9":"V","\\er":"es","\\eq":"W","\\ep":"W","\\ej":"W","\\ek":"W","\\eo":"W","\\et":"W","\\eu":"W","\\eA":"W","\\eB":"W","\\ez":"X","\\ey":"X","\\ev":"X","\\ew":"X","\\ei":"Y","\\eh":"Y","\\e7":"Y","\\e8":"Y","\\e6":"Y","\\e5":"Y","\\e2":"Y","\\e3":"Y","\\e4":"Y","\\e9":"Y","\\ea":"Y","\\cU":"Y","\\eg":"Y","\\ee":"Y","\\ed":"Z","\\eb":"Z","\\ec":"Z","\\eC":"Z","\\eD":"Z","\\eZ":"Z","\\f0":"Z","\\eY":"Z","\\eX":"Z","\\eV":"Z","\\eW":"Z","\\f1":"Z","\\f2":"Z","\\f7":"a","\\f8":"a","\\f6":"a","\\f5":"a","\\f3":"a","\\f4":"a","\\eU":"a","\\eT":"a","\\eJ":"a","\\eK":"a","\\eI":"a","\\eH":"a","\\eE":"a","\\eF":"a","\\eG":"a","\\eL":"a","\\eM":"a","\\eR":"a","\\eS":"a","\\eQ":"a","\\eP":"a","\\eN":"a","\\eO":"a","\\e1":"a","\\e0":"a","\\dh":"a","\\di":"a","\\dg":"a","\\df":"a","\\dc":"a","\\dd":"a","\\de":"a","\\dj":"a","\\dk":"a","\\dp":"aa","\\dq":"ae","\\do":"ae","\\dn":"ae","\\dl":"ao","\\dm":"au","\\db":"av","\\da":"av","\\d0":"ay","\\d1":"b","\\cZ":"b","\\cY":"b","\\cV":"b","\\cW":"b","\\cX":"b","\\d2":"b","\\d3":"b","\\d8":"c","\\d9":"c","\\d7":"c","\\d6":"c","\\d4":"c","\\d5":"c","\\dr":"c","\\ds":"c","\\dQ":"c","\\dR":"c","\\dP":"c","\\dO":"c","\\dL":"d","\\dM":"d","\\dN":"d","\\dS":"d","\\dT":"d","\\dY":"d","\\dZ":"d","\\dX":"d","\\dW":"d","\\dU":"d","\\dV":"d","\\dK":"d","\\dJ":"d","\\dy":"dz","\\dA":"dz","\\dx":"e","\\dw":"e","\\dt":"e","\\du":"e","\\dv":"e","\\dB":"e","\\dC":"e","\\dH":"e","\\dI":"e","\\dG":"e","\\dF":"e","\\dD":"e","\\dE":"e","\\gq":"e","\\lp":"e","\\oX":"e","\\oY":"e","\\oW":"e","\\oV":"e","\\oT":"e","\\oU":"e","\\oZ":"e","\\p0":"e","\\p5":"e","\\p4":"e","\\p3":"e","\\p1":"e","\\p2":"e","\\oS":"e","\\oR":"e","\\oI":"f","\\oJ":"f","\\oH":"f","\\oG":"f","\\oE":"f","\\oF":"g","\\oK":"g","\\oL":"g","\\oQ":"g","\\oP":"g","\\oO":"g","\\oM":"g","\\oN":"g","\\p6":"g","\\p7":"g","\\ps":"g","\\pr":"g","\\pq":"g","\\po":"g","\\pp":"h","\\pu":"h","\\pv":"h","\\pB":"h","\\pA":"h","\\pz":"h","\\pw":"h","\\py":"h","\\pn":"h","\\pm":"h","\\pd":"h","\\pe":"h","\\pb":"h","\\pa":"h","\\p8":"hv","\\p9":"i","\\pf":"i","\\pg":"i","\\pl":"i","\\pk":"i","\\pj":"i","\\ph":"i","\\pi":"i","\\oD":"i","\\oC":"i","\\nT":"i","\\nU":"i","\\nS":"i","\\nR":"i","\\nP":"i","\\nQ":"i","\\nV":"i","\\nW":"i","\\o1":"i","\\o0":"j","\\nZ":"j","\\nX":"j","\\nY":"j","\\nO":"j","\\nN":"k","\\nE":"k","\\nF":"k","\\nD":"k","\\nC":"k","\\nA":"k","\\nB":"k","\\nG":"k","\\nH":"k","\\nM":"k","\\pD":"k","\\nK":"k","\\nI":"k","\\nJ":"l","\\o2":"l","\\o3":"l","\\os":"l","\\ot":"l","\\oq":"l","\\op":"l","\\ol":"l","\\om":"l","\\ov":"l","\\ow":"l","\\oB":"l","\\oA":"l","\\oz":"l","\\ox":"l","\\oy":"l","\\ok":"l","\\oj":"l","\\o8":"lj","\\o9":"m","\\o7":"m","\\o6":"m","\\o4":"m","\\o5":"m","\\oa":"m","\\ob":"m","\\oh":"n","\\og":"n","\\oe":"n","\\oc":"n","\\od":"n","\\pC":"n","\\r5":"n","\\r0":"n","\\qX":"n","\\r4":"n","\\qG":"n","\\qB":"n","\\qC":"n","\\qJ":"n","\\qO":"n","\\qL":"n","\\qH":"nj","\\qN":"o","\\qM":"o","\\qK":"o","\\qP":"o","\\qR":"o","\\qQ":"o","\\qI":"o","\\qA":"o","\\qz":"o","\\qD":"o","\\qE":"o","\\qU":"o","\\qF":"o","\\qT":"o","\\r7":"o","\\r6":"o","\\r8":"o","\\r2":"o","\\qZ":"o","\\r1":"o","\\r3":"o","\\qS":"o","\\pW":"o","\\pV":"o","\\pT":"o","\\pU":"o","\\pY":"o","\\pZ":"o","\\q4":"o","\\qy":"o","\\q0":"o","\\q1":"o","\\pS":"o","\\pR":"o","\\pI":"o","\\pJ":"o","\\pH":"o","\\pF":"o","\\pL":"o","\\pQ":"o","\\pP":"o","\\pO":"o","\\pM":"oi","\\qp":"ou","\\qs":"oo","\\qt":"p","\\qk":"p","\\qj":"p","\\qb":"p","\\q9":"p","\\q7":"p","\\q8":"p","\\qc":"p","\\qd":"p","\\qi":"q","\\qh":"q","\\qg":"q","\\qe":"q","\\qf":"q","\\qa":"r","\\qu":"r","\\qv":"r","\\qw":"r","\\qr":"r","\\qq":"r","\\qm":"r","\\ql":"r","\\qn":"r","\\qo":"r","\\q6":"r","\\q5":"r","\\pN":"r","\\pK":"r","\\pE":"r","\\pG":"r","\\q2":"s","\\q3":"s","\\pX":"s","\\qx":"s","\\qV":"s","\\qW":"s","\\qY":"s","\\nL":"s","\\ny":"s","\\kQ":"s","\\kR":"s","\\kP":"s","\\kO":"s","\\kM":"s","\\kN":"s","\\kS":"s","\\kT":"s","\\kY":"t","\\kX":"t","\\kW":"t","\\kU":"t","\\kV":"t","\\kL":"t","\\kK":"t","\\kA":"t","\\kB":"t","\\kz":"t","\\ky":"t","\\kw":"t","\\kx":"t","\\kC":"t","\\kD":"t","\\kI":"kJ","\\kH":"u","\\kG":"u","\\kE":"u","\\kF":"u","\\kZ":"u","\\l0":"u","\\lm":"u","\\ln":"u","\\ll":"u","\\lk":"u","\\lg":"u","\\lh":"u","\\lo":"u","\\nz":"u","\\jv":"u","\\lv":"u","\\lu":"u","\\ls":"u","\\lq":"u","\\lr":"u","\\lf":"u","\\le":"u","\\l5":"u","\\l6":"u","\\l4":"u","\\l3":"u","\\l1":"u","\\l2":"u","\\l7":"u","\\l8":"u","\\ld":"u","\\lc":"u","\\lb":"u","\\l9":"v","\\la":"v","\\kv":"v","\\ku":"v","\\jQ":"v","\\jR":"v","\\jP":"v","\\jO":"jM","\\jN":"w","\\jS":"w","\\jT":"w","\\jY":"w","\\jX":"w","\\jW":"w","\\jU":"w","\\jV":"w","\\jL":"w","\\jK":"w","\\jA":"x","\\jB":"x","\\jz":"x","\\jy":"x","\\jw":"y","\\jx":"y","\\jC":"y","\\jD":"y","\\jI":"y","\\jJ":"y","\\jH":"y","\\jG":"y","\\jE":"y","\\jF":"y","\\jZ":"y","\\k0":"y","\\kl":"y","\\km":"y","\\kk":"y","\\kj":"z","\\kh":"z","\\ki":"z","\\kn":"z","\\ko":"z","\\kt":"z","\\ks":"z","\\kr":"z","\\kp":"z","\\kq":"z","\\kg":"z","\\kf":"z","\\k5":"z","\\k6":"\\k4","\\k3":"\\k1","\\k2":"\\k7","\\k8":"\\8r","\\kd":"\\8r","\\ke":"\\kc","\\kb":"\\8N","\\k9":"\\8N","\\ka":"\\lw","\\lx":"\\mT","\\mU":"\\mS","\\mR":"\\mP","\\mQ":"\\7N","\\mV":"\\7N","\\mW":"\\7N","\\n1":"\\n0","\\mZ":"\\7L","\\mX":"\\7L","\\mY":"\\7L","\\8G":"\\8G","\\mO":"\\mN"};$1W=$(1W);4J=(5(){14 8H=1;11 5(){11 8H++}}());5 72(12){14 2m=$(1W.mD(\'\'));12.6i(2m);2m.6i(12);2m.3p()}5 4k(8D){5 29(a){11 8E[a]||a}11 8D.5f(/[^\\mE-\\mC]/g,29)}5 2k(25,7Z){14 i=0,l=7Z.1d;1N(;i<l;i=i+1){if(2x(25,7Z[i]))11 i}11-1}5 94(){14 $4n=$(8J);$4n.51(1W.2V);14 8O={1r:$4n.1r()-$4n[0].mB,3l:$4n.3l()-$4n[0].9i};$4n.3p();11 8O}5 2x(a,b){if(a===b)11 1l;if(a===1h||b===1h)11 1e;if(a===1o||b===1o)11 1e;if(a.2W===7J)11 a+\'\'===b+\'\';if(b.2W===7J)11 b+\'\'===a+\'\';11 1e}5 6g(4t,3e,8P){14 19,i,l;if(4t===1o||4t.1d<1)11[];19=4t.6t(3e);1N(i=0,l=19.1d;i<l;i=i+1)19[i]=8P(19[i]);11 19}5 87(12){11 12.2S(1e)-12.1r()}5 77(12){14 5i="4R-2Y-25";12.on("5T",5(){if($.7(12,5i)===1h){$.7(12,5i,12.19())}});12.on("4R",5(){14 19=$.7(12,5i);if(19!==1h&&12.19()!==19){$.7m(12,5i);12.1L("4R-2Y")}})}5 8U(12){12.on("5G",5(e){14 6O=6s;if(6O===1h||6O.x!==e.9m||6O.y!==e.9l){$(e.4P).1L("5G-31",e)}})}5 6E(54,fn,6e){6e=6e||1h;14 4V;11 5(){14 26=1H;1I.9g(4V);4V=1I.4W(5(){fn.2g(6e,26)},54)}}5 98(8M,12){14 8K=6E(8M,5(e){12.1L("3r-99",e)});12.on("3r",5(e){if(2k(e.4P,12.2w())>=0)8K(e)})}5 1t($el){if($el[0]===1W.6A)11;1I.4W(5(){14 el=$el[0],52=$el.19().1d,41;$el.1t();14 8B=(el.mz>0||el.mA>0);if(8B&&el===1W.6A){if(el.5S){el.5S(52,52)}1k if(el.5U){41=el.5U();41.am(1e);41.1A()}}},0)}5 9O(el){el=$(el)[0];14 1K=0;14 1d=0;if(\'8L\'in el){1K=el.8L;1d=el.mF-1K}1k if(\'1q\'in 1W){el.1t();14 7W=1W.1q.8Q();1d=1W.1q.8Q().1j.1d;7W.mG(\'7X\',-el.25.1d);1K=7W.1j.1d-1d}11{1K:1K,1d:1d}}5 1P(2o){2o.5W();2o.4G()}5 aQ(2o){2o.5W();2o.aj()}5 9U(e){if(!3W){14 2c=e[0].mL||1I.mM(e[0],1o);3W=$(1W.5k("1X")).1Y({8Y:"mK",2O:"-8t",23:"-8t",5Z:"61",8p:2c.8p,8q:2c.8q,8z:2c.8z,8u:2c.8u,8x:2c.8x,8w:2c.8w,mJ:"mH"});3W.1f("1s","6-3W");$(1W.2V).4g(3W)}3W.1j(e.19());11 3W.1r()}5 57(7T,8I,9v){14 3c,6V=[],6Q;3c=$.4N(7T.1f("1s"));if(3c){3c=\'\'+3c;$(3c.6t(/\\s+/)).2E(5(){if(3.2k("6-")===0){6V.1O(3)}})}3c=$.4N(8I.1f("1s"));if(3c){3c=\'\'+3c;$(3c.6t(/\\s+/)).2E(5(){if(3.2k("6-")!==0){6Q=9v(3);if(6Q){6V.1O(6Q)}}})}7T.1f("1s",6V.5g(" "))}5 6D(1j,1C,2Q,2e){14 29=4k(1j.6j()).2k(4k(1C.6j())),7U=1C.1d;if(29<0){2Q.1O(2e(1j));11}2Q.1O(2e(1j.5F(0,29)));2Q.1O("<4x 1s=\'6-29\'>");2Q.1O(2e(1j.5F(29,29+7U)));2Q.1O("</4x>");2Q.1O(2e(1j.5F(29+7U,1j.1d)))}5 7O(2Q){14 9k={\'\\\\\':\'\\',\'&\':\'&mI;\',\'<\':\'<\',\'>\':\'>\',\'"\':\'&n2;\',"\'":\''\',"/":\'/\'};11 7J(2Q).5f(/[&<>"\'\\/\\\\]/g,5(29){11 9k[29]})}5 2U(1J){14 4V,5C=1o,54=1J.54||n3,4i=1J.3k,1c=3;11 5(1p){1I.9g(4V);4V=1I.4W(5(){14 7=1J.7,3k=4i,5r=1J.5r||$.fn.6.7M.5r,9e={2q:1J.2q||\'aP\',7K:1J.7K||1e,9d:1J.9d||1h,5y:1J.5y||"9M"},3f=$.2Z({},$.fn.6.7M.3f,9e);7=7?7.20(1c,1p.1C,1p.2J,1p.24):1o;3k=(3m 3k===\'5\')?3k.20(1c,1p.1C,1p.2J,1p.24):3k;if(5C&&3m 5C.9f==="5"){5C.9f()}if(1J.3f){if($.2G(1J.3f)){$.2Z(3f,1J.3f.20(1c))}1k{$.2Z(3f,1J.3f)}}$.2Z(3f,{3k:3k,5y:1J.5y,7:7,np:5(7){14 1b=1J.1b(7,1p.2J,1p);1p.1V(1b)},aR:5(5I,5B,5E){14 1b={aG:1l,5I:5I,5B:5B,5E:5E};1p.1V(1b)}});5C=5r.20(1c,3f)},54)}}5 6w(1J){14 7=1J,7w,53,1j=5(2K){11""+2K.1j};if($.6z(7)){53=7;7={1b:53}}if($.2G(7)===1e){53=7;7=5(){11 53}}14 6o=7();if(6o.1j){1j=6o.1j;if(!$.2G(1j)){7w=6o.1j;1j=5(2K){11 2K[7w]}}}11 5(1p){14 t=1p.1C,31={1b:[]},3S;if(t===""){1p.1V(7());11}3S=5(2A,4Q){14 2F,1f;2A=2A[0];if(2A.1F){2F={};1N(1f in 2A){if(2A.nq(1f))2F[1f]=2A[1f]}2F.1F=[];$(2A.1F).2E(5(i,9r){3S(9r,2F.1F)});if(2F.1F.1d||1p.3g(t,1j(2F),2A)){4Q.1O(2F)}}1k{if(1p.3g(t,1j(2A),2A)){4Q.1O(2A)}}};$(7().1b).2E(5(i,2A){3S(2A,31.1b)});1p.1V(31)}}5 28(7){14 9n=$.2G(7);11 5(1p){14 t=1p.1C,31={1b:[]};14 1z=9n?7(1p):7;if($.6z(1z)){$(1z).2i(5(){14 7v=3.1j!==1h,1j=7v?3.1j:3;if(t===""||1p.3g(t,1j)){31.1b.1O(7v?3:{id:3,1j:3})}});1p.1V(31)}}}5 3N(5K,9c){if($.2G(5K))11 1l;if(!5K)11 1e;if(3m(5K)===\'4t\')11 1l;2X 3u 5s(9c+" 8X be a 4t, 5, or nn 25")}5 2b(19,24){if($.2G(19)){14 26=a0.3F.5u.20(1H,2);11 19.2g(24,26)}11 19}5 7j(1b){14 68=0;$.2i(1b,5(i,2K){if(2K.1F){68+=7j(2K.1F)}1k{68++}});11 68}5 9E(1y,1q,8Z,4){14 8W=1y,6K=1e,3b,1D,i,l,3e;if(!4.3P||!4.58||4.58.1d<1)11 1h;6H(1l){1D=-1;1N(i=0,l=4.58.1d;i<l;i++){3e=4.58[i];1D=1y.2k(3e);if(1D>=0)5z}if(1D<0)5z;3b=1y.5F(0,1D);1y=1y.5F(1D+3e.1d);if(3b.1d>0){3b=4.3P.20(3,3b,1q);if(3b!==1h&&3b!==1o&&4.id(3b)!==1h&&4.id(3b)!==1o){6K=1e;1N(i=0,l=1q.1d;i<l;i++){if(2x(4.id(3b),4.id(1q[i]))){6K=1l;5z}}if(!6K)8Z(3b)}}}if(8W!==1y)11 1y}5 5P(){14 1c=3;$.2i(1H,5(i,12){1c[12].3p();1c[12]=1o})}5 6M(7G,8V){14 2W=5(){};2W.3F=3u 7G;2W.3F.2W=2W;2W.3F.2r=7G.3F;2W.3F=$.2Z(2W.3F,8V);11 2W}5e=6M(nm,{1x:5(8S){14 1c=3;11 5(){8S.2g(1c,1H)}},9Z:5(4){14 1b,15,3E=".6-1b";3.4=4=3.4O(4);3.id=4.id;if(4.12.7("6")!==1h&&4.12.7("6")!==1o){4.12.7("6").4u()}3.1a=3.75();3.3a=$(\'.6-6B-8T\');if(3.3a.1d==0){3.3a=$("<4x>",{3X:"nk","42-nl":"nr"}).1w("6-6B-8T").51(1W.2V)}3.7F="ns"+(4.12.1f("id")||"nx"+4J());3.7l=3.7F.5f(/([.])/g,\'nw\').5f(/([;&,\\-\\.\\+\\*\\~\':"\\!\\^#$%@\\[\\]\\(\\)=>\\|])/g,\'\\\\$1\');3.1a.1f("id",3.7F);3.1a.1f("6Z",4.12.1f("6Z"));3.2V=$(1W.2V);57(3.1a,3.4.12,3.4.7x);3.1a.1f("2c",4.12.1f("2c"));3.1a.1Y(2b(4.ad,3.4.12));3.1a.1w(2b(4.7A,3.4.12));3.5J=3.4.12.1f("3Q");3.4.12.7("6",3).1f("3Q","-1").6i(3.1a).on("3h.6",1P);3.1a.7("6",3);3.1i=3.1a.1u(".6-1S");57(3.1i,3.4.12,3.4.7I);3.1i.1w(2b(4.7z,3.4.12));3.1i.7("6",3);3.1i.on("3h",1P);3.1b=1b=3.1a.1u(3E);3.15=15=3.1a.1u("1y.6-1y");3.7b=0;3.4v=0;3.24=1o;3.8o();3.1a.on("3h",1P);8U(3.1b);3.1i.on("5G-31",3E,3.1x(3.6p));3.1i.on("4c 90 7C",3E,3.1x(5(2o){3.7E=1l;3.6p(2o)}));3.1i.on("90",3E,3.1x(3.8s));3.1i.on("4c 7C",3E,3.1x(3.7g));3.1i.on(\'3h\',3.1x(5(2o){if(3.7E){3.7E=1e;3.3B()}}));98(80,3.1b);3.1i.on("3r-99",3E,3.1x(3.5Q));$(3.1a).on("2Y",".6-1y",5(e){e.4G()});$(3.1i).on("2Y",".6-1y",5(e){e.4G()});if($.fn.9a){1b.9a(5(e,7k,nv,5v){14 23=1b.2T();if(5v>0&&23-5v<=0){1b.2T(0);1P(e)}1k if(5v<0&&1b.2w(0).7i-1b.2T()+5v<=1b.3l()){1b.2T(1b.2w(0).7i-1b.3l());1P(e)}})}77(15);15.on("4R-2Y 1y 9N",3.1x(3.3O));15.on("1t",5(){15.1w("6-5j")});15.on("3y",5(){15.1U("6-5j")});3.1i.on("96",3E,3.1x(5(e){if($(e.4P).59(".6-1z-2M").1d>0){3.6p(e);3.3B(e)}}));3.1i.on("3h 96 4E 4c 7C nt",5(e){e.4G()});3.2v=1h;if($.2G(3.4.1T)){3.1T();3.9b()}if(4.4Y!==1o){3.15.1f("nu",4.4Y)}14 1B=4.12.22("1B");if(1B===1h)1B=1e;3.5p(!1B);14 2p=4.12.22("2p");if(2p===1h)2p=1e;3.2p(2p);67=67||94();3.4B=4.12.22("4B");4.12.22("4B",1e);if(3.4B)3.1t();3.15.1f("2m",4.9C)},4u:5(){14 12=3.4.12,6=12.7("6"),1c=3;3.1E();if(12.1d&&12[0].95&&1c.4s){12.2i(5(){if(1c.4s){3.95("9o",1c.4s)}})}if(3.3R){3.3R.ni();3.3R=1o}3.4s=1o;if(6!==1h){6.1a.3p();6.3a.3p();6.1i.3p();12.50().7m("6").2I(".6").22("4B",3.4B||1e);if(3.5J){12.1f({3Q:3.5J})}1k{12.7e("3Q")}12.50()}5P.20(3,"1a","3a","1i","1b","15")},4F:5(12){if(12.is("3H")){11{id:12.22("25"),1j:12.1j(),12:12.2w(),1Y:12.1f("1s"),1B:12.22("1B"),3j:2x(12.1f("3j"),"3j")||2x(12.7("3j"),1l)}}1k if(12.is("91")){11{1j:12.1f("1Q"),1F:[],12:12.2w(),1Y:12.1f("1s")}}},4O:5(4){14 12,1A,8n,4i,1c=3;12=4.12;if(12.2w(0).6x.6T()==="1A"){3.1A=1A=4.12}if(1A){$.2i(["id","3t","2U","1p","3P","1T","7","28"],5(){if(3 in 4){2X 3u 5s("nh \'"+3+"\' is 2f n8 1N 49 9X 9W 4z a <1A> 12.")}})}4=$.2Z({},{7o:5(1a,1b,1p){14 6r,id=3.4.id,3a=3.3a;6r=5(1b,1a,7D){14 i,l,1z,2M,1B,4y,2D,1Q,5w,2L;1b=4.a8(1b,1a,1p);14 8e=[];1N(i=0,l=1b.1d;i<l;i=i+1){1z=1b[i];1B=(1z.1B===1l);2M=(!1B)&&(id(1z)!==1h);4y=1z.1F&&1z.1F.1d>0;2D=$("<li></li>");2D.1w("6-1b-n9-"+7D);2D.1w("6-1z");2D.1w(2M?"6-1z-2M":"6-1z-n7");if(1B){2D.1w("6-1B")}if(4y){2D.1w("6-1z-88-1F")}2D.1w(1c.4.a9(1z));2D.1f("3X","74");1Q=$(1W.5k("1X"));1Q.1w("6-1z-1Q");1Q.1f("id","6-1z-1Q-"+4J());1Q.1f("3X","3H");2L=4.a7(1z,1Q,1p,1c.4.2e);if(2L!==1h){1Q.3C(2L);2D.4g(1Q)}if(4y){5w=$("<3G></3G>");5w.1w("6-1z-n6");6r(1z.1F,5w,7D+1);2D.4g(5w)}2D.7("6-7",1z);8e.1O(2D[0])}1a.4g(8e);3a.1j(4.7V(1b.1d))};6r(1b,1a,0)}},$.fn.6.7S,4);if(3m(4.id)!=="5"){8n=4.id;4.id=5(e){11 e[8n]}}if($.6z(4.12.7("93"))){if("28"in 4){2X"28 n4 as n5 an na \'7-6-28\' aw in 1J of 49 "+4.12.1f("id")}4.28=4.12.7("93")}if(1A){4.1p=3.1x(5(1p){14 7={1b:[],1Z:1e},1C=1p.1C,1F,2a,3S;3S=5(12,4Q){14 2F;if(12.is("3H")){if(1p.3g(1C,12.1j(),12)){4Q.1O(1c.4F(12))}}1k if(12.is("91")){2F=1c.4F(12);12.1F().2E(5(i,3o){3S(3o,2F.1F)});if(2F.1F.1d>0){4Q.1O(2F)}}};1F=12.1F();if(3.3V()!==1h&&1F.1d>0){2a=3.4d();if(2a){1F=1F.2f(2a)}}1F.2E(5(i,3o){3S(3o,7.1b)});1p.1V(7)});4.id=5(e){11 e.id}}1k{if(!("1p"in 4)){if("2U"in 4){4i=4.12.7("2U-3k");if(4i&&4i.1d>0){4.2U.3k=4i}4.1p=2U.20(4.12,4.2U)}1k if("7"in 4){4.1p=6w(4.7)}1k if("28"in 4){4.1p=28(4.28);if(4.3P===1h){4.3P=5(1C){11{id:$.4N(1C),1j:$.4N(1C)}}}if(4.1T===1h){4.1T=5(12,1V){14 7=[];$(6g(12.19(),4.3e,4.5L)).2i(5(){14 6X={id:3,1j:3},28=4.28;if($.2G(28))28=28();$(28).2i(5(){if(2x(3.id,6X.id)){6X=3;11 1e}});7.1O(6X)});1V(7)}}}}}if(3m(4.1p)!=="5"){2X"1p 5 2f 81 1N 49 "+4.12.1f("id")}if(4.3J===\'23\'){4.3J=5(55,2K){55.nb(2K)}}1k if(4.3J===\'6q\'){4.3J=5(55,2K){55.1O(2K)}}1k if(3m(4.3J)!=="5"){2X"ng 3J 3H 8X be \'23\', \'6q\' or a nf 5"}11 4},9b:5(){14 el=3.4.12,6I,1c=3;el.on("2Y.6",3.1x(5(e){if(3.4.12.7("6-2Y-8f")!==1l){3.1T()}}));3.4s=3.1x(5(){14 1B=el.22("1B");if(1B===1h)1B=1e;3.5p(!1B);14 2p=el.22("2p");if(2p===1h)2p=1e;3.2p(2p);if(3.1a){57(3.1a,3.4.12,3.4.7x);3.1a.1w(2b(3.4.7A,3.4.12))}if(3.1i){57(3.1i,3.4.12,3.4.7I);3.1i.1w(2b(3.4.7z,3.4.12))}});if(el.1d&&el[0].9p){el.2i(5(){3.9p("9o",1c.4s)})}6I=1I.ne||1I.nc||1I.nd;if(6I!==1h){if(3.3R){aC 3.3R;3.3R=1o}3.3R=3u 6I(5(9t){$.2i(9t,1c.4s)});3.3R.my(el.2w(0),{mx:1l,lS:1e})}},8d:5(7){14 30=$.2y("6-lT",{19:3.id(7),a4:7,1g:7});3.4.12.1L(30);11!30.6N()},1G:5(4D){4D=4D||{};4D=$.2Z({},4D,{2q:"2Y",19:3.19()});3.4.12.7("6-2Y-8f",1l);3.4.12.1L(4D);3.4.12.7("6-2Y-8f",1e);3.4.12.3h();if(3.4.9F)3.4.12.3y()},2B:5(){11 3.8a===1l},4m:5(){14 2l=3.6J&&!3.5V,1B=!2l;if(2l===3.8a)11 1e;3.1a.6f("6-1a-1B",1B);3.1E();3.8a=2l;11 1l},5p:5(2l){if(2l===1h)2l=1l;if(3.6J===2l)11;3.6J=2l;3.4.12.22("1B",!2l);3.4m()},9P:5(){3.5p(1e)},2p:5(2l){if(2l===1h)2l=1e;if(3.5V===2l)11;3.5V=2l;3.4.12.22("2p",2l);3.4m()},21:5(){11(3.1a)?3.1a.2z("6-1i-2h"):1e},3K:5(){14 $1i=3.1i,1a=3.1a,1K=1a.1K(),3l=1a.3I(1e),1r=1a.2S(1e),4M=$1i.3I(1e),$1I=$(1I),7s=$1I.1r(),7p=$1I.3l(),5O=$1I.8v()+7s,73=$1I.2T()+7p,5H=1K.23+3l,4C=1K.2O,86=5H+4M<=73,8i=(1K.23-4M)>=$1I.2T(),3s=$1i.2S(1e),97=5(){11 4C+3s<=5O},9w=5(){11 1K.2O+5O+1a.2S(1e)>3s},8F=$1i.2z("6-1S-2C"),70,2C,5N,1Y,63;if(8F){2C=1l;if(!8i&&86){5N=1l;2C=1e}}1k{2C=1e;if(!86&&8i){5N=1l;2C=1l}}if(5N){$1i.43();1K=3.1a.1K();3l=3.1a.3I(1e);1r=3.1a.2S(1e);4M=$1i.3I(1e);5O=$1I.8v()+7s;73=$1I.2T()+7p;5H=1K.23+3l;4C=1K.2O;3s=$1i.2S(1e);$1i.50();3.4q()}if(3.4.lR){63=$(\'.6-1b\',$1i)[0];$1i.1w(\'6-1S-4S-1r\');$1i.1Y(\'1r\',\'\');3s=$1i.2S(1e)+(63.7i===63.9i?0:67.1r);3s>1r?1r=3s:3s=1r;4M=$1i.3I(1e)}1k{3.1a.1U(\'6-1S-4S-1r\')}if(3.2V.1Y(\'8Y\')!==\'lQ\'){70=3.2V.1K();5H-=70.23;4C-=70.2O}if(!97()&&9w()){4C=1K.2O+3.1a.2S(1e)-3s}1Y={2O:4C,1r:1r};if(2C){1Y.23=1K.23-4M;1Y.6q=\'4S\';3.1a.1w("6-1S-2C");$1i.1w("6-1S-2C")}1k{1Y.23=5H;1Y.6q=\'4S\';3.1a.1U("6-1S-2C");$1i.1U("6-1S-2C")}1Y=$.2Z(1Y,2b(3.4.ac,3.4.12));$1i.1Y(1Y)},9q:5(){14 2o;if(3.21())11 1e;if(3.6J===1e||3.5V===1l)11 1e;2o=$.2y("6-44");3.4.12.1L(2o);11!2o.6N()},7d:5(){3.1a.1U("6-1S-2C");3.1i.1U("6-1S-2C")},2h:5(){if(!3.9q())11 1e;3.44();$1W.on("5G.8A",5(e){6s.x=e.9m;6s.y=e.9l});11 1l},44:5(){14 3Y=3.7l,3r="3r."+3Y,4T="4T."+3Y,6l="9h."+3Y,2n;3.1a.1w("6-1i-2h").1w("6-1a-1R");3.7d();if(3.1i[0]!==3.2V.1F().69()[0]){3.1i.9z().51(3.2V)}2n=$("#6-1S-2n");if(2n.1d===0){2n=$(1W.5k("1X"));2n.1f("id","6-1S-2n").1f("1s","6-1S-2n");2n.43();2n.51(3.2V);2n.on("4E 4c 3h",5(e){72(2n);14 1i=$("#6-1S"),1c;if(1i.1d>0){1c=1i.7("6");if(1c.4.7y){1c.3B({4a:1l})}1c.1E();e.5W();e.4G()}})}if(3.1i.3n()[0]!==2n[0]){3.1i.6i(2n)}$("#6-1S").7e("id");3.1i.1f("id","6-1S");2n.50();3.3K();3.1i.50();3.3K();3.1i.1w("6-1S-1R");14 78=3;3.1a.8R().9j(1I).2i(5(){$(3).on(4T+" "+3r+" "+6l,5(e){if(78.21())78.3K()})})},1E:5(){if(!3.21())11;14 3Y=3.7l,3r="3r."+3Y,4T="4T."+3Y,6l="9h."+3Y;3.1a.8R().9j(1I).2i(5(){$(3).2I(3r).2I(4T).2I(6l)});3.7d();$("#6-1S-2n").43();3.1i.7e("id");3.1i.43();3.1a.1U("6-1i-2h").1U("6-1a-1R");3.1b.6n();$1W.2I("5G.8A");3.2s();3.15.1U("6-1R");3.4.12.1L($.2y("6-1E"))},a1:5(1C){3.2h();3.15.19(1C);3.3O(1e)},2s:5(){},5R:5(){11 2b(3.4.ab,3.4.12)},8C:5(){14 1b=3.1b,1F,1D,5c,hb,6F,y,1Z,6P;1D=3.2P();if(1D<0)11;if(1D==0){1b.2T(0);11}1F=3.3M().1u(\'.6-1z-1Q\');5c=$(1F[1D]);6P=(5c.1K()||{}).23||0;hb=6P+5c.3I(1l);if(1D===1F.1d-1){1Z=1b.1u("li.6-1Z-1b");if(1Z.1d>0){hb=1Z.1K().23+1Z.3I(1l)}}6F=1b.1K().23+1b.3I(1e);if(hb>6F){1b.2T(1b.2T()+(hb-6F))}y=6P-1b.1K().23;if(y<0&&5c.1Y(\'5Z\')!=\'61\'){1b.2T(1b.2T()+y)}},3M:5(){11 3.1b.1u(".6-1z-2M:2f(.6-1B):2f(.6-1n)")},8l:5(7k){14 2j=3.3M(),1D=3.2P();6H(1D>-1&&1D<2j.1d){1D+=7k;14 1g=$(2j[1D]);if(1g.2z("6-1z-2M")&&!1g.2z("6-1B")&&!1g.2z("6-1n")){3.2P(1D);5z}}},2P:5(1D){14 2j=3.3M(),1g,7;if(1H.1d===0){11 2k(2j.4K(".6-3D")[0],2j.2w())}if(1D>=2j.1d)1D=2j.1d-1;if(1D<0)1D=0;3.6Y();1g=$(2j[1D]);1g.1w("6-3D");3.15.1f("42-lO",1g.1u(".6-1z-1Q").1f("id"));3.8C();3.3a.1j(1g.1j());7=1g.7("6-7");if(7){3.4.12.1L({2q:"6-2P",19:3.id(7),1g:7})}},6Y:5(){3.1b.1u(".6-3D").1U("6-3D")},8s:5(){3.7n=1l},7g:5(){3.7n=1e},9I:5(){11 3.3M().1d},6p:5(2o){14 el=$(2o.4P).59(".6-1z-2M");if(el.1d>0&&!el.is(".6-3D")){14 2j=3.3M();3.2P(2j.1D(el))}1k if(el.1d==0){3.6Y()}},5Q:5(){14 1b=3.1b,1Z=1b.1u("li.6-1Z-1b"),7f,2J=3.4v+1,1c=3,1C=3.15.19(),24=3.24;if(1Z.1d===0)11;7f=1Z.1K().23-1b.1K().23-1b.3l();if(7f<=3.4.ag){1Z.1w("6-1R");3.4.1p({12:3.4.12,1C:1C,2J:2J,24:24,3g:3.4.3g,1V:3.1x(5(7){if(!1c.21())11;1c.4.7o.20(3,1b,7.1b,{1C:1C,2J:2J,24:24});1c.45(7,1e,1e);if(7.1Z===1l){1Z.9z().51(1b).3C(1c.4.2e(2b(1c.4.5D,1c.4.12,2J+1)));1I.4W(5(){1c.5Q()},10)}1k{1Z.3p()}1c.3K();1c.4v=2J;1c.24=7.24;3.4.12.1L({2q:"6-aN",aO:7})})})}},8b:5(){},3O:5(3q){14 15=3.15,1b=3.1b,4=3.4,7,1c=3,1y,1C=15.19(),7h=$.7(3.1a,"6-69-1C"),7c;if(3q!==1l&&7h&&2x(1C,7h))11;$.7(3.1a,"6-69-1C",1C);if(3q!==1l&&(3.3d===1e||!3.21())){11}5 71(){15.1U("6-1R");1c.3K();if(1b.1u(\'.6-no-1b,.6-1q-5b,.6-aJ\').1d){1c.3a.1j(1b.1j())}1k{1c.3a.1j(1c.4.7V(1b.1u(\'.6-1z-2M:2f(".6-1n")\').1d))}}5 3x(3C){1b.3C(3C);71()}7c=++3.7b;14 6a=3.5R();if(6a>=1){7=3.7();if($.6z(7)&&7.1d>=6a&&3N(4.6R,"6R")){3x("<li 1s=\'6-1q-5b\'>"+2b(4.6R,4.12,6a)+"</li>");11}}if(15.19().1d<4.82){if(3N(4.6u,"6u")){3x("<li 1s=\'6-no-1b\'>"+2b(4.6u,4.12,15.19(),4.82)+"</li>")}1k{3x("")}if(3q&&3.4l)3.4l(1l);11}if(4.4Y&&15.19().1d>4.4Y){if(3N(4.6C,"6C")){3x("<li 1s=\'6-no-1b\'>"+2b(4.6C,4.12,15.19(),4.4Y)+"</li>")}1k{3x("")}11}if(4.7Y&&3.3M().1d===0){3x("<li 1s=\'6-aJ\'>"+2b(4.7Y,4.12)+"</li>")}15.1w("6-1R");3.6Y();1y=3.8b();if(1y!=1h&&1y!=1o){15.19(1y)}3.4v=1;4.1p({12:4.12,1C:15.19(),2J:3.4v,24:1o,3g:4.3g,1V:3.1x(5(7){14 3Z;if(7c!=3.7b){11}if(!3.21()){3.15.1U("6-1R");11}if(7.aG!==1h&&3N(4.6m,"6m")){3x("<li 1s=\'6-2U-aR\'>"+2b(4.6m,4.12,7.5I,7.5B,7.5E)+"</li>");11}3.24=(7.24===1h)?1o:7.24;if(3.4.3P&&15.19()!==""){3Z=3.4.3P.20(1c,15.19(),7.1b);if(3Z!==1h&&3Z!==1o&&1c.id(3Z)!==1h&&1c.id(3Z)!==1o){if($(7.1b).4K(5(){11 2x(1c.id(3),1c.id(3Z))}).1d===0){3.4.3J(7.1b,3Z)}}}if(7.1b.1d===0&&3N(4.4w,"4w")){3x("<li 1s=\'6-no-1b\'>"+2b(4.4w,4.12,15.19())+"</li>");11}1b.6n();1c.4.7o.20(3,1b,7.1b,{1C:15.19(),2J:3.4v,24:1o});if(7.1Z===1l&&3N(4.5D,"5D")){1b.4g("<li 1s=\'6-1Z-1b\'>"+4.2e(2b(4.5D,4.12,3.4v))+"</li>");1I.4W(5(){1c.5Q()},10)}3.45(7,3q);71();3.4.12.1L({2q:"6-aN",aO:7})})})},4X:5(){3.1E()},3y:5(){if(3.4.7y)3.3B({4a:1l});3.1E();3.1a.1U("6-1a-1R");if(3.15[0]===1W.6A){3.15.3y()}3.2s();3.1q.1u(".6-15-1g-1t").1U("6-15-1g-1t")},4q:5(){1t(3.15)},3B:5(1J){if(3.7n){3.7g();11}14 1D=3.2P(),3D=3.1b.1u(".6-3D"),7=3D.59(\'.6-1z\').7("6-7");if(7){3.2P(1D);3.66(7,1J)}1k if(1J&&1J.4a){3.1E()}},3V:5(){14 2a;11 3.4.12.1f("2m")||3.4.12.1f("7-2m")||3.4.12.7("2m")||3.4.2m||((2a=3.4d())!==1h?2a.1j():1h)},4d:5(){if(3.1A){14 5A=3.1A.1F(\'3H\').65();if(3.4.2a!==1h){11(3.4.2a==="65"&&5A)||(3m 3.4.2a==="5"&&3.4.2a(3.1A))}1k if($.4N(5A.1j())===""&&5A.19()===""){11 5A}}},8c:5(){5 aq(){14 2c,5Y,2u,i,l,1f;if(3.4.1r==="2I"){11 1o}1k if(3.4.1r==="12"){11 3.4.12.2S(1e)===0?\'4S\':3.4.12.2S(1e)+\'px\'}1k if(3.4.1r==="af"||3.4.1r==="aH"){2c=3.4.12.1f(\'2c\');if(2c!==1h){5Y=2c.6t(\';\');1N(i=0,l=5Y.1d;i<l;i=i+1){1f=5Y[i].5f(/\\s/g,\'\');2u=1f.29(/^1r:(([-+]?([0-9]*\\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i);if(2u!==1o&&2u.1d>=1)11 2u[1]}}if(3.4.1r==="aH"){2c=3.4.12.1Y(\'1r\');if(2c.2k("%")>0)11 2c;11(3.4.12.2S(1e)===0?\'4S\':3.4.12.2S(1e)+\'px\')}11 1o}1k if($.2G(3.4.1r)){11 3.4.1r()}1k{11 3.4.1r}};14 1r=aq.20(3);if(1r!==1o){3.1a.1Y("1r",1r)}}});7Q=6M(5e,{75:5(){14 1a=$(1W.5k("1X")).1f({"1s":"6-1a"}).3C(["<a 9H=\'lP:lU(0)\' 1s=\'6-1g\' 3Q=\'-1\'>"," <4x 1s=\'6-4j\'>&#lV;</4x><76 1s=\'6-15-1g-1E\'></76>"," <4x 1s=\'6-ar\' 3X=\'74\'><b 3X=\'74\'></b></4x>","</a>","<1Q 1N=\'\' 1s=\'6-5d\'></1Q>","<1y 1s=\'6-1M 6-5d\' 2q=\'1j\' 42-m0=\'1l\' 3X=\'lZ\' />","<1X 1s=\'6-1S 6-5Z-61\'>"," <1X 1s=\'6-15\'>"," <1Q 1N=\'\' 1s=\'6-5d\'></1Q>"," <1y 2q=\'1j\' 7q=\'2I\' aI=\'2I\' aK=\'2I\' ai=\'1e\' 1s=\'6-1y\' 3X=\'lY\' 42-lW=\'1l\'"," 42-7q=\'55\' />"," </1X>"," <3G 1s=\'6-1b\' 3X=\'lX\'>"," </3G>","</1X>"].5g(""));11 1a},4m:5(){if(3.2r.4m.2g(3,1H)){3.1M.22("1B",!3.2B())}},44:5(){14 el,41,64;if(3.4.4H>=0){3.4l(1l)}3.2r.44.2g(3,1H);if(3.3d!==1e){3.15.19(3.1M.19())}if(3.4.3L(3)){3.15.1t();el=3.15.2w(0);if(el.5U){41=el.5U();41.am(1e);41.1A()}1k if(el.5S){64=3.15.19().1d;el.5S(64,64)}}if(3.15.19()===""){if(3.2v!=1h){3.15.19(3.2v);3.15.1A()}}3.1M.22("1B",1l).19("");3.3O(1l);3.4.12.1L($.2y("6-2h"))},1E:5(){if(!3.21())11;3.2r.1E.2g(3,1H);3.1M.22("1B",1e);if(3.4.3L(3)){3.1M.1t()}},1t:5(){if(3.21()){3.1E()}1k{3.1M.22("1B",1e);if(3.4.3L(3)){3.1M.1t()}}},6v:5(){11 3.1a.2z("6-1a-1R")},4X:5(){3.2r.4X.2g(3,1H);3.1M.22("1B",1e);if(3.4.3L(3)){3.1M.1t()}},4u:5(){$("1Q[1N=\'"+3.1M.1f(\'id\')+"\']").1f(\'1N\',3.4.12.1f("id"));3.2r.4u.2g(3,1H);5P.20(3,"1q","1M")},8o:5(){14 1q,1a=3.1a,1i=3.1i,4Z=4J(),6W;if(3.4.4H<0){3.4l(1e)}1k{3.4l(1l)}3.1q=1q=1a.1u(".6-1g");3.1M=1a.1u(".6-1M");1q.1u(".6-4j").1f("id","6-4j-"+4Z);3.1M.1f("42-lN","6-4j-"+4Z);3.1b.1f("id","6-1b-"+4Z);3.15.1f("42-lM","6-1b-"+4Z);3.1M.1f("id","9J"+4Z);6W=$("1Q[1N=\'"+3.4.12.1f("id")+"\']");3.4.12.1t(3.1x(5(){3.1t()}));3.1M.3n().1j(6W.1j()).1f(\'1N\',3.1M.1f(\'id\'));14 aE=3.4.12.1f("6Z");3.4.12.1f("6Z",(aE||6W.1j()));3.1M.1f("3Q",3.5J);3.15.1f("id",3.1M.1f(\'id\')+\'lC\');3.15.3n().1j($("1Q[1N=\'"+3.1M.1f(\'id\')+"\']").1j()).1f(\'1N\',3.15.1f(\'id\'));3.15.on("5T",3.1x(5(e){if(!3.2B())11;if(lD==e.lB)11;if(e.1v===1m.8h||e.1v===1m.84){1P(e);11}6c(e.1v){2d 1m.4f:2d 1m.5t:3.8l((e.1v===1m.4f)?-1:1);1P(e);11;2d 1m.3z:3.3B();1P(e);11;2d 1m.5x:3.3B({4a:1l});11;2d 1m.5l:3.4X(e);1P(e);11}}));3.15.on("3y",3.1x(5(e){if(1W.6A===3.2V.2w(0)){1I.4W(3.1x(5(){if(3.21()){3.15.1t()}}),0)}}));3.1M.on("5T",3.1x(5(e){if(!3.2B())11;if(e.1v===1m.5x||1m.8m(e)||1m.8g(e)||e.1v===1m.5l){11}if(3.4.6S===1e&&e.1v===1m.3z){1P(e);11}if(e.1v==1m.5t||e.1v==1m.4f||(e.1v==1m.3z&&3.4.6S)){if(e.9S||e.9R||e.9Q||e.85)11;3.2h();1P(e);11}if(e.1v==1m.6d||e.1v==1m.4L){if(3.4.aM){3.5a()}1P(e);11}}));77(3.1M);3.1M.on("4R-2Y 1y",3.1x(5(e){if(3.4.4H>=0){e.4G();if(3.21())11;3.2h()}}));1q.on("4E 4c","76",3.1x(5(e){if(!3.2B()){11}3.5a();aQ(e);3.1E();if(3.1q){3.1q.1t()}}));1q.on("4E 4c",3.1x(5(e){72(1q);if(!3.1a.2z("6-1a-1R")){3.4.12.1L($.2y("6-1t"))}if(3.21()){3.1E()}1k if(3.2B()){3.2h()}1P(e)}));1i.on("4E 4c",3.1x(5(){if(3.4.3L(3)){3.15.1t()}}));1q.on("1t",3.1x(5(e){1P(e)}));3.1M.on("1t",3.1x(5(){if(!3.1a.2z("6-1a-1R")){3.4.12.1L($.2y("6-1t"))}3.1a.1w("6-1a-1R")})).on("3y",3.1x(5(){if(!3.21()){3.1a.1U("6-1a-1R");3.4.12.1L($.2y("6-3y"))}}));3.15.on("1t",3.1x(5(){if(!3.1a.2z("6-1a-1R")){3.4.12.1L($.2y("6-1t"))}3.1a.1w("6-1a-1R")}));3.8c();3.4.12.43();3.4e()},5a:5(1G){14 7=3.1q.7("6-7");if(7){14 30=$.2y("6-lA");3.4.12.1L(30);if(30.6N()){11}14 2a=3.4d();3.4.12.19(2a?2a.19():"");3.1q.1u(".6-4j").6n();3.1q.7m("6-7");3.4e();if(1G!==1e){3.4.12.1L({2q:"6-3i",19:3.id(7),1g:7});3.1G({3i:7})}}},1T:5(){14 1n;if(3.7a()){3.2t(1o);3.1E();3.4e()}1k{14 1c=3;3.4.1T.20(1o,3.4.12,5(1n){if(1n!==1h&&1n!==1o){1c.2t(1n);1c.1E();1c.4e();1c.2v=1c.4.2v(1n,1c.15.19())}})}},7a:5(){14 2a;if(3.3V()===1h)11 1e;11((2a=3.4d())!==1h&&2a.22("1n"))||(3.4.12.19()==="")||(3.4.12.19()===1h)||(3.4.12.19()===1o)},4O:5(){14 4=3.2r.4O.2g(3,1H),1c=3;if(4.12.2w(0).6x.6T()==="1A"){4.1T=5(12,1V){14 1n=12.1u("3H").4K(5(){11 3.1n&&!3.1B});1V(1c.4F(1n))}}1k if("7"in 4){4.1T=4.1T||5(12,1V){14 id=12.19();14 29=1o;4.1p({3g:5(1C,1j,el){14 4U=2x(id,4.id(el));if(4U){29=el}11 4U},1V:!$.2G(1V)?$.9L:5(){1V(29)}})}}11 4},3V:5(){if(3.1A){if(3.4d()===1h){11 1h}}11 3.2r.3V.2g(3,1H)},4e:5(){14 2m=3.3V();if(3.7a()&&2m!==1h){if(3.1A&&3.4d()===1h)11;3.1q.1u(".6-4j").3C(3.4.2e(2m));3.1q.1w("6-56");3.1a.1U("6-aF")}},45:5(7,3q,6U){14 1n=0,1c=3,3d=1l;3.3M().2E(5(i,3o){if(2x(1c.id(3o.7("6-7")),1c.4.12.19())){1n=i;11 1e}});if(6U!==1e){if(3q===1l&&1n>=0){3.2P(1n)}1k{3.2P(0)}}if(3q===1l){14 5m=3.4.4H;if(5m>=0){3.4l(7j(7.1b)>=5m)}}},4l:5(3d){if(3.3d===3d)11;3.3d=3d;3.1i.1u(".6-15").6f("6-15-6B",!3d);3.1i.1u(".6-15").6f("6-5d",!3d);$(3.1i,3.1a).6f("6-88-ly",3d)},66:5(7,1J){if(!3.8d(7)){11}14 2N=3.4.12.19(),2R=3.7();3.4.12.19(3.id(7));3.2t(7);3.4.12.1L({2q:"6-1n",19:3.id(7),1g:7});3.2v=3.4.2v(7,3.15.19());3.1E();if((!1J||!1J.4a)&&3.4.3L(3)){3.1M.1t()}if(!2x(2N,3.id(7))){3.1G({4o:7,3i:2R})}},2t:5(7){14 1a=3.1q.1u(".6-4j"),2L,3U;3.1q.7("6-7",7);1a.6n();if(7!==1o){2L=3.4.7u(7,1a,3.4.2e)}if(2L!==1h){1a.4g(2L)}3U=3.4.7t(7,1a);if(3U!==1h){1a.1w(3U)}3.1q.1U("6-56");if(3.4.aM&&3.3V()!==1h){3.1a.1w("6-aF")}},19:5(){14 19,1G=1e,7=1o,1c=3,2R=3.7();if(1H.1d===0){11 3.4.12.19()}19=1H[0];if(1H.1d>1){1G=1H[1]}if(3.1A){3.1A.19(19).1u("3H").4K(5(){11 3.1n}).2E(5(i,3o){7=1c.4F(3o);11 1e});3.2t(7);3.4e();if(1G){3.1G({4o:7,3i:2R})}}1k{if(!19&&19!==0){3.5a(1G);11}if(3.4.1T===1h){2X 3u 5s("ah 20 19() if 1T() is 2f 81")}3.4.12.19(19);3.4.1T(3.4.12,5(7){1c.4.12.19(!7?"":1c.id(7));1c.2t(7);1c.4e();if(1G){1c.1G({4o:7,3i:2R})}})}},2s:5(){3.15.19("");3.1M.19("")},7:5(25){14 7,1G=1e;if(1H.1d===0){7=3.1q.7("6-7");if(7==1h)7=1o;11 7}1k{if(1H.1d>1){1G=1H[1]}if(!25){3.5a(1G)}1k{7=3.7();3.4.12.19(!25?"":3.id(25));3.2t(25);if(1G){3.1G({4o:25,3i:7})}}}}});7P=6M(5e,{75:5(){14 1a=$(1W.5k("1X")).1f({"1s":"6-1a 6-1a-60"}).3C(["<3G 1s=\'6-2j\'>"," <li 1s=\'6-15-9K\'>"," <1Q 1N=\'\' 1s=\'6-5d\'></1Q>"," <1y 2q=\'1j\' 7q=\'2I\' aI=\'2I\' aK=\'2I\' ai=\'1e\' 1s=\'6-1y\'>"," </li>","</3G>","<1X 1s=\'6-1S 6-1S-60 6-5Z-61\'>"," <3G 1s=\'6-1b\'>"," </3G>","</1X>"].5g(""));11 1a},4O:5(){14 4=3.2r.4O.2g(3,1H),1c=3;if(4.12.2w(0).6x.6T()==="1A"){4.1T=5(12,1V){14 7=[];12.1u("3H").4K(5(){11 3.1n&&!3.1B}).2E(5(i,3o){7.1O(1c.4F(3o))});1V(7)}}1k if("7"in 4){4.1T=4.1T||5(12,1V){14 2H=6g(12.19(),4.3e,4.5L);14 2u=[];4.1p({3g:5(1C,1j,el){14 4U=$.lz(2H,5(id){11 2x(id,4.id(el))}).1d;if(4U){2u.1O(el)}11 4U},1V:!$.2G(1V)?$.9L:5(){14 79=[];1N(14 i=0;i<2H.1d;i++){14 id=2H[i];1N(14 j=0;j<2u.1d;j++){14 29=2u[j];if(2x(id,4.id(29))){79.1O(29);2u.6h(j,1);5z}}}1V(79)}})}}11 4},4h:5(1g){14 1n=3.1a.1u(".6-15-1g-1t");if(1n.1d&&1g&&1g[0]==1n[0]){}1k{if(1n.1d){3.4.12.1L("1g-lE",1n)}1n.1U("6-15-1g-1t");if(1g&&1g.1d){3.1E();1g.1w("6-15-1g-1t");3.4.12.1L("1g-1n",1g)}}},4u:5(){$("1Q[1N=\'"+3.15.1f(\'id\')+"\']").1f(\'1N\',3.4.12.1f("id"));3.2r.4u.2g(3,1H);5P.20(3,"4r","1q")},8o:5(){14 5X=".6-2j",1q;3.4r=3.1a.1u(".6-15-9K");3.1q=1q=3.1a.1u(5X);14 8k=3;3.1q.on("3h",".6-1a:2f(.6-1a-1B) .6-15-1g:2f(.6-3j)",5(e){8k.15[0].1t();8k.4h($(3))});3.15.1f("id","9J"+4J());3.15.3n().1j($("1Q[1N=\'"+3.4.12.1f("id")+"\']").1j()).1f(\'1N\',3.15.1f(\'id\'));3.4.12.1t(3.1x(5(){3.1t()}));3.15.on("1y 9N",3.1x(5(){if(3.15.1f(\'2m\')&&3.15.19().1d==0)11;if(!3.2B())11;if(!3.21()){3.2h()}}));3.15.1f("3Q",3.5J);3.62=0;3.15.on("5T",3.1x(5(e){if(!3.2B())11;++3.62;14 1n=1q.1u(".6-15-1g-1t");14 3n=1n.3n(".6-15-1g:2f(.6-3j)");14 48=1n.48(".6-15-1g:2f(.6-3j)");14 52=9O(3.15);if(1n.1d&&(e.1v==1m.5q||e.1v==1m.5M||e.1v==1m.4L||e.1v==1m.6d||e.1v==1m.3z)){14 3A=1n;if(e.1v==1m.5q&&3n.1d){3A=3n}1k if(e.1v==1m.5M){3A=48.1d?48:1o}1k if(e.1v===1m.4L){if(3.6L(1n.65())){3.15.1r(10);3A=3n.1d?3n:48}}1k if(e.1v==1m.6d){if(3.6L(1n.65())){3.15.1r(10);3A=48.1d?48:1o}}1k if(e.1v==1m.3z){3A=1o}3.4h(3A);1P(e);if(!3A||!3A.1d){3.2h()}11}1k if(((e.1v===1m.4L&&3.62==1)||e.1v==1m.5q)&&(52.1K==0&&!52.1d)){3.4h(1q.1u(".6-15-1g:2f(.6-3j)").69());1P(e);11}1k{3.4h(1o)}if(3.21()){6c(e.1v){2d 1m.4f:2d 1m.5t:3.8l((e.1v===1m.4f)?-1:1);1P(e);11;2d 1m.3z:3.3B();1P(e);11;2d 1m.5x:3.3B({4a:1l});3.1E();11;2d 1m.5l:3.4X(e);1P(e);11}}if(e.1v===1m.5x||1m.8m(e)||1m.8g(e)||e.1v===1m.4L||e.1v===1m.5l){11}if(e.1v===1m.3z){if(3.4.6S===1e){11}1k if(e.9S||e.9R||e.9Q||e.85){11}}3.2h();if(e.1v===1m.8h||e.1v===1m.84){1P(e)}if(e.1v===1m.3z){1P(e)}}));3.15.on("4R",3.1x(5(e){3.62=0;3.5o()}));3.15.on("3y",3.1x(5(e){3.1a.1U("6-1a-1R");3.15.1U("6-5j");3.4h(1o);if(!3.21())3.2s();e.aj();3.4.12.1L($.2y("6-3y"))}));3.1a.on("3h",5X,3.1x(5(e){if(!3.2B())11;if($(e.4P).59(".6-15-1g").1d>0){11}3.4h(1o);3.6b();if(!3.1a.2z("6-1a-1R")){3.4.12.1L($.2y("6-1t"))}3.2h();3.4q();e.5W()}));3.1a.on("1t",5X,3.1x(5(){if(!3.2B())11;if(!3.1a.2z("6-1a-1R")){3.4.12.1L($.2y("6-1t"))}3.1a.1w("6-1a-1R");3.1i.1w("6-1S-1R");3.6b()}));3.8c();3.4.12.43();3.2s()},4m:5(){if(3.2r.4m.2g(3,1H)){3.15.22("1B",!3.2B())}},1T:5(){14 7;if(3.4.12.19()===""&&3.4.12.1j()===""){3.2t([]);3.1E();3.2s()}if(3.1A||3.4.12.19()!==""){14 1c=3;3.4.1T.20(1o,3.4.12,5(7){if(7!==1h&&7!==1o){1c.2t(7);1c.1E();1c.2s()}})}},2s:5(){14 2m=3.3V(),3T=3.9T();if(2m!==1h&&3.4I().1d===0&&3.15.2z("6-5j")===1e){3.15.19(2m).1w("6-56");3.15.1r(3T>0?3T:3.1a.1Y("1r"))}1k{3.15.19("").1r(10)}},6b:5(){if(3.15.2z("6-56")){3.15.19("").1U("6-56")}},44:5(){3.6b();3.5o();3.2r.44.2g(3,1H);3.4q();if(3.15.19()===""){if(3.2v!=1h){3.15.19(3.2v);3.15.1A()}}3.3O(1l);if(3.4.3L(3)){3.15.1t()}3.4.12.1L($.2y("6-2h"))},1E:5(){if(!3.21())11;3.2r.1E.2g(3,1H)},1t:5(){3.1E();3.15.1t()},6v:5(){11 3.15.2z("6-5j")},2t:5(7){14 2H=[],31=[],1c=3;$(7).2i(5(){if(2k(1c.id(3),2H)<0){2H.1O(1c.id(3));31.1O(3)}});7=31;3.1q.1u(".6-15-1g").3p();$(7).2i(5(){1c.89(3)});1c.45()},8b:5(){14 1y=3.15.19();1y=3.4.9D.20(3,1y,3.7(),3.1x(3.66),3.4);if(1y!=1o&&1y!=1h){3.15.19(1y);if(1y.1d>0){3.2h()}}},66:5(7,1J){if(!3.8d(7)||7.1j===""){11}3.89(7);3.4.12.1L({2q:"1n",19:3.id(7),1g:7});3.2v=3.4.2v(7,3.15.19());3.2s();3.3O();if(3.1A||!3.4.5h)3.45(7,1e,3.4.5h===1l);if(3.4.5h){3.1E();3.15.1r(10)}1k{if(3.9I()>0){3.15.1r(10);3.5o();if(3.5R()>0&&3.19().1d>=3.5R()){3.3O(1l)}1k{if(3.2v!=1h){3.15.19(3.2v);3.3O();3.15.1A()}}3.3K()}1k{3.1E();3.15.1r(10)}}3.1G({4o:7});if(!1J||!1J.4a)3.4q()},4X:5(){3.1E();3.4q()},89:5(7){14 83=!7.3j,9x=$("<li 1s=\'6-15-1g\'>"+" <1X></1X>"+" <a 9H=\'#\' 1s=\'6-15-1g-1E\' 3Q=\'-1\'></a>"+"</li>"),9B=$("<li 1s=\'6-15-1g 6-3j\'>"+"<1X></1X>"+"</li>");14 1g=83?9x:9B,id=3.id(7),19=3.4I(),2L,3U;2L=3.4.7u(7,1g.1u("1X"),3.4.2e);if(2L!=1h){1g.1u("1X").lF($("<1X></1X>").3C(2L))}3U=3.4.7t(7,1g.1u("1X"));if(3U!=1h){1g.1w(3U)}if(83){1g.1u(".6-15-1g-1E").on("4E",1P).on("3h lK",3.1x(5(e){if(!3.2B())11;3.6L($(e.4P));3.1q.1u(".6-15-1g-1t").1U("6-15-1g-1t");1P(e);3.1E();3.4q()})).on("1t",3.1x(5(){if(!3.2B())11;3.1a.1w("6-1a-1R");3.1i.1w("6-1S-1R")}))}1g.7("6-7",7);1g.lL(3.4r);19.1O(id);3.4b(19)},6L:5(1n){14 19=3.4I(),7,1D;1n=1n.59(".6-15-1g");if(1n.1d===0){2X"a6 lJ: "+1n+". lI be .6-15-1g"}7=1n.7("6-7");if(!7){11}14 30=$.2y("6-lG");30.19=3.id(7);30.1g=7;3.4.12.1L(30);if(30.6N()){11 1e}6H((1D=2k(3.id(7),19))>=0){19.6h(1D,1);3.4b(19);if(3.1A)3.45()}1n.3p();3.4.12.1L({2q:"6-3i",19:3.id(7),1g:7});3.1G({3i:7});11 1l},45:5(7,3q,6U){14 19=3.4I(),2j=3.1b.1u(".6-1z"),4y=3.1b.1u(".6-1z-88-1F"),1c=3;2j.2E(5(i,1g){14 id=1c.id(1g.7("6-7"));if(2k(id,19)>=0){1g.1w("6-1n");1g.1u(".6-1z-2M").1w("6-1n")}});4y.2E(5(i,1g){if(!1g.is(\'.6-1z-2M\')&&1g.1u(".6-1z-2M:2f(.6-1n)").1d===0){1g.1w("6-1n")}});if(3.2P()==-1&&6U!==1e&&3.4.5h===1l){1c.2P(0)}if(!3.4.3P&&!2j.4K(\'.6-1z:2f(.6-1n)\').1d>0){if(!7||7&&!7.1Z&&3.1b.1u(".6-no-1b").1d===0){if(3N(1c.4.4w,"4w")){3.1b.4g("<li 1s=\'6-no-1b\'>"+2b(1c.4.4w,1c.4.12,1c.15.19())+"</li>")}}}},9T:5(){11 3.1q.1r()-87(3.15)},5o:5(){14 6k,2O,3T,7r,3w,6G=87(3.15);6k=9U(3.15)+10;2O=3.15.1K().2O;3T=3.1q.1r();7r=3.1q.1K().2O;3w=3T-(2O-7r)-6G;if(3w<6k){3w=3T-6G}if(3w<40){3w=3T-6G}if(3w<=0){3w=6k}3.15.1r(lH.m1(3w))},4I:5(){14 19;if(3.1A){19=3.1A.19();11 19===1o?[]:19}1k{19=3.4.12.19();11 6g(19,3.4.3e,3.4.5L)}},4b:5(19){14 4A;if(3.1A){3.1A.19(19)}1k{4A=[];$(19).2i(5(){if(2k(3,4A)<0)4A.1O(3)});3.4.12.19(4A.1d===0?"":4A.5g(3.4.3e))}},6y:5(2N,4p){14 4p=4p.5u(0),2N=2N.5u(0);1N(14 i=0;i<4p.1d;i++){1N(14 j=0;j<2N.1d;j++){if(2x(3.4.id(4p[i]),3.4.id(2N[j]))){4p.6h(i,1);if(i>0){i--}2N.6h(j,1);j--}}}11{4o:4p,3i:2N}},19:5(19,1G){14 2R,1c=3;if(1H.1d===0){11 3.4I()}2R=3.7();if(!2R.1d)2R=[];if(!19&&19!==0){3.4.12.19("");3.2t([]);3.2s();if(1G){3.1G({4o:3.7(),3i:2R})}11}3.4b(19);if(3.1A){3.4.1T(3.1A,3.1x(3.2t));if(1G){3.1G(3.6y(2R,3.7()))}}1k{if(3.4.1T===1h){2X 3u 5s("19() ah be m2 if 1T() is 2f 81")}3.4.1T(3.4.12,5(7){14 2H=$.7B(7,1c.id);1c.4b(2H);1c.2t(7);1c.2s();if(1G){1c.1G(1c.6y(2R,1c.7()))}})}3.2s()},a3:5(){if(3.1A){2X 3u 5s("mo of mp is 2f mn 9X 9W 4z <1A>. ml 4z <1y 2q=\'6B\'/> mj.")}3.15.1r(0);3.4r.43()},a2:5(){14 19=[],1c=3;3.4r.50();3.4r.51(3.4r.2r());3.5o();3.1q.1u(".6-15-1g").2i(5(){19.1O(1c.4.id($(3).7("6-7")))});3.4b(19);3.1G()},7:5(5n,1G){14 1c=3,2H,2N;if(1H.1d===0){11 3.1q.1F(".6-15-1g").7B(5(){11 $(3).7("6-7")}).2w()}1k{2N=3.7();if(!5n){5n=[]}2H=$.7B(5n,5(e){11 1c.4.id(e)});3.4b(2H);3.2t(5n);3.2s();if(1G){3.1G(3.6y(2N,3.7()))}}}});$.fn.6=5(){14 26=a0.3F.5u.20(1H,0),4,6,3v,25,3t,9V=["19","4u","21","2h","1E","1t","6v","1a","1i","a3","a2","5p","9P","2p","3K","7","15"],9Y=["21","6v","1a","1i"],a5=["19","7"],7H={15:"a1"};3.2i(5(){if(26.1d===0||3m(26[0])==="a4"){4=26.1d===0?{}:$.2Z({},26[0]);4.12=$(3);if(4.12.2w(0).6x.6T()==="1A"){3t=4.12.22("3t")}1k{3t=4.3t||1e;if("28"in 4){4.3t=3t=1l}}6=3t?3u 1I.49["1s"].60():3u 1I.49["1s"].ax();6.9Z(4)}1k if(3m(26[0])==="4t"){if(2k(26[0],9V)<0){2X"mk 3v: "+26[0]}25=1h;6=$(3).7("6");if(6===1h)11;3v=26[0];if(3v==="1a"){25=6.1a}1k if(3v==="1i"){25=6.1i}1k{if(7H[3v])3v=7H[3v];25=6[3v].2g(6,26.5u(1))}if(2k(26[0],9Y)>=0||(2k(26[0],a5)>=0&&26.1d==1)){11 1e}}1k{2X"a6 1H 4z 6 mq: "+26}});11(25===1h)?3:25};$.fn.6.7S={1r:"af",ag:0,5h:1l,6S:1l,ad:{},ac:{},7A:"",7z:"",a7:5(1z,1a,1p,2e){14 2Q=[];6D(3.1j(1z),1p.1C,2Q,2e);11 2Q.5g("")},5L:5(19){11 $.4N(19)},7u:5(7,1a,2e){11 7?2e(3.1j(7)):1h},a8:5(1b,1a,1p){11 1b},a9:5(7){11 7.1Y},7t:5(7,1a){11 1h},4H:0,82:0,4Y:1o,ab:0,id:5(e){11 e==1h?1o:e.id},1j:5(e){if(e&&3.7&&3.7.1j){if($.2G(3.7.1j)){11 3.7.1j(e)}1k{11 e[3.7.1j]}}1k{11 e.1j}},3g:5(1C,1j){11 4k(\'\'+1j).6j().2k(4k(\'\'+1C).6j())>=0},3e:",",58:[],9D:9E,2e:7O,9F:1e,7y:1e,7x:5(c){11 c},7I:5(c){11 1o},2v:5(mr,mw){11 1h},9C:\'\',3J:\'23\',3L:5(9A){14 9y=((\'mv\'in 1I)||(mu.ms>0));if(!9y){11 1l}if(9A.4.4H<0){11 1e}11 1l}};$.fn.6.7R=[];$.fn.6.7R[\'en\']={7V:5(2u){if(2u===1){11"mt 1z is aB, mi aL 4z 1A it."}11 2u+" 1b mh aB, aA m7 aw m8 ar m6 4z m5."},4w:5(){11"m3 2u m4"},6m:5(5I,5B,5E){11"az m9"},6u:5(1y,5m){14 n=5m-1y.1d;11"ap aL "+n+" or 1Z 7X"+(n==1?"":"s")},6C:5(1y,aD){14 n=1y.1d-aD;11"ap aC "+n+" 7X"+(n==1?"":"s")},6R:5(5b){11"ma mf mg 1A "+5b+" 2K"+(5b==1?"":"s")},5D:5(me){11"az 1Z 1b…"},7Y:5(){11"md…"}};$.2Z($.fn.6.7S,$.fn.6.7R[\'en\']);$.fn.6.7M={5r:$.2U,3f:{2q:"aP",7K:1e,5y:"9M"}};1I.49={1p:{2U:2U,6w:6w,28:28},mb:{6E:6E,6D:6D,2e:7O,4k:4k},"1s":{"mc":5e,"ax":7Q,"60":7P}}}(8y));',62,1683,'|||this|opts|function|select2|data||||||||||||||||||||||||||||||||||||||||||||||||||||||||return|element||var|search||||val|container|results|self|length|false|attr|choice|undefined|dropdown|text|else|true|KEY|selected|null|query|selection|width|class|focus|find|which|addClass|bind|input|result|select|disabled|term|index|close|children|triggerChange|arguments|window|options|offset|trigger|focusser|for|push|killEvent|label|active|drop|initSelection|removeClass|callback|document|div|css|more|call|opened|prop|top|context|value|args||tags|match|placeholderOption|evaluate|style|case|escapeMarkup|not|apply|open|each|choices|indexOf|enabled|placeholder|mask|event|readonly|type|parent|clearSearch|updateSelection|matches|nextSearchTerm|get|equal|Event|hasClass|datum|isInterfaceEnabled|above|node|each2|group|isFunction|ids|off|page|item|formatted|selectable|old|left|highlight|markup|oldData|outerWidth|scrollTop|ajax|body|constructor|throw|change|extend|evt|filtered|||||||||liveRegion|token|classes|showSearchInput|separator|params|matcher|click|removed|locked|url|height|typeof|prev|elm|remove|initial|scroll|dropWidth|multiple|new|method|searchWidth|render|blur|ENTER|selectedChoice|selectHighlighted|html|highlighted|resultsSelector|prototype|ul|option|outerHeight|createSearchChoicePosition|positionDropdown|shouldFocusInput|findHighlightableChoices|checkFormatter|updateResults|createSearchChoice|tabindex|propertyObserver|process|maxWidth|cssClass|getPlaceholder|sizer|role|cid|def||range|aria|hide|opening|postprocessResults|||next|Select2|noFocus|setVal|touchstart|getPlaceholderOption|setPlaceholder|UP|append|selectChoice|ajaxUrl|chosen|stripDiacritics|showSearch|enableInterface|template|added|current|focusSearch|searchContainer|_sync|string|destroy|resultsPage|formatNoMatches|span|compound|to|unique|autofocus|dropLeft|details|mousedown|optionToData|stopPropagation|minimumResultsForSearch|getVal|nextUid|filter|BACKSPACE|dropHeight|trim|prepareOpts|target|collection|keyup|auto|resize|is_match|timeout|setTimeout|cancel|maximumInputLength|idSuffix|show|appendTo|pos|tmp|quietMillis|list|default|syncCssClasses|tokenSeparators|closest|clear|limit|child|offscreen|AbstractSelect2|replace|join|closeOnSelect|key|focused|createElement|ESC|min|values|resizeSearch|enable|LEFT|transport|Error|DOWN|slice|deltaY|innerContainer|TAB|dataType|break|firstOption|textStatus|handler|formatLoadMore|errorThrown|substring|mousemove|dropTop|jqXHR|elementTabIndex|formatter|transformVal|RIGHT|changeDirection|viewPortRight|cleanupJQueryElements|loadMoreIfNeeded|getMaximumSelectionSize|setSelectionRange|keydown|createTextRange|_readonly|preventDefault|selector|attrs|display|multi|none|keydowns|resultsListNode|len|first|onSelect|scrollBarDimensions|count|last|maxSelSize|clearPlaceholder|switch|DELETE|ctx|toggleClass|splitVal|splice|before|toUpperCase|minimumWidth|orient|formatAjaxError|empty|dataItem|highlightUnderEvent|bottom|populate|lastMousePosition|split|formatInputTooShort|isFocused|local|tagName|buildChangeDetails|isArray|activeElement|hidden|formatInputTooLong|markMatch|debounce|rb|sideBorderPadding|while|observer|_enabled|dupe|unselect|clazz|isDefaultPrevented|lastpos|topOffset|adapted|formatSelectionTooBig|openOnEnter|toLowerCase|noHighlightUpdate|replacements|elementLabel|obj|removeHighlight|title|bodyOffset|postRender|reinsertElement|viewportBottom|presentation|createContainer|abbr|installKeyUpChangeEvent|that|ordered|isPlaceholderOptionSelected|queryCount|queryNumber|clearDropdownAlignmentPreference|removeAttr|below|clearTouchMoved|lastTerm|scrollHeight|countResults|delta|containerEventName|removeData|_touchMoved|populateResults|windowHeight|autocomplete|containerLeft|windowWidth|formatSelectionCssClass|formatSelection|isObject|dataText|adaptContainerCssClass|selectOnBlur|dropdownCssClass|containerCssClass|map|touchend|depth|_touchEvent|containerId|SuperClass|methodsMap|adaptDropdownCssClass|String|cache|u03C5|ajaxDefaults|u03B9|defaultEscapeMarkup|MultiSelect2|SingleSelect2|locales|defaults|dest|tl|formatMatches|sel|character|formatSearching|array||defined|minimumInputLength|enableChoice|PAGE_DOWN|metaKey|enoughRoomBelow|getSideBorderPadding|with|addSelectedChoice|enabledInterface|tokenize|initContainerWidth|triggerSelect|nodes|triggered|isFunctionKey|PAGE_UP|enoughRoomAbove|AE|_this|moveHighlight|isControl|idKey|initContainer|fontSize|fontFamily|u0399|touchMoved|10000px|fontWeight|scrollLeft|textTransform|letterSpacing|jQuery|fontStyle|select2Event|isVisible|ensureHighlightVisible|str|DIACRITICS|aboveNow|u03C9|counter|src|MEASURE_SCROLLBAR_TEMPLATE|notify|selectionStart|threshold|u03A5|dim|transform|createRange|parents|func|accessible|installFilteredMouseMove|methods|original|must|position|selectCallback|touchmove|optgroup||select2Tags|measureScrollbar|detachEvent|mouseup|enoughRoomOnRight|installDebouncedScroll|debounced|mousewheel|monitorSource|formatterName|jsonpCallback|deprecated|abort|clearTimeout|orientationchange|clientHeight|add|replace_map|pageY|pageX|isFunc|onpropertychange|attachEvent|shouldOpen|childDatum|Dz|mutations|DZ|adapter|enoughRoomOnLeft|enabledItem|supportsTouchEvents|detach|instance|disabledItem|searchInputPlaceholder|tokenizer|defaultTokenizer|blurOnChange|AV|href|countSelectableResults|s2id_autogen|field|noop|json|paste|getCursorInfo|disable|shiftKey|ctrlKey|altKey|getMaxSearchWidth|measureTextWidth|allowedMethods|attached|when|valueMethods|init|Array|externalSearch|onSortEnd|onSortStart|object|propertyMethods|Invalid|formatResult|sortResults|formatResultCssClass||maximumSelectionSize|dropdownCss|containerCss||copy|loadMorePadding|cannot|spellcheck|stopImmediatePropagation|CTRL|ALT|collapse|||Please|resolveContainerWidth|arrow||SHIFT|||and|single||Loading|use|available|delete|max|originalTitle|allowclear|hasError|resolve|autocorrect|searching|autocapitalize|enter|allowClear|loaded|items|GET|killEventImmediately|error|u0244|uFF36|u24CB|u00D9|uA786|u023E|u01AE|u01AC|u01B2|uA728|TZ|u1E7E|uFF35|u24CA|u1E7C|u016A|u0170|u1EF0|u1EE4|u1E72|u016E|u0172||u1EEC|u1EEE|u01D3|u0214|u01AF|u1EEA|u1EE8|u1EE6|u01D9|u0216|u1E74|u1E78|u0168|u00DB|u1E76|u1E7A|u01D7|u01D5|u01DB|u00DC|u016C|u00DA|u0218|u1E54|u1E56|u01A4|uFF30|u24C5|OO|u0222|OU|u2C63|uA750|uA758|u024A|u24C7|uA756|uFF31|uA752|uA754|u24C6|uA74E|OI|u1EDE|u1EE2|u1ECC|u1EE0|u1EDA|u020E|u01A0|u1EDC|u1ED8|u01EA|uA74A|uA74C|u01A2|u019F|u0186|u01EC|u00D8|u01FE|uFF32|u0154|u015E|u2C7E|uA7A8|uA75E|u1E68|u0160||u1E66|u1E62|uA784|u24C9|u0162|u1E70|u1E6E|u021A|u1E6C|uFF34|u1E6A|u0164|u1E60|u015C|u1E5C|u0156|u1E5E|u1E5A|u0212|u1E58|u0158|u0210|u024C|u2C64|u1E9E|u015A|u1E64|uFF33|u24C8|uA75A|uA7A6|uA782|u0166|u01B3|u1E05|u1E07|u0180|u1E03|uFF42|uA73D|u24D1|u0183|u0253|u010B|u010D|u0109|u0107|u24D2|uFF43|uA73B|uA739|u1EB7|u1E01|u0105|u1EAD|u1EA1|u0201|u0203|u2C65|u0250|uA735|uA737|u01E3|u01FD|uA733|u00E6|u00E7|u1E09|u00E8|u00E9|u00EA|uFF45|u24D4|u01F3||u01C6|u1EC1|u1EBF|u1E15|u1E17|u0113|u1EBD|u1EC5|u1EC3|uA77A|u0257|u24D3|uFF44|u1E0B|u2184|uA73F|u0188|u023C|u010F|u1E0D|u018C|u0256|u0111|u1E0F|u1E11|u1E13|u01CE|u01FB|u0232|u1E8E|u0178|u1EF8|u0176|u1EF2|u00DD|u1EF6|u1EF4|uFF3A|u0179|u24CF|u1EFE|u020C|u024E|uFF39|u24CE|u1E80|u1E82||||u0174|uFF37|u24CC|uA760|VY|u1E86|u1E84|u1E8A|u1E8C||uFF38|u24CD|u1E88|u2C72|u1E90|u017B|u0103|u1EB1|u1EAF|u0101|u00E3|u1EAB|u1EA9|u1EB5|u1EB3|u1EA3|u00E5|u01DF|u00E4|u0227|u01E1|u1EA5|u1EA7|u0224|u2C7F|u01B5|u1E94|u017D|u1E92|u2C6B|uA762|u00E1|u00E2|u00E0|u1E9A|u24D0|uFF41|u0245|u1E44|u0190|u018E|u24BB|u0202|u1E1A|u0118|u1E18|uFF26|u0200|u01FA|u24BC|uA77B||u01CD|u1E1E|u0191|u1E1C|u0228|u1EBA|u011A|u00CB|u0116|u023A|u0104|u0204|u1E00|u1EAC|u1EA0|u1EC6|u1EB8|u0206|u1EB6|u00C5|u1EA2|u1EA8|u0193|u00C3|u0100|u1EB0|u0102|uA7A0|u1EAA|uA77D|uA77E|u00C1|u00C2|u1EA4|u1EA6|u1EAE|u01E4|u0226|u1EB2|u01E0|u00C4|u01DE|uFF27|u01F4|u1EB4|u01E6|u0122|u0120|u011E|u011C|u1E20|u2C6F|uA732|u010C|u010A|u0108|u00C7|u1E08|u023B|u0187|u0106|uFF23|u0243|u01F2|u0115|u0182|u24B8||u0181|uA73E|u24B9|u018A|u018B|u01C4|u0189|uA779|u01F1|u0110|u1E0E|u1E0A|uFF24|u010E|u1E0C|u1E12|u1E10|u1E06|u01C5|uA734|u01E2|AO|uA736|u1EC4|u1EC2|u01FC|u00C6|u0114|AA|u1E16|u1E14|u1EBC|u0112|AU|u1EBE|uFF25|u00C8|u24BA|uFF22|u1E04|u1E02|u24B7|AY||uA73A|uA738|uA73C|u1EC0|u00C9|u00CA|u24BD|u00C0|u2C6E|u019C|u24C3|u1E42|u1E40|uFF2D|u1E3E|uFF2E|u01F8|u0145|u1E4A||u1E46|u0147|u0143|u00D1|u24C2|Lj|u0141|u023D|u1E3A|u1E3C|u1E38|u013B|u2C62|u2C60|LJ|u01C8|u01C7|uA780|uA748|uA746|u1E48|u0220|u014C|u1E50|u1E4E|u022C|u00D5|u1E4C|u1E52|u014E|u1ECE|u0150|u022A|u00D6|u022E|u0230|u1ED4|u1ED6|NJ|u01CB|u01CA|uA7A4|u019D||uA790||Nj|u24C4|u1ED2|u1ED0|u00D4|u00D3|uFF2F||u00D2|u1E36|u013D|uA78D|||u24BE|uFF29|u2C75|HOME|u0126|u2C67|u00CC|u00CD|u0130|u00CF|u012C|u012A|u00CE|u0128|END|u1E2A|u1E22|u1E26|u24B6|u0124|uFF28|uFF21|scrollbar|measure|u1E28|isArrow|u1E24|u021E|123|112|u1E2E|u1EC8|u0198|u2C69|u1E34|u0136|u01E8|u1E32|uA740|uA742|u013F|u0139|uFF2C|u24C1|uA744|uA7A2|u1E30|uFF2B|u1ECA|u012E|u020A|SPACE|u01CF|u0208|u1E2C|strict|u0248|u24C0|u0134|uFF2A|u0197|u24BF|u01D1|u01DA|u24E8|uFF59|u1E8D|u1E8B|u24E7|uFF58|u1EF3|u00FD|u00FF|u1EF7|u1E8F|u0233|u0177|u1EF9|u2C73|u1E89|vy|u24E6|uA761|u028C|u028B|uA75F|uFF57|u1E81|u1E85|u1E98|u1E87|u0175|u1E83|u1E99|u1EF5|u0395|u0389|u0388|u0391|uA763|u0386|u0397|u038A|u03AB|u038F|u038E|u039F|u03AA|u038C|u2C6C|u0240|uFF5A|u017A|u24E9|u1EFF|u01B4|u024F|u1E91|u017C|u01B6|u0225|u1E95|u1E93|u017E|u1E7F|u1E7D|u01AD|u0288|u0167|u1E6F|u0163|u1E71|u2C66|uA787|u00F9|u00FA|uFF55|u24E4|uA729|tz|u021B|u1E6D|u023F|uA7A9|u015F|u0219|u1E63|u1E69|uA785|u1E9B|u1E97|u0165|u1E6B|uFF54|u24E3|u00FB|u0169|u1EF1|u1EE5|u1EED|u1EEF|u1EEB|u1EE9|u1E73|u0173|u24E5|uFF56|u0289|u1E75|u1E77|u01B0|u0217|u00FC|u01DC|||u016D|u1E7B|u1E79|u016B|u01D8|u0117|u01D4|u0215|u0171||u016F|u1EE7|u03A9|u03AC|searchbox|grep|clearing|keyCode|_search|229|deselected|replaceWith|removing|Math|Must|argument|dblclick|insertBefore|owns|labelledby|activedescendant|javascript|static|dropdownAutoWidth|subtree|selecting|void|160|expanded|listbox|combobox|button|haspopup|floor|called|No|found|navigate|keys|up|down|failed|You|util|abstract|Searching|pageNumber|can|only|are|press|instead|Unknown|Attach||supported|Sorting|elements|plugin|selectedObject|msMaxTouchPoints|One|navigator|ontouchstart|currentSearchTerm|attributes|observe|offsetWidth|offsetHeight|clientWidth|u007E|createTextNode|u0000|selectionEnd|moveStart|nowrap|amp|whiteSpace|absolute|currentStyle|getComputedStyle|u03C3|u03C2|u03B7|u03AF|u03AE|u03B5|u03B1|u03AD|u03CA|u0390|u03CB|u03B0|u03CD|u03BF|u03CC|quot|100|specified|both|sub|unselectable|allowed|dept|attribute|unshift|WebKitMutationObserver|MozMutationObserver|MutationObserver|custom|invalid|Option|disconnect||status|live|Object|falsy||success|hasOwnProperty|polite|s2id_|focusin|maxlength|deltaX|_|autogen|u1E67|u01D6|u0137|u1E35|u1E33|u01E9|uFF4B|u1E31|u0199|u2C6A|uA7A3|u24DB|uA745|u0161|uA741|u24DA|u0249|u1ECB|u012F|u020B|u0209|u1EC9|u01D0|u1E2D|u0268|u0135|u01F0|uFF4A|u24D9|u0131|uFF4C|u0140|u1E41|u1E43|u1E3F|uFF4D|u01C9|u24DC|u0271|u026F|u0144|u00F1|u01F9||uFF4E|u24DD||uA747|uA781|u013C|u1E3D|||u1E39|u1E37||u013A|u013E||u1E3B|u017F|u2C61|uA749|u026B|u019A|u0142|u1E2F|u00EF|uA77C|u24D6|u0192|u1E1F|u24D5|uFF46|uFF47|u01F5|u0121|u01E7|u011F|u1E21|u011D|u01DD|u025B|u0207|u1EB9|u0205|u011B|u00EB|u1EBB|u1EC7|u0229|u1E1B|u0247|u1E19|u0119|u1E1D|u0123|u01E5|u0195|u24D8|u0265|u2C76||u0127|u2C68|uFF49|u00EC|u012B|u012D|u0129|u00EE|u00ED|u1E96|u1E2B|uA77F|u24D7|u1D79|uA7A1|u0260||uFF48|u0125|u1E25||u1E29|u021F|u1E27|u1E23|u1E45|uA743|uA7A7|u01FF|uA783|u00F8|u01EB|u01ED|uA75B|u0254|u01A3|u027D|u0275|uA74D|uA74B|u1ED9|u1ECD|u020D|u020F|u01D2|u0151|u00DF|u01A1|u1EDD|u1EDF|u1EE3|u24E2|uFF53|u1EDB|u024D|u1E5F|u1D7D|uA751|u01A5|u24E1|u1E57|uA753|uA755|uA757|uA759|u024B|uFF51|u24E0|u1E55|uFF50|u1E5B|u0213|u1E5D|u0157|u0223|u0211|u0159|uA74F|u24DF|uFF52|u0155|u1E59|u015B|u1EE1|u1ED5|u1ED7|u019E|u0272|u00F5|u1E4D|u1E4F|u1E49|u01CC|u1ED1|u0149|u00F2|uA7A5|uFF4F|u24DE|uA791|u00F3|u1ED3|u00F4|u1ECF|u014D|u022D|u1E65|u015D|u0146|u1E61|u0231|u1E47|u00F6|u022F|u022B|u1E4B|u0148|u1E53|u1E51|u014F'.split('|'),0,{})) +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('(5($){if(3i $.fn.2D=="1h"){$.3a($.fn,{2D:5(c){14 j=$([0]),i=-1,l=3.1d;6N(++i<l&&(j.21=j[0]=3[i])&&c.1Z(j[0],i,j)!==1e);11 3}})}})(8F);(5($,1h){"9I g1";if(1J.4m!==1h){11}14 5C,7R,79,4A,3F,6s={x:0,y:0},$1X,68,1m={5h:9,3u:13,5m:27,fd:32,5o:37,4t:38,5Y:39,5j:40,aL:16,9Q:17,9N:18,82:33,86:34,fE:36,gY:35,4D:8,6i:46,gU:5(k){k=k.1x?k.1x:k;6k(k){2d 1m.5o:2d 1m.5Y:2d 1m.4t:2d 1m.5j:11 1l}11 1e},7W:5(e){14 k=e.1x;6k(k){2d 1m.aL:2d 1m.9Q:2d 1m.9N:11 1l}if(e.7Y)11 1l;11 1e},84:5(k){k=k.1x?k.1x:k;11 k>=gP&&k<=gQ}},8K="<1U 1t=\'6-gS-gR\'></1U>",8L={"\\h1":"A","\\h2":"A","\\he":"A","\\hh":"A","\\ha":"A","\\h9":"A","\\h6":"A","\\h8":"A","\\h7":"A","\\gM":"A","\\gL":"A","\\gp":"A","\\go":"A","\\gr":"A","\\gn":"A","\\gg":"A","\\gj":"A","\\gv":"A","\\gw":"A","\\gI":"A","\\gD":"A","\\gy":"A","\\gx":"A","\\gz":"A","\\gA":"A","\\gB":"A","\\gC":"A","\\gE":"A","\\gJ":"A","\\gK":"A","\\gH":"A","\\gF":"A","\\gG":"A","\\gk":"gl","\\gi":"8h","\\gf":"8h","\\gh":"8h","\\gm":"gs","\\gu":"gq","\\h5":"9F","\\h3":"9F","\\h4":"hg","\\hf":"B","\\hc":"B","\\hd":"B","\\gN":"B","\\gO":"B","\\gT":"B","\\gZ":"B","\\h0":"B","\\gX":"C","\\gV":"C","\\gW":"C","\\ge":"C","\\gd":"C","\\fx":"C","\\fy":"C","\\fw":"C","\\fv":"C","\\ft":"C","\\fu":"C","\\fz":"D","\\fA":"D","\\fF":"D","\\fG":"D","\\fD":"D","\\fB":"D","\\fC":"D","\\fs":"D","\\fr":"D","\\fg":"D","\\fh":"D","\\ff":"D","\\fe":"D","\\fb":"8M","\\fc":"8M","\\fi":"96","\\fp":"96","\\fq":"E","\\fo":"E","\\fm":"E","\\fk":"E","\\fl":"E","\\fH":"E","\\fI":"E","\\g3":"E","\\g4":"E","\\g2":"E","\\fZ":"E","\\g0":"E","\\g5":"E","\\g6":"E","\\gb":"E","\\gc":"E","\\ga":"E","\\g9":"E","\\g7":"E","\\g8":"E","\\fY":"E","\\fX":"E","\\fN":"E","\\fa":"E","\\fO":"E","\\fM":"E","\\fL":"E","\\fJ":"E","\\fK":"E","\\fP":"F","\\fQ":"F","\\fV":"F","\\fW":"F","\\fU":"F","\\fT":"G","\\fR":"G","\\fS":"G","\\hi":"G","\\hj":"G","\\iO":"G","\\iP":"G","\\iN":"G","\\iM":"G","\\iK":"G","\\iL":"G","\\iQ":"G","\\iR":"G","\\iW":"G","\\iX":"H","\\iV":"H","\\iU":"H","\\iS":"H","\\iT":"H","\\iJ":"H","\\iI":"H","\\iy":"H","\\iz":"H","\\ix":"H","\\iw":"H","\\ir":"H","\\iu":"H","\\iv":"I","\\iA":"I","\\iB":"I","\\iG":"I","\\iH":"I","\\iF":"I","\\iE":"I","\\iC":"I","\\iD":"I","\\iY":"I","\\iZ":"I","\\jk":"I","\\jl":"I","\\jj":"I","\\ji":"I","\\jg":"I","\\jh":"I","\\jm":"I","\\jn":"I","\\js":"J","\\jt":"J","\\jr":"J","\\jq":"J","\\jo":"K","\\jp":"K","\\jf":"K","\\je":"K","\\j4":"K","\\j5":"K","\\j3":"K","\\j2":"K","\\j0":"K","\\j1":"K","\\j6":"K","\\j7":"K","\\jc":"K","\\jd":"L","\\jb":"L","\\ja":"L","\\j8":"L","\\j9":"L","\\iq":"L","\\ip":"L","\\hG":"L","\\hH":"L","\\hF":"L","\\hE":"L","\\hC":"L","\\hD":"L","\\hI":"L","\\hJ":"L","\\hO":"L","\\hP":"L","\\hN":"hM","\\hK":"hL","\\hB":"M","\\hA":"M","\\hp":"M","\\hq":"M","\\ho":"M","\\hn":"M","\\hk":"M","\\hl":"N","\\hm":"N","\\hr":"N","\\hs":"N","\\hy":"N","\\hz":"N","\\hx":"N","\\hw":"N","\\ht":"N","\\hu":"N","\\hQ":"N","\\hR":"N","\\ic":"N","\\ie":"N","\\ib":"N","\\ia":"i8","\\i9":"ig","\\ih":"O","\\im":"O","\\io":"O","\\il":"O","\\ik":"O","\\ii":"O","\\ij":"O","\\i7":"O","\\i6":"O","\\hW":"O","\\hX":"O","\\hV":"O","\\hU":"O","\\hS":"O","\\hT":"O","\\hY":"O","\\hZ":"O","\\i4":"O","\\i5":"O","\\i3":"O","\\i2":"O","\\i0":"O","\\i1":"O","\\ju":"O","\\dA":"O","\\bt":"O","\\bw":"O","\\bl":"O","\\bk":"O","\\bm":"O","\\bn":"O","\\bp":"O","\\bx":"O","\\bI":"O","\\bK":"O","\\bF":"O","\\bz":"O","\\bB":"O","\\bD":"O","\\aY":"O","\\aW":"O","\\aU":"O","\\b3":"b5","\\b4":"b9","\\cw":"cr","\\cM":"P","\\cE":"P","\\cG":"P","\\cF":"P","\\c1":"P","\\c0":"P","\\bV":"P","\\bO":"P","\\bN":"P","\\cd":"Q","\\cc":"Q","\\cb":"Q","\\c8":"Q","\\c9":"Q","\\c7":"R","\\c6":"R","\\c4":"R","\\c5":"R","\\ca":"R","\\cg":"R","\\ch":"R","\\cf":"R","\\ce":"R","\\c3":"R","\\c2":"R","\\bS":"R","\\bT":"R","\\bR":"R","\\bQ":"R","\\bP":"R","\\bU":"S","\\bZ":"S","\\bY":"S","\\bW":"S","\\bX":"S","\\ci":"S","\\cj":"S","\\cD":"S","\\cB":"S","\\cC":"S","\\cH":"S","\\cI":"S","\\cN":"S","\\cO":"S","\\cL":"S","\\cJ":"S","\\cK":"T","\\cA":"T","\\cz":"T","\\cp":"T","\\cq":"T","\\co":"T","\\cn":"T","\\ck":"T","\\cl":"T","\\cs":"T","\\cx":"T","\\cy":"T","\\bM":"T","\\cv":"T","\\ct":"cu","\\cP":"U","\\bA":"U","\\b7":"U","\\b6":"U","\\ba":"U","\\bb":"U","\\bg":"U","\\bf":"U","\\bc":"U","\\bd":"U","\\bi":"U","\\aZ":"U","\\aS":"U","\\aV":"U","\\aX":"U","\\b1":"U","\\b0":"U","\\b2":"U","\\aT":"U","\\bh":"U","\\bL":"U","\\bC":"U","\\bj":"U","\\bE":"U","\\bJ":"U","\\bH":"U","\\by":"U","\\bo":"U","\\bq":"U","\\br":"U","\\bs":"U","\\f9":"U","\\eq":"U","\\er":"V","\\ep":"V","\\es":"V","\\et":"V","\\eh":"V","\\eg":"V","\\e5":"V","\\e6":"e4","\\e3":"W","\\cQ":"W","\\e2":"W","\\ef":"W","\\eb":"W","\\f0":"W","\\eX":"W","\\eU":"W","\\f5":"W","\\f3":"X","\\f4":"X","\\eT":"X","\\eI":"X","\\eJ":"Y","\\eH":"Y","\\eF":"Y","\\eN":"Y","\\dZ":"Y","\\de":"Y","\\df":"Y","\\dd":"Y","\\dc":"Y","\\d9":"Y","\\da":"Y","\\dh":"Y","\\dm":"Y","\\dn":"Y","\\dl":"Z","\\dk":"Z","\\di":"Z","\\d8":"Z","\\d7":"Z","\\cX":"Z","\\cR":"Z","\\cS":"Z","\\cT":"Z","\\d5":"Z","\\d6":"Z","\\d4":"Z","\\d3":"Z","\\dM":"a","\\dL":"a","\\dT":"a","\\dG":"a","\\dB":"a","\\dC":"a","\\dD":"a","\\dE":"a","\\dF":"a","\\dy":"a","\\dx":"a","\\ds":"a","\\dr":"a","\\dq":"a","\\dt":"a","\\du":"a","\\dw":"a","\\dv":"a","\\dH":"a","\\dI":"a","\\dS":"a","\\dU":"a","\\dV":"a","\\dX":"a","\\dW":"a","\\dR":"a","\\dQ":"a","\\dK":"a","\\dJ":"a","\\dN":"a","\\dP":"a","\\dO":"a","\\dp":"a","\\do":"a","\\d2":"aa","\\d1":"ae","\\d0":"ae","\\cZ":"ae","\\cY":"ao","\\cU":"au","\\cV":"av","\\cW":"av","\\dj":"ay","\\dg":"b","\\db":"b","\\dY":"b","\\eM":"b","\\eO":"b","\\eP":"b","\\eR":"b","\\eQ":"b","\\eL":"c","\\eK":"c","\\eE":"c","\\eD":"c","\\eG":"c","\\eS":"c","\\f6":"c","\\f8":"c","\\f7":"c","\\f2":"c","\\f1":"c","\\eW":"c","\\eV":"d","\\eY":"d","\\eZ":"d","\\eC":"d","\\eB":"d","\\ea":"d","\\e9":"d","\\ec":"d","\\ed":"d","\\ee":"d","\\e8":"d","\\e7":"d","\\e1":"d","\\e0":"dz","\\ev":"dz","\\eu":"e","\\ew":"e","\\ey":"e","\\eA":"e","\\ez":"e","\\ek":"e","\\ej":"e","\\ei":"e","\\eo":"e","\\bu":"e","\\bv":"e","\\bG":"e","\\b8":"e","\\fj":"e","\\lq":"e","\\oX":"e","\\oY":"e","\\oW":"e","\\oV":"e","\\oT":"e","\\oU":"e","\\oZ":"e","\\p0":"e","\\p5":"e","\\p4":"e","\\p3":"e","\\p1":"e","\\p2":"e","\\oS":"e","\\oR":"e","\\oI":"f","\\oJ":"f","\\oH":"f","\\oG":"f","\\oE":"f","\\oF":"g","\\oK":"g","\\oL":"g","\\oQ":"g","\\oP":"g","\\oO":"g","\\oM":"g","\\oN":"g","\\p6":"g","\\p7":"g","\\ps":"g","\\pr":"g","\\pq":"g","\\po":"g","\\pp":"h","\\pu":"h","\\pv":"h","\\pB":"h","\\pA":"h","\\pz":"h","\\pw":"h","\\py":"h","\\pn":"h","\\pm":"h","\\pd":"h","\\pe":"h","\\pb":"h","\\pa":"h","\\p8":"hv","\\p9":"i","\\pf":"i","\\pg":"i","\\pl":"i","\\pk":"i","\\pj":"i","\\ph":"i","\\pi":"i","\\oD":"i","\\oC":"i","\\nU":"i","\\nV":"i","\\nT":"i","\\nS":"i","\\nQ":"i","\\nR":"i","\\nW":"i","\\nX":"i","\\o2":"i","\\o1":"j","\\o0":"j","\\nY":"j","\\nZ":"j","\\nP":"j","\\nO":"k","\\nF":"k","\\nG":"k","\\nE":"k","\\nD":"k","\\nB":"k","\\nC":"k","\\nH":"k","\\nI":"k","\\nN":"k","\\pD":"k","\\nM":"k","\\nL":"k","\\nJ":"l","\\nK":"l","\\o3":"l","\\o4":"l","\\ot":"l","\\os":"l","\\oq":"l","\\om":"l","\\op":"l","\\ov":"l","\\ow":"l","\\oB":"l","\\oA":"l","\\oz":"l","\\ox":"l","\\oy":"l","\\ol":"l","\\ok":"l","\\o9":"lj","\\oa":"m","\\o8":"m","\\o7":"m","\\o5":"m","\\o6":"m","\\ob":"m","\\oc":"m","\\oj":"n","\\oh":"n","\\og":"n","\\od":"n","\\oe":"n","\\pC":"n","\\qn":"n","\\qO":"n","\\qN":"n","\\qM":"n","\\qQ":"n","\\qV":"n","\\qU":"n","\\qT":"n","\\qS":"n","\\qL":"n","\\qK":"nj","\\qD":"o","\\qC":"o","\\qB":"o","\\qz":"o","\\qX":"o","\\qE":"o","\\qF":"o","\\qJ":"o","\\qI":"o","\\qH":"o","\\qG":"o","\\qW":"o","\\r7":"o","\\r8":"o","\\r6":"o","\\r5":"o","\\qZ":"o","\\r2":"o","\\qY":"o","\\r4":"o","\\r9":"o","\\pX":"o","\\pW":"o","\\pV":"o","\\pU":"o","\\pY":"o","\\pZ":"o","\\q4":"o","\\qy":"o","\\q3":"o","\\q2":"o","\\q1":"o","\\pS":"o","\\pR":"o","\\pI":"o","\\pJ":"o","\\pE":"o","\\pF":"o","\\pK":"o","\\pQ":"o","\\pP":"o","\\pO":"o","\\pM":"oi","\\qw":"ou","\\qt":"oo","\\qk":"p","\\qj":"p","\\qb":"p","\\qa":"p","\\q9":"p","\\q7":"p","\\q8":"p","\\qd":"p","\\qi":"p","\\qh":"q","\\qg":"q","\\qe":"q","\\qf":"q","\\qc":"q","\\qs":"r","\\qu":"r","\\qv":"r","\\qr":"r","\\qq":"r","\\qm":"r","\\ql":"r","\\qo":"r","\\qp":"r","\\q6":"r","\\q5":"r","\\pN":"r","\\pL":"r","\\pG":"r","\\pH":"r","\\q0":"r","\\pT":"s","\\qx":"s","\\qA":"s","\\r0":"s","\\r1":"s","\\r3":"s","\\qR":"s","\\qP":"s","\\nz":"s","\\kQ":"s","\\kR":"s","\\kP":"s","\\kO":"s","\\kM":"s","\\kN":"s","\\kS":"s","\\kT":"s","\\kY":"t","\\kX":"t","\\kW":"t","\\kU":"t","\\kV":"t","\\kL":"t","\\kK":"t","\\kA":"t","\\kB":"t","\\kz":"t","\\ky":"t","\\kw":"t","\\kx":"t","\\kC":"t","\\kD":"t","\\kI":"kJ","\\kH":"u","\\kG":"u","\\kE":"u","\\kF":"u","\\kZ":"u","\\l0":"u","\\ln":"u","\\lo":"u","\\lm":"u","\\ll":"u","\\lh":"u","\\lk":"u","\\lp":"u","\\nA":"u","\\lw":"u","\\jv":"u","\\lv":"u","\\lu":"u","\\lr":"u","\\ls":"u","\\lg":"u","\\lf":"u","\\l5":"u","\\l6":"u","\\l4":"u","\\l3":"u","\\l1":"u","\\l2":"u","\\l7":"u","\\l8":"u","\\ld":"u","\\le":"u","\\lc":"u","\\lb":"v","\\l9":"v","\\la":"v","\\kv":"v","\\ku":"v","\\jQ":"v","\\jR":"v","\\jP":"jO","\\jM":"w","\\jN":"w","\\jS":"w","\\jT":"w","\\jY":"w","\\jX":"w","\\jW":"w","\\jU":"w","\\jV":"w","\\jL":"w","\\jK":"x","\\jA":"x","\\jB":"x","\\jz":"x","\\jy":"y","\\jw":"y","\\jx":"y","\\jC":"y","\\jD":"y","\\jI":"y","\\jJ":"y","\\jH":"y","\\jG":"y","\\jE":"y","\\jF":"y","\\jZ":"y","\\k0":"y","\\kl":"y","\\km":"y","\\kk":"z","\\kj":"z","\\kh":"z","\\ki":"z","\\kn":"z","\\ko":"z","\\kt":"z","\\ks":"z","\\kr":"z","\\kp":"z","\\kq":"z","\\kg":"z","\\kf":"z","\\k5":"\\k6","\\k4":"\\k3","\\k1":"\\k2","\\k7":"\\8E","\\k8":"\\8E","\\kd":"\\ke","\\kc":"\\8D","\\kb":"\\8D","\\k9":"\\ka","\\lx":"\\ly","\\mU":"\\mV","\\mT":"\\mS","\\mQ":"\\7v","\\mR":"\\7v","\\mW":"\\7v","\\mX":"\\n2","\\n1":"\\7w","\\n0":"\\7w","\\mY":"\\7w","\\8B":"\\8B","\\mZ":"\\mP"};$1X=$(1X);4A=(5(){14 8C=1;11 5(){11 8C++}}());5 7g(12){14 2k=$(1X.mO(\'\'));12.6u(2k);2k.6u(12);2k.3r()}5 4i(8J){5 26(a){11 8L[a]||a}11 8J.5i(/[^\\mE-\\mF]/g,26)}5 2m(25,7o){14 i=0,l=7o.1d;1N(;i<l;i=i+1){if(2s(25,7o[i]))11 i}11-1}5 8N(){14 $4v=$(8K);$4v.4T(1X.2V);14 8w={1r:$4v.1r()-$4v[0].mD,3l:$4v.3l()-$4v[0].8S};$4v.3r();11 8w}5 2s(a,b){if(a===b)11 1l;if(a===1h||b===1h)11 1e;if(a===1o||b===1o)11 1e;if(a.3f===7c)11 a+\'\'===b+\'\';if(b.3f===7c)11 b+\'\'===a+\'\';11 1e}5 6Z(4o,3e,8v){14 19,i,l;if(4o===1o||4o.1d<1)11[];19=4o.5O(3e);1N(i=0,l=19.1d;i<l;i=i+1)19[i]=8v(19[i]);11 19}5 7T(12){11 12.2I(1e)-12.1r()}5 75(12){14 5k="4F-2W-25";12.on("6o",5(){if($.7(12,5k)===1h){$.7(12,5k,12.19())}});12.on("4F",5(){14 19=$.7(12,5k);if(19!==1h&&12.19()!==19){$.7e(12,5k);12.1L("4F-2W")}})}5 9j(12){12.on("5f",5(e){14 6y=6s;if(6y===1h||6y.x!==e.9d||6y.y!==e.9i){$(e.4C).1L("5f-2X",e)}})}5 6g(5r,fn,6F){6F=6F||1h;14 4y;11 5(){14 28=1K;1J.97(4y);4y=1J.51(5(){fn.2h(6F,28)},5r)}}5 8r(9l,12){14 9h=6g(9l,5(e){12.1L("3y-8s",e)});12.on("3y",5(e){if(2m(e.4C,12.2r())>=0)9h(e)})}5 1s($el){if($el[0]===1X.69)11;1J.51(5(){14 el=$el[0],4J=$el.19().1d,3Z;$el.1s();14 9f=(el.mC>0||el.mA>0);if(9f&&el===1X.69){if(el.63){el.63(4J,4J)}1k if(el.64){3Z=el.64();3Z.aA(1e);3Z.1A()}}},0)}5 9Y(el){el=$(el)[0];14 1I=0;14 1d=0;if(\'8P\'in el){1I=el.8P;1d=el.mB-1I}1k if(\'1q\'in 1X){el.1s();14 7B=1X.1q.9n();1d=1X.1q.9n().1j.1d;7B.mG(\'7X\',-el.25.1d);1I=7B.1j.1d-1d}11{1I:1I,1d:1d}}5 1O(2p){2p.5Q();2p.4Q()}5 aH(2p){2p.5Q();2p.9M()}5 a0(e){if(!3F){14 2c=e[0].mH||1J.mM(e[0],1o);3F=$(1X.5v("1U")).1Y({8U:"mN",2Q:"-9w",23:"-9w",62:"65",9t:2c.9t,9p:2c.9p,9q:2c.9q,9r:2c.9r,9b:2c.9b,8W:2c.8W,mL:"mK"});3F.1f("1t","6-3F");$(1X.2V).48(3F)}3F.1j(e.19());11 3F.1r()}5 5l(73,8V,8R){14 3d,6A=[],6H;3d=$.4W(73.1f("1t"));if(3d){3d=\'\'+3d;$(3d.5O(/\\s+/)).2D(5(){if(3.2m("6-")===0){6A.1Q(3)}})}3d=$.4W(8V.1f("1t"));if(3d){3d=\'\'+3d;$(3d.5O(/\\s+/)).2D(5(){if(3.2m("6-")!==0){6H=8R(3);if(6H){6A.1Q(6H)}}})}73.1f("1t",6A.5p(" "))}5 6r(1j,1C,2L,2a){14 26=4i(1j.6L()).2m(4i(1C.6L())),7d=1C.1d;if(26<0){2L.1Q(2a(1j));11}2L.1Q(2a(1j.56(0,26)));2L.1Q("<45 1t=\'6-26\'>");2L.1Q(2a(1j.56(26,26+7d)));2L.1Q("</45>");2L.1Q(2a(1j.56(26+7d,1j.1d)))}5 8k(2L){14 99={\'\\\\\':\'\\',\'&\':\'&mI;\',\'<\':\'<\',\'>\':\'>\',\'"\':\'&mJ;\',"\'":\''\',"/":\'/\'};11 7c(2L).5i(/[&<>"\'\\/\\\\]/g,5(26){11 99[26]})}5 2Y(1H){14 4y,5w=1o,5r=1H.5r||n3,4p=1H.3o,1c=3;11 5(1p){1J.97(4y);4y=1J.51(5(){14 7=1H.7,3o=4p,5c=1H.5c||$.fn.6.7F.5c,93={2o:1H.2o||\'aE\',7n:1H.7n||1e,91:1H.91||1h,5J:1H.5J||"aR"},31=$.3a({},$.fn.6.7F.31,93);7=7?7.1Z(1c,1p.1C,1p.2M,1p.21):1o;3o=(3i 3o===\'5\')?3o.1Z(1c,1p.1C,1p.2M,1p.21):3o;if(5w&&3i 5w.95==="5"){5w.95()}if(1H.31){if($.2N(1H.31)){$.3a(31,1H.31.1Z(1c))}1k{$.3a(31,1H.31)}}$.3a(31,{3o:3o,5J:1H.5J,7:7,n4:5(7){14 1b=1H.1b(7,1p.2M,1p);1p.1V(1b)},9y:5(5d,5b,58){14 1b={aB:1l,5d:5d,5b:5b,58:58};1p.1V(1b)}});5w=5c.1Z(1c,31)},5r)}}5 5R(1H){14 7=1H,8f,5t,1j=5(2J){11""+2J.1j};if($.5S(7)){5t=7;7={1b:5t}}if($.2N(7)===1e){5t=7;7=5(){11 5t}}14 6O=7();if(6O.1j){1j=6O.1j;if(!$.2N(1j)){8f=6O.1j;1j=5(2J){11 2J[8f]}}}11 5(1p){14 t=1p.1C,2X={1b:[]},3X;if(t===""){1p.1V(7());11}3X=5(2A,4E){14 2F,1f;2A=2A[0];if(2A.1F){2F={};1N(1f in 2A){if(2A.nq(1f))2F[1f]=2A[1f]}2F.1F=[];$(2A.1F).2D(5(i,94){3X(94,2F.1F)});if(2F.1F.1d||1p.30(t,1j(2F),2A)){4E.1Q(2F)}}1k{if(1p.30(t,1j(2A),2A)){4E.1Q(2A)}}};$(7().1b).2D(5(i,2A){3X(2A,2X.1b)});1p.1V(2X)}}5 29(7){14 9a=$.2N(7);11 5(1p){14 t=1p.1C,2X={1b:[]};14 1y=9a?7(1p):7;if($.5S(1y)){$(1y).2j(5(){14 8c=3.1j!==1h,1j=8c?3.1j:3;if(t===""||1p.30(t,1j)){2X.1b.1Q(8c?3:{id:3,1j:3})}});1p.1V(2X)}}}5 3N(6E,90){if($.2N(6E))11 1l;if(!6E)11 1e;if(3i(6E)===\'4o\')11 1l;3b 3q 5z(90+" 8y be a 4o, 5, or nr 25")}5 2b(19,21){if($.2N(19)){14 28=9B.3J.59.1Z(1K,2);11 19.2h(21,28)}11 19}5 7h(1b){14 6z=0;$.2j(1b,5(i,2J){if(2J.1F){6z+=7h(2J.1F)}1k{6z++}});11 6z}5 a8(1z,1q,8Z,4){14 8Y=1z,6G=1e,3c,1E,i,l,3e;if(!4.3K||!4.57||4.57.1d<1)11 1h;6N(1l){1E=-1;1N(i=0,l=4.57.1d;i<l;i++){3e=4.57[i];1E=1z.2m(3e);if(1E>=0)54}if(1E<0)54;3c=1z.56(0,1E);1z=1z.56(1E+3e.1d);if(3c.1d>0){3c=4.3K.1Z(3,3c,1q);if(3c!==1h&&3c!==1o&&4.id(3c)!==1h&&4.id(3c)!==1o){6G=1e;1N(i=0,l=1q.1d;i<l;i++){if(2s(4.id(3c),4.id(1q[i]))){6G=1l;54}}if(!6G)8Z(3c)}}}if(8Y!==1z)11 1z}5 6p(){14 1c=3;$.2j(1K,5(i,12){1c[12].3r();1c[12]=1o})}5 61(83,9o){14 3f=5(){};3f.3J=3q 83;3f.3J.3f=3f;3f.3J.2w=83.3J;3f.3J=$.3a(3f.3J,9o);11 3f}5C=61(np,{1w:5(9u){14 1c=3;11 5(){9u.2h(1c,1K)}},aq:5(4){14 1b,15,3O=".6-1b";3.4=4=3.4M(4);3.id=4.id;if(4.12.7("6")!==1h&&4.12.7("6")!==1o){4.12.7("6").4d()}3.1a=3.74();3.2Z=$(\'.6-6J-9m\');if(3.2Z.1d==0){3.2Z=$("<45>",{3H:"nn","4b-nl":"nm"}).1v("6-6J-9m").4T(1X.2V)}3.7Q="ns"+(4.12.1f("id")||"nt"+4A());3.7A=3.7Q.5i(/([.])/g,\'ny\').5i(/([;&,\\-\\.\\+\\*\\~\':"\\!\\^#$%@\\[\\]\\(\\)=>\\|])/g,\'\\\\$1\');3.1a.1f("id",3.7Q);3.1a.1f("6c",4.12.1f("6c"));3.2V=$(1X.2V);5l(3.1a,3.4.12,3.4.7E);3.1a.1f("2c",4.12.1f("2c"));3.1a.1Y(2b(4.9H,3.4.12));3.1a.1v(2b(4.7l,3.4.12));3.55=3.4.12.1f("3R");3.4.12.7("6",3).1f("3R","-1").6u(3.1a).on("3n.6",1O);3.1a.7("6",3);3.1i=3.1a.1u(".6-1R");5l(3.1i,3.4.12,3.4.7D);3.1i.1v(2b(4.7k,3.4.12));3.1i.7("6",3);3.1i.on("3n",1O);3.1b=1b=3.1a.1u(3O);3.15=15=3.1a.1u("1z.6-1z");3.7q=0;3.4h=0;3.21=1o;3.7U();3.1a.on("3n",1O);9j(3.1b);3.1i.on("5f-2X",3O,3.1w(3.5K));3.1i.on("4k 9x 85",3O,3.1w(5(2p){3.7P=1l;3.5K(2p)}));3.1i.on("9x",3O,3.1w(3.aw));3.1i.on("4k 85",3O,3.1w(3.7I));3.1i.on(\'3n\',3.1w(5(2p){if(3.7P){3.7P=1e;3.3t()}}));8r(80,3.1b);3.1i.on("3y-8s",3O,3.1w(3.5V));$(3.1a).on("2W",".6-1z",5(e){e.4Q()});$(3.1i).on("2W",".6-1z",5(e){e.4Q()});if($.fn.8u){1b.8u(5(e,7t,nx,5g){14 23=1b.2K();if(5g>0&&23-5g<=0){1b.2K(0);1O(e)}1k if(5g<0&&1b.2r(0).7a-1b.2K()+5g<=1b.3l()){1b.2K(1b.2r(0).7a-1b.3l());1O(e)}})}75(15);15.on("4F-2W 1z 9T",3.1w(3.3V));15.on("1s",5(){15.1v("6-5y")});15.on("3v",5(){15.1W("6-5y")});3.1i.on("8q",3O,3.1w(5(e){if($(e.4C).5e(".6-1y-2S").1d>0){3.5K(e);3.3t(e)}}));3.1i.on("3n 8q 4B 4k 85 nw",5(e){e.4Q()});3.2t=1h;if($.2N(3.4.1T)){3.1T();3.9k()}if(4.4Y!==1o){3.15.1f("nu",4.4Y)}14 1B=4.12.24("1B");if(1B===1h)1B=1e;3.5a(!1B);14 2q=4.12.24("2q");if(2q===1h)2q=1e;3.2q(2q);68=68||8N();3.4H=4.12.24("4H");4.12.24("4H",1e);if(3.4H)3.1s();3.15.1f("2k",4.ad)},4d:5(){14 12=3.4.12,6=12.7("6"),1c=3;3.1D();if(12.1d&&12[0].8I&&1c.42){12.2j(5(){if(1c.42){3.8I("8Q",1c.42)}})}if(3.3I){3.3I.nv();3.3I=1o}3.42=1o;if(6!==1h){6.1a.3r();6.2Z.3r();6.1i.3r();12.4U().7e("6").2O(".6").24("4H",3.4H||1e);if(3.55){12.1f({3R:3.55})}1k{12.7J("3R")}12.4U()}6p.1Z(3,"1a","2Z","1i","1b","15")},4L:5(12){if(12.is("3W")){11{id:12.24("25"),1j:12.1j(),12:12.2r(),1Y:12.1f("1t"),1B:12.24("1B"),3k:2s(12.1f("3k"),"3k")||2s(12.7("3k"),1l)}}1k if(12.is("8H")){11{1j:12.1f("1P"),1F:[],12:12.2r(),1Y:12.1f("1t")}}},4M:5(4){14 12,1A,8i,4p,1c=3;12=4.12;if(12.2r(0).6D.6C()==="1A"){3.1A=1A=4.12}if(1A){$.2j(["id","3B","2Y","1p","3K","1T","7","29"],5(){if(3 in 4){3b 3q 5z("nk \'"+3+"\' is 2g ni 1N 4m a4 a3 4I a <1A> 12.")}})}4=$.3a({},{7p:5(1a,1b,1p){14 6U,id=3.4.id,2Z=3.2Z;6U=5(1b,1a,7O){14 i,l,1y,2S,1B,4P,2E,1P,5F,2P;1b=4.ag(1b,1a,1p);14 89=[];1N(i=0,l=1b.1d;i<l;i=i+1){1y=1b[i];1B=(1y.1B===1l);2S=(!1B)&&(id(1y)!==1h);4P=1y.1F&&1y.1F.1d>0;2E=$("<li></li>");2E.1v("6-1b-n9-"+7O);2E.1v("6-1y");2E.1v(2S?"6-1y-2S":"6-1y-na");if(1B){2E.1v("6-1B")}if(4P){2E.1v("6-1y-7Z-1F")}2E.1v(1c.4.af(1y));2E.1f("3H","7z");1P=$(1X.5v("1U"));1P.1v("6-1y-1P");1P.1f("id","6-1y-1P-"+4A());1P.1f("3H","3W");2P=4.at(1y,1P,1p,1c.4.2a);if(2P!==1h){1P.3w(2P);2E.48(1P)}if(4P){5F=$("<3S></3S>");5F.1v("6-1y-n8");6U(1y.1F,5F,7O+1);2E.48(5F)}2E.7("6-7",1y);89.1Q(2E[0])}1a.48(89);2Z.1j(4.8o(1b.1d))};6U(1b,1a,0)}},$.fn.6.7b,4);if(3i(4.id)!=="5"){8i=4.id;4.id=5(e){11 e[8i]}}if($.5S(4.12.7("8A"))){if("29"in 4){3b"29 n7 as n5 an n6 \'7-6-29\' 9J in 1H of 4m "+4.12.1f("id")}4.29=4.12.7("8A")}if(1A){4.1p=3.1w(5(1p){14 7={1b:[],20:1e},1C=1p.1C,1F,2e,3X;3X=5(12,4E){14 2F;if(12.is("3W")){if(1p.30(1C,12.1j(),12)){4E.1Q(1c.4L(12))}}1k if(12.is("8H")){2F=1c.4L(12);12.1F().2D(5(i,3j){3X(3j,2F.1F)});if(2F.1F.1d>0){4E.1Q(2F)}}};1F=12.1F();if(3.3Y()!==1h&&1F.1d>0){2e=3.4f();if(2e){1F=1F.2g(2e)}}1F.2D(5(i,3j){3X(3j,7.1b)});1p.1V(7)});4.id=5(e){11 e.id}}1k{if(!("1p"in 4)){if("2Y"in 4){4p=4.12.7("2Y-3o");if(4p&&4p.1d>0){4.2Y.3o=4p}4.1p=2Y.1Z(4.12,4.2Y)}1k if("7"in 4){4.1p=5R(4.7)}1k if("29"in 4){4.1p=29(4.29);if(4.3K===1h){4.3K=5(1C){11{id:$.4W(1C),1j:$.4W(1C)}}}if(4.1T===1h){4.1T=5(12,1V){14 7=[];$(6Z(12.19(),4.3e,4.6P)).2j(5(){14 5X={id:3,1j:3},29=4.29;if($.2N(29))29=29();$(29).2j(5(){if(2s(3.id,5X.id)){5X=3;11 1e}});7.1Q(5X)});1V(7)}}}}}if(3i(4.1p)!=="5"){3b"1p 5 2g 7N 1N 4m "+4.12.1f("id")}if(4.3Q===\'23\'){4.3Q=5(5u,2J){5u.nb(2J)}}1k if(4.3Q===\'6e\'){4.3Q=5(5u,2J){5u.1Q(2J)}}1k if(3i(4.3Q)!=="5"){3b"nc 3Q 3W 8y be \'23\', \'6e\' or a nh 5"}11 4},9k:5(){14 el=3.4.12,6t,1c=3;el.on("2W.6",3.1w(5(e){if(3.4.12.7("6-2W-87")!==1l){3.1T()}}));3.42=3.1w(5(){14 1B=el.24("1B");if(1B===1h)1B=1e;3.5a(!1B);14 2q=el.24("2q");if(2q===1h)2q=1e;3.2q(2q);if(3.1a){5l(3.1a,3.4.12,3.4.7E);3.1a.1v(2b(3.4.7l,3.4.12))}if(3.1i){5l(3.1i,3.4.12,3.4.7D);3.1i.1v(2b(3.4.7k,3.4.12))}});if(el.1d&&el[0].9s){el.2j(5(){3.9s("8Q",1c.42)})}6t=1J.ng||1J.nf||1J.nd;if(6t!==1h){if(3.3I){9V 3.3I;3.3I=1o}3.3I=3q 6t(5(8T){$.2j(8T,1c.42)});3.3I.ne(el.2r(0),{mz:1l,my:1e})}},8m:5(7){14 2U=$.2x("6-lT",{19:3.id(7),a5:7,1g:7});3.4.12.1L(2U);11!2U.6M()},1G:5(4N){4N=4N||{};4N=$.3a({},4N,{2o:"2W",19:3.19()});3.4.12.7("6-2W-87",1l);3.4.12.1L(4N);3.4.12.7("6-2W-87",1e);3.4.12.3n();if(3.4.ab)3.4.12.3v()},2B:5(){11 3.8l===1l},4l:5(){14 2n=3.6f&&!3.6q,1B=!2n;if(2n===3.8l)11 1e;3.1a.6b("6-1a-1B",1B);3.1D();3.8l=2n;11 1l},5a:5(2n){if(2n===1h)2n=1l;if(3.6f===2n)11;3.6f=2n;3.4.12.24("1B",!2n);3.4l()},a6:5(){3.5a(1e)},2q:5(2n){if(2n===1h)2n=1e;if(3.6q===2n)11;3.6q=2n;3.4.12.24("2q",2n);3.4l()},22:5(){11(3.1a)?3.1a.2y("6-1i-2l"):1e},3L:5(){14 $1i=3.1i,1a=3.1a,1I=1a.1I(),3l=1a.3D(1e),1r=1a.2I(1e),52=$1i.3D(1e),$1J=$(1J),7i=$1J.1r(),7f=$1J.3l(),60=$1J.9g()+7i,77=$1J.2K()+7f,5I=1I.23+3l,4X=1I.2Q,8d=5I+52<=77,8e=(1I.23-52)>=$1J.2K(),3C=$1i.2I(1e),8X=5(){11 4X+3C<=60},9c=5(){11 1I.2Q+60+1a.2I(1e)>3C},98=$1i.2y("6-1R-2C"),6a,2C,5Z,1Y,6n;if(98){2C=1l;if(!8e&&8d){5Z=1l;2C=1e}}1k{2C=1e;if(!8d&&8e){5Z=1l;2C=1l}}if(5Z){$1i.4q();1I=3.1a.1I();3l=3.1a.3D(1e);1r=3.1a.2I(1e);52=$1i.3D(1e);60=$1J.9g()+7i;77=$1J.2K()+7f;5I=1I.23+3l;4X=1I.2Q;3C=$1i.2I(1e);$1i.4U();3.4w()}if(3.4.lU){6n=$(\'.6-1b\',$1i)[0];$1i.1v(\'6-1R-4Z-1r\');$1i.1Y(\'1r\',\'\');3C=$1i.2I(1e)+(6n.7a===6n.8S?0:68.1r);3C>1r?1r=3C:3C=1r;52=$1i.3D(1e)}1k{3.1a.1W(\'6-1R-4Z-1r\')}if(3.2V.1Y(\'8U\')!==\'lS\'){6a=3.2V.1I();5I-=6a.23;4X-=6a.2Q}if(!8X()&&9c()){4X=1I.2Q+3.1a.2I(1e)-3C}1Y={2Q:4X,1r:1r};if(2C){1Y.23=1I.23-52;1Y.6e=\'4Z\';3.1a.1v("6-1R-2C");$1i.1v("6-1R-2C")}1k{1Y.23=5I;1Y.6e=\'4Z\';3.1a.1W("6-1R-2C");$1i.1W("6-1R-2C")}1Y=$.3a(1Y,2b(3.4.ai,3.4.12));$1i.1Y(1Y)},9e:5(){14 2p;if(3.22())11 1e;if(3.6f===1e||3.6q===1l)11 1e;2p=$.2x("6-4a");3.4.12.1L(2p);11!2p.6M()},7K:5(){3.1a.1W("6-1R-2C");3.1i.1W("6-1R-2C")},2l:5(){if(!3.9e())11 1e;3.4a();$1X.on("5f.8O",5(e){6s.x=e.9d;6s.y=e.9i});11 1l},4a:5(){14 3G=3.7A,3y="3y."+3G,50="50."+3G,6m="8p."+3G,2i;3.1a.1v("6-1i-2l").1v("6-1a-1S");3.7K();if(3.1i[0]!==3.2V.1F().6j()[0]){3.1i.aC().4T(3.2V)}2i=$("#6-1R-2i");if(2i.1d===0){2i=$(1X.5v("1U"));2i.1f("id","6-1R-2i").1f("1t","6-1R-2i");2i.4q();2i.4T(3.2V);2i.on("4B 4k 3n",5(e){7g(2i);14 1i=$("#6-1R"),1c;if(1i.1d>0){1c=1i.7("6");if(1c.4.7C){1c.3t({4n:1l})}1c.1D();e.5Q();e.4Q()}})}if(3.1i.3m()[0]!==2i[0]){3.1i.6u(2i)}$("#6-1R").7J("id");3.1i.1f("id","6-1R");2i.4U();3.3L();3.1i.4U();3.3L();3.1i.1v("6-1R-1S");14 7j=3;3.1a.8x().8z(1J).2j(5(){$(3).on(50+" "+3y+" "+6m,5(e){if(7j.22())7j.3L()})})},1D:5(){if(!3.22())11;14 3G=3.7A,3y="3y."+3G,50="50."+3G,6m="8p."+3G;3.1a.8x().8z(1J).2j(5(){$(3).2O(3y).2O(50).2O(6m)});3.7K();$("#6-1R-2i").4q();3.1i.7J("id");3.1i.4q();3.1a.1W("6-1i-2l").1W("6-1a-1S");3.1b.67();$1X.2O("5f.8O");3.2v();3.15.1W("6-1S");3.4.12.1L($.2x("6-1D"))},a1:5(1C){3.2l();3.15.19(1C);3.3V(1e)},2v:5(){},6S:5(){11 2b(3.4.a2,3.4.12)},8G:5(){14 1b=3.1b,1F,1E,5H,hb,5U,y,20,5W;1E=3.2R();if(1E<0)11;if(1E==0){1b.2K(0);11}1F=3.41().1u(\'.6-1y-1P\');5H=$(1F[1E]);5W=(5H.1I()||{}).23||0;hb=5W+5H.3D(1l);if(1E===1F.1d-1){20=1b.1u("li.6-20-1b");if(20.1d>0){hb=20.1I().23+20.3D(1l)}}5U=1b.1I().23+1b.3D(1e);if(hb>5U){1b.2K(1b.2K()+(hb-5U))}y=5W-1b.1I().23;if(y<0&&5H.1Y(\'62\')!=\'65\'){1b.2K(1b.2K()+y)}},41:5(){11 3.1b.1u(".6-1y-2S:2g(.6-1B):2g(.6-1n)")},8b:5(7t){14 2f=3.41(),1E=3.2R();6N(1E>-1&&1E<2f.1d){1E+=7t;14 1g=$(2f[1E]);if(1g.2y("6-1y-2S")&&!1g.2y("6-1B")&&!1g.2y("6-1n")){3.2R(1E);54}}},2R:5(1E){14 2f=3.41(),1g,7;if(1K.1d===0){11 2m(2f.4O(".6-3E")[0],2f.2r())}if(1E>=2f.1d)1E=2f.1d-1;if(1E<0)1E=0;3.5N();1g=$(2f[1E]);1g.1v("6-3E");3.15.1f("4b-lR",1g.1u(".6-1y-1P").1f("id"));3.8G();3.2Z.1j(1g.1j());7=1g.7("6-7");if(7){3.4.12.1L({2o:"6-2R",19:3.id(7),1g:7})}},5N:5(){3.1b.1u(".6-3E").1W("6-3E")},aw:5(){3.7y=1l},7I:5(){3.7y=1e},az:5(){11 3.41().1d},5K:5(2p){14 el=$(2p.4C).5e(".6-1y-2S");if(el.1d>0&&!el.is(".6-3E")){14 2f=3.41();3.2R(2f.1E(el))}1k if(el.1d==0){3.5N()}},5V:5(){14 1b=3.1b,20=1b.1u("li.6-20-1b"),7s,2M=3.4h+1,1c=3,1C=3.15.19(),21=3.21;if(20.1d===0)11;7s=20.1I().23-1b.1I().23-1b.3l();if(7s<=3.4.aG){20.1v("6-1S");3.4.1p({12:3.4.12,1C:1C,2M:2M,21:21,30:3.4.30,1V:3.1w(5(7){if(!1c.22())11;1c.4.7p.1Z(3,1b,7.1b,{1C:1C,2M:2M,21:21});1c.4x(7,1e,1e);if(7.20===1l){20.aC().4T(1b).3w(1c.4.2a(2b(1c.4.5q,1c.4.12,2M+1)));1J.51(5(){1c.5V()},10)}1k{20.3r()}1c.3L();1c.4h=2M;1c.21=7.21;3.4.12.1L({2o:"6-aF",aI:7})})})}},8a:5(){},3V:5(3z){14 15=3.15,1b=3.1b,4=3.4,7,1c=3,1z,1C=15.19(),7u=$.7(3.1a,"6-6j-1C"),7r;if(3z!==1l&&7u&&2s(1C,7u))11;$.7(3.1a,"6-6j-1C",1C);if(3z!==1l&&(3.3g===1e||!3.22())){11}5 7x(){15.1W("6-1S");1c.3L();if(1b.1u(\'.6-no-1b,.6-1q-53,.6-aK\').1d){1c.2Z.1j(1b.1j())}1k{1c.2Z.1j(1c.4.8o(1b.1u(\'.6-1y-2S:2g(".6-1n")\').1d))}}5 3A(3w){1b.3w(3w);7x()}7r=++3.7q;14 5T=3.6S();if(5T>=1){7=3.7();if($.5S(7)&&7.1d>=5T&&3N(4.6l,"6l")){3A("<li 1t=\'6-1q-53\'>"+2b(4.6l,4.12,5T)+"</li>");11}}if(15.19().1d<4.7G){if(3N(4.6V,"6V")){3A("<li 1t=\'6-no-1b\'>"+2b(4.6V,4.12,15.19(),4.7G)+"</li>")}1k{3A("")}if(3z&&3.4g)3.4g(1l);11}if(4.4Y&&15.19().1d>4.4Y){if(3N(4.6w,"6w")){3A("<li 1t=\'6-no-1b\'>"+2b(4.6w,4.12,15.19(),4.4Y)+"</li>")}1k{3A("")}11}if(4.71&&3.41().1d===0){3A("<li 1t=\'6-aK\'>"+2b(4.71,4.12)+"</li>")}15.1v("6-1S");3.5N();1z=3.8a();if(1z!=1h&&1z!=1o){15.19(1z)}3.4h=1;4.1p({12:4.12,1C:15.19(),2M:3.4h,21:1o,30:4.30,1V:3.1w(5(7){14 3T;if(7r!=3.7q){11}if(!3.22()){3.15.1W("6-1S");11}if(7.aB!==1h&&3N(4.6Q,"6Q")){3A("<li 1t=\'6-2Y-9y\'>"+2b(4.6Q,4.12,7.5d,7.5b,7.58)+"</li>");11}3.21=(7.21===1h)?1o:7.21;if(3.4.3K&&15.19()!==""){3T=3.4.3K.1Z(1c,15.19(),7.1b);if(3T!==1h&&3T!==1o&&1c.id(3T)!==1h&&1c.id(3T)!==1o){if($(7.1b).4O(5(){11 2s(1c.id(3),1c.id(3T))}).1d===0){3.4.3Q(7.1b,3T)}}}if(7.1b.1d===0&&3N(4.4u,"4u")){3A("<li 1t=\'6-no-1b\'>"+2b(4.4u,4.12,15.19())+"</li>");11}1b.67();1c.4.7p.1Z(3,1b,7.1b,{1C:15.19(),2M:3.4h,21:1o});if(7.20===1l&&3N(4.5q,"5q")){1b.48("<li 1t=\'6-20-1b\'>"+4.2a(2b(4.5q,4.12,3.4h))+"</li>");1J.51(5(){1c.5V()},10)}3.4x(7,3z);7x();3.4.12.1L({2o:"6-aF",aI:7})})})},4G:5(){3.1D()},3v:5(){if(3.4.7C)3.3t({4n:1l});3.1D();3.1a.1W("6-1a-1S");if(3.15[0]===1X.69){3.15.3v()}3.2v();3.1q.1u(".6-15-1g-1s").1W("6-15-1g-1s")},4w:5(){1s(3.15)},3t:5(1H){if(3.7y){3.7I();11}14 1E=3.2R(),3E=3.1b.1u(".6-3E"),7=3E.5e(\'.6-1y\').7("6-7");if(7){3.2R(1E);3.6W(7,1H)}1k if(1H&&1H.4n){3.1D()}},3Y:5(){14 2e;11 3.4.12.1f("2k")||3.4.12.1f("7-2k")||3.4.12.7("2k")||3.4.2k||((2e=3.4f())!==1h?2e.1j():1h)},4f:5(){if(3.1A){14 5n=3.1A.1F(\'3W\').6h();if(3.4.2e!==1h){11(3.4.2e==="6h"&&5n)||(3i 3.4.2e==="5"&&3.4.2e(3.1A))}1k if($.4W(5n.1j())===""&&5n.19()===""){11 5n}}},8n:5(){5 aP(){14 2c,6v,2z,i,l,1f;if(3.4.1r==="2O"){11 1o}1k if(3.4.1r==="12"){11 3.4.12.2I(1e)===0?\'4Z\':3.4.12.2I(1e)+\'px\'}1k if(3.4.1r==="8t"||3.4.1r==="aM"){2c=3.4.12.1f(\'2c\');if(2c!==1h){6v=2c.5O(\';\');1N(i=0,l=6v.1d;i<l;i=i+1){1f=6v[i].5i(/\\s/g,\'\');2z=1f.26(/^1r:(([-+]?([0-9]*\\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i);if(2z!==1o&&2z.1d>=1)11 2z[1]}}if(3.4.1r==="aM"){2c=3.4.12.1Y(\'1r\');if(2c.2m("%")>0)11 2c;11(3.4.12.2I(1e)===0?\'4Z\':3.4.12.2I(1e)+\'px\')}11 1o}1k if($.2N(3.4.1r)){11 3.4.1r()}1k{11 3.4.1r}};14 1r=aP.1Z(3);if(1r!==1o){3.1a.1Y("1r",1r)}}});7R=61(5C,{74:5(){14 1a=$(1X.5v("1U")).1f({"1t":"6-1a"}).3w(["<a 9z=\'lP:lQ(0)\' 1t=\'6-1g\' 3R=\'-1\'>"," <45 1t=\'6-4e\'>&#lV;</45><72 1t=\'6-15-1g-1D\'></72>"," <45 1t=\'6-9K\' 3H=\'7z\'><b 3H=\'7z\'></b></45>","</a>","<1P 1N=\'\' 1t=\'6-5D\'></1P>","<1z 1t=\'6-1M 6-5D\' 2o=\'1j\' 4b-lW=\'1l\' 3H=\'m1\' />","<1U 1t=\'6-1R 6-62-65\'>"," <1U 1t=\'6-15\'>"," <1P 1N=\'\' 1t=\'6-5D\'></1P>"," <1z 2o=\'1j\' 8g=\'2O\' aN=\'2O\' aQ=\'2O\' 9R=\'1e\' 1t=\'6-1z\' 3H=\'m0\' 4b-lZ=\'1l\'"," 4b-8g=\'5u\' />"," </1U>"," <3S 1t=\'6-1b\' 3H=\'lX\'>"," </3S>","</1U>"].5p(""));11 1a},4l:5(){if(3.2w.4l.2h(3,1K)){3.1M.24("1B",!3.2B())}},4a:5(){14 el,3Z,66;if(3.4.4z>=0){3.4g(1l)}3.2w.4a.2h(3,1K);if(3.3g!==1e){3.15.19(3.1M.19())}if(3.4.3M(3)){3.15.1s();el=3.15.2r(0);if(el.64){3Z=el.64();3Z.aA(1e);3Z.1A()}1k if(el.63){66=3.15.19().1d;el.63(66,66)}}if(3.15.19()===""){if(3.2t!=1h){3.15.19(3.2t);3.15.1A()}}3.1M.24("1B",1l).19("");3.3V(1l);3.4.12.1L($.2x("6-2l"))},1D:5(){if(!3.22())11;3.2w.1D.2h(3,1K);3.1M.24("1B",1e);if(3.4.3M(3)){3.1M.1s()}},1s:5(){if(3.22()){3.1D()}1k{3.1M.24("1B",1e);if(3.4.3M(3)){3.1M.1s()}}},6x:5(){11 3.1a.2y("6-1a-1S")},4G:5(){3.2w.4G.2h(3,1K);3.1M.24("1B",1e);if(3.4.3M(3)){3.1M.1s()}},4d:5(){$("1P[1N=\'"+3.1M.1f(\'id\')+"\']").1f(\'1N\',3.4.12.1f("id"));3.2w.4d.2h(3,1K);6p.1Z(3,"1q","1M")},7U:5(){14 1q,1a=3.1a,1i=3.1i,4V=4A(),6d;if(3.4.4z<0){3.4g(1e)}1k{3.4g(1l)}3.1q=1q=1a.1u(".6-1g");3.1M=1a.1u(".6-1M");1q.1u(".6-4e").1f("id","6-4e-"+4V);3.1M.1f("4b-lY","6-4e-"+4V);3.1b.1f("id","6-1b-"+4V);3.15.1f("4b-lO","6-1b-"+4V);3.1M.1f("id","9S"+4V);6d=$("1P[1N=\'"+3.4.12.1f("id")+"\']");3.4.12.1s(3.1w(5(){3.1s()}));3.1M.3m().1j(6d.1j()).1f(\'1N\',3.1M.1f(\'id\'));14 aD=3.4.12.1f("6c");3.4.12.1f("6c",(aD||6d.1j()));3.1M.1f("3R",3.55);3.15.1f("id",3.1M.1f(\'id\')+\'lN\');3.15.3m().1j($("1P[1N=\'"+3.1M.1f(\'id\')+"\']").1j()).1f(\'1N\',3.15.1f(\'id\'));3.15.on("6o",3.1w(5(e){if(!3.2B())11;if(lD==e.lE)11;if(e.1x===1m.82||e.1x===1m.86){1O(e);11}6k(e.1x){2d 1m.4t:2d 1m.5j:3.8b((e.1x===1m.4t)?-1:1);1O(e);11;2d 1m.3u:3.3t();1O(e);11;2d 1m.5h:3.3t({4n:1l});11;2d 1m.5m:3.4G(e);1O(e);11}}));3.15.on("3v",3.1w(5(e){if(1X.69===3.2V.2r(0)){1J.51(3.1w(5(){if(3.22()){3.15.1s()}}),0)}}));3.1M.on("6o",3.1w(5(e){if(!3.2B())11;if(e.1x===1m.5h||1m.7W(e)||1m.84(e)||e.1x===1m.5m){11}if(3.4.6Y===1e&&e.1x===1m.3u){1O(e);11}if(e.1x==1m.5j||e.1x==1m.4t||(e.1x==1m.3u&&3.4.6Y)){if(e.9X||e.9W||e.9U||e.7Y)11;3.2l();1O(e);11}if(e.1x==1m.6i||e.1x==1m.4D){if(3.4.aJ){3.5s()}1O(e);11}}));75(3.1M);3.1M.on("4F-2W 1z",3.1w(5(e){if(3.4.4z>=0){e.4Q();if(3.22())11;3.2l()}}));1q.on("4B 4k","72",3.1w(5(e){if(!3.2B()){11}3.5s();aH(e);3.1D();if(3.1q){3.1q.1s()}}));1q.on("4B 4k",3.1w(5(e){7g(1q);if(!3.1a.2y("6-1a-1S")){3.4.12.1L($.2x("6-1s"))}if(3.22()){3.1D()}1k if(3.2B()){3.2l()}1O(e)}));1i.on("4B 4k",3.1w(5(){if(3.4.3M(3)){3.15.1s()}}));1q.on("1s",3.1w(5(e){1O(e)}));3.1M.on("1s",3.1w(5(){if(!3.1a.2y("6-1a-1S")){3.4.12.1L($.2x("6-1s"))}3.1a.1v("6-1a-1S")})).on("3v",3.1w(5(){if(!3.22()){3.1a.1W("6-1a-1S");3.4.12.1L($.2x("6-3v"))}}));3.15.on("1s",3.1w(5(){if(!3.1a.2y("6-1a-1S")){3.4.12.1L($.2x("6-1s"))}3.1a.1v("6-1a-1S")}));3.8n();3.4.12.4q();3.4r()},5s:5(1G){14 7=3.1q.7("6-7");if(7){14 2U=$.2x("6-lC");3.4.12.1L(2U);if(2U.6M()){11}14 2e=3.4f();3.4.12.19(2e?2e.19():"");3.1q.1u(".6-4e").67();3.1q.7e("6-7");3.4r();if(1G!==1e){3.4.12.1L({2o:"6-3h",19:3.id(7),1g:7});3.1G({3h:7})}}},1T:5(){14 1n;if(3.78()){3.2u(1o);3.1D();3.4r()}1k{14 1c=3;3.4.1T.1Z(1o,3.4.12,5(1n){if(1n!==1h&&1n!==1o){1c.2u(1n);1c.1D();1c.4r();1c.2t=1c.4.2t(1n,1c.15.19())}})}},78:5(){14 2e;if(3.3Y()===1h)11 1e;11((2e=3.4f())!==1h&&2e.24("1n"))||(3.4.12.19()==="")||(3.4.12.19()===1h)||(3.4.12.19()===1o)},4M:5(){14 4=3.2w.4M.2h(3,1K),1c=3;if(4.12.2r(0).6D.6C()==="1A"){4.1T=5(12,1V){14 1n=12.1u("3W").4O(5(){11 3.1n&&!3.1B});1V(1c.4L(1n))}}1k if("7"in 4){4.1T=4.1T||5(12,1V){14 id=12.19();14 26=1o;4.1p({30:5(1C,1j,el){14 4K=2s(id,4.id(el));if(4K){26=el}11 4K},1V:!$.2N(1V)?$.9P:5(){1V(26)}})}}11 4},3Y:5(){if(3.1A){if(3.4f()===1h){11 1h}}11 3.2w.3Y.2h(3,1K)},4r:5(){14 2k=3.3Y();if(3.78()&&2k!==1h){if(3.1A&&3.4f()===1h)11;3.1q.1u(".6-4e").3w(3.4.2a(2k));3.1q.1v("6-5A");3.1a.1W("6-aO")}},4x:5(7,3z,6I){14 1n=0,1c=3,3g=1l;3.41().2D(5(i,3j){if(2s(1c.id(3j.7("6-7")),1c.4.12.19())){1n=i;11 1e}});if(6I!==1e){if(3z===1l&&1n>=0){3.2R(1n)}1k{3.2R(0)}}if(3z===1l){14 5E=3.4.4z;if(5E>=0){3.4g(7h(7.1b)>=5E)}}},4g:5(3g){if(3.3g===3g)11;3.3g=3g;3.1i.1u(".6-15").6b("6-15-6J",!3g);3.1i.1u(".6-15").6b("6-5D",!3g);$(3.1i,3.1a).6b("6-7Z-lB",3g)},6W:5(7,1H){if(!3.8m(7)){11}14 2H=3.4.12.19(),2T=3.7();3.4.12.19(3.id(7));3.2u(7);3.4.12.1L({2o:"6-1n",19:3.id(7),1g:7});3.2t=3.4.2t(7,3.15.19());3.1D();if((!1H||!1H.4n)&&3.4.3M(3)){3.1M.1s()}if(!2s(2H,3.id(7))){3.1G({44:7,3h:2T})}},2u:5(7){14 1a=3.1q.1u(".6-4e"),2P,3P;3.1q.7("6-7",7);1a.67();if(7!==1o){2P=3.4.7H(7,1a,3.4.2a)}if(2P!==1h){1a.48(2P)}3P=3.4.7L(7,1a);if(3P!==1h){1a.1v(3P)}3.1q.1W("6-5A");if(3.4.aJ&&3.3Y()!==1h){3.1a.1v("6-aO")}},19:5(){14 19,1G=1e,7=1o,1c=3,2T=3.7();if(1K.1d===0){11 3.4.12.19()}19=1K[0];if(1K.1d>1){1G=1K[1]}if(3.1A){3.1A.19(19).1u("3W").4O(5(){11 3.1n}).2D(5(i,3j){7=1c.4L(3j);11 1e});3.2u(7);3.4r();if(1G){3.1G({44:7,3h:2T})}}1k{if(!19&&19!==0){3.5s(1G);11}if(3.4.1T===1h){3b 3q 5z("ah 1Z 19() if 1T() is 2g 7N")}3.4.12.19(19);3.4.1T(3.4.12,5(7){1c.4.12.19(!7?"":1c.id(7));1c.2u(7);1c.4r();if(1G){1c.1G({44:7,3h:2T})}})}},2v:5(){3.15.19("");3.1M.19("")},7:5(25){14 7,1G=1e;if(1K.1d===0){7=3.1q.7("6-7");if(7==1h)7=1o;11 7}1k{if(1K.1d>1){1G=1K[1]}if(!25){3.5s(1G)}1k{7=3.7();3.4.12.19(!25?"":3.id(25));3.2u(25);if(1G){3.1G({44:25,3h:7})}}}}});79=61(5C,{74:5(){14 1a=$(1X.5v("1U")).1f({"1t":"6-1a 6-1a-6T"}).3w(["<3S 1t=\'6-2f\'>"," <li 1t=\'6-15-9O\'>"," <1P 1N=\'\' 1t=\'6-5D\'></1P>"," <1z 2o=\'1j\' 8g=\'2O\' aN=\'2O\' aQ=\'2O\' 9R=\'1e\' 1t=\'6-1z\'>"," </li>","</3S>","<1U 1t=\'6-1R 6-1R-6T 6-62-65\'>"," <3S 1t=\'6-1b\'>"," </3S>","</1U>"].5p(""));11 1a},4M:5(){14 4=3.2w.4M.2h(3,1K),1c=3;if(4.12.2r(0).6D.6C()==="1A"){4.1T=5(12,1V){14 7=[];12.1u("3W").4O(5(){11 3.1n&&!3.1B}).2D(5(i,3j){7.1Q(1c.4L(3j))});1V(7)}}1k if("7"in 4){4.1T=4.1T||5(12,1V){14 2G=6Z(12.19(),4.3e,4.6P);14 2z=[];4.1p({30:5(1C,1j,el){14 4K=$.lz(2G,5(id){11 2s(id,4.id(el))}).1d;if(4K){2z.1Q(el)}11 4K},1V:!$.2N(1V)?$.9P:5(){14 88=[];1N(14 i=0;i<2G.1d;i++){14 id=2G[i];1N(14 j=0;j<2z.1d;j++){14 26=2z[j];if(2s(id,4.id(26))){88.1Q(26);2z.6R(j,1);54}}}1V(88)}})}}11 4},4j:5(1g){14 1n=3.1a.1u(".6-15-1g-1s");if(1n.1d&&1g&&1g[0]==1n[0]){}1k{if(1n.1d){3.4.12.1L("1g-lA",1n)}1n.1W("6-15-1g-1s");if(1g&&1g.1d){3.1D();1g.1v("6-15-1g-1s");3.4.12.1L("1g-1n",1g)}}},4d:5(){$("1P[1N=\'"+3.15.1f(\'id\')+"\']").1f(\'1N\',3.4.12.1f("id"));3.2w.4d.2h(3,1K);6p.1Z(3,"43","1q")},7U:5(){14 5P=".6-2f",1q;3.43=3.1a.1u(".6-15-9O");3.1q=1q=3.1a.1u(5P);14 7V=3;3.1q.on("3n",".6-1a:2g(.6-1a-1B) .6-15-1g:2g(.6-3k)",5(e){7V.15[0].1s();7V.4j($(3))});3.15.1f("id","9S"+4A());3.15.3m().1j($("1P[1N=\'"+3.4.12.1f("id")+"\']").1j()).1f(\'1N\',3.15.1f(\'id\'));3.4.12.1s(3.1w(5(){3.1s()}));3.15.on("1z 9T",3.1w(5(){if(3.15.1f(\'2k\')&&3.15.19().1d==0)11;if(!3.2B())11;if(!3.22()){3.2l()}}));3.15.1f("3R",3.55);3.5M=0;3.15.on("6o",3.1w(5(e){if(!3.2B())11;++3.5M;14 1n=1q.1u(".6-15-1g-1s");14 3m=1n.3m(".6-15-1g:2g(.6-3k)");14 4s=1n.4s(".6-15-1g:2g(.6-3k)");14 4J=9Y(3.15);if(1n.1d&&(e.1x==1m.5o||e.1x==1m.5Y||e.1x==1m.4D||e.1x==1m.6i||e.1x==1m.3u)){14 3s=1n;if(e.1x==1m.5o&&3m.1d){3s=3m}1k if(e.1x==1m.5Y){3s=4s.1d?4s:1o}1k if(e.1x===1m.4D){if(3.6B(1n.6h())){3.15.1r(10);3s=3m.1d?3m:4s}}1k if(e.1x==1m.6i){if(3.6B(1n.6h())){3.15.1r(10);3s=4s.1d?4s:1o}}1k if(e.1x==1m.3u){3s=1o}3.4j(3s);1O(e);if(!3s||!3s.1d){3.2l()}11}1k if(((e.1x===1m.4D&&3.5M==1)||e.1x==1m.5o)&&(4J.1I==0&&!4J.1d)){3.4j(1q.1u(".6-15-1g:2g(.6-3k)").6j());1O(e);11}1k{3.4j(1o)}if(3.22()){6k(e.1x){2d 1m.4t:2d 1m.5j:3.8b((e.1x===1m.4t)?-1:1);1O(e);11;2d 1m.3u:3.3t();1O(e);11;2d 1m.5h:3.3t({4n:1l});3.1D();11;2d 1m.5m:3.4G(e);1O(e);11}}if(e.1x===1m.5h||1m.7W(e)||1m.84(e)||e.1x===1m.4D||e.1x===1m.5m){11}if(e.1x===1m.3u){if(3.4.6Y===1e){11}1k if(e.9X||e.9W||e.9U||e.7Y){11}}3.2l();if(e.1x===1m.82||e.1x===1m.86){1O(e)}if(e.1x===1m.3u){1O(e)}}));3.15.on("4F",3.1w(5(e){3.5M=0;3.5x()}));3.15.on("3v",3.1w(5(e){3.1a.1W("6-1a-1S");3.15.1W("6-5y");3.4j(1o);if(!3.22())3.2v();e.9M();3.4.12.1L($.2x("6-3v"))}));3.1a.on("3n",5P,3.1w(5(e){if(!3.2B())11;if($(e.4C).5e(".6-15-1g").1d>0){11}3.4j(1o);3.5L();if(!3.1a.2y("6-1a-1S")){3.4.12.1L($.2x("6-1s"))}3.2l();3.4w();e.5Q()}));3.1a.on("1s",5P,3.1w(5(){if(!3.2B())11;if(!3.1a.2y("6-1a-1S")){3.4.12.1L($.2x("6-1s"))}3.1a.1v("6-1a-1S");3.1i.1v("6-1R-1S");3.5L()}));3.8n();3.4.12.4q();3.2v()},4l:5(){if(3.2w.4l.2h(3,1K)){3.15.24("1B",!3.2B())}},1T:5(){14 7;if(3.4.12.19()===""&&3.4.12.1j()===""){3.2u([]);3.1D();3.2v()}if(3.1A||3.4.12.19()!==""){14 1c=3;3.4.1T.1Z(1o,3.4.12,5(7){if(7!==1h&&7!==1o){1c.2u(7);1c.1D();1c.2v()}})}},2v:5(){14 2k=3.3Y(),3U=3.9Z();if(2k!==1h&&3.4S().1d===0&&3.15.2y("6-5y")===1e){3.15.19(2k).1v("6-5A");3.15.1r(3U>0?3U:3.1a.1Y("1r"))}1k{3.15.19("").1r(10)}},5L:5(){if(3.15.2y("6-5A")){3.15.19("").1W("6-5A")}},4a:5(){3.5L();3.5x();3.2w.4a.2h(3,1K);3.4w();if(3.15.19()===""){if(3.2t!=1h){3.15.19(3.2t);3.15.1A()}}3.3V(1l);if(3.4.3M(3)){3.15.1s()}3.4.12.1L($.2x("6-2l"))},1D:5(){if(!3.22())11;3.2w.1D.2h(3,1K)},1s:5(){3.1D();3.15.1s()},6x:5(){11 3.15.2y("6-5y")},2u:5(7){14 2G=[],2X=[],1c=3;$(7).2j(5(){if(2m(1c.id(3),2G)<0){2G.1Q(1c.id(3));2X.1Q(3)}});7=2X;3.1q.1u(".6-15-1g").3r();$(7).2j(5(){1c.7S(3)});1c.4x()},8a:5(){14 1z=3.15.19();1z=3.4.a9.1Z(3,1z,3.7(),3.1w(3.6W),3.4);if(1z!=1o&&1z!=1h){3.15.19(1z);if(1z.1d>0){3.2l()}}},6W:5(7,1H){if(!3.8m(7)||7.1j===""){11}3.7S(7);3.4.12.1L({2o:"1n",19:3.id(7),1g:7});3.2t=3.4.2t(7,3.15.19());3.2v();3.3V();if(3.1A||!3.4.5B)3.4x(7,1e,3.4.5B===1l);if(3.4.5B){3.1D();3.15.1r(10)}1k{if(3.az()>0){3.15.1r(10);3.5x();if(3.6S()>0&&3.19().1d>=3.6S()){3.3V(1l)}1k{if(3.2t!=1h){3.15.19(3.2t);3.3V();3.15.1A()}}3.3L()}1k{3.1D();3.15.1r(10)}}3.1G({44:7});if(!1H||!1H.4n)3.4w()},4G:5(){3.1D();3.4w()},7S:5(7){14 81=!7.3k,9A=$("<li 1t=\'6-15-1g\'>"+" <1U></1U>"+" <a 9z=\'#\' 1t=\'6-15-1g-1D\' 3R=\'-1\'></a>"+"</li>"),9E=$("<li 1t=\'6-15-1g 6-3k\'>"+"<1U></1U>"+"</li>");14 1g=81?9A:9E,id=3.id(7),19=3.4S(),2P,3P;2P=3.4.7H(7,1g.1u("1U"),3.4.2a);if(2P!=1h){1g.1u("1U").lF($("<1U></1U>").3w(2P))}3P=3.4.7L(7,1g.1u("1U"));if(3P!=1h){1g.1v(3P)}if(81){1g.1u(".6-15-1g-1D").on("4B",1O).on("3n lG",3.1w(5(e){if(!3.2B())11;3.6B($(e.4C));3.1q.1u(".6-15-1g-1s").1W("6-15-1g-1s");1O(e);3.1D();3.4w()})).on("1s",3.1w(5(){if(!3.2B())11;3.1a.1v("6-1a-1S");3.1i.1v("6-1R-1S")}))}1g.7("6-7",7);1g.lL(3.43);19.1Q(id);3.4c(19)},6B:5(1n){14 19=3.4S(),7,1E;1n=1n.5e(".6-15-1g");if(1n.1d===0){3b"al lM: "+1n+". lK be .6-15-1g"}7=1n.7("6-7");if(!7){11}14 2U=$.2x("6-lJ");2U.19=3.id(7);2U.1g=7;3.4.12.1L(2U);if(2U.6M()){11 1e}6N((1E=2m(3.id(7),19))>=0){19.6R(1E,1);3.4c(19);if(3.1A)3.4x()}1n.3r();3.4.12.1L({2o:"6-3h",19:3.id(7),1g:7});3.1G({3h:7});11 1l},4x:5(7,3z,6I){14 19=3.4S(),2f=3.1b.1u(".6-1y"),4P=3.1b.1u(".6-1y-7Z-1F"),1c=3;2f.2D(5(i,1g){14 id=1c.id(1g.7("6-7"));if(2m(id,19)>=0){1g.1v("6-1n");1g.1u(".6-1y-2S").1v("6-1n")}});4P.2D(5(i,1g){if(!1g.is(\'.6-1y-2S\')&&1g.1u(".6-1y-2S:2g(.6-1n)").1d===0){1g.1v("6-1n")}});if(3.2R()==-1&&6I!==1e&&3.4.5B===1l){1c.2R(0)}if(!3.4.3K&&!2f.4O(\'.6-1y:2g(.6-1n)\').1d>0){if(!7||7&&!7.20&&3.1b.1u(".6-no-1b").1d===0){if(3N(1c.4.4u,"4u")){3.1b.48("<li 1t=\'6-no-1b\'>"+2b(1c.4.4u,1c.4.12,1c.15.19())+"</li>")}}}},9Z:5(){11 3.1q.1r()-7T(3.15)},5x:5(){14 6X,2Q,3U,8j,3x,70=7T(3.15);6X=a0(3.15)+10;2Q=3.15.1I().2Q;3U=3.1q.1r();8j=3.1q.1I().2Q;3x=3U-(2Q-8j)-70;if(3x<6X){3x=3U-70}if(3x<40){3x=3U-70}if(3x<=0){3x=6X}3.15.1r(lH.lI(3x))},4S:5(){14 19;if(3.1A){19=3.1A.19();11 19===1o?[]:19}1k{19=3.4.12.19();11 6Z(19,3.4.3e,3.4.6P)}},4c:5(19){14 4R;if(3.1A){3.1A.19(19)}1k{4R=[];$(19).2j(5(){if(2m(3,4R)<0)4R.1Q(3)});3.4.12.19(4R.1d===0?"":4R.5p(3.4.3e))}},6K:5(2H,49){14 49=49.59(0),2H=2H.59(0);1N(14 i=0;i<49.1d;i++){1N(14 j=0;j<2H.1d;j++){if(2s(3.4.id(49[i]),3.4.id(2H[j]))){49.6R(i,1);if(i>0){i--}2H.6R(j,1);j--}}}11{44:49,3h:2H}},19:5(19,1G){14 2T,1c=3;if(1K.1d===0){11 3.4S()}2T=3.7();if(!2T.1d)2T=[];if(!19&&19!==0){3.4.12.19("");3.2u([]);3.2v();if(1G){3.1G({44:3.7(),3h:2T})}11}3.4c(19);if(3.1A){3.4.1T(3.1A,3.1w(3.2u));if(1G){3.1G(3.6K(2T,3.7()))}}1k{if(3.4.1T===1h){3b 3q 5z("19() ah be m2 if 1T() is 2g 7N")}3.4.1T(3.4.12,5(7){14 2G=$.7M(7,1c.id);1c.4c(2G);1c.2u(7);1c.2v();if(1G){1c.1G(1c.6K(2T,1c.7()))}})}3.2v()},ac:5(){if(3.1A){3b 3q 5z("m3 of mp is 2g mq a4 a3 4I <1A>. mo 4I <1z 2o=\'6J\'/> mn.")}3.15.1r(0);3.43.4q()},a7:5(){14 19=[],1c=3;3.43.4U();3.43.4T(3.43.2w());3.5x();3.1q.1u(".6-15-1g").2j(5(){19.1Q(1c.4.id($(3).7("6-7")))});3.4c(19);3.1G()},7:5(5G,1G){14 1c=3,2G,2H;if(1K.1d===0){11 3.1q.1F(".6-15-1g").7M(5(){11 $(3).7("6-7")}).2r()}1k{2H=3.7();if(!5G){5G=[]}2G=$.7M(5G,5(e){11 1c.4.id(e)});3.4c(2G);3.2u(5G);3.2v();if(1G){3.1G(3.6K(2H,3.7()))}}}});$.fn.6=5(){14 28=9B.3J.59.1Z(1K,0),4,6,3p,25,3B,ar=["19","4d","22","2l","1D","1s","6x","1a","1i","ac","a7","5a","a6","2q","3L","7","15"],ap=["22","6x","1a","1i"],am=["19","7"],7m={15:"a1"};3.2j(5(){if(28.1d===0||3i(28[0])==="a5"){4=28.1d===0?{}:$.3a({},28[0]);4.12=$(3);if(4.12.2r(0).6D.6C()==="1A"){3B=4.12.24("3B")}1k{3B=4.3B||1e;if("29"in 4){4.3B=3B=1l}}6=3B?3q 1J.4m["1t"].6T():3q 1J.4m["1t"].9v();6.aq(4)}1k if(3i(28[0])==="4o"){if(2m(28[0],ar)<0){3b"mk 3p: "+28[0]}25=1h;6=$(3).7("6");if(6===1h)11;3p=28[0];if(3p==="1a"){25=6.1a}1k if(3p==="1i"){25=6.1i}1k{if(7m[3p])3p=7m[3p];25=6[3p].2h(6,28.59(1))}if(2m(28[0],ap)>=0||(2m(28[0],am)>=0&&28.1d==1)){11 1e}}1k{3b"al 1K 4I 6 ml: "+28}});11(25===1h)?3:25};$.fn.6.7b={1r:"8t",aG:0,5B:1l,6Y:1l,9H:{},ai:{},7l:"",7k:"",at:5(1y,1a,1p,2a){14 2L=[];6r(3.1j(1y),1p.1C,2L,2a);11 2L.5p("")},6P:5(19){11 $.4W(19)},7H:5(7,1a,2a){11 7?2a(3.1j(7)):1h},ag:5(1b,1a,1p){11 1b},af:5(7){11 7.1Y},7L:5(7,1a){11 1h},4z:0,7G:0,4Y:1o,a2:0,id:5(e){11 e==1h?1o:e.id},1j:5(e){if(e&&3.7&&3.7.1j){if($.2N(3.7.1j)){11 3.7.1j(e)}1k{11 e[3.7.1j]}}1k{11 e.1j}},30:5(1C,1j){11 4i(\'\'+1j).6L().2m(4i(\'\'+1C).6L())>=0},3e:",",57:[],a9:a8,2a:8k,ab:1e,7C:1e,7E:5(c){11 c},7D:5(c){11 1o},2t:5(mr,ms){11 1h},ad:\'\',3Q:\'23\',3M:5(ak){14 aj=((\'mx\'in 1J)||(mw.mv>0));if(!aj){11 1l}if(ak.4.4z<0){11 1e}11 1l}};$.fn.6.76=[];$.fn.6.76[\'en\']={8o:5(2z){if(2z===1){11"mt 1y is 9G, mu 9C 4I 1A it."}11 2z+" 1b mj 9G, 9I mi 9J m8 9K m9 4I m7."},4u:5(){11"m6 2z m4"},6Q:5(5d,5b,58){11"ax m5"},6V:5(1z,5E){14 n=5E-1z.1d;11"9L 9C "+n+" or 20 7X"+(n==1?"":"s")},6w:5(1z,9D){14 n=1z.1d-9D;11"9L 9V "+n+" 7X"+(n==1?"":"s")},6l:5(53){11"ma mb mg 1A "+53+" 2J"+(53==1?"":"s")},5q:5(mh){11"ax 20 mf��"},71:5(){11"me��"}};$.3a($.fn.6.7b,$.fn.6.76[\'en\']);$.fn.6.7F={5c:$.2Y,31:{2o:"aE",7n:1e,5J:"aR"}};1J.4m={1p:{2Y:2Y,5R:5R,29:29},mc:{6g:6g,6r:6r,2a:8k,4i:4i},"1t":{"md":5C,"9v":7R,"6T":79}}}(8F));',62,1684,'|||this|opts|function|select2|data||||||||||||||||||||||||||||||||||||||||||||||||||||||||return|element||var|search||||val|container|results|self|length|false|attr|choice|undefined|dropdown|text|else|true|KEY|selected|null|query|selection|width|focus|class|find|addClass|bind|which|result|input|select|disabled|term|close|index|children|triggerChange|options|offset|window|arguments|trigger|focusser|for|killEvent|label|push|drop|active|initSelection|div|callback|removeClass|document|css|call|more|context|opened|top|prop|value|match||args|tags|escapeMarkup|evaluate|style|case|placeholderOption|choices|not|apply|mask|each|placeholder|open|indexOf|enabled|type|event|readonly|get|equal|nextSearchTerm|updateSelection|clearSearch|parent|Event|hasClass|matches|datum|isInterfaceEnabled|above|each2|node|group|ids|old|outerWidth|item|scrollTop|markup|page|isFunction|off|formatted|left|highlight|selectable|oldData|evt|body|change|filtered|ajax|liveRegion|matcher|params|||||||||extend|throw|token|classes|separator|constructor|showSearchInput|removed|typeof|elm|locked|height|prev|click|url|method|new|remove|selectedChoice|selectHighlighted|ENTER|blur|html|searchWidth|scroll|initial|render|multiple|dropWidth|outerHeight|highlighted|sizer|cid|role|propertyObserver|prototype|createSearchChoice|positionDropdown|shouldFocusInput|checkFormatter|resultsSelector|cssClass|createSearchChoicePosition|tabindex|ul|def|maxWidth|updateResults|option|process|getPlaceholder|range||findHighlightableChoices|_sync|searchContainer|added|span|||append|current|opening|aria|setVal|destroy|chosen|getPlaceholderOption|showSearch|resultsPage|stripDiacritics|selectChoice|touchstart|enableInterface|Select2|noFocus|string|ajaxUrl|hide|setPlaceholder|next|UP|formatNoMatches|template|focusSearch|postprocessResults|timeout|minimumResultsForSearch|nextUid|mousedown|target|BACKSPACE|collection|keyup|cancel|autofocus|to|pos|is_match|optionToData|prepareOpts|details|filter|compound|stopPropagation|unique|getVal|appendTo|show|idSuffix|trim|dropLeft|maximumInputLength|auto|resize|setTimeout|dropHeight|limit|break|elementTabIndex|substring|tokenSeparators|errorThrown|slice|enable|textStatus|transport|jqXHR|closest|mousemove|deltaY|TAB|replace|DOWN|key|syncCssClasses|ESC|firstOption|LEFT|join|formatLoadMore|quietMillis|clear|tmp|list|createElement|handler|resizeSearch|focused|Error|default|closeOnSelect|AbstractSelect2|offscreen|min|innerContainer|values|child|dropTop|dataType|highlightUnderEvent|clearPlaceholder|keydowns|removeHighlight|split|selector|preventDefault|local|isArray|maxSelSize|rb|loadMoreIfNeeded|topOffset|obj|RIGHT|changeDirection|viewPortRight|clazz|display|setSelectionRange|createTextRange|none|len|empty|scrollBarDimensions|activeElement|bodyOffset|toggleClass|title|elementLabel|bottom|_enabled|debounce|first|DELETE|last|switch|formatSelectionTooBig|orient|resultsListNode|keydown|cleanupJQueryElements|_readonly|markMatch|lastMousePosition|observer|before|attrs|formatInputTooLong|isFocused|lastpos|count|replacements|unselect|toLowerCase|tagName|formatter|ctx|dupe|adapted|noHighlightUpdate|hidden|buildChangeDetails|toUpperCase|isDefaultPrevented|while|dataItem|transformVal|formatAjaxError|splice|getMaximumSelectionSize|multi|populate|formatInputTooShort|onSelect|minimumWidth|openOnEnter|splitVal|sideBorderPadding|formatSearching|abbr|dest|createContainer|installKeyUpChangeEvent|locales|viewportBottom|isPlaceholderOptionSelected|MultiSelect2|scrollHeight|defaults|String|tl|removeData|windowHeight|reinsertElement|countResults|windowWidth|that|dropdownCssClass|containerCssClass|methodsMap|cache|array|populateResults|queryCount|queryNumber|below|delta|lastTerm|u03B9|u03C5|postRender|_touchMoved|presentation|containerEventName|sel|selectOnBlur|adaptDropdownCssClass|adaptContainerCssClass|ajaxDefaults|minimumInputLength|formatSelection|clearTouchMoved|removeAttr|clearDropdownAlignmentPreference|formatSelectionCssClass|map|defined|depth|_touchEvent|containerId|SingleSelect2|addSelectedChoice|getSideBorderPadding|initContainer|_this|isControl|character|metaKey|with||enableChoice|PAGE_UP|SuperClass|isFunctionKey|touchend|PAGE_DOWN|triggered|ordered|nodes|tokenize|moveHighlight|isObject|enoughRoomBelow|enoughRoomAbove|dataText|autocomplete|AE|idKey|containerLeft|defaultEscapeMarkup|enabledInterface|triggerSelect|initContainerWidth|formatMatches|orientationchange|mouseup|installDebouncedScroll|debounced|copy|mousewheel|transform|dim|parents|must|add|select2Tags|u03C9|counter|u03A5|u0399|jQuery|ensureHighlightVisible|optgroup|detachEvent|str|MEASURE_SCROLLBAR_TEMPLATE|DIACRITICS|DZ|measureScrollbar|select2Event|selectionStart|onpropertychange|adapter|clientHeight|mutations|position|src|textTransform|enoughRoomOnRight|original|selectCallback|formatterName|jsonpCallback||deprecated|childDatum|abort|Dz|clearTimeout|aboveNow|replace_map|isFunc|letterSpacing|enoughRoomOnLeft|pageX|shouldOpen|isVisible|scrollLeft|notify|pageY|installFilteredMouseMove|monitorSource|threshold|accessible|createRange|methods|fontFamily|fontStyle|fontWeight|attachEvent|fontSize|func|single|10000px|touchmove|error|href|enabledItem|Array|enter|max|disabledItem|AV|available|containerCss|use|and|arrow|Please|stopImmediatePropagation|ALT|field|noop|CTRL|spellcheck|s2id_autogen|paste|shiftKey|delete|ctrlKey|altKey|getCursorInfo|getMaxSearchWidth|measureTextWidth|externalSearch|maximumSelectionSize|attached|when|object|disable|onSortEnd|defaultTokenizer|tokenizer||blurOnChange|onSortStart|searchInputPlaceholder||formatResultCssClass|sortResults|cannot|dropdownCss|supportsTouchEvents|instance|Invalid|propertyMethods|||valueMethods|init|allowedMethods||formatResult|||touchMoved|Loading||countSelectableResults|collapse|hasError|detach|originalTitle|GET|loaded|loadMorePadding|killEventImmediately|items|allowClear|searching|SHIFT|resolve|autocorrect|allowclear|resolveContainerWidth|autocapitalize|json|u01D7|u01D3|uA74C|u01D5|uA74A|u01D9|u019F|u01DB|u016E|u1EE6|u0170|u01A2|uA74E|OI|u00DA|u00D9|u1E17|OO|u00DB|u0168|u1E7A|u016C||u016A|u1E78|u0214|u00DC|u1EEA|u1EDA|u1EDC|u1EE0|u1EDE|u1EE4|u1EE2|u1E72|u0172|u1E76|u020E|u1EBD|u0113|u01A0|u1ECC|u1EF0|u00D8|uFF35|u01FE|u01AF|u0186|u1EE8|u01EC|u1E15|u1EEC|u1ED8|u1EEE|u01EA|u0216|u023E|uA754|uA752|uA782|uA7A6|uA75A|u024C|u2C64|u24C8|uA750|u015A|u1E64|u1E9E|uFF33|u2C63|u01A4|u1E5E|u0156|u0154|u1E58|uFF32|u24C7|uA758|u024A|u0158|uA756|uFF31|u24C6|u1E5C|u1E5A|u0210|u0212|u015C|u1E60|u1E70|u1E6E||u0162|u021A|u0164|u1E6C|OU|u0166|uA728|TZ|uA786|u0222|u01AC|u01AE|u1E6A|uFF34|u1E66|u1E62|u0160|uFF30|u1E56|u1E54|u1E68|u0218|uA784|u24C9|uA7A8|u24C5|u015E|u2C7E|u24CA|uFF37|u1E92|u1E94|u01B5|uA737|uA739|uA73B|u017D|uA735|u01E3|u01FD|u00E6|uA733|uA762|u2C6B|u0224|u2C7F|u017B|u1E90|u1EF6|u1EF4|uFF42|u0178|u1E8E|u1EF8|u0232|u24D1|u01B3|u0179|uA73D|uFF3A|u24CF|u024E|u1EFE|u0250|u2C65|u1EB1|u0103|u0101|u1EAF|u1EB5|u0227|u1EB3|u00E3|u1EA9||u020C|u00E1|u00E2|u1EA7|u1EA5|u1EAB|u00E0|u01E1|u00E4|u1EAD|u1EA1|uFF41|u24D0|u1EB7|u0105|u1E01|u0203|u0201|u01DF|u1E9A|u1EA3|u00E5|u01CE|u01FB|u1E03|u0176|u01F3|uA77A|u1E80|u24CC|VY|u0245|uA760|u0257|u0256|u1E13|u1E11|u0174|u1E0F|u0111|u018C|u1E82|uA75E|u01B2|u1EC5|u1EBF|u1EC1||||u1EC3|uFF36|u0244|u24CB|u1E7C|u1E7E|u24D4|u01C6|uFF45||u00E8|u00EA|u00E9|u1E0D|u010F|u0109|u0107|u1EF2|u010B|uFF39|u1E8C|u24CE|uFF43|u24D2|u1E05|u00DD|u1E07|u0180|u0253|u0183|u010D|u1E8A|u1E88|u24D3|u2184|u1E84|uFF44|u1E0B|u1E86|uA73F|u023C|u24CD|uFF38|u2C72|u00E7|u0188|u1E09|u1E74|u1E1C|u01F1|u01C4|SPACE|uA779|u0189|u018B|u018A|u01F2|u0115|u00C9|u00CA|u00C8||uFF25|u01C5|u24BA|u0110|u1E0E|u023B|uA73E|u0187|u1E08|u010C|u00C7|u24B9|uFF24|u1E10|u1E12|u1E0C|HOME|u1E0A|u010E|u1EC0|u1EBE|u0190|u018E|u1E1A|u1E18|u0228|u0118|u24BB|uFF26|uFF27|u01F4|u24BC|uA77B|u1E1E|u0191|u1EC6|u1EB8|u0112|u1E14|strict|u1EBC|u1EC4|u1EC2|u1E16|u0114|u0204|u0206|u011A|u1EBA|u0116|u00CB|u010A|u0108|u01FC|u1EB2|u01E2|u00C6|u0226|uA732|AA|uA734|u1EB4|u1EB0|u0102|AU|u1EAE|AO||uA736|u01E0|u00C4|u01FA|u00C5|u01CD|u0200|u0202|u1EA0|u1EA2|u1EAC|u023A|u2C6F|u0104|u01DE|u1EB6|u1E00|u0100|u00C3|u1E04|u1E06|112|123|scrollbar|measure|u0243|isArrow|uFF23|u0106|u24B8|END|u0182|u0181|u24B6|uFF21|uA73A|uA73C|uA738|u1EA4|u1EA8|u1EAA|u1EA6|u00C2||uFF22|u1E02|u00C0|u24B7|AY|u00C1|u011C|u1E20|u019C|u24C3|uFF2E|u2C6E|u1E42|u1E3E|u1E40|u01F8|u0143|u0145|u1E4A||u1E46|u0147|u00D1|u1E44|uFF2D|u24C2|u023D|u2C62|u0141|u1E3A|u013B|u1E3C|u2C60|uA748|u01C8|Lj|LJ|u01C7|uA746|uA780|u1E48|u0220|u014C|u1E50|u1E4E|u022C|u00D5|u1E4C|u1E52|u014E|u1ECE|u0150|u022A|u00D6|u022E|u0230|u1ED4|u1ED6|NJ|u01CB|u01CA|uA7A4|u019D||uA790||Nj|u24C4|u1ED2|u1ED0|u00D4|u00D3|uFF2F||u00D2|u1E38|u1E36|u2C75|||uA78D|u24BE|u2C67|u0126|u1E28|u1E2A|uFF29|u00CC|u012C|u0130|u012A|u0128|u00CD|u00CE|u1E24|u021E|u01E4|u0193|u0122|u01E6|u011E|u0120|uA7A0|uA77D|u1E22|u1E26|u0124|uFF28|uA77E|u24BD|u00CF|u1E2E|u2C69|uA740|u0198|u1E34|u1E32|u0136|uA742|uA744|u0139|u013D|u013F|uFF2C|uA7A2|u24C1|u01E8|u1E30|u1ECA|u012E|u020A|u0208|u1EC8|u01CF|u1E2C|u0197|u24C0|uFF2B|u0248|u0134|u24BF|uFF2A|u01D1|u1EE7|uFF59|u1EF3|u24E8|u1E8D|uFF58|u1E8B|u00FD|u0177|u1EF7|u1E99|u00FF|u1E8F|u1EF9|u0233|u24E7|u2C73|u24E6|uFF57|vy|uA761|uA75F|u028C|u1E81|u1E83|u1E98|u1E89|u1E85|u1E87|u0175|u1EF5|u01B4|u0389|u0397|u0395|u0388|u0386|u0391|u038A|u03AA|u038F|u03A9|u03AB|u038E|u038C|u039F|uA763|u2C6C|u017A|u1E91|uFF5A|u24E9|u024F|u1EFF|u017C|u017E|u0225|u0240|u01B6|u1E95|u1E93|u028B|u1E7F|u01AD|u0288|u0167|u1E6F|u0163|u1E71|u2C66|uA787|u00F9|u00FA|uFF55|u24E4|uA729|tz|u021B|u1E6D|u023F|uA7A9|u015F|u0219|u1E63|u1E69|uA785|u1E9B|u1E97|u0165|u1E6B|uFF54|u24E3|u00FB|u0169|u1EF1|u1EE5|u1EED|u1EEF|u1EEB|u1EE9|u1E73|u0173|uFF56|u1E7D|u24E5|u0289|u1E77|u1E75|u01B0|u0217|u00FC|||u01DC|u016D|u1E7B|u1E79|u016B|u01D8|u0117|u01D4|u0215||u0171|u016F|u01DA|u03AC|u03B1|grep|deselected|searchbox|clearing|229|keyCode|replaceWith|dblclick|Math|floor|removing|Must|insertBefore|argument|_search|owns|javascript|void|activedescendant|static|selecting|dropdownAutoWidth|160|haspopup|listbox|labelledby|expanded|combobox|button|called|Sorting|found|failed|No|navigate|down|keys|You|can|util|abstract|Searching�|results�|only|pageNumber|up|are|Unknown|plugin||instead|Attach|elements|supported|selectedObject|currentSearchTerm|One|press|msMaxTouchPoints|navigator|ontouchstart|subtree|attributes|offsetHeight|selectionEnd|offsetWidth|clientWidth|u0000|u007E|moveStart|currentStyle|amp|quot|nowrap|whiteSpace|getComputedStyle|absolute|createTextNode|u03C3|u03AF|u03CA|u03B7|u03AE|u03AD|u03B5|u0390|u03CC|u03B0|u03C2|u03CB|u03CD|u03BF|100|success|both|attribute|specified|sub|dept|unselectable|unshift|invalid|MozMutationObserver|observe|WebKitMutationObserver|MutationObserver|custom|allowed||Option|live|polite|status||Object|hasOwnProperty|falsy|s2id_|autogen|maxlength|disconnect|focusin|deltaX|_|u1E67|u01D6|u0137|u1E35|u1E33|u01E9|uFF4B|u1E31|u0199|u2C6A|u24DB|uFF4C|uA7A3|uA745|uA741|u24DA|u0249|u1ECB|u012F|u020B|u0209|u1EC9|u01D0|u1E2D|u0268|u0135|u01F0|uFF4A|u24D9|u0131|u0140|u013A|u1E41|u1E43|u1E3F|uFF4D|u01C9|u24DC|u0271|u026F|u0144|u00F1||u01F9|uFF4E||u24DD|uA747|uA781|u013C|||u1E3D|u1E39||u1E37|u013E||u1E3B|u017F|u2C61|uA749|u026B|u019A|u0142|u1E2F|u00EF|uA77C|u24D6|u0192|u1E1F|u24D5|uFF46|uFF47|u01F5|u0121|u01E7|u011F|u1E21|u011D|u01DD|u025B|u0207|u1EB9|u0205|u011B|u00EB|u1EBB|u1EC7|u0229|u1E1B|u0247|u1E19|u0119|u1E1D|u0123|u01E5|u0195|u24D8|u0265|u2C76||u0127|u2C68|uFF49|u00EC|u012B|u012D|u0129|u00EE|u00ED|u1E96|u1E2B|uA77F|u24D7|u1D79|uA7A1|u0260||uFF48|u0125|u1E25||u1E29|u021F|u1E27|u1E23|u1E45|uA743|u00F8|u01FF|uA75B|uA7A7|u01EB|u01ED|u0254|u027D|u01A3|u024D|u0275|uA74D|uA74B|u1ED9|u1ECD|u24E2|u020D|u01D2|u0151|u1ECF|u020F|u01A1|uA783|u1EE3|u1EDF|u1EE1|u1EDD|u1E5F|u0157|u1D7D|uA751|u01A5|u1E57|u1E55|uA759|uA753|u024B|uA757|uFF51|u24E0|uA755|uFF50|u24DF|u0213|u0211|u0148|u1E5B|u1E5D|u0159|u1E59|u24E1|uA74F|uFF52|u0155|u0223|uFF53|u1EDB|u00F3|u00DF|u00F2|uFF4F|u24DE|u1ED3|u1ED1|u1E4D|u00F5|u1ED5|u1ED7|u01CC|uA7A5|u1E4B|u0146|u1E47|u0161|u1E49|u1E61|uA791|u0149|u0272|u019E|u022D|u00F4|u0231|u014F|u015B|u1E65|u022F|u015D|u00F6|u1E53|u1E51|u1E4F|u014D|u022B'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_album/module.nextgen_basic_album.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_album/module.nextgen_basic_album.php index 366265fa005fb463040ac79728ffcb4b864a3682..416c3cc3aa4241044bdea75766b7bf3c02126fe0 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_album/module.nextgen_basic_album.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_album/module.nextgen_basic_album.php @@ -18,7 +18,7 @@ class M_NextGen_Basic_Album extends C_Base_Module 'photocrati-nextgen_basic_album', 'NextGEN Basic Album', "Provides support for NextGEN's Basic Album", - '0.10', + '0.12', 'https://www.imagely.com/wordpress-gallery-plugin/nextgen-gallery/', 'Photocrati Media', 'https://www.imagely.com' @@ -73,6 +73,7 @@ class M_NextGen_Basic_Album extends C_Base_Module ); $this->get_registry()->add_adapter('I_MVC_View', 'A_NextGen_Album_Breadcrumbs'); + $this->get_registry()->add_adapter('I_MVC_View', 'A_NextGen_Album_Descriptions'); } @@ -166,6 +167,7 @@ class M_NextGen_Basic_Album extends C_Base_Module { return array( 'A_NextGen_Album_Breadcrumbs' => 'adapter.nextgen_album_breadcrumbs.php', + 'A_NextGen_Album_Descriptions' => 'adapter.nextgen_album_descriptions.php', 'A_Nextgen_Basic_Album' => 'adapter.nextgen_basic_album.php', 'A_Nextgen_Basic_Album_Controller' => 'adapter.nextgen_basic_album_controller.php', 'A_Nextgen_Basic_Album_Mapper' => 'adapter.nextgen_basic_album_mapper.php', diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_album/package.module.nextgen_basic_album.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_album/package.module.nextgen_basic_album.php index 4d7921140d5cfc1a7a32cfca4937576638964db0..8c7b466c8560850ea19df80696b7e3f21ac6ee2a 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_album/package.module.nextgen_basic_album.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_album/package.module.nextgen_basic_album.php @@ -47,7 +47,11 @@ class A_NextGen_Album_Breadcrumbs extends Mixin $ds = $displayed_gallery->display_settings; if (!empty($entities) && !empty($ds['template']) && $this->are_breadcrumbs_enabled($ds)) { if ($gallery_id) { - $ids = array($gallery_id); + if (is_array($gallery_id)) { + $ids = $gallery_id; + } else { + $ids = array($gallery_id); + } } elseif (!empty($ds['original_album_id'])) { $ids = $ds['original_album_id']; } else { @@ -96,6 +100,9 @@ class A_NextGen_Album_Breadcrumbs extends Mixin if (is_array($gallery_id)) { $gallery_id = array_shift($gallery_id); } + if (is_array($gallery_id)) { + $gallery_id = $gallery_id[0]; + } foreach ($entities as $ndx => $entity) { $tmpid = (isset($entity->albumdesc) ? 'a' : '') . $entity->{$entity->id_field}; $this->breadcrumb_cache[$tmpid] = $entity; @@ -175,6 +182,85 @@ class A_NextGen_Album_Breadcrumbs extends Mixin return $view->render(TRUE); } } +class A_NextGen_Album_Descriptions extends Mixin +{ + // When viewing a child gallery the album controller's add_description_to_legacy_templates() method will be + // called for the gallery and then again for the root album; we only want to run once + public static $_description_added_once = FALSE; + public function are_descriptions_enabled($display_settings) + { + $retval = FALSE; + if (isset($display_settings['enable_descriptions']) && $display_settings['enable_descriptions']) { + $retval = TRUE; + } elseif (isset($display_settings['original_settings']) && $this->are_descriptions_enabled($display_settings['original_settings'])) { + $retval = TRUE; + } + return $retval; + } + public function render_object() + { + $root_element = $this->call_parent('render_object'); + if ($displayed_gallery = $this->object->get_param('displayed_gallery')) { + $ds = $displayed_gallery->display_settings; + if ($this->are_descriptions_enabled($ds)) { + $description = $this->object->generate_description($displayed_gallery); + foreach ($root_element->find('nextgen_gallery.gallery_container', TRUE) as $container) { + // Determine where (to be compatible with breadcrumbs) in the container to insert + $pos = 0; + foreach ($container->_list as $ndx => $item) { + if (is_string($item)) { + $pos = $ndx; + } else { + break; + } + } + $container->insert($description, $pos); + } + } + } + return $root_element; + } + public function render_legacy_template_description($displayed_gallery) + { + if (!empty($displayed_gallery->display_settings['template']) && $this->are_descriptions_enabled($displayed_gallery->display_settings)) { + return $this->object->generate_description($displayed_gallery); + } else { + return ''; + } + } + public function generate_description($displayed_gallery) + { + if (self::$_description_added_once) { + return ''; + } + self::$_description_added_once = TRUE; + $description = $this->get_description($displayed_gallery); + $view = new C_MVC_View('photocrati-nextgen_basic_album#descriptions', array('description' => $description)); + return $view->render(TRUE); + } + public function get_description($displayed_gallery) + { + $description = ''; + // Important: do not array_shift() $displayed_gallery->container_ids as it will affect breadcrumbs + $container_ids = $displayed_gallery->container_ids; + if ($displayed_gallery->source == 'galleries') { + $gallery_id = array_shift($container_ids); + $gallery = C_Gallery_Mapper::get_instance()->find($gallery_id); + if ($gallery && !empty($gallery->galdesc)) { + $description = $gallery->galdesc; + } + } else { + if ($displayed_gallery->source == 'albums') { + $album_id = array_shift($container_ids); + $album = C_Album_Mapper::get_instance()->find($album_id); + if ($album && !empty($album->albumdesc)) { + $description = $album->albumdesc; + } + } + } + return $description; + } +} /** * Provides validation for NextGen Basic Albums */ @@ -224,7 +310,9 @@ class A_NextGen_Basic_Album_Controller extends Mixin_NextGen_Basic_Pagination // Try finding the gallery by slug first. If nothing is found, we assume that // the user passed in a gallery id instead $mapper = C_Gallery_Mapper::get_instance(); - $result = reset($mapper->select()->where(array('slug = %s', $gallery))->limit(1)->run_query()); + $tmp = $mapper->select()->where(array('slug = %s', $gallery))->limit(1)->run_query(); + $result = reset($tmp); + unset($tmp); if ($result) { $gallery = $result->{$result->id_field}; } @@ -233,14 +321,17 @@ class A_NextGen_Basic_Album_Controller extends Mixin_NextGen_Basic_Pagination if (!empty($display_settings['gallery_display_template'])) { $gallery_params['template'] = $display_settings['gallery_display_template']; } - add_filter('ngg_displayed_gallery_rendering', array($this, 'add_breadcrumbs_to_legacy_templates'), 10, 2); + add_filter('ngg_displayed_gallery_rendering', array($this, 'add_description_to_legacy_templates'), 8, 2); + add_filter('ngg_displayed_gallery_rendering', array($this, 'add_breadcrumbs_to_legacy_templates'), 9, 2); $output = $renderer->display_images($gallery_params, $return); remove_filter('ngg_displayed_gallery_rendering', array($this, 'add_breadcrumbs_to_legacy_templates')); + remove_filter('ngg_displayed_gallery_rendering', array($this, 'add_description_to_legacy_templates')); return $output; } else { if ($album = $this->param('album')) { $mapper = C_Album_Mapper::get_instance(); - $result = array_pop($mapper->select()->where(array('slug = %s', $album))->limit(1)->run_query()); + $result = $mapper->select()->where(array('slug = %s', $album))->limit(1)->run_query(); + $result = array_pop($result); $album_sub = $result ? $result->{$result->id_field} : null; if ($album_sub != null) { $album = $album_sub; @@ -262,7 +353,7 @@ class A_NextGen_Basic_Album_Controller extends Mixin_NextGen_Basic_Pagination // If there are entities to be displayed if ($entities) { $pagination_result = $this->object->create_pagination($current_page, $displayed_gallery->get_entity_count(), $display_settings['galleries_per_page'], urldecode($this->object->param('ajax_pagination_referrer'))); - if (!empty($display_settings['template'])) { + if (!empty($display_settings['template']) && $display_settings['template'] != 'default') { // Add additional parameters $this->object->remove_param('ajax_pagination_referrer'); $display_settings['current_page'] = $current_page; @@ -270,12 +361,18 @@ class A_NextGen_Basic_Album_Controller extends Mixin_NextGen_Basic_Pagination $display_settings['pagination_prev'] = $pagination_result['prev']; $display_settings['pagination_next'] = $pagination_result['next']; $display_settings['pagination'] = $pagination_result['output']; + // Legacy templates lack a good way of injecting content at the right time $this->object->add_mixin('A_NextGen_Album_Breadcrumbs'); + $this->object->add_mixin('A_NextGen_Album_Descriptions'); $breadcrumbs = $this->object->render_legacy_template_breadcrumbs($displayed_gallery, $entities); + $description = $this->object->render_legacy_template_description($displayed_gallery); // Render legacy template $this->object->add_mixin('Mixin_NextGen_Basic_Templates'); $display_settings = $this->prepare_legacy_album_params($displayed_gallery->get_entity(), $display_settings); $retval = $this->object->legacy_render($display_settings['template'], $display_settings, $return, 'album'); + if (!empty($description)) { + $retval = $description . $retval; + } if (!empty($breadcrumbs)) { $retval = $breadcrumbs . $retval; } @@ -317,6 +414,15 @@ class A_NextGen_Basic_Album_Controller extends Mixin_NextGen_Basic_Pagination } return $html; } + public function add_description_to_legacy_templates($html, $displayed_gallery) + { + $this->object->add_mixin('A_NextGen_Album_Descriptions'); + $description = $this->object->render_legacy_template_description($displayed_gallery); + if (!empty($description)) { + $html = $description . $html; + } + return $html; + } /** * Gets the parent album for the entity being displayed * @param int $entity_id @@ -441,6 +547,7 @@ class A_NextGen_Basic_Album_Mapper extends Mixin $this->object->_set_default_value($entity, 'settings', 'galleries_per_page', $settings->galPagedGalleries); $this->object->_set_default_value($entity, 'settings', 'enable_breadcrumbs', 1); $this->object->_set_default_value($entity, 'settings', 'disable_pagination', 0); + $this->object->_set_default_value($entity, 'settings', 'enable_descriptions', 0); $this->object->_set_default_value($entity, 'settings', 'template', ''); // Thumbnail dimensions -- only used by extended albums if ($entity->name == NGG_BASIC_EXTENDED_ALBUM) { @@ -530,7 +637,7 @@ class Mixin_NextGen_Basic_Album_Form extends Mixin_Display_Type_Form { public function _get_field_names() { - return array('nextgen_basic_album_gallery_display_type', 'nextgen_basic_album_galleries_per_page', 'nextgen_basic_album_enable_breadcrumbs', 'nextgen_basic_templates_template'); + return array('nextgen_basic_album_gallery_display_type', 'nextgen_basic_album_galleries_per_page', 'nextgen_basic_album_enable_breadcrumbs', 'nextgen_basic_templates_template', 'nextgen_basic_album_enable_descriptions'); } /** * Renders the Gallery Display Type field @@ -553,6 +660,10 @@ class Mixin_NextGen_Basic_Album_Form extends Mixin_Display_Type_Form { return $this->_render_radio_field($display_type, 'enable_breadcrumbs', __('Enable breadcrumbs', 'nggallery'), isset($display_type->settings['enable_breadcrumbs']) ? $display_type->settings['enable_breadcrumbs'] : FALSE); } + public function _render_nextgen_basic_album_enable_descriptions_field($display_type) + { + return $this->_render_radio_field($display_type, 'enable_descriptions', __('Display descriptions', 'nggallery'), $display_type->settings['enable_descriptions']); + } } class A_NextGen_Basic_Extended_Album_Form extends Mixin_NextGen_Basic_Album_Form { diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_album/static/jquery.dotdotdot-1.5.7-packed.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_album/static/jquery.dotdotdot-1.5.7-packed.js index 67ef39d494645af967e6690e55866bba3cc8d63a..c469b84297d5653836c7279a9b085a37ebfcd7c9 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_album/static/jquery.dotdotdot-1.5.7-packed.js +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_album/static/jquery.dotdotdot-1.5.7-packed.js @@ -1,15 +1,15 @@ -/* - * jQuery dotdotdot 1.5.7 - * - * Copyright (c) 2013 Fred Heusschen - * www.frebsite.nl - * - * Plugin website: - * dotdotdot.frebsite.nl - * - * Dual licensed under the MIT and GPL licenses. - * http://en.wikipedia.org/wiki/MIT_License - * http://en.wikipedia.org/wiki/GNU_General_Public_License - */ - +/* + * jQuery dotdotdot 1.5.7 + * + * Copyright (c) 2013 Fred Heusschen + * www.frebsite.nl + * + * Plugin website: + * dotdotdot.frebsite.nl + * + * Dual licensed under the MIT and GPL licenses. + * http://en.wikipedia.org/wiki/MIT_License + * http://en.wikipedia.org/wiki/GNU_General_Public_License + */ + (function(a){function c(a,b,c){var d=a.children(),e=!1;a.empty();for(var g=0,h=d.length;h>g;g++){var i=d.eq(g);if(a.append(i),c&&a.append(c),f(a,b)){i.remove(),e=!0;break}c&&c.remove()}return e}function d(b,c,g,h,i){var j=b.contents(),k=!1;b.empty();for(var l="table, thead, tbody, tfoot, tr, col, colgroup, object, embed, param, ol, ul, dl, select, optgroup, option, textarea, script, style",m=0,n=j.length;n>m&&!k;m++){var o=j[m],p=a(o);void 0!==o&&(b.append(p),i&&b[b.is(l)?"after":"append"](i),3==o.nodeType?f(g,h)&&(k=e(p,c,g,h,i)):k=d(p,c,g,h,i),k||i&&i.remove())}return k}function e(a,b,c,d,h){var k=!1,l=a[0];if(l===void 0)return!1;for(var m="letter"==d.wrap?"":" ",n=j(l).split(m),o=-1,p=-1,q=0,r=n.length-1;r>=q;){var s=Math.floor((q+r)/2);if(s==p)break;p=s,i(l,n.slice(0,p+1).join(m)+d.ellipsis),f(c,d)?r=p:(o=p,q=p)}if(-1==o||1==n.length&&0==n[0].length){var u=a.parent();a.remove();var v=h?h.length:0;if(u.contents().size()>v){var w=u.contents().eq(-1-v);k=e(w,b,c,d,h)}else{var l=u.prev().contents().eq(-1)[0];if(l!==void 0){var t=g(j(l),d);i(l,t),u.remove(),k=!0}}}else{var t=g(n.slice(0,o+1).join(m),d);k=!0,i(l,t)}return k}function f(a,b){return a.innerHeight()>b.maxHeight}function g(b,c){for(;a.inArray(b.slice(-1),c.lastCharacter.remove)>-1;)b=b.slice(0,-1);return 0>a.inArray(b.slice(-1),c.lastCharacter.noEllipsis)&&(b+=c.ellipsis),b}function h(a){return{width:a.innerWidth(),height:a.innerHeight()}}function i(a,b){a.innerText?a.innerText=b:a.nodeValue?a.nodeValue=b:a.textContent&&(a.textContent=b)}function j(a){return a.innerText?a.innerText:a.nodeValue?a.nodeValue:a.textContent?a.textContent:""}function k(b,c){return b===void 0?!1:b?"string"==typeof b?(b=a(b,c),b.length?b:!1):"object"==typeof b?b.jquery===void 0?!1:b:!1:!1}function l(a){for(var b=a.innerHeight(),c=["paddingTop","paddingBottom"],d=0,e=c.length;e>d;d++){var f=parseInt(a.css(c[d]),10);isNaN(f)&&(f=0),b-=f}return b}function m(a,b){return a?(b="string"==typeof b?"dotdotdot: "+b:["dotdotdot:",b],window.console!==void 0&&window.console.log!==void 0&&window.console.log(b),!1):!1}if(!a.fn.dotdotdot){a.fn.dotdotdot=function(e){if(0==this.length)return e&&e.debug===!1||m(!0,'No element found for "'+this.selector+'".'),this;if(this.length>1)return this.each(function(){a(this).dotdotdot(e)});var g=this;g.data("dotdotdot")&&g.trigger("destroy.dot"),g.bind_events=function(){return g.bind("update.dot",function(b,e){b.preventDefault(),b.stopPropagation(),j.maxHeight="number"==typeof j.height?j.height:l(g),j.maxHeight+=j.tolerance,e!==void 0&&(("string"==typeof e||e instanceof HTMLElement)&&(e=a("<div />").append(e).contents()),e instanceof a&&(i=e)),q=g.wrapInner('<div class="dotdotdot" />').children(),q.empty().append(i.clone(!0)).css({height:"auto",width:"auto",border:"none",padding:0,margin:0});var h=!1,k=!1;return n.afterElement&&(h=n.afterElement.clone(!0),n.afterElement.remove()),f(q,j)&&(k="children"==j.wrap?c(q,j,h):d(q,g,q,j,h)),q.replaceWith(q.contents()),q=null,a.isFunction(j.callback)&&j.callback.call(g[0],k,i),n.isTruncated=k,k}).bind("isTruncated.dot",function(a,b){return a.preventDefault(),a.stopPropagation(),"function"==typeof b&&b.call(g[0],n.isTruncated),n.isTruncated}).bind("originalContent.dot",function(a,b){return a.preventDefault(),a.stopPropagation(),"function"==typeof b&&b.call(g[0],i),i}).bind("destroy.dot",function(a){a.preventDefault(),a.stopPropagation(),g.unwatch().unbind_events().empty().append(i).data("dotdotdot",!1)}),g},g.unbind_events=function(){return g.unbind(".dot"),g},g.watch=function(){if(g.unwatch(),"window"==j.watch){var b=a(window),c=b.width(),d=b.height();b.bind("resize.dot"+n.dotId,function(){c==b.width()&&d==b.height()&&j.windowResizeFix||(c=b.width(),d=b.height(),p&&clearInterval(p),p=setTimeout(function(){g.trigger("update.dot")},10))})}else o=h(g),p=setInterval(function(){var a=h(g);(o.width!=a.width||o.height!=a.height)&&(g.trigger("update.dot"),o=h(g))},100);return g},g.unwatch=function(){return a(window).unbind("resize.dot"+n.dotId),p&&clearInterval(p),g};var i=g.contents(),j=a.extend(!0,{},a.fn.dotdotdot.defaults,e),n={},o={},p=null,q=null;return n.afterElement=k(j.after,g),n.isTruncated=!1,n.dotId=b++,g.data("dotdotdot",!0).bind_events().trigger("update.dot"),j.watch&&g.watch(),g},a.fn.dotdotdot.defaults={ellipsis:"... ",wrap:"word",lastCharacter:{remove:[" ",",",";",".","!","?"],noEllipsis:[]},tolerance:0,callback:null,after:null,height:null,watch:!1,windowResizeFix:!0,debug:!1};var b=1,n=a.fn.html;a.fn.html=function(a){return a!==void 0?this.data("dotdotdot")&&"function"!=typeof a?this.trigger("update",[a]):n.call(this,a):n.call(this)};var o=a.fn.text;a.fn.text=function(b){if(b!==void 0){if(this.data("dotdotdot")){var c=a("<div />");return c.text(b),b=c.html(),c.remove(),this.trigger("update",[b])}return o.call(this,b)}return o.call(this)}}})(jQuery); \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_album/templates/descriptions.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_album/templates/descriptions.php new file mode 100644 index 0000000000000000000000000000000000000000..22814ab31ed63666be86c17d6e5e18a35336e36c --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_album/templates/descriptions.php @@ -0,0 +1,3 @@ +<?php if (!empty($description)) { ?> + <p><?php echo $description; ?></p> +<?php } ?> \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_gallery/module.nextgen_basic_gallery.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_gallery/module.nextgen_basic_gallery.php index deeff0ca7d298a16d1a6ba895300d0dce9dc623f..04aeaf3a1d206445ecfa4c11a89c4a49182c8ed4 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_gallery/module.nextgen_basic_gallery.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_gallery/module.nextgen_basic_gallery.php @@ -25,7 +25,7 @@ class M_NextGen_Basic_Gallery extends C_Base_Module 'photocrati-nextgen_basic_gallery', 'NextGEN Basic Gallery', "Provides NextGEN Gallery's basic thumbnail/slideshow integrated gallery", - '0.13', + '0.14', 'https://www.imagely.com/wordpress-gallery-plugin/nextgen-gallery/', 'Photocrati Media', 'https://www.imagely.com' diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_gallery/package.module.nextgen_basic_gallery.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_gallery/package.module.nextgen_basic_gallery.php index bd882b4a44d3879d731d0564ae52fe054a60491f..5b0d5272e2e4a87bf8ca5ff5c62ec6878cc8601e 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_gallery/package.module.nextgen_basic_gallery.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_gallery/package.module.nextgen_basic_gallery.php @@ -501,7 +501,7 @@ class A_NextGen_Basic_Thumbnails_Controller extends Mixin $effect_code = $this->object->get_effect_code($displayed_gallery); } // The render functions require different processing - if (!empty($display_settings['template'])) { + if (!empty($display_settings['template']) && $display_settings['template'] != 'default') { $this->object->add_mixin('A_NextGen_Basic_Template_Form'); $this->object->add_mixin('Mixin_NextGen_Basic_Templates'); $params = $this->object->prepare_legacy_parameters($images, $displayed_gallery, array('next' => empty($pagination_next) ? FALSE : $pagination_next, 'prev' => empty($pagination_prev) ? FALSE : $pagination_prev, 'pagination' => $pagination, 'slideshow_link' => $slideshow_link, 'effect_code' => $effect_code)); diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_imagebrowser/module.nextgen_basic_imagebrowser.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_imagebrowser/module.nextgen_basic_imagebrowser.php index 66f31b846dbe325448cd0d73d327f06d5c7f0681..9d8a220678df7a02903a01d1c6b8977c2027af39 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_imagebrowser/module.nextgen_basic_imagebrowser.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_imagebrowser/module.nextgen_basic_imagebrowser.php @@ -19,7 +19,7 @@ class M_NextGen_Basic_ImageBrowser extends C_Base_Module 'photocrati-nextgen_basic_imagebrowser', 'NextGEN Basic ImageBrowser', 'Provides the NextGEN Basic ImageBrowser Display Type', - '0.10', + '0.11', 'https://www.imagely.com/wordpress-gallery-plugin/nextgen-gallery/', 'Photocrati Media', 'https://www.imagely.com' diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_imagebrowser/package.module.nextgen_basic_imagebrowser.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_imagebrowser/package.module.nextgen_basic_imagebrowser.php index ec20d7bce46da0d893f7126ad7ebe7b72f9bd759..44100644591b5a360ee01780af68269480d39ea8 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_imagebrowser/package.module.nextgen_basic_imagebrowser.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_imagebrowser/package.module.nextgen_basic_imagebrowser.php @@ -113,7 +113,7 @@ class A_NextGen_Basic_ImageBrowser_Controller extends Mixin if (!empty($_POST['ajax_referrer'])) { $displayed_gallery->display_settings['ngg_triggers_display'] = 'never'; } - if (!empty($display_settings['template'])) { + if (!empty($display_settings['template']) && $display_settings['template'] != 'default') { $this->object->add_mixin('Mixin_NextGen_Basic_Templates'); $picture->href_link = $picture->get_href_link(); $picture->previous_image_link = $prev_image_link; diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_singlepic/module.nextgen_basic_singlepic.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_singlepic/module.nextgen_basic_singlepic.php index e8dbada93fa3c1b80833ed4ad69668e053b360d4..a5ecaf4cb0ea168227954cb629983b2d4ffc21e9 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_singlepic/module.nextgen_basic_singlepic.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_singlepic/module.nextgen_basic_singlepic.php @@ -17,7 +17,7 @@ class M_NextGen_Basic_Singlepic extends C_Base_Module NGG_BASIC_SINGLEPIC, 'NextGen Basic Singlepic', 'Provides a singlepic gallery for NextGEN Gallery', - '0.11', + '0.12', 'https://www.imagely.com', 'Photocrati Media', 'https://www.imagely.com' diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_singlepic/package.module.nextgen_basic_singlepic.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_singlepic/package.module.nextgen_basic_singlepic.php index 093a0e3015e59998fb50e9f4cd5bd415a9a9bfbf..54a0b61768a4e6fda0fdc9ff2b9a5d5099255eae 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_singlepic/package.module.nextgen_basic_singlepic.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_singlepic/package.module.nextgen_basic_singlepic.php @@ -90,7 +90,7 @@ class A_NextGen_Basic_Singlepic_Controller extends Mixin $size = $dynthumbs->get_size_name($params); } $thumbnail_url = $storage->get_image_url($image, $size); - if (!empty($display_settings['template'])) { + if (!empty($display_settings['template']) && $display_settings['template'] != 'default') { $this->object->add_mixin('A_NextGen_Basic_Template_Form'); $this->object->add_mixin('Mixin_NextGen_Basic_Templates'); $params = $this->object->prepare_legacy_parameters(array($image), $displayed_gallery, array('single_image' => TRUE)); diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_templates/module.nextgen_basic_templates.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_templates/module.nextgen_basic_templates.php index 8b3c32445b7551797d02f063ee868cfd08c3db99..27ed32e094d3aff18733e5bdb899e19c07386c04 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_templates/module.nextgen_basic_templates.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_templates/module.nextgen_basic_templates.php @@ -15,7 +15,7 @@ class M_NextGen_Basic_Templates extends C_Base_Module 'photocrati-nextgen_basic_templates', 'NextGen Basic Templates', 'Provides a NextGen-Legacy compatible thumbnail gallery for NextGEN Gallery', - '0.5', + '0.6', 'https://www.imagely.com', 'Photocrati Media', 'https://www.imagely.com' diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_templates/package.module.nextgen_basic_templates.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_templates/package.module.nextgen_basic_templates.php index 8a814034695151f16144f1b911b2efbf96cb4e4a..b90c819c881a82c3f755565a419ef1912ad29481 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_templates/package.module.nextgen_basic_templates.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_templates/package.module.nextgen_basic_templates.php @@ -37,6 +37,8 @@ class A_NextGen_Basic_Template_Form extends Mixin if (!isset($templates[$display_type->settings['template']])) { $templates[$display_type->settings['template']] = $display_type->settings['template']; } + // add <default> template that acts the same way as having no template specified + $templates['default'] = __('Default', 'nggallery'); return $this->object->render_partial('photocrati-nextgen_basic_templates#nextgen_basic_templates_settings_template', array('display_type_name' => $display_type->name, 'template_label' => __('Template', 'nggallery'), 'template_text' => __('Use a legacy template when rendering (not recommended).', 'nggallery'), 'chosen_file' => $display_type->settings['template'], 'templates' => $templates), True); } /** diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_templates/templates/nextgen_basic_templates_settings_template.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_templates/templates/nextgen_basic_templates_settings_template.php index 08ee8682256777a9113230289dc259cc4a43a17f..5a0ed3e65e642a2501165479abb05fbcc4e20f19 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_templates/templates/nextgen_basic_templates_settings_template.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_templates/templates/nextgen_basic_templates_settings_template.php @@ -11,7 +11,7 @@ <select name='<?php echo esc_attr($display_type_name); ?>[template]' id='<?php echo esc_attr($display_type_name); ?>_template>' class='ngg_thumbnail_template ngg_settings_template'> - <option></option> + <option></option> <?php foreach ($templates as $file => $label): ?> <?php if ($file && $label): ?> <option value="<?php echo esc_attr($file) ?>" <?php selected($chosen_file, $file, TRUE); ?>><?php esc_html_e($label); ?></option> diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/module.nextgen_data.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/module.nextgen_data.php index da2a541b7acbb87ea44373e16181515a4ff88157..a9331c35eaa2314abd8b0df993b3e44b7a788308 100755 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/module.nextgen_data.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/module.nextgen_data.php @@ -15,7 +15,7 @@ class M_NextGen_Data extends C_Base_Module 'photocrati-nextgen-data', 'NextGEN Data Tier', "Provides a data tier for NextGEN gallery based on the DataMapper module", - '0.10', + '0.11', 'https://www.imagely.com', 'Photocrati Media', 'https://www.imagely.com' diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/package.module.nextgen_data.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/package.module.nextgen_data.php index 67ac96a18c91a24decc8b21fb8b72e3c48b5364e..e1094f7a75cef6eb31700315becee87bcd8f58e3 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/package.module.nextgen_data.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/package.module.nextgen_data.php @@ -268,7 +268,7 @@ class C_Gallery extends C_DataMapper_Model * Defines the interfaces and methods (through extensions and hooks) * that this class provides */ - public function define($properties, $mapper = FALSE, $context = FALSE) + public function define($properties = array(), $mapper = FALSE, $context = FALSE) { parent::define($mapper, $properties, $context); $this->add_mixin('Mixin_NextGen_Gallery_Validation'); @@ -519,11 +519,11 @@ class C_GalleryStorage_Base extends C_Component class C_Gallery_Storage extends C_GalleryStorage_Base { public static $_instances = array(); - public function define($object_name, $context = FALSE) + public function define($context = FALSE) { parent::define($context); $this->add_mixin('Mixin_GalleryStorage'); - $this->wrap('I_GalleryStorage_Driver', array(&$this, '_get_driver'), array($object_name, $context)); + $this->wrap('I_GalleryStorage_Driver', array(&$this, '_get_driver'), $context); $this->implement('I_Gallery_Storage'); } static function get_instance($context = False) @@ -538,13 +538,11 @@ class C_Gallery_Storage extends C_GalleryStorage_Base * @param array $args * @return mixed */ - public function _get_driver($args) + public function _get_driver($context) { - $object_name = $args[0]; - $context = $args[1]; $factory_method = $this->_get_driver_factory_method($context); $factory = C_Component_Factory::get_instance(); - return $factory->create($factory_method, $object_name, $context); + return $factory->create($factory_method, FALSE, $context); } } class E_UploadException extends E_NggErrorException @@ -1151,7 +1149,9 @@ class Mixin_GalleryStorage_Driver_Base extends Mixin $image = NULL; if ($image_id) { $image = $this->object->_image_mapper->find($image_id, TRUE); - unset($image->meta_data['saved']); + if ($image) { + unset($image->meta_data['saved']); + } } if (!$image) { $image = $this->object->_image_mapper->create(); @@ -1604,7 +1604,7 @@ class Mixin_GalleryStorage_Driver_Base extends Mixin $thumbnail = NULL; $result = $this->object->calculate_image_clone_result($image_path, $clone_path, $params); // XXX this should maybe be removed and extra settings go into $params? - $settings = C_NextGen_Settings::get_instance(); + $settings = apply_filters('ngg_settings_during_image_generation', C_NextGen_Settings::get_instance()->to_array()); // Ensure we have a valid image if ($image_path && @file_exists($image_path) && $result != null && !isset($result['error'])) { $image_dir = dirname($image_path); @@ -1677,6 +1677,10 @@ class Mixin_GalleryStorage_Driver_Base extends Mixin } if (is_null($thumbnail)) { $thumbnail = new C_NggLegacy_Thumbnail($destpath, true); + if ($thumbnail->error) { + $thumbnail = null; + return null; + } } else { $thumbnail->fileName = $destpath; } @@ -1686,8 +1690,8 @@ class Mixin_GalleryStorage_Driver_Base extends Mixin $watermark = null; } if ($watermark == 1 || $watermark === true) { - if (in_array(strval($settings->wmType), array('image', 'text'))) { - $watermark = $settings->wmType; + if (in_array(strval($settings['wmType']), array('image', 'text'))) { + $watermark = $settings['wmType']; } else { $watermark = 'text'; } @@ -1719,6 +1723,7 @@ class Mixin_GalleryStorage_Driver_Base extends Mixin // Force format $thumbnail->format = strtoupper($format_list[$clone_format]); } + $thumbnail = apply_filters('ngg_before_save_thumbnail', $thumbnail); $thumbnail->save($destpath, $quality); // IF the original contained IPTC metadata we should attempt to copy it if (isset($detailed_size['APP13']) && function_exists('iptcembed')) { @@ -1735,7 +1740,7 @@ class Mixin_GalleryStorage_Driver_Base extends Mixin class C_GalleryStorage_Driver_Base extends C_GalleryStorage_Base { public static $_instances = array(); - public function define($context) + public function define($context = FALSE) { parent::define($context); $this->add_mixin('Mixin_GalleryStorage_Driver_Base'); @@ -3019,7 +3024,7 @@ class Mixin_NggLegacy_GalleryStorage_Driver extends Mixin } elseif (isset($gallery->slug)) { $fs = C_Fs::get_instance(); $basepath = C_NextGen_Settings::get_instance()->gallerypath; - $retval = $fs->join_paths($basepath, $gallery->slug); + $retval = $fs->join_paths($basepath, sanitize_file_name(sanitize_title($gallery->slug))); } } $root_type = defined('NGG_GALLERY_ROOT_TYPE') ? NGG_GALLERY_ROOT_TYPE : 'site'; @@ -3919,19 +3924,35 @@ class C_NggLegacy_Thumbnail } //initialize resources if no errors if ($this->error == false) { + $img_err = null; switch ($this->format) { case 'GIF': - $this->oldImage = @ImageCreateFromGif($this->fileName); + if (function_exists('ImageCreateFromGif')) { + $this->oldImage = @ImageCreateFromGif($this->fileName); + } else { + $img_err = __('Support for GIF format is missing.', 'nggallery'); + } break; case 'JPG': - $this->oldImage = @ImageCreateFromJpeg($this->fileName); + if (function_exists('ImageCreateFromJpeg')) { + $this->oldImage = @ImageCreateFromJpeg($this->fileName); + } else { + $img_err = __('Support for JPEG format is missing.', 'nggallery'); + } break; case 'PNG': - $this->oldImage = @ImageCreateFromPng($this->fileName); + if (function_exists('ImageCreateFromPng')) { + $this->oldImage = @ImageCreateFromPng($this->fileName); + } else { + $img_err = __('Support for PNG format is missing.', 'nggallery'); + } break; } if (!$this->oldImage) { - $this->errmsg = 'Create Image failed. Check memory limit'; + if ($img_err == null) { + $img_err = __('Check memory limit', 'nggallery'); + } + $this->errmsg = sprintf(__('Create Image failed. %1$s', 'nggallery'), $img_err); $this->error = true; } else { $size = GetImageSize($this->fileName); @@ -4501,7 +4522,7 @@ class C_NggLegacy_Thumbnail // attempt adding a new word until the width is too large; then start a new line and start again foreach ($words as $word) { // sanitize the text being input; imagettftext() can be sensitive - $TextSize = $this->ImageTTFBBoxDimensions($wmSize, 0, $wmFontPath, $line . preg_replace('~^(&([a-zA-Z0-9]);)~', htmlentities('${1}'), mb_convert_encoding($word, 'HTML-ENTITIES', 'UTF-8'))); + $TextSize = $this->ImageTTFBBoxDimensions($wmSize, 0, $this->correct_gd_unc_path($wmFontPath), $line . preg_replace('~^(&([a-zA-Z0-9]);)~', htmlentities('${1}'), mb_convert_encoding($word, 'HTML-ENTITIES', 'UTF-8'))); if ($watermark_image_width == 0) { $watermark_image_width = $TextSize['width']; } @@ -4517,7 +4538,7 @@ class C_NggLegacy_Thumbnail } $lines[] = trim($line); // use this string to determine our largest possible line height - $line_dimensions = $this->ImageTTFBBoxDimensions($wmSize, 0, $wmFontPath, 'MXQJALYmxqjabdfghjklpqry019`@$^&*(,!132'); + $line_dimensions = $this->ImageTTFBBoxDimensions($wmSize, 0, $this->correct_gd_unc_path($wmFontPath), 'MXQJALYmxqjabdfghjklpqry019`@$^&*(,!132'); $line_height = $line_dimensions['height'] * 1.05; // Create an image to apply our text to $this->workingImage = ImageCreateTrueColor($watermark_image_width, count($lines) * $line_height); @@ -4531,12 +4552,28 @@ class C_NggLegacy_Thumbnail // Put text on the image, line-by-line $y_pos = $wmSize; foreach ($lines as $line) { - imagettftext($this->workingImage, $wmSize, 0, 0, $y_pos, $TextColor, $wmFontPath, $line); + imagettftext($this->workingImage, $wmSize, 0, 0, $y_pos, $TextColor, $this->correct_gd_unc_path($wmFontPath), $line); $y_pos += $line_height; } $this->watermarkImgPath = $this->workingImage; return; } + /** + * Returns a path that can be used with imagettftext() and ImageTTFBBox() + * + * imagettftext() and ImageTTFBBox() cannot load resources from Windows UNC paths + * and require they be mangled to be like //server\filename instead of \\server\filename + * @param string $path Absolute file path + * @return string $path Mangled absolute file path + */ + public function correct_gd_unc_path($path) + { + if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN' && substr($path, 0, 2) === '\\\\') { + $path = ltrim($path, '\\\\'); + $path = '//' . $path; + } + return $path; + } /** * Calculates the width & height dimensions of ImageTTFBBox(). * @@ -4549,13 +4586,19 @@ class C_NggLegacy_Thumbnail */ public function ImageTTFBBoxDimensions($wmSize, $fontAngle, $wmFontPath, $text) { - $box = @ImageTTFBBox($wmSize, $fontAngle, $wmFontPath, $text) or die; + $box = @ImageTTFBBox($wmSize, $fontAngle, $this->correct_gd_unc_path($wmFontPath), $text); $max_x = max(array($box[0], $box[2], $box[4], $box[6])); $max_y = max(array($box[1], $box[3], $box[5], $box[7])); $min_x = min(array($box[0], $box[2], $box[4], $box[6])); $min_y = min(array($box[1], $box[3], $box[5], $box[7])); return array('width' => $max_x - $min_x, 'height' => $max_y - $min_y); } + public function applyFilter($filterType) + { + $args = func_get_args(); + array_unshift($args, $this->newImage); + return call_user_func_array('imagefilter', $args); + } /** * Modfied Watermark function by Steve Peart * http://parasitehosting.com/ diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_other_options/package.module.nextgen_other_options.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_other_options/package.module.nextgen_other_options.php index f6aed21204446e86f552724686b8b9678ca15e14..38549b1db72b09be849aea4d30d78617aa28d3c6 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_other_options/package.module.nextgen_other_options.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_other_options/package.module.nextgen_other_options.php @@ -526,8 +526,9 @@ class A_Watermarking_Ajax_Actions extends Mixin $settings->load(); } return array('thumbnail_url' => $thumbnail_url); + } else { + return array('thumbnail_url' => '', 'error' => 'You are not allowed to perform this operation'); } - return null; } } class A_Watermarks_Form extends Mixin diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_pro_upgrade/module.nextgen_pro_upgrade.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_pro_upgrade/module.nextgen_pro_upgrade.php index 42fb370d8da4ee7aecc72c614e7dc0c1745190d9..5580a128b3bfd5f1c80db096a605cae6520950cc 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_pro_upgrade/module.nextgen_pro_upgrade.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_pro_upgrade/module.nextgen_pro_upgrade.php @@ -14,7 +14,7 @@ class M_NextGen_Pro_Upgrade extends C_Base_Module 'photocrati-nextgen_pro_upgrade', 'NextGEN Pro Page', 'NextGEN Gallery Pro Upgrade Page', - '0.4', + '0.5', 'https://www.imagely.com/wordpress-gallery-plugin/nextgen-gallery/', 'Photocrati Media', 'https://www.imagely.com' diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_pro_upgrade/package.module.nextgen_pro_upgrade.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_pro_upgrade/package.module.nextgen_pro_upgrade.php index 11cc52974a5872deb905683614ba4d6aff5065f7..832125d22c9fb9472aafcbeb2be295252f3bc6bd 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_pro_upgrade/package.module.nextgen_pro_upgrade.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_pro_upgrade/package.module.nextgen_pro_upgrade.php @@ -28,12 +28,25 @@ class A_NextGen_Pro_Upgrade_Controller extends Mixin } public function get_page_title() { - return 'Upgrade to Pro'; + return __('Upgrade to Pro', 'nggallery'); } public function get_required_permission() { return 'NextGEN Change options'; } + public function get_i18n_strings() + { + $i18n = new stdClass(); + $i18n->plus_title = __('Upgrade to NextGEN Plus or Pro!', 'nggallery'); + $i18n->pro_title = __('Upgrade to NextGEN Pro!', 'nggallery'); + $i18n->plus_desc_first = __('Introducing the most powerful gallery system ever made for WordPress.', 'nggallery'); + $i18n->plus_desc_second = __('Take your galleries to the next level with the Plus and Pro extensions for NextGEN Gallery. ', 'nggallery'); + $i18n->pro_desc = __('NextGEN Pro now offers proofing and ecommerce! Extend NextGEN Gallery and NextGEN Plus with a complete solution for providing client galleries and for selling prints and digital downloads. Includes unlimited pricelists, PayPal and Stripe integration, and more.', 'nggallery'); + $i18n->plus_button = __('Learn More About NextGEN Plus', 'nggallery'); + $i18n->pro_button = __('Learn More About NextGEN Pro', 'nggallery'); + $i18n->click = __('CLICK TO LEARN MORE:', 'nggallery'); + return $i18n; + } public function index_action() { $this->object->enqueue_backend_resources(); @@ -41,19 +54,12 @@ class A_NextGen_Pro_Upgrade_Controller extends Mixin if ($html = C_Photocrati_Transient_Manager::fetch($key, FALSE)) { echo $html; } else { - // Get page content + // Get template and page content $template = 'photocrati-nextgen_pro_upgrade#plus'; if (defined('NGG_PLUS_PLUGIN_BASENAME')) { $template = 'photocrati-nextgen_pro_upgrade#pro'; } - $description = 'Extend NextGEN Gallery with 8 new pro gallery displays, a full screen responsive pro lightbox, commenting / social sharing / deep linking for individual images, ecommerce, digital downloads, and pro email support.'; - $headline = 'Upgrade to NextGEN Plus or NextGEN Pro'; - if (defined('NGG_PLUS_PLUGIN_BASENAME')) { - $description = 'NextGEN Pro now offers ecommerce! Extend NextGEN Gallery and NextGEN Plus with a complete solution for selling prints and digital downloads, including unlimited pricelists, PayPal and Stripe integration, and more.'; - $headline = 'Upgrade to NextGEN Pro with Ecommerce'; - } - $params = array('description' => $description, 'headline' => $headline); - $html = $this->render_view($template, $params, TRUE); + $html = $this->render_view($template, array('i18n' => $this->get_i18n_strings()), TRUE); // Cache it C_Photocrati_Transient_Manager::update($key, $html); // Render it diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_pro_upgrade/static/style.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_pro_upgrade/static/style.css index 0a11eac6a6ef08f31e5b5731a3800da24bff207e..d8a9df56bb0a429a8399d0cd89519adb1224c482 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_pro_upgrade/static/style.css +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_pro_upgrade/static/style.css @@ -1,44 +1,20 @@ -#nextgen_pro_upgrade_page { - width: 100%; - text-align: center; +#nextgen_pro_upgrade_page.wrap.about-wrap { + margin: 60px auto; } -#nextgen_pro_upgrade_page h1 { - font-size: 2.5em; - line-height: 1.01em; - margin-bottom: 40px; +#nextgen_pro_upgrade_page .centered { text-align: center; - padding: 20px 0 0px 0; -} - -#nextgen_pro_upgrade_page hr { - width: 25%; + margin: 1em; } -#nextgen_pro_upgrade_page h2 { - color: #afafaf; - line-height: 1.2em; - width: 65%; - margin: 0 auto; - margin-top: 2em; - margin-bottom: 2em; +#nextgen_pro_upgrade_page img { + width: 600px; + max-width: 100%; } -#nextgen_pro_upgrade_page a { - font-size: 1.2em; +#nextgen_pro_upgrade_page a.button-primary { + font-size: .8em; height: 2.8em; line-height: 1.6em; padding: .5em 1em .5em 1em; - min-width: 300px; -} - -#nextgen_pro_upgrade_first_link { - margin-right: .5em; -} - -@media only screen and (max-width: 655px) { - #nextgen_pro_upgrade_first_link { - margin-right: 0; - margin-bottom: 1em; - } } diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_pro_upgrade/static/style.min.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_pro_upgrade/static/style.min.css index 90ddedeee53dbad94981c61b28ec714eece4f326..94c2652f228ce2f7012148e6b04addb1a1c85fb7 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_pro_upgrade/static/style.min.css +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_pro_upgrade/static/style.min.css @@ -1 +1 @@ -#nextgen_pro_upgrade_page{width:100%;text-align:center}#nextgen_pro_upgrade_page h1{font-size:2.5em;line-height:1.01em;margin-bottom:40px;text-align:center;padding:20px 0 0 0}#nextgen_pro_upgrade_page hr{width:25%}#nextgen_pro_upgrade_page h2{color:#afafaf;line-height:1.2em;width:65%;margin:0 auto;margin-top:2em;margin-bottom:2em}#nextgen_pro_upgrade_page a{font-size:1.2em;height:2.8em;line-height:1.6em;padding:.5em 1em .5em 1em;min-width:300px}#nextgen_pro_upgrade_first_link{margin-right:.5em}@media only screen and (max-width:655px){#nextgen_pro_upgrade_first_link{margin-right:0;margin-bottom:1em}} \ No newline at end of file +#nextgen_pro_upgrade_page.wrap.about-wrap{margin:60px auto}#nextgen_pro_upgrade_page .centered{text-align:center;margin:1em}#nextgen_pro_upgrade_page img{width:600px;max-width:100%}#nextgen_pro_upgrade_page a.button-primary{font-size:.8em;height:2.8em;line-height:1.6em;padding:.5em 1em .5em 1em} \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_pro_upgrade/templates/plus.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_pro_upgrade/templates/plus.php index ebd8ca9c841b4d075407dd990a0facd09a1e7791..a298ca1f9147c578c716b92089cd8a61d0fbd0ca 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_pro_upgrade/templates/plus.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_pro_upgrade/templates/plus.php @@ -1,17 +1,21 @@ -<div id='nextgen_pro_upgrade_page' class='plus'> - <h1><?php echo $headline; ?></h1> - - <hr/> - - <h2><?php echo $description; ?></h2> - <h2>LEARN MORE:</h2> - - <a href='https://www.imagely.com/wordpress-gallery-plugin/nextgen-plus/' target='_blank' class="button-primary" id="nextgen_pro_upgrade_first_link"> - NextGEN Plus (Displays Only) - </a> - - <a href='https://www.imagely.com/wordpress-gallery-plugin/nextgen-pro/' target='_blank' class="button-primary"> - NextGEN Pro (Displays + Ecommerce) - </a> - +<div id='nextgen_pro_upgrade_page' class="wrap about-wrap"> + <h1 class="centered"><?php esc_html_e($i18n->plus_title); ?></h1> + <p class="about-text centered"><?php esc_html_e($i18n->plus_desc_first); ?><br> + <?php esc_html_e($i18n->plus_desc_second); ?> + </p> + <h3 class="about-text centered"><?php esc_html_e($i18n->click); ?></h3> + <div class="feature-section two-col"> + <div class="col"> + <a href="https://www.imagely.com/wordpress-gallery-plugin/nextgen-plus/" target="_blank"><img src="https://f001.backblaze.com/file/nextgen-gallery/nextgen-plus-ngg.jpg"></a> + <p class="about-text centered"> + <a href='https://www.imagely.com/wordpress-gallery-plugin/nextgen-plus/' target='_blank' class="button-primary"><?php esc_html_e($i18n->plus_button); ?></a> + </p> + </div> + <div class="col"> + <a href="https://www.imagely.com/wordpress-gallery-plugin/nextgen-pro/" target="_blank"><img src="https://f001.backblaze.com/file/nextgen-gallery/nextgen-pro-ngg.jpg"></a> + <p class="about-text centered"> + <a href='https://www.imagely.com/wordpress-gallery-plugin/nextgen-pro/' target='_blank' class="button-primary"><?php esc_html_e($i18n->pro_button); ?></a> + </p> + </div> + </div> </div> diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_pro_upgrade/templates/pro.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_pro_upgrade/templates/pro.php index 069e66509f787f702f3fe9591a56ec1c7db904a8..b1377101b1501340e12258e488ce5675f33ced5c 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_pro_upgrade/templates/pro.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_pro_upgrade/templates/pro.php @@ -1,12 +1,12 @@ -<div id='nextgen_pro_upgrade_page' class='pro'> - <h1><?php echo $headline; ?></h1> - - <hr/> - - <h2><?php echo $description; ?></h2> - - <a href='https://www.imagely.com/wordpress-gallery-plugin/nextgen-pro/' target='_blank' class="button-primary"> - Learn More About NextGEN Pro - </a> - +<div id='nextgen_pro_upgrade_page' class="wrap about-wrap"> + <h1 class="centered"><?php esc_html_e($i18n->pro_title); ?></h1> + <p class="about-text centered"><?php esc_html_e($i18n->pro_desc); ?></p> + <h3 class="about-text centered"><?php esc_html_e($i18n->click); ?></h3> + <p class="about-text centered"> + <a href="https://www.imagely.com/wordpress-gallery-plugin/nextgen-pro/" target="_blank"><img src="https://f001.backblaze.com/file/nextgen-gallery/nextgen-pro-ngg.jpg"></a> + </p> + <p class="about-text centered"> + <a href='https://www.imagely.com/wordpress-gallery-plugin/nextgen-pro/' target='_blank' class="button-primary"><?php esc_html_e($i18n->pro_button); ?></a> + </p> </div> + diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_xmlrpc/module.nextgen_xmlrpc.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_xmlrpc/module.nextgen_xmlrpc.php index 038f9b0fcdcb22315dc8b2edff0f8c70532a5f05..a52c83dac4476f26ba9e35d02b4d00d042e4bce4 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_xmlrpc/module.nextgen_xmlrpc.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_xmlrpc/module.nextgen_xmlrpc.php @@ -5,6 +5,7 @@ Module: photocrati-nextgen_xmlrpc } ***/ + class M_NextGen_XmlRpc extends C_Base_Module { function define() @@ -20,645 +21,62 @@ class M_NextGen_XmlRpc extends C_Base_Module ); } + function get_type_list() + { + return array( + 'C_NextGen_API' => 'class.nextgen_api.php', + 'C_NextGen_API_XMLRPC' => 'class.nextgen_api_xmlrpc.php', + 'A_NextGen_API_Ajax' => 'adapter.nextgen_api_ajax.php', + ); + } + + function _register_utilities() + { + $this->nextgen_api = C_NextGen_API::get_instance(); + $this->nextgen_api_xmlrpc = C_NextGen_API_XMLRPC::get_instance(); + } + function _register_hooks() { - add_filter('xmlrpc_methods', array(&$this, 'add_methods') ); + add_filter('xmlrpc_methods', array($this, 'add_methods') ); + } + + function _register_adapters() + { + // Provides AJAX actions for the JSON API interface + $this->get_registry()->add_adapter( + 'I_Ajax_Controller', 'A_NextGen_API_Ajax' + ); } function add_methods($methods) { - $methods['ngg.installed'] = array(&$this, 'get_version'); - $methods['ngg.setPostThumbnail'] = array(&$this, 'set_post_thumbnail'); + $methods['ngg.installed'] = array($this->nextgen_api_xmlrpc, 'get_version'); + $methods['ngg.setPostThumbnail'] = array($this->nextgen_api_xmlrpc, 'set_post_thumbnail'); // Image methods - $methods['ngg.getImage'] = array(&$this, 'get_image'); - $methods['ngg.getImages'] = array(&$this, 'get_images'); - $methods['ngg.uploadImage'] = array(&$this, 'upload_image'); - $methods['ngg.editImage'] = array(&$this, 'edit_image'); - $methods['ngg.deleteImage'] = array(&$this, 'delete_image'); + $methods['ngg.getImage'] = array($this->nextgen_api_xmlrpc, 'get_image'); + $methods['ngg.getImages'] = array($this->nextgen_api_xmlrpc, 'get_images'); + $methods['ngg.uploadImage'] = array($this->nextgen_api_xmlrpc, 'upload_image'); + $methods['ngg.editImage'] = array($this->nextgen_api_xmlrpc, 'edit_image'); + $methods['ngg.deleteImage'] = array($this->nextgen_api_xmlrpc, 'delete_image'); // Gallery methods - $methods['ngg.getGallery'] = array(&$this, 'get_gallery'); - $methods['ngg.getGalleries'] = array(&$this, 'get_galleries'); - $methods['ngg.newGallery'] = array(&$this, 'create_gallery'); - $methods['ngg.editGallery'] = array(&$this, 'edit_gallery'); - $methods['ngg.deleteGallery'] = array(&$this, 'delete_gallery'); + $methods['ngg.getGallery'] = array($this->nextgen_api_xmlrpc, 'get_gallery'); + $methods['ngg.getGalleries'] = array($this->nextgen_api_xmlrpc, 'get_galleries'); + $methods['ngg.newGallery'] = array($this->nextgen_api_xmlrpc, 'create_gallery'); + $methods['ngg.editGallery'] = array($this->nextgen_api_xmlrpc, 'edit_gallery'); + $methods['ngg.deleteGallery'] = array($this->nextgen_api_xmlrpc, 'delete_gallery'); // Album methods - $methods['ngg.getAlbum'] = array(&$this, 'get_album'); - $methods['ngg.getAlbums'] = array(&$this, 'get_albums'); - $methods['ngg.newAlbum'] = array(&$this, 'create_album'); - $methods['ngg.editAlbum'] = array(&$this, 'edit_album'); - $methods['ngg.deleteAlbum'] = array(&$this, 'delete_album'); + $methods['ngg.getAlbum'] = array($this->nextgen_api_xmlrpc, 'get_album'); + $methods['ngg.getAlbums'] = array($this->nextgen_api_xmlrpc, 'get_albums'); + $methods['ngg.newAlbum'] = array($this->nextgen_api_xmlrpc, 'create_album'); + $methods['ngg.editAlbum'] = array($this->nextgen_api_xmlrpc, 'edit_album'); + $methods['ngg.deleteAlbum'] = array($this->nextgen_api_xmlrpc, 'delete_album'); return $methods; } - - /** - * Gets the version of NextGEN Gallery installed - * @return string - */ - function get_version() - { - return array('version' => NGG_PLUGIN_VERSION); - } - - /** - * Login a user - * @param $username - * @param $password - * @return bool|WP_Error|WP_User - */ - function _login($username, $password, $blog_id=1) - { - $retval = FALSE; - - if (!is_a(($user_obj = wp_authenticate($username, $password)), 'WP_Error')) { - wp_set_current_user($user_obj->ID); - $retval = $user_obj; - - if (is_multisite()) switch_to_blog($blog_id); - } - - return $retval; - } - - function _can_manage_gallery($gallery_id_or_obj, $check_upload_capability=FALSE) - { - $retval = FALSE; - - // Get the gallery object, if we don't have it already - $gallery = NULL; - if (is_int($gallery_id_or_obj)) { - $gallery_mapper = C_Gallery_Mapper::get_instance(); - $gallery = $gallery_mapper->find($gallery_id_or_obj); - } - else $gallery = $gallery_id_or_obj; - - if ($gallery) { - $security = $this->get_registry()->get_utility('I_Security_Manager'); - $actor = $security->get_current_actor(); - if ($actor->get_entity_id() == $gallery->author) $retval = TRUE; - elseif ($actor->is_allowed('nextgen_edit_gallery_unowned')) $retval = TRUE; - - // Optionally, check if the user can upload to this gallery - if ($retval && $check_upload_capability) { - $retval = $actor->is_allowed('nextgen_upload_image'); - } - } - - return $retval; - } - - function _add_gallery_properties($gallery) - { - if (is_object($gallery)) { - - $image_mapper = C_Image_Mapper::get_instance(); - $storage = C_Gallery_Storage::get_instance(); - - // Vladimir's Lightroom plugins requires the 'id' to be a string - // Ask if he can accept integers as well. Currently, integers break - // his plugin - $gallery->gid = (string) $gallery->gid; - - // Set other gallery properties - $image_counter = array_pop($image_mapper->select('DISTINCT COUNT(*) as counter')->where(array("galleryid = %d", $gallery->gid))->run_query(FALSE, FALSE, TRUE)); - $gallery->counter = $image_counter->counter; - $gallery->abspath = $storage->get_gallery_abspath($gallery); - } - else return FALSE; - - return TRUE; - } - - /** - * Returns a single image object - * @param $args (blog_id, username, password, pid) - */ - function get_image($args, $return_model=FALSE) - { - $retval = new IXR_Error(403, 'Invalid username or password'); - $blog_id = intval($args[0]); - $username = strval($args[1]); - $password = strval($args[2]); - $image_id = intval($args[3]); - - // Authenticate the user - if ($this->_login($username, $password, $blog_id)) { - - // Try to find the image - $image_mapper = C_Image_Mapper::get_instance(); - if (($image = $image_mapper->find($image_id, TRUE))) { - - // Try to find the gallery that the image belongs to - $gallery_mapper = C_Gallery_Mapper::get_instance(); - if (($gallery = $gallery_mapper->find($image->galleryid))) { - - // Does the user have sufficient capabilities? - if ($this->_can_manage_gallery($gallery)) { - $storage = C_Gallery_Storage::get_instance(); - $image->imageURL = $storage->get_image_url($image,'full', TRUE); - $image->thumbURL = $storage->get_thumb_url($image, TRUE); - $image->imagePath = $storage->get_image_abspath($image); - $image->thumbPath = $storage->get_thumb_abspath($image); - $retval = $return_model ? $image : $image->get_entity(); - } - - else { - $retval = new IXR_Error(403, "You don't have permission to manage gallery #{$image->galleryid}"); - } - } - - // No gallery found - else { - $retval = new IXR_Error(404, "Gallery not found (with id #{$image->gallerid}"); - } - } - - // No image found - else $retval = FALSE; - } - - return $retval; - } - - /** - * Returns a collection of images - * @param $args (blog_id, username, password, gallery_id - */ - function get_images($args) - { - $retval = new IXR_Error(403, 'Invalid username or password'); - $blog_id = intval($args[0]); - $username = strval($args[1]); - $password = strval($args[2]); - $gallery_id = intval($args[3]); - - // Authenticate the user - if ($this->_login($username, $password, $blog_id)) { - - // Try to find the gallery - $mapper = C_Gallery_Mapper::get_instance(); - if (($gallery = $mapper->find($gallery_id, TRUE))) { - - // Does the user have sufficient capabilities? - if ($this->_can_manage_gallery($gallery)) { - $retval = $gallery->get_images(); - } - else { - $retval = new IXR_Error(403, "You don't have permission to manage gallery #{$image->galleryid}"); - } - } - - // No gallery found - else { - $retval = new IXR_Error(404, "Gallery not found (with id #{$image->gallerid}"); - } - } - - return $retval; - } - - /** - * Uploads an image to a particular gallery - * @param $args (blog_id, username, password, data) - * - * Data is an assoc array: - * o string name - * o string type (optional) - * o base64 bits - * o bool overwrite (optional) - * o int gallery - * o int image_id (optional) - * @return image - */ - function upload_image($args) - { - $retval = new IXR_Error(403, 'Invalid username or password'); - $blog_id = intval($args[0]); - $username = strval($args[1]); - $password = strval($args[2]); - $data = $args[3]; - $gallery_id = isset($data['gallery_id']) ? $data['gallery_id'] : $data['gallery']; - if (!isset($data['override'])) $data['override'] = FALSE; - if (!isset($data['overwrite']))$data['overwrite']= FALSE; - $data['override'] = $data['overwrite']; - - // Authenticate the user - if ($this->_login($username, $password, $blog_id)) { - - // Try to find the gallery - $mapper = C_Gallery_Mapper::get_instance(); - if (($gallery = $mapper->find($gallery_id, TRUE))) { - - // Does the user have sufficient capabilities? - if ($this->_can_manage_gallery($gallery, TRUE)) { - - // Upload the image - $storage = C_Gallery_Storage::get_instance(); - $image = $storage->upload_base64_image($gallery, $data['bits'], $data['name'], $data['image_id'], $data['override']); - if ($image) { - $storage = C_Gallery_Storage::get_instance(); - $image->imageURL = $storage->get_image_url($image); - $image->thumbURL = $storage->get_thumb_url($image); - $image->imagePath = $storage->get_image_abspath($image); - $image->thumbPath = $storage->get_thumb_abspath($image); - $retval = $image->get_entity(); - } - else - $retval = new IXR_Error(500, "Could not upload image"); - } - else { - $retval = new IXR_Error(403, "You don't have permission to upload to gallery #{$image->galleryid}"); - } - } - - // No gallery found - else { - $retval = new IXR_Error(404, "Gallery not found (with id #{$image->gallerid}"); - } - } - - return $retval; - } - - /** - * Edits an image object - * @param $args (blog_id, username, password, image_id, alttext, description, exclude, other_properties - */ - function edit_image($args) - { - $alttext = strval($args[4]); - $description = strval($args[5]); - $exclude = intval($args[6]); - $properties = isset($args[7]) ? (array)$args[7] : array(); - - $retval = $this->get_image($args, TRUE); - if (!($retval instanceof IXR_Error)) { - $retval->alttext = $alttext; - $retval->description = $description; - $retval->exclude = $exclude; - - // Other properties can be specified using an associative array - foreach ($properties as $key => $value) { - $retval->$key = $value; - } - - // Unset any dynamic properties not part of the schema - foreach (array('imageURL', 'thumbURL', 'imagePath', 'thumbPath') as $key) { - unset($retval->$key); - } - - $retval = $retval->save(); - } - - return $retval; - } - - /** - * Deletes an existing image from a gallery - * @param $args (blog_id, username, password, image_id) - */ - function delete_image($args) - { - $retval = $this->get_image($args, TRUE); - if (!($retval instanceof IXR_Error)) { - $retval = $retval->destroy(); - } - return $retval; - } - - /** - * Creates a new gallery - * @param $args (blog_id, username, password, title) - */ - function create_gallery($args) - { - $retval = new IXR_Error(403, 'Invalid username or password'); - $blog_id = intval($args[0]); - $username = strval($args[1]); - $password = strval($args[2]); - $title = strval($args[3]); - - // Authenticate the user - if ($this->_login($username, $password, $blog_id)) { - - $security = $this->get_registry()->get_utility('I_Security_Manager'); - if ($security->is_allowed('nextgen_edit_gallery')) { - $mapper = C_Gallery_Mapper::get_instance(); - if (($gallery = $mapper->create(array('title' => $title))) && $gallery->save()) { - $retval = $gallery->id(); - } - else $retval = new IXR_Error(500, "Unable to create gallery"); - - } - else $retval = new IXR_Error(403, "Sorry, but you must be able to manage galleries. Check your roles/capabilities."); - } - - return $retval; - } - - /** - * Edits an existing gallery - * @param $args (blog_id, username, password, gallery_id, name, title, description, preview_pic_id) - */ - function edit_gallery($args) - { - $retval = new IXR_Error(403, 'Invalid username or password'); - $blog_id = intval($args[0]); - $username = strval($args[1]); - $password = strval($args[2]); - $gallery_id = intval($args[3]); - $name = strval($args[4]); - $title = strval($args[5]); - $galdesc = strval($args[6]); - $image_id = intval($args[7]); - $properties = isset($args[8]) ? (array) $args[8] : array(); - - // Authenticate the user - if ($this->_login($username, $password, $blog_id)) { - - $mapper = C_Gallery_Mapper::get_instance(); - if (($gallery = $mapper->find($gallery_id, TRUE))) { - if ($this->_can_manage_gallery($gallery)) { - $gallery->name = $name; - $gallery->title = $title; - $gallery->galdesc = $galdesc; - $gallery->previewpic = $image_id; - foreach ($properties as $key => $value) { - $gallery->$key = $value; - } - - // Unset dynamic properties not part of the schema - unset($gallery->counter); - unset($gallery->abspath); - - $retval = $gallery->save(); - } - else $retval = new IXR_Error(403, "You don't have permission to modify this gallery"); - } - else $retval = new IXR_Error(404, "Gallery #{$gallery_id} doesn't exist"); - } - - return $retval; - } - - /** - * Returns all galleries - * @param $args (blog_id, username, password) - */ - function get_galleries($args) - { - $retval = new IXR_Error(403, 'Invalid username or password'); - $blog_id = intval($args[0]); - $username = strval($args[1]); - $password = strval($args[2]); - - // Authenticate the user - if ($this->_login($username, $password, $blog_id)) { - - // Do we have permission? - $security = $this->get_registry()->get_utility('I_Security_Manager'); - if ($security->is_allowed('nextgen_edit_gallery')) { - $mapper = C_Gallery_Mapper::get_instance(); - $retval = array(); - foreach ($mapper->find_all() as $gallery) { - $this->_add_gallery_properties($gallery); - $retval[$gallery->{$gallery->id_field}] = (array)$gallery; - } - } - else $retval = new IXR_Error( 401, __( 'Sorry, you must be able to manage galleries' ) ); - } - - return $retval; - } - - /** - * Gets a single gallery instance - * @param $args (blog_id, username, password, gallery_id) - */ - function get_gallery($args, $return_model=FALSE) - { - $retval = new IXR_Error(403, 'Invalid username or password'); - $blog_id = intval($args[0]); - $username = strval($args[1]); - $password = strval($args[2]); - $gallery_id = intval($args[3]); - - // Authenticate the user - if ($this->_login($username, $password, $blog_id)) { - $mapper = C_Gallery_Mapper::get_instance(); - if (($gallery = $mapper->find($gallery_id, TRUE))) { - if ($this->_can_manage_gallery($gallery)) { - $this->_add_gallery_properties($gallery); - $retval = $return_model ? $gallery : $gallery->get_entity(); - } - else $retval = new IXR_Error(403, "Sorry, but you don't have permission to manage gallery #{$gallery->gid}"); - } - else $retval = FALSE; - } - - return $retval; - } - - /** - * Deletes a gallery - * @param $args (blog_id, username, password, gallery_id) - */ - function delete_gallery($args) - { - $retval = $this->get_gallery($args, TRUE); - - if (!($retval instanceof IXR_Error) and is_object($retval)) { - $retval = $retval->destroy(); - } - - return $retval; - } - - /** - * Creates a new album - * @param $args (blog_id, username, password, title, previewpic, description, galleries - */ - function create_album($args) - { - $retval = new IXR_Error(403, 'Invalid username or password'); - $blog_id = intval($args[0]); - $username = strval($args[1]); - $password = strval($args[2]); - $title = strval($args[3]); - $previewpic = isset($args[4]) ? intval($args[4]): 0; - $desc = isset($args[5]) ? strval($args[5]) : ''; - $sortorder = isset($args[6]) ? $args[6] : ''; - $page_id = isset($args[7]) ? intval($args[7]) : 0; - - // Authenticate the user - if ($this->_login($username, $password, $blog_id)) { - - // Is request allowed? - $security = $this->get_registry()->get_utility('I_Security_Manager'); - if ($security->is_allowed('nextgen_edit_album')) { - - $mapper = C_Album_Mapper::get_instance(); - $album = $mapper->create(array( - 'name' => $title, - 'previewpic' => $previewpic, - 'albumdesc' => $desc, - 'sortorder' => $sortorder, - 'pageid' => $page_id - )); - - if ($album->save()) $retval = $album->id(); - else $retval = new IXR_Error(500, "Unable to create album"); - } - } - - return $retval; - } - - - /** - * Returns all albums - * @param $args (blog_id, username, password) - * @return IXR_Error - */ - function get_albums($args) - { - $retval = new IXR_Error(403, 'Invalid username or password'); - $blog_id = intval($args[0]); - $username = strval($args[1]); - $password = strval($args[2]); - - // Authenticate the user - if ($this->_login($username, $password, $blog_id)) { - - // Are we allowed? - $security = $this->get_registry()->get_utility('I_Security_Manager'); - if ($security->is_allowed('nextgen_edit_album')) { - - // Fetch all albums - $mapper = C_Album_Mapper::get_instance(); - $retval = array(); - foreach ($mapper->find_all() as $album) { - // Vladimir's Lightroom plugins requires the 'id' to be a string - // Ask if he can accept integers as well. Currently, integers break - // his plugin - $album->id = (string) $album->id; - $album->galleries = $album->sortorder; - - $retval[$album->{$album->id_field}] = (array) $album; - } - } - else $retval = new IXR_Error(403, "Sorry, you must be able to manage albums"); - - - } - - return $retval; - } - - /** - * Gets a single album - * @param $args (blog_id, username, password, album_id) - */ - function get_album($args, $return_model=FALSE) - { - $retval = new IXR_Error(403, 'Invalid username or password'); - $blog_id = intval($args[0]); - $username = strval($args[1]); - $password = strval($args[2]); - $album_id = intval($args[3]); - - // Authenticate the user - if ($this->_login($username, $password, $blog_id)) { - - // Are we allowed? - $security = $this->get_registry()->get_utility('I_Security_Manager'); - if ($security->is_allowed('nextgen_edit_album')) { - $mapper = C_Album_Mapper::get_instance(); - if (($album = $mapper->find($album_id, TRUE))) { - // Vladimir's Lightroom plugins requires the 'id' to be a string - // Ask if he can accept integers as well. Currently, integers break - // his plugin - $album->id = (string) $album->id; - $album->galleries = $album->sortorder; - - $retval = $return_model ? $album : $album->get_entity(); - } - else $retval = FALSE; - - } - else $retval = new IXR_Error(403, "Sorry, you must be able to manage albums"); - } - - return $retval; - } - - /** - * Deletes an existing album - * @param $args (blog_id, username, password, album_id) - */ - function delete_album($args) - { - $retval = $this->get_album($args, TRUE); - - if (!($retval instanceof IXR_Error)) { - $retval = $retval->destroy(); - } - - return $retval; - } - - /** - * Edit an existing album - * @param $args (blog_id, username, password, album_id, name, preview pic id, description, galleries) - */ - function edit_album($args) - { - $retval = $this->get_album($args, TRUE); - - if (!($retval instanceof IXR_Error)) { - $retval->name = strval($args[4]); - $retval->previewpic = intval($args[5]); - $retval->albumdesc = strval($args[6]); - $retval->sortorder = $args[7]; - - $properties = isset($args[8]) ? $args[8] : array(); - foreach ($properties as $key => $value) $retval->$key = $value; - unset($retval->galleries); - - $retval = $retval->save(); - } - - return $retval; - } - - /** - * Sets the post thumbnail for a post to a NextGEN Gallery image - * @param $args (blog_id, username, password, post_id, image_id) - * - * @return IXR_Error|int attachment id - */ - function set_post_thumbnail($args) - { - $retval = new IXR_Error(403, 'Invalid username or password'); - $blog_id = intval($args[0]); - $username = strval($args[1]); - $password = strval($args[2]); - $post_ID = intval($args[3]); - $image_id = intval($args[4]); - - // Authenticate the user - if ($this->_login($username, $password, $blog_id)) { - if ( current_user_can( 'edit_post', $post_ID )) { - $retval = C_Gallery_Storage::get_instance()->set_post_thumbnail($post_ID, $image_id); - } - else $retval = new IXR_Error(403, "Sorry but you need permission to do this"); - } - - return $retval; - } } -new M_NextGen_XmlRpc; \ No newline at end of file +new M_NextGen_XmlRpc; diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_xmlrpc/package.module.nextgen_xmlrpc.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_xmlrpc/package.module.nextgen_xmlrpc.php new file mode 100644 index 0000000000000000000000000000000000000000..820dbcbee769f21a873d7bf137e1cdc06f47bb39 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_xmlrpc/package.module.nextgen_xmlrpc.php @@ -0,0 +1,1386 @@ +<?php +/** + * Provides AJAX actions for JSON API interface + */ +class A_NextGen_API_Ajax extends Mixin +{ + public $nextgen_api = NULL; + public function get_nextgen_api() + { + if (is_null($this->nextgen_api)) { + $this->nextgen_api = C_NextGen_API::get_instance(); + } + return $this->nextgen_api; + } + public function get_nextgen_api_path_list_action() + { + $api = $this->get_nextgen_api(); + $username = $this->object->param('q'); + $password = $this->object->param('z'); + $app_config = $this->object->param('app_config'); + $user_obj = wp_authenticate($username, $password); + $response = array(); + if ($user_obj != null && !is_a($user_obj, 'WP_Error')) { + wp_set_current_user($user_obj->ID); + $ftp_method = isset($app_config['ftp_method']) ? $app_config['ftp_method'] : 'ftp'; + $creds = array('connection_type' => $ftp_method == 'sftp' ? 'ssh' : 'ftp', 'hostname' => $app_config['ftp_host'], 'port' => $app_config['ftp_port'], 'username' => $app_config['ftp_user'], 'password' => $app_config['ftp_pass']); + require_once ABSPATH . 'wp-admin/includes/file.php'; + $wp_filesystem = $api->create_filesystem_access($creds); + $root_path = null; + $base_path = null; + $plugin_path = null; + if ($wp_filesystem) { + $root_path = $wp_filesystem->wp_content_dir(); + $base_path = $wp_filesystem->abspath(); + $plugin_path = $wp_filesystem->wp_plugins_dir(); + } else { + // fallbacks when unable to connect, try to see if we know the path already + $root_path = get_option('ngg_ftp_root_path'); + if (defined('FTP_BASE')) { + $base_path = FTP_BASE; + } + if ($root_path == null && defined('FTP_CONTENT_DIR')) { + $root_path = FTP_CONTENT_DIR; + } + if (defined('FTP_PLUGIN_DIR')) { + $plugin_path = FTP_PLUGIN_DIR; + } + if ($base_path == null && $root_path != null) { + $base_path = dirname($root_path); + } + if ($root_path == null && $base_path != null) { + $root_path = rtrim($base_path, '/\\') . '/wp-content/'; + } + if ($plugin_path == null && $base_path != null) { + $plugin_path = rtrim($base_path, '/\\') . '/wp-content/plugins/'; + } + } + if ($root_path != NULL) { + $response['result'] = 'ok'; + $response['result_object'] = array('root_path' => $root_path, 'wp_content_path' => $root_path, 'wp_base_path' => $base_path, 'wp_plugin_path' => $plugin_path); + } else { + if ($wp_filesystem != null) { + $response['result'] = 'error'; + $response['error'] = array('code' => C_NextGen_API::ERR_FTP_NO_PATH, 'message' => __('Could not determine FTP path.', 'nggallery')); + } else { + $response['result'] = 'error'; + $response['error'] = array('code' => C_NextGen_API::ERR_FTP_NOT_CONNECTED, 'message' => __('Could not connect to FTP to determine path.', 'nggallery')); + } + } + } else { + $response['result'] = 'error'; + $response['error'] = array('code' => C_NextGen_API::ERR_NOT_AUTHENTICATED, 'message' => __('Authentication Failed.', 'nggallery')); + } + return $response; + } + public function enqueue_nextgen_api_task_list_action() + { + $api = $this->get_nextgen_api(); + $username = $this->object->param('q'); + $password = $this->object->param('z'); + $response = array(); + $user_obj = wp_authenticate($username, $password); + if ($user_obj != null && !is_a($user_obj, 'WP_Error')) { + wp_set_current_user($user_obj->ID); + $security = $this->get_registry()->get_utility('I_Security_Manager'); + $app_config = $this->object->param('app_config'); + $task_list = $this->object->param('task_list'); + if ($task_list != null) { + $task_count = count($task_list); + $auth_count = 0; + foreach ($task_list as &$task_item) { + $task_id = isset($task_item['id']) ? $task_item['id'] : null; + $task_name = isset($task_item['name']) ? $task_item['name'] : null; + $task_type = isset($task_item['type']) ? $task_item['type'] : null; + $task_query = isset($task_item['query']) ? $task_item['query'] : null; + $type_parts = explode('_', $task_name); + $type_context = array_pop($type_parts); + $type_action = array_pop($type_parts); + $task_auth = false; + switch ($task_type) { + case 'gallery_add': + $task_auth = $security->is_allowed('nextgen_edit_gallery'); + break; + case 'gallery_remove': + case 'gallery_edit': + $query_id = $api->get_query_id($task_query['id']); + $gallery = null; + // The old NextGEN XMLRPC API had this logic so replicating it here for safety + if ($query_id) { + $gallery_mapper = C_Gallery_Mapper::get_instance(); + $gallery = $gallery_mapper->find($query_id); + } + if ($gallery != null) { + $actor = $security->get_current_actor(); + $task_auth = $actor->get_entity_id() == $gallery->author || $actor->is_allowed('nextgen_edit_gallery_unowned'); + } else { + $task_auth = $security->is_allowed('nextgen_edit_gallery'); + } + break; + case 'album_add': + $task_auth = $security->is_allowed('nextgen_edit_album'); + break; + case 'album_remove': + $task_auth = $security->is_allowed('nextgen_edit_album'); + break; + case 'album_edit': + $task_auth = $security->is_allowed('nextgen_edit_album'); + break; + case 'image_list_move': + break; + } + if ($task_auth) { + $auth_count++; + } + $task_item['auth'] = $task_auth ? 'allow' : 'forbid'; + } + if ($task_count == $auth_count) { + $job_id = $api->add_job(array('user' => $user_obj->ID), $app_config, $task_list); + if ($job_id != null) { + $handler_delay = defined('NGG_API_JOB_HANDLER_DELAY') ? intval(NGG_API_JOB_HANDLER_DELAY) : 0; + $handler_delay = $handler_delay > 0 ? $handler_delay : 30; + /* in seconds */ + $response['result'] = 'ok'; + $response['result_object'] = array('job_id' => $job_id, 'job_handler_url' => home_url('/photocrati_ajax?action=execute_nextgen_api_task_list'), 'job_handler_delay' => $handler_delay); + } else { + $response['result'] = 'error'; + $response['error'] = array('code' => C_NextGen_API::ERR_JOB_NOT_ADDED, 'message' => __('Job could not be added.', 'nggallery')); + } + } else { + $response['result'] = 'error'; + $response['error'] = array('code' => C_NextGen_API::ERR_NOT_AUTHORIZED, 'message' => __('Authorization Failed.', 'nggallery')); + } + } else { + $response['result'] = 'error'; + $response['error'] = array('code' => C_NextGen_API::ERR_NO_TASK_LIST, 'message' => __('No task list was specified.', 'nggallery')); + } + } else { + $response['result'] = 'error'; + $response['error'] = array('code' => C_NextGen_API::ERR_NOT_AUTHENTICATED, 'message' => __('Authentication Failed.', 'nggallery')); + } + return $response; + } + public function execute_nextgen_api_task_list_action() + { + $api = $this->get_nextgen_api(); + $job_list = $api->get_job_list(); + $response = array(); + if ($api->is_execution_locked()) { + $response['result'] = 'ok'; + $response['info'] = array('code' => C_NextGen_API::INFO_EXECUTION_LOCKED, 'message' => __('Job execution is locked.', 'nggallery')); + } else { + if ($job_list != null) { + $api->set_execution_locked(true); + $job_count = count($job_list); + $done_count = 0; + foreach ($job_list as $job) { + $result = $api->handle_job($job['id'], $job['data'], $job['app_config'], $job['task_list']); + if ($result) { + $done_count++; + } + if ($api->should_stop_execution()) { + break; + } + } + $api->set_execution_locked(false); + if ($done_count == $job_count) { + $response['result'] = 'ok'; + $response['info'] = array('code' => C_NextGen_API::INFO_JOB_LIST_FINISHED, 'message' => __('Job list is finished.', 'nggallery')); + } else { + $response['result'] = 'ok'; + $response['info'] = array('code' => C_NextGen_API::INFO_JOB_LIST_UNFINISHED, 'message' => __('Job list is unfinished.', 'nggallery')); + } + } else { + $response['result'] = 'ok'; + $response['info'] = array('code' => C_NextGen_API::INFO_NO_JOB_LIST, 'message' => __('Job list is empty.', 'nggallery')); + } + } + return $response; + } +} +class C_NextGen_API extends C_Component +{ + const CRON_KEY = 'nextgen.api.task_list'; + /* NOTE: these constants' numeric values are used elsewhere, don't change the values */ + const ERR_NO_TASK_LIST = 1001; + const ERR_NOT_AUTHENTICATED = 1002; + const ERR_NOT_AUTHORIZED = 1003; + const ERR_JOB_NOT_ADDED = 1004; + const ERR_FTP_NOT_AUTHENTICATED = 1101; + const ERR_FTP_NOT_CONNECTED = 1102; + const ERR_FTP_NO_PATH = 1103; + const INFO_NO_JOB_LIST = 6001; + const INFO_JOB_LIST_FINISHED = 6002; + const INFO_JOB_LIST_UNFINISHED = 6003; + const INFO_EXECUTION_LOCKED = 6004; + public static $_instances = array(); + public $_start_time; + public static function get_instance($context = false) + { + if (!isset(self::$_instances[$context])) { + self::$_instances[$context] = new self($context); + } + return self::$_instances[$context]; + } + public function define($context = false) + { + parent::define($context); + $this->implement('I_NextGen_API'); + $this->_start_time = time(); + } + public function should_stop_execution() + { + $timeout = defined('NGG_API_JOB_HANDLER_TIMEOUT') ? intval(NGG_API_JOB_HANDLER_TIMEOUT) : intval(ini_get('max_execution_time')) - 3; + $timeout = $timeout > 0 ? $timeout : 27; + /* most hosts have a limit of 30 seconds execution time, so 27 should be a safe default */ + return time() - $this->_start_time >= $timeout; + } + public function is_execution_locked() + { + $lock_time = get_option('ngg_api_execution_lock', 0); + if ($lock_time == 0) { + return false; + } + $lock_max = defined('NGG_API_EXECUTION_LOCK_MAX') ? intval(NGG_API_EXECUTION_LOCK_MAX) : 0; + $lock_max = $lock_max > 0 ? $lock_max : 60 * 5; + /* if the lock is 5 minutes old assume something went wrong and the lock couldn't be unset */ + $time_diff = time() - $lock_time; + if ($time_diff > $lock_max) { + return false; + } + return true; + } + public function set_execution_locked($locked) + { + if ($locked) { + update_option('ngg_api_execution_lock', time()); + } else { + update_option('ngg_api_execution_lock', 0); + } + } + public function get_job_list() + { + return get_option('ngg_api_job_list'); + } + public function add_job($job_data, $app_config, $task_list) + { + $job_list = $this->get_job_list(); + $job_id = uniqid(); + while (isset($job_list[$job_id])) { + $job_id = uniqid(); + } + $job = array('id' => $job_id, 'data' => $job_data, 'app_config' => $app_config, 'task_list' => $task_list); + $job_list[$job_id] = $job; + update_option('ngg_api_job_list', $job_list); + return $job_id; + } + public function _update_job($job_id, $job) + { + $job_list = $this->get_job_list(); + if (isset($job_list[$job_id])) { + $job_list[$job_id] = $job; + update_option('ngg_api_job_list', $job_list); + } + } + public function remove_job($job_id) + { + $job_list = $this->get_job_list(); + if (isset($job_list[$job_id])) { + unset($job_list[$job_id]); + update_option('ngg_api_job_list', $job_list); + } + } + public function get_job($job_id) + { + $job_list = $this->get_job_list(); + if (isset($job_list[$job_id])) { + return $job_list[$job_id]; + } + return null; + } + public function get_job_data($job_id) + { + $job = $this->get_job($job_id); + if ($job != null) { + return $job['data']; + } + return null; + } + public function get_job_task_list($job_id) + { + $job = $this->get_job($job_id); + if ($job != null) { + return $job['task_list']; + } + return null; + } + public function set_job_task_list($job_id, $task_list) + { + $job = $this->get_job($job_id); + if ($job != null) { + $job['task_list'] = $task_list; + $this->_update_job($job_id, $job); + return true; + } + return false; + } + public function get_job_status_file($job_id) + { + $job = $this->get_job($job_id); + if ($job != null) { + return $job['task_list']; + } + return null; + } + public function create_filesystem_access($args, $method = null) + { + // taken from wp-admin/includes/file.php but with modifications + if (!$method && isset($args['connection_type']) && 'ssh' == $args['connection_type'] && extension_loaded('ssh2') && function_exists('stream_get_contents')) { + $method = 'ssh2'; + } + if (!$method && extension_loaded('ftp')) { + $method = 'ftpext'; + } + if (!$method && (extension_loaded('sockets') || function_exists('fsockopen'))) { + $method = 'ftpsockets'; + } + //Sockets: Socket extension; PHP Mode: FSockopen / fwrite / fread + if (!$method) { + return false; + } + require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php'; + if (!class_exists("WP_Filesystem_{$method}")) { + /** + * Filter the path for a specific filesystem method class file. + * + * @since 2.6.0 + * + * @see get_filesystem_method() + * + * @param string $path Path to the specific filesystem method class file. + * @param string $method The filesystem method to use. + */ + $abstraction_file = apply_filters('filesystem_method_file', ABSPATH . 'wp-admin/includes/class-wp-filesystem-' . $method . '.php', $method); + if (!file_exists($abstraction_file)) { + return false; + } + require_once $abstraction_file; + } + $method_class = "WP_Filesystem_{$method}"; + $wp_filesystem = new $method_class($args); + //Define the timeouts for the connections. Only available after the construct is called to allow for per-transport overriding of the default. + if (!defined('FS_CONNECT_TIMEOUT')) { + define('FS_CONNECT_TIMEOUT', 30); + } + if (!defined('FS_TIMEOUT')) { + define('FS_TIMEOUT', 30); + } + if (is_wp_error($wp_filesystem->errors) && $wp_filesystem->errors->get_error_code()) { + return false; + } + if (!$wp_filesystem->connect()) { + if ($method == 'ftpext') { + // attempt connecting with alternative method + return $this->create_filesystem_access($args, 'ftpsockets'); + } + return false; + } + // Set the permission constants if not already set. + if (!defined('FS_CHMOD_DIR')) { + define('FS_CHMOD_DIR', fileperms(ABSPATH) & 511 | 493); + } + if (!defined('FS_CHMOD_FILE')) { + define('FS_CHMOD_FILE', fileperms(ABSPATH . 'index.php') & 511 | 420); + } + return $wp_filesystem; + } + // returns an actual scalar ID based on parametric ID (e.g. a parametric ID could represent the query ID from another task) + public function get_query_id($id, &$task_list) + { + $task_id = $id; + if (is_object($task_id) || is_array($task_id)) { + $id = null; + // it was specified that the query ID is referencing the result from another task + if (isset($task_id['target']) && $task_id['target'] == 'task') { + if (isset($task_id['id']) && isset($task_list[$task_id['id']])) { + $target_task = $task_list[$task_id['id']]; + if (isset($target_task['query']['id'])) { + $id = $target_task['query']['id']; + } + } + } + } + return $id; + } + // returns an actual scalar ID based on parametric ID (e.g. a parametric ID could represent the resulting object ID from another task) + public function get_object_id($id, &$result_list) + { + $task_id = $id; + if (is_object($task_id) || is_array($task_id)) { + $id = null; + // it was specified that the query ID is referencing the result from another task + if (isset($task_id['target']) && $task_id['target'] == 'task') { + if (isset($task_id['id']) && isset($result_list[$task_id['id']])) { + $target_result = $result_list[$task_id['id']]; + if (isset($target_result['object_id'])) { + $id = $target_result['object_id']; + } + } + } + } + return $id; + } + public function handle_job($job_id, $job_data, $app_config, $task_list) + { + $job_user = $job_data['user']; + $task_count = count($task_list); + $done_count = 0; + $skip_count = 0; + $task_list_result = array(); + wp_set_current_user($job_user); + /* This block does all of the filesystem magic: + * - determines web paths based on FTP paths + * - initializes the WP_Filesystem mechanism in case this host doesn't support direct file access + * (this might not be 100% reliable right now due to NG core not making use of WP_Filesystem) + */ + // $ftp_path is assumed to be WP_CONTENT_DIR as accessed through the FTP mount point + $ftp_path = rtrim($app_config['ftp_path'], '/\\'); + $full_path = rtrim($app_config['full_path'], '/\\'); + $root_path = rtrim(WP_CONTENT_DIR, '/\\'); + $creds = true; + // WP_Filesystem(true) requests direct filesystem access + $fs_sep = DIRECTORY_SEPARATOR; + $wp_fs = null; + require_once ABSPATH . 'wp-admin/includes/file.php'; + if (get_filesystem_method() !== 'direct') { + $fs_sep = '/'; + $ftp_method = isset($app_config['ftp_method']) ? $app_config['ftp_method'] : 'ftp'; + $creds = array('connection_type' => $ftp_method == 'sftp' ? 'ssh' : 'ftp', 'hostname' => $app_config['ftp_host'], 'port' => $app_config['ftp_port'], 'username' => $app_config['ftp_user'], 'password' => $app_config['ftp_pass']); + } + if (WP_Filesystem($creds)) { + $wp_fs = $GLOBALS['wp_filesystem']; + $path_prefix = $full_path; + if ($wp_fs->method === 'direct') { + $path_prefix = str_replace($ftp_path, $root_path, $full_path); + } + } + foreach ($task_list as &$task_item) { + $task_id = isset($task_item['id']) ? $task_item['id'] : null; + $task_name = isset($task_item['name']) ? $task_item['name'] : null; + $task_type = isset($task_item['type']) ? $task_item['type'] : null; + $task_auth = isset($task_item['auth']) ? $task_item['auth'] : null; + $task_query = isset($task_item['query']) ? $task_item['query'] : null; + $task_object = isset($task_item['object']) ? $task_item['object'] : null; + $task_status = isset($task_item['status']) ? $task_item['status'] : null; + $task_result = isset($task_item['result']) ? $task_item['result'] : null; + // make sure we don't repeat execution of already finished tasks + if ($task_status == 'done') { + $done_count++; + // for previously finished tasks, store the result as it may be needed by future tasks + if ($task_id != null && $task_result != null) { + $task_list_result[$task_id] = $task_result; + } + continue; + } + // make sure only valid and authorized tasks are executed + if ($task_status == 'error' || $task_auth != 'allow') { + $skip_count++; + continue; + } + // the task query ID can be a simple (integer) ID or more complex ID that gets converted to a simple ID, for instance to point to an object that is the result of a previously finished task + if (isset($task_query['id'])) { + $task_query['id'] = $this->get_object_id($task_query['id'], $task_list_result); + } + $task_error = null; + switch ($task_type) { + case 'gallery_add': + $mapper = C_Gallery_Mapper::get_instance(); + $gallery = null; + $gal_errors = ''; + if (isset($task_query['id'])) { + $gallery = $mapper->find($task_query['id'], true); + } + if ($gallery == null) { + $title = isset($task_object['title']) ? $task_object['title'] : ''; + $gallery = $mapper->create(array('title' => $title)); + if (!$gallery || !$gallery->save()) { + if ($gallery != null) { + $gal_errors = $gallery->get_errors(); + if ($gal_errors != null) { + $gal_errors = ' [' . json_encode($gal_errors) . ']'; + } + } + $gallery = null; + } + } + if ($gallery != null) { + $task_status = 'done'; + $task_result['object_id'] = $gallery->id(); + } else { + $task_status = 'error'; + $task_error = array('level' => 'fatal', 'message' => sprintf(__('Gallery creation failed for "%1$s"%2$s.', 'nggallery'), $title, $gal_errors)); + } + break; + case 'gallery_remove': + case 'gallery_edit': + if (isset($task_query['id'])) { + $mapper = C_Gallery_Mapper::get_instance(); + $gallery = $mapper->find($task_query['id'], true); + $error = null; + if ($gallery != null) { + if ($task_type == 'gallery_remove') { + if (!$gallery->destroy()) { + $error = __('Failed to remove gallery (%1$s).', 'nggallery'); + } + } else { + if ($task_type == 'gallery_edit') { + if (isset($task_object['name'])) { + $gallery->name = $task_object['name']; + } + if (isset($task_object['title'])) { + $gallery->title = $task_object['title']; + } + if (isset($task_object['description'])) { + $gallery->galdesc = $task_object['description']; + } + if (isset($task_object['preview_image'])) { + $gallery->previewpic = $task_object['preview_image']; + } + if (isset($task_object['property_list'])) { + $properties = $task_object['property_list']; + foreach ($properties as $key => $value) { + $gallery->{$key} = $value; + } + } + // this is used to determine whether the task is complete + $image_list_unfinished = false; + if (isset($task_object['image_list']) && $wp_fs != null) { + $storage_path = isset($task_object['storage_path']) ? $task_object['storage_path'] : null; + $storage_path = trim($storage_path, '/\\'); + $storage = C_Gallery_Storage::get_instance(); + $image_mapper = C_Image_Mapper::get_instance(); + $creds = true; + $images_folder = $path_prefix . $fs_sep . $storage_path . $fs_sep; + $images_folder = str_replace(array('\\', '/'), $fs_sep, $images_folder); + $images = $task_object['image_list']; + $result_images = isset($task_result['image_list']) ? $task_result['image_list'] : array(); + $image_count = count($images); + $result_image_count = count($result_images); + for ($image_index = $result_image_count; $image_index < $image_count; $image_index++) { + $image = $images[$image_index]; + $image_id = isset($image['id']) ? $image['id'] : null; + $image_filename = isset($image['filename']) ? $image['filename'] : null; + $image_path = isset($image['path']) ? $image['path'] : null; + $image_action = isset($image['action']) ? $image['action'] : null; + $image_status = 'skip'; + if ($image_filename == null) { + $image_filename = basename($image_path); + } + $ngg_image = $image_mapper->find($image_id, TRUE); + // ensure that we don't transpose the image from one gallery to another in case a remoteId is passed in for the image but the gallery associated to the collection cannot be found + if ($ngg_image && $ngg_image->galleryid != $gallery->id()) { + $ngg_image = null; + $image_id = null; + } + $image_error = null; + if ($image_action == 'delete') { + // image was deleted + if ($ngg_image != null) { + $settings = C_NextGen_Settings::get_instance(); + $delete_fine = true; + if ($settings->deleteImg) { + if (!$storage->delete_image($ngg_image)) { + $image_error = __('Could not delete image file(s) from disk (%1$s).', 'nggallery'); + } + } else { + if (!$image_mapper->destroy($ngg_image)) { + $image_error = __('Could not remove image from gallery (%1$s).', 'nggallery'); + } + } + if ($image_error == null) { + do_action('ngg_delete_picture', $ngg_image->{$ngg_image->id_field}); + $image_status = 'done'; + } + } else { + $image_error = __('Could not remove image because image was not found (%1$s).', 'nggallery'); + } + } else { + /* image was added or edited and needs updating */ + $image_path = $images_folder . $image_path; + if ($image_path != null && $wp_fs->exists($image_path)) { + try { + $ngg_image = $storage->upload_base64_image($gallery, $wp_fs->get_contents($image_path), $image_filename, $image_id, true); + if ($ngg_image != null) { + $image_status = 'done'; + $image_id = $ngg_image->{$ngg_image->id_field}; + } + } catch (E_NoSpaceAvailableException $e) { + $image_error = __('No space available for image (%1$s).', 'nggallery'); + } catch (E_UploadException $e) { + $image_error = $e->getMessage . __(' (%1$s).', 'nggallery'); + } catch (E_No_Image_Library_Exception $e) { + $error = __('No image library present, image uploads will fail (%1$s).', 'nggallery'); + } catch (E_InsufficientWriteAccessException $e) { + $image_error = __('Inadequate system permissions to write image (%1$s).', 'nggallery'); + } catch (E_InvalidEntityException $e) { + $image_error = __('Requested image with id (%2$s) doesn\'t exist (%1$s).', 'nggallery'); + } catch (E_EntityNotFoundException $e) { + } + // delete temporary image + $wp_fs->delete($image_path); + } else { + $image_error = __('Could not find image file for image (%1$s).', 'nggallery'); + } + } + if ($image_error != null) { + $image_status = 'error'; + $image['error'] = array('level' => 'fatal', 'message' => sprintf($image_error, $image_filename, $image_id)); + } + if ($image_id) { + $image['id'] = $image_id; + } + if ($image_status) { + $image['status'] = $image_status; + } + // append processed image to result image_list array + $result_images[] = $image; + if ($this->should_stop_execution()) { + break; + } + } + $task_result['image_list'] = $result_images; + $image_list_unfinished = count($result_images) < $image_count; + // if images have finished processing, remove the folder used to store the temporary images (the folder should be empty due to delete() calls above) + if (!$image_list_unfinished) { + $wp_fs->rmdir($images_folder); + } + } else { + if ($wp_fs == null) { + $error = __('Could not access file system for gallery (%1$s).', 'nggallery'); + } + } + if (!$gallery->save()) { + if ($error == null) { + $gal_errors = '[' . json_encode($gallery->get_errors()) . ']'; + $error = __('Failed to save modified gallery (%1$s). ' . $gal_errors, 'nggallery'); + } + } + } + } + } else { + $error = __('Could not find gallery (%1$s).', 'nggallery'); + } + // XXX workaround for $gallery->save() returning false even if successful + if (isset($task_result['image_list'])) { + $task_result['object_id'] = $gallery->id(); + } + if ($error == null) { + $task_status = 'done'; + $task_result['object_id'] = $gallery->id(); + } else { + $task_status = 'error'; + $task_error = array('level' => 'fatal', 'message' => sprintf($error, (string) $task_query['id'])); + } + if ($image_list_unfinished) { + // we override the status of the task when the image list has not finished processing + $task_status = 'unfinished'; + } + } else { + $task_status = 'error'; + $task_error = array('level' => 'fatal', 'message' => __('No gallery was specified to edit.', 'nggallery')); + } + break; + case 'album_add': + $mapper = C_Album_Mapper::get_instance(); + $name = isset($task_object['name']) ? $task_object['name'] : ''; + $desc = isset($task_object['description']) ? $task_object['description'] : ''; + $previewpic = isset($task_object['preview_image']) ? $task_object['preview_image'] : 0; + $sortorder = isset($task_object['sort_order']) ? $task_object['sort_order'] : ''; + $page_id = isset($task_object['page_id']) ? $task_object['page_id'] : 0; + $album = null; + if (isset($task_query['id'])) { + $album = $mapper->find($task_query['id'], true); + } + if ($album == null) { + $album = $mapper->create(array('name' => $name, 'previewpic' => $previewpic, 'albumdesc' => $desc, 'sortorder' => $sortorder, 'pageid' => $page_id)); + if (!$album || !$album->save()) { + $album = null; + } + } + if ($album != null) { + $task_status = 'done'; + $task_result['object_id'] = $album->id(); + } else { + $task_status = 'error'; + $task_error = array('level' => 'fatal', 'message' => __('Album creation failed.', 'nggallery')); + } + break; + case 'album_remove': + case 'album_edit': + if (isset($task_query['id'])) { + $mapper = C_Album_Mapper::get_instance(); + $album = $mapper->find($task_query['id'], true); + $error = null; + if ($album) { + if ($task_type == 'album_remove') { + if (!$album->destroy()) { + $error = __('Failed to remove album (%1$s).', 'nggallery'); + } + } else { + if ($task_type == 'album_edit') { + if (isset($task_object['name'])) { + $album->name = $task_object['name']; + } + if (isset($task_object['description'])) { + $album->albumdesc = $task_object['description']; + } + if (isset($task_object['preview_image'])) { + $album->previewpic = $task_object['preview_image']; + } + if (isset($task_object['property_list'])) { + $properties = $task_object['property_list']; + foreach ($properties as $key => $value) { + $album->{$key} = $value; + } + } + if (isset($task_object['item_list'])) { + $item_list = $task_object['item_list']; + $sortorder = $album->sortorder; + $count = count($sortorder); + $album_items = array(); + for ($index = 0; $index < $count; $index++) { + $album_items[$sortorder[$index]] = $index; + } + foreach ($item_list as $item_info) { + $item_id = isset($item_info['id']) ? $item_info['id'] : null; + $item_type = isset($item_info['type']) ? $item_info['type'] : null; + $item_index = isset($item_info['index']) ? $item_info['index'] : null; + // translate ID in case this gallery has been created as part of this job + $item_id = $this->get_object_id($item_id, $task_list_result); + if ($item_id != null) { + if ($item_type == 'album') { + $item_id = 'a' . $item_id; + } + $album_items[$item_id] = $count + $item_index; + } + } + asort($album_items); + $album->sortorder = array_keys($album_items); + } + if (!$mapper->save($album)) { + $error = __('Failed to save modified album (%1$s).', 'nggallery'); + } + } + } + } else { + $error = __('Could not find album (%1$s).', 'nggallery'); + } + if ($error == null) { + $task_status = 'done'; + $task_result['object_id'] = $album->id(); + } else { + $task_status = 'error'; + $task_error = array('level' => 'fatal', 'message' => sprintf($error, (string) $task_query['id'])); + } + } else { + $task_status = 'error'; + $task_error = array('level' => 'fatal', 'message' => __('No album was specified to edit.', 'nggallery')); + } + break; + case 'gallery_list_get': + $mapper = C_Gallery_Mapper::get_instance(); + $gallery_list = $mapper->find_all(); + $result_list = array(); + foreach ($gallery_list as $gallery) { + $gallery_result = array('id' => $gallery->id(), 'name' => $gallery->name, 'title' => $gallery->title, 'description' => $gallery->galdesc, 'preview_image' => $gallery->previewpic); + $result_list[] = $gallery_result; + } + $task_status = 'done'; + $task_result['gallery_list'] = $result_list; + break; + case 'image_list_move': + break; + } + $task_item['result'] = $task_result; + $task_item['status'] = $task_status; + $task_item['error'] = $task_error; + // for previously finished tasks, store the result as it may be needed by future tasks + if ($task_id != null && $task_result != null) { + $task_list_result[$task_id] = $task_result; + } + // if the task has finished, either successfully or unsuccessfully, increase count for done tasks + if ($task_status != 'unfinished') { + $done_count++; + } + if ($this->should_stop_execution()) { + break; + } + } + $this->set_job_task_list($job_id, $task_list); + if ($task_count > $done_count + $skip_count) { + // unfinished tasks, return false + return false; + } else { + // everything was finished, remove job and write status file + $this->remove_job($job_id); + $status_file = '_ngg_job_status_' . strval($job_id) . '.txt'; + $status_content = json_encode($task_list); + if ($wp_fs != null) { + $status_path = $path_prefix . $fs_sep . $status_file; + $status_path = str_replace(array('\\', '/'), $fs_sep, $status_path); + $wp_fs->put_contents($status_path, $status_content); + } else { + // if WP_Filesystem failed try one last desperate attempt at direct file writing + $status_path = str_replace($ftp_path, $root_path, $full_path) . DIRECTORY_SEPARATOR . $status_file; + $status_path = str_replace(array('\\', '/'), DIRECTORY_SEPARATOR, $status_path); + file_put_contents($status_path, $status_content); + } + return true; + } + } +} +class C_NextGen_API_XMLRPC extends C_Component +{ + public static $_instances = array(); + public function define($context = false) + { + parent::define($context); + $this->implement('I_NextGen_API_XMLRPC'); + } + public static function get_instance($context = false) + { + if (!isset(self::$_instances[$context])) { + self::$_instances[$context] = new self($context); + } + return self::$_instances[$context]; + } + /** + * Gets the version of NextGEN Gallery installed + * @return string + */ + public function get_version() + { + return array('version' => NGG_PLUGIN_VERSION); + } + /** + * Login a user + * @param $username + * @param $password + * @return bool|WP_Error|WP_User + */ + public function _login($username, $password, $blog_id = 1) + { + $retval = FALSE; + if (!is_a($user_obj = wp_authenticate($username, $password), 'WP_Error')) { + wp_set_current_user($user_obj->ID); + $retval = $user_obj; + if (is_multisite()) { + switch_to_blog($blog_id); + } + } + return $retval; + } + public function _can_manage_gallery($gallery_id_or_obj, $check_upload_capability = FALSE) + { + $retval = FALSE; + // Get the gallery object, if we don't have it already + $gallery = NULL; + if (is_int($gallery_id_or_obj)) { + $gallery_mapper = C_Gallery_Mapper::get_instance(); + $gallery = $gallery_mapper->find($gallery_id_or_obj); + } else { + $gallery = $gallery_id_or_obj; + } + if ($gallery) { + $security = $this->get_registry()->get_utility('I_Security_Manager'); + $actor = $security->get_current_actor(); + if ($actor->get_entity_id() == $gallery->author) { + $retval = TRUE; + } elseif ($actor->is_allowed('nextgen_edit_gallery_unowned')) { + $retval = TRUE; + } + // Optionally, check if the user can upload to this gallery + if ($retval && $check_upload_capability) { + $retval = $actor->is_allowed('nextgen_upload_image'); + } + } + return $retval; + } + public function _add_gallery_properties($gallery) + { + if (is_object($gallery)) { + $image_mapper = C_Image_Mapper::get_instance(); + $storage = C_Gallery_Storage::get_instance(); + // Vladimir's Lightroom plugins requires the 'id' to be a string + // Ask if he can accept integers as well. Currently, integers break + // his plugin + $gallery->gid = (string) $gallery->gid; + // Set other gallery properties + $image_counter = array_pop($image_mapper->select('DISTINCT COUNT(*) as counter')->where(array('galleryid = %d', $gallery->gid))->run_query(FALSE, FALSE, TRUE)); + $gallery->counter = $image_counter->counter; + $gallery->abspath = $storage->get_gallery_abspath($gallery); + } else { + return FALSE; + } + return TRUE; + } + /** + * Returns a single image object + * @param $args (blog_id, username, password, pid) + */ + public function get_image($args, $return_model = FALSE) + { + $retval = new IXR_Error(403, 'Invalid username or password'); + $blog_id = intval($args[0]); + $username = strval($args[1]); + $password = strval($args[2]); + $image_id = intval($args[3]); + // Authenticate the user + if ($this->_login($username, $password, $blog_id)) { + // Try to find the image + $image_mapper = C_Image_Mapper::get_instance(); + if ($image = $image_mapper->find($image_id, TRUE)) { + // Try to find the gallery that the image belongs to + $gallery_mapper = C_Gallery_Mapper::get_instance(); + if ($gallery = $gallery_mapper->find($image->galleryid)) { + // Does the user have sufficient capabilities? + if ($this->_can_manage_gallery($gallery)) { + $storage = C_Gallery_Storage::get_instance(); + $image->imageURL = $storage->get_image_url($image, 'full', TRUE); + $image->thumbURL = $storage->get_thumb_url($image, TRUE); + $image->imagePath = $storage->get_image_abspath($image); + $image->thumbPath = $storage->get_thumb_abspath($image); + $retval = $return_model ? $image : $image->get_entity(); + } else { + $retval = new IXR_Error(403, "You don't have permission to manage gallery #{$image->galleryid}"); + } + } else { + // No gallery found + $retval = new IXR_Error(404, "Gallery not found (with id #{$image->gallerid})"); + } + } else { + // No image found + $retval = new IXR_Error(404, "Image not found (with id #{$image_id})"); + } + } + return $retval; + } + /** + * Returns a collection of images + * @param $args (blog_id, username, password, gallery_id + */ + public function get_images($args) + { + $retval = new IXR_Error(403, 'Invalid username or password'); + $blog_id = intval($args[0]); + $username = strval($args[1]); + $password = strval($args[2]); + $gallery_id = intval($args[3]); + // Authenticate the user + if ($this->_login($username, $password, $blog_id)) { + // Try to find the gallery + $mapper = C_Gallery_Mapper::get_instance(); + if ($gallery = $mapper->find($gallery_id, TRUE)) { + // Does the user have sufficient capabilities? + if ($this->_can_manage_gallery($gallery)) { + $retval = $gallery->get_images(); + } else { + $retval = new IXR_Error(403, "You don't have permission to manage gallery #{$image->galleryid}"); + } + } else { + $retval = new IXR_Error(404, "Gallery not found (with id #{$image->gallerid}"); + } + } + return $retval; + } + /** + * Uploads an image to a particular gallery + * @param $args (blog_id, username, password, data) + * + * Data is an assoc array: + * o string name + * o string type (optional) + * o base64 bits + * o bool overwrite (optional) + * o int gallery + * o int image_id (optional) + * @return image + */ + public function upload_image($args) + { + $retval = new IXR_Error(403, 'Invalid username or password'); + $blog_id = intval($args[0]); + $username = strval($args[1]); + $password = strval($args[2]); + $data = $args[3]; + $gallery_id = isset($data['gallery_id']) ? $data['gallery_id'] : $data['gallery']; + if (!isset($data['override'])) { + $data['override'] = FALSE; + } + if (!isset($data['overwrite'])) { + $data['overwrite'] = FALSE; + } + $data['override'] = $data['overwrite']; + // Authenticate the user + if ($this->_login($username, $password, $blog_id)) { + // Try to find the gallery + $mapper = C_Gallery_Mapper::get_instance(); + if ($gallery = $mapper->find($gallery_id, TRUE)) { + // Does the user have sufficient capabilities? + if ($this->_can_manage_gallery($gallery, TRUE)) { + // Upload the image + $storage = C_Gallery_Storage::get_instance(); + $image = $storage->upload_base64_image($gallery, $data['bits'], $data['name'], $data['image_id'], $data['override']); + if ($image) { + $storage = C_Gallery_Storage::get_instance(); + $image->imageURL = $storage->get_image_url($image); + $image->thumbURL = $storage->get_thumb_url($image); + $image->imagePath = $storage->get_image_abspath($image); + $image->thumbPath = $storage->get_thumb_abspath($image); + $retval = $image->get_entity(); + } else { + $retval = new IXR_Error(500, 'Could not upload image'); + } + } else { + $retval = new IXR_Error(403, "You don't have permission to upload to gallery #{$image->galleryid}"); + } + } else { + $retval = new IXR_Error(404, "Gallery not found (with id #{$image->gallerid}"); + } + } + return $retval; + } + /** + * Edits an image object + * @param $args (blog_id, username, password, image_id, alttext, description, exclude, other_properties + */ + public function edit_image($args) + { + $alttext = strval($args[4]); + $description = strval($args[5]); + $exclude = intval($args[6]); + $properties = isset($args[7]) ? (array) $args[7] : array(); + $retval = $this->get_image($args, TRUE); + if (!$retval instanceof IXR_Error) { + $retval->alttext = $alttext; + $retval->description = $description; + $retval->exclude = $exclude; + // Other properties can be specified using an associative array + foreach ($properties as $key => $value) { + $retval->{$key} = $value; + } + // Unset any dynamic properties not part of the schema + foreach (array('imageURL', 'thumbURL', 'imagePath', 'thumbPath') as $key) { + unset($retval->{$key}); + } + $retval = $retval->save(); + } + return $retval; + } + /** + * Deletes an existing image from a gallery + * @param $args (blog_id, username, password, image_id) + */ + public function delete_image($args) + { + $retval = $this->get_image($args, TRUE); + if (!$retval instanceof IXR_Error) { + $retval = $retval->destroy(); + } + return $retval; + } + /** + * Creates a new gallery + * @param $args (blog_id, username, password, title) + */ + public function create_gallery($args) + { + $retval = new IXR_Error(403, 'Invalid username or password'); + $blog_id = intval($args[0]); + $username = strval($args[1]); + $password = strval($args[2]); + $title = strval($args[3]); + // Authenticate the user + if ($this->_login($username, $password, $blog_id)) { + $security = $this->get_registry()->get_utility('I_Security_Manager'); + if ($security->is_allowed('nextgen_edit_gallery')) { + $mapper = C_Gallery_Mapper::get_instance(); + if (($gallery = $mapper->create(array('title' => $title))) && $gallery->save()) { + $retval = $gallery->id(); + } else { + $retval = new IXR_Error(500, 'Unable to create gallery'); + } + } else { + $retval = new IXR_Error(403, 'Sorry, but you must be able to manage galleries. Check your roles/capabilities.'); + } + } + return $retval; + } + /** + * Edits an existing gallery + * @param $args (blog_id, username, password, gallery_id, name, title, description, preview_pic_id) + */ + public function edit_gallery($args) + { + $retval = new IXR_Error(403, 'Invalid username or password'); + $blog_id = intval($args[0]); + $username = strval($args[1]); + $password = strval($args[2]); + $gallery_id = intval($args[3]); + $name = strval($args[4]); + $title = strval($args[5]); + $galdesc = strval($args[6]); + $image_id = intval($args[7]); + $properties = isset($args[8]) ? (array) $args[8] : array(); + // Authenticate the user + if ($this->_login($username, $password, $blog_id)) { + $mapper = C_Gallery_Mapper::get_instance(); + if ($gallery = $mapper->find($gallery_id, TRUE)) { + if ($this->_can_manage_gallery($gallery)) { + $gallery->name = $name; + $gallery->title = $title; + $gallery->galdesc = $galdesc; + $gallery->previewpic = $image_id; + foreach ($properties as $key => $value) { + $gallery->{$key} = $value; + } + // Unset dynamic properties not part of the schema + unset($gallery->counter); + unset($gallery->abspath); + $retval = $gallery->save(); + } else { + $retval = new IXR_Error(403, 'You don\'t have permission to modify this gallery'); + } + } else { + $retval = new IXR_Error(404, "Gallery #{$gallery_id} doesn't exist"); + } + } + return $retval; + } + /** + * Returns all galleries + * @param $args (blog_id, username, password) + */ + public function get_galleries($args) + { + $retval = new IXR_Error(403, 'Invalid username or password'); + $blog_id = intval($args[0]); + $username = strval($args[1]); + $password = strval($args[2]); + // Authenticate the user + if ($this->_login($username, $password, $blog_id)) { + // Do we have permission? + $security = $this->get_registry()->get_utility('I_Security_Manager'); + if ($security->is_allowed('nextgen_edit_gallery')) { + $mapper = C_Gallery_Mapper::get_instance(); + $retval = array(); + foreach ($mapper->find_all() as $gallery) { + $this->_add_gallery_properties($gallery); + $retval[$gallery->{$gallery->id_field}] = (array) $gallery; + } + } else { + $retval = new IXR_Error(401, __('Sorry, you must be able to manage galleries')); + } + } + return $retval; + } + /** + * Gets a single gallery instance + * @param $args (blog_id, username, password, gallery_id) + */ + public function get_gallery($args, $return_model = FALSE) + { + $retval = new IXR_Error(403, 'Invalid username or password'); + $blog_id = intval($args[0]); + $username = strval($args[1]); + $password = strval($args[2]); + $gallery_id = intval($args[3]); + // Authenticate the user + if ($this->_login($username, $password, $blog_id)) { + $mapper = C_Gallery_Mapper::get_instance(); + if ($gallery = $mapper->find($gallery_id, TRUE)) { + if ($this->_can_manage_gallery($gallery)) { + $this->_add_gallery_properties($gallery); + $retval = $return_model ? $gallery : $gallery->get_entity(); + } else { + $retval = new IXR_Error(403, "Sorry, but you don't have permission to manage gallery #{$gallery->gid}"); + } + } else { + $retval = FALSE; + } + } + return $retval; + } + /** + * Deletes a gallery + * @param $args (blog_id, username, password, gallery_id) + */ + public function delete_gallery($args) + { + $retval = $this->get_gallery($args, TRUE); + if (!$retval instanceof IXR_Error and is_object($retval)) { + $retval = $retval->destroy(); + } + return $retval; + } + /** + * Creates a new album + * @param $args (blog_id, username, password, title, previewpic, description, galleries + */ + public function create_album($args) + { + $retval = new IXR_Error(403, 'Invalid username or password'); + $blog_id = intval($args[0]); + $username = strval($args[1]); + $password = strval($args[2]); + $title = strval($args[3]); + $previewpic = isset($args[4]) ? intval($args[4]) : 0; + $desc = isset($args[5]) ? strval($args[5]) : ''; + $sortorder = isset($args[6]) ? $args[6] : ''; + $page_id = isset($args[7]) ? intval($args[7]) : 0; + // Authenticate the user + if ($this->_login($username, $password, $blog_id)) { + // Is request allowed? + $security = $this->get_registry()->get_utility('I_Security_Manager'); + if ($security->is_allowed('nextgen_edit_album')) { + $mapper = C_Album_Mapper::get_instance(); + $album = $mapper->create(array('name' => $title, 'previewpic' => $previewpic, 'albumdesc' => $desc, 'sortorder' => $sortorder, 'pageid' => $page_id)); + if ($album->save()) { + $retval = $album->id(); + } else { + $retval = new IXR_Error(500, 'Unable to create album'); + } + } + } + return $retval; + } + /** + * Returns all albums + * @param $args (blog_id, username, password) + * @return IXR_Error + */ + public function get_albums($args) + { + $retval = new IXR_Error(403, 'Invalid username or password'); + $blog_id = intval($args[0]); + $username = strval($args[1]); + $password = strval($args[2]); + // Authenticate the user + if ($this->_login($username, $password, $blog_id)) { + // Are we allowed? + $security = $this->get_registry()->get_utility('I_Security_Manager'); + if ($security->is_allowed('nextgen_edit_album')) { + // Fetch all albums + $mapper = C_Album_Mapper::get_instance(); + $retval = array(); + foreach ($mapper->find_all() as $album) { + // Vladimir's Lightroom plugins requires the 'id' to be a string + // Ask if he can accept integers as well. Currently, integers break + // his plugin + $album->id = (string) $album->id; + $album->galleries = $album->sortorder; + $retval[$album->{$album->id_field}] = (array) $album; + } + } else { + $retval = new IXR_Error(403, 'Sorry, you must be able to manage albums'); + } + } + return $retval; + } + /** + * Gets a single album + * @param $args (blog_id, username, password, album_id) + */ + public function get_album($args, $return_model = FALSE) + { + $retval = new IXR_Error(403, 'Invalid username or password'); + $blog_id = intval($args[0]); + $username = strval($args[1]); + $password = strval($args[2]); + $album_id = intval($args[3]); + // Authenticate the user + if ($this->_login($username, $password, $blog_id)) { + // Are we allowed? + $security = $this->get_registry()->get_utility('I_Security_Manager'); + if ($security->is_allowed('nextgen_edit_album')) { + $mapper = C_Album_Mapper::get_instance(); + if ($album = $mapper->find($album_id, TRUE)) { + // Vladimir's Lightroom plugins requires the 'id' to be a string + // Ask if he can accept integers as well. Currently, integers break + // his plugin + $album->id = (string) $album->id; + $album->galleries = $album->sortorder; + $retval = $return_model ? $album : $album->get_entity(); + } else { + $retval = FALSE; + } + } else { + $retval = new IXR_Error(403, 'Sorry, you must be able to manage albums'); + } + } + return $retval; + } + /** + * Deletes an existing album + * @param $args (blog_id, username, password, album_id) + */ + public function delete_album($args) + { + $retval = $this->get_album($args, TRUE); + if (!$retval instanceof IXR_Error) { + $retval = $retval->destroy(); + } + return $retval; + } + /** + * Edit an existing album + * @param $args (blog_id, username, password, album_id, name, preview pic id, description, galleries) + */ + public function edit_album($args) + { + $retval = $this->get_album($args, TRUE); + if (!$retval instanceof IXR_Error) { + $retval->name = strval($args[4]); + $retval->previewpic = intval($args[5]); + $retval->albumdesc = strval($args[6]); + $retval->sortorder = $args[7]; + $properties = isset($args[8]) ? $args[8] : array(); + foreach ($properties as $key => $value) { + $retval->{$key} = $value; + } + unset($retval->galleries); + $retval = $retval->save(); + } + return $retval; + } + /** + * Sets the post thumbnail for a post to a NextGEN Gallery image + * @param $args (blog_id, username, password, post_id, image_id) + * + * @return IXR_Error|int attachment id + */ + public function set_post_thumbnail($args) + { + $retval = new IXR_Error(403, 'Invalid username or password'); + $blog_id = intval($args[0]); + $username = strval($args[1]); + $password = strval($args[2]); + $post_ID = intval($args[3]); + $image_id = intval($args[4]); + // Authenticate the user + if ($this->_login($username, $password, $blog_id)) { + if (current_user_can('edit_post', $post_ID)) { + $retval = C_Gallery_Storage::get_instance()->set_post_thumbnail($post_ID, $image_id); + } else { + $retval = new IXR_Error(403, 'Sorry but you need permission to do this'); + } + } + return $retval; + } +} +interface I_NextGen_API +{ +} +interface I_NextGen_API_XMLRPC +{ +} \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/admin.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/admin.php index cae6147603957140570a19fb3ea6e10556f443bc..c88c7e782cb7f623277b97a6911302550e009689 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/admin.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/admin.php @@ -284,8 +284,7 @@ class nggAdminPanel{ switch ($_GET['page']) { case NGGFOLDER : - wp_enqueue_script( 'postbox' ); - add_thickbox(); + wp_enqueue_script( 'ngg_overview', $router->get_static_url('photocrati-nextgen-legacy#overview.js'), array('jquery'), NGG_SCRIPT_VERSION); break; case "nggallery-manage-gallery" : wp_enqueue_script( 'postbox' ); @@ -342,7 +341,7 @@ class nggAdminPanel{ switch ($_GET['page']) { case NGGFOLDER : - wp_enqueue_style( 'thickbox' ); + wp_add_inline_style( 'nggadmin', file_get_contents(C_Fs::get_instance()->find_static_abspath('photocrati-nextgen-legacy#overview.css') ) ); case "nggallery-about" : wp_enqueue_style( 'nggadmin' ); //TODO:Remove after WP 3.3 release diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/jquery.ui.tabs.min.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/jquery.ui.tabs.min.css new file mode 100644 index 0000000000000000000000000000000000000000..0586303c354b2ac583935d8f70a6fa2534b783a8 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/jquery.ui.tabs.min.css @@ -0,0 +1 @@ +@media projection,screen{.ui-tabs-hide{display:none}}@media print{.ui-tabs-nav{display:none}}#slider{border-color:#ebebeb #ccc #ccc #ebebeb;border-style:solid;border-width:1px;margin:15px 15% 0 15px;padding:2px}#tabs{display:block;background:#f1f1f1 none repeat scroll 0;font-size:14px;overflow:hidden}.ui-tabs-nav{list-style:none;margin:0;padding:0 0 0 10px}.ui-tabs-nav:after{display:block;clear:both;content:" "}.ui-tabs-nav li{float:left;padding:6px 5px;min-width:84px;margin:2px 2px 0 1px !important;text-decoration:none;list-style:none}.ui-tabs-nav a,.ui-tabs-nav a span{display:block;padding:0 1px}.ui-tabs-nav a{margin:1px 0 0;padding-left:0;color:#2583ad;line-height:1.2;text-align:center;text-decoration:none;white-space:nowrap;outline:0}.ui-tabs-nav .ui-tabs-selected{background:#6d6d6d url(../images/menu-bits.gif) repeat-x scroll left top;border-color:#6d6d6d;color:#fff;text-shadow:0 -1px 0 #666;-moz-border-radius-topright:6px;-khtml-border-top-right-radius:6px;-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-moz-border-radius-topleft:6px;-khtml-border-top-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px}.ui-tabs-selected a,.ui-tabs-selected a:hover{color:#fff !important}.ui-tabs-nav .ui-tabs-selected a,.ui-tabs-nav .ui-tabs-selected a:hover{position:relative;top:1px;z-index:2;margin-top:0}.ui-tabs-nav li a:hover{color:#d54e21}.ui-tabs-nav a span{width:64px;min-width:64px;height:18px;min-height:18px;padding-top:6px;padding-right:0}*>.ui-tabs-nav a span{width:auto;height:auto}.ui-tabs-nav .ui-tabs-selected a span{padding-bottom:1px}.ui-tabs-nav .ui-tabs-selected a,.ui-tabs-nav a:hover,.ui-tabs-nav a:focus,.ui-tabs-nav a:active{background-position:100% -150px}.ui-tabs-nav a,.ui-tabs-nav .ui-tabs-disabled a:hover,.ui-tabs-nav .ui-tabs-disabled a:focus,.ui-tabs-nav .ui-tabs-disabled a:active{background-position:100% -100px}.ui-tabs-nav .ui-tabs-selected a span,.ui-tabs-nav a:hover span,.ui-tabs-nav a:focus span,.ui-tabs-nav a:active span{background-position:0 -50px}.ui-tabs-nav a span,.ui-tabs-nav .ui-tabs-disabled a:hover span,.ui-tabs-nav .ui-tabs-disabled a:focus span,.ui-tabs-nav .ui-tabs-disabled a:active span{background-position:0 0}.ui-tabs-nav .ui-tabs-selected a:link,.ui-tabs-nav .ui-tabs-selected a:visited,.ui-tabs-nav .ui-tabs-disabled a:link,.ui-tabs-nav .ui-tabs-disabled a:visited{cursor:text}.ui-tabs-nav a:hover,.ui-tabs-nav a:focus,.ui-tabs-nav a:active,.ui-tabs-nav .ui-tabs-unselect a:hover,.ui-tabs-nav .ui-tabs-unselect a:focus,.ui-tabs-nav .ui-tabs-unselect a:active{cursor:pointer}.ui-tabs-disabled{opacity:.4;filter:alpha(opacity=40)}.ui-tabs-panel{border-top:1px solid #97a5b0 !important;padding:1em 8px;background:#fff;border:0 !important;height:100% !important;margin:0 !important;overflow:visible !important}.ui-tabs-panel a{display:inline}* html .ui-tabs-nav{display:inline-block}*:first-child+html .ui-tabs-nav{display:inline-block} \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/menu.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/menu.css index f59d26c3e90d4e8f0c5649d6b51040c166200506..3fe128b9236f8563a7cc415904fc24036f550aa0 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/menu.css +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/menu.css @@ -1,3 +1,3 @@ -#icon-nextgen-gallery { - background:url("../images/nextgen_32_grey.png") no-repeat scroll 1px 1px transparent; +#icon-nextgen-gallery { + background:url("../images/nextgen_32_grey.png") no-repeat scroll 1px 1px transparent; } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/menu.min.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/menu.min.css new file mode 100644 index 0000000000000000000000000000000000000000..aa416894540cd87d36b56a488ab474307e38ab39 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/menu.min.css @@ -0,0 +1 @@ +#icon-nextgen-gallery{background:url("../images/nextgen_32_grey.png") no-repeat scroll 1px 1px transparent} \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/nggColorPicker.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/nggColorPicker.css index f772424108442d5df64fcde0809f1c985ed4910f..6b7775fb962c18c35924800f292780bb63b8d11c 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/nggColorPicker.css +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/nggColorPicker.css @@ -1,14 +1,14 @@ -#colorSelector{ - background:transparent url(../images/select.png) repeat scroll 0 0; - height:36px; - position:relative; - width:36px; -} -#colorSelector div{ - background:transparent url(../images/select.png) repeat scroll center center; - height:30px; - left:3px; - position:absolute; - top:3px; - width:30px; +#colorSelector{ + background:transparent url(../images/select.png) repeat scroll 0 0; + height:36px; + position:relative; + width:36px; +} +#colorSelector div{ + background:transparent url(../images/select.png) repeat scroll center center; + height:30px; + left:3px; + position:absolute; + top:3px; + width:30px; } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/nggColorPicker.min.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/nggColorPicker.min.css new file mode 100644 index 0000000000000000000000000000000000000000..c8123e475dbab50828ae5bb93a8cd7841bb78924 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/nggColorPicker.min.css @@ -0,0 +1 @@ +#colorSelector{background:transparent url(../images/select.png) repeat scroll 0 0;height:36px;position:relative;width:36px}#colorSelector div{background:transparent url(../images/select.png) repeat scroll center center;height:30px;left:3px;position:absolute;top:3px;width:30px} \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/nggSorter.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/nggSorter.css index 73a0ed8300c40e17b51fde88bd671be9f3ae3a4c..e0d61b9b451fe5135e010e88001de81e3ccff698 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/nggSorter.css +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/nggSorter.css @@ -1,76 +1,76 @@ -.imageBox,.imageBoxHighlighted{ - width:130px; /* Total width of each image box */ - height:160px; /* Total height of each image box */ - float:left; -} -.imageBox_theImage{ - width:110px; /* Width of image */ - height:125px; /* Height of image */ - - /* - Don't change these values * - */ - background-position: center; - background-repeat: no-repeat; - margin: 0 auto; - margin-bottom:2px; -} - -.imageBox .imageBox_theImage{ - border:1px solid #DDD; /* Border color for not selected images */ - padding:2px; -} -.imageBoxHighlighted .imageBox_theImage{ - border:3px solid #316AC5; /* Border color for selected image */ - padding:0px; - -} -.imageBoxHighlighted span{ /* Title of selected image */ - background-color: #316AC5; - color:#FFFFFF; - padding:2px; -} - -.imageBox_label{ /* Title of images - both selected and not selected */ - text-align:center; - font-family: arial; - font-size:11px; - padding-top:2px; - margin: 0 auto; -} - -/* -DIV that indicates where the dragged image will be placed -*/ -#insertionMarker{ - height:150px; - width:6px; - position:absolute; -} - -#insertionMarkerLine{ - width:6px; /* No need to change this value */ - height:145px; /* To adjust the height of the div that indicates where the dragged image will be dropped */ - -} - -#insertionMarker img{ - float:left; -} - -/* -DIV that shows the image as you drag it -*/ -#dragDropContent{ - - opacity:0.4; /* 40 % opacity */ - filter:alpha(opacity=40); /* 40 % opacity */ - - /* - No need to change these three values - */ - position:absolute; - z-index:10; - display:none; - +.imageBox,.imageBoxHighlighted{ + width:130px; /* Total width of each image box */ + height:160px; /* Total height of each image box */ + float:left; +} +.imageBox_theImage{ + width:110px; /* Width of image */ + height:125px; /* Height of image */ + + /* + Don't change these values * + */ + background-position: center; + background-repeat: no-repeat; + margin: 0 auto; + margin-bottom:2px; +} + +.imageBox .imageBox_theImage{ + border:1px solid #DDD; /* Border color for not selected images */ + padding:2px; +} +.imageBoxHighlighted .imageBox_theImage{ + border:3px solid #316AC5; /* Border color for selected image */ + padding:0px; + +} +.imageBoxHighlighted span{ /* Title of selected image */ + background-color: #316AC5; + color:#FFFFFF; + padding:2px; +} + +.imageBox_label{ /* Title of images - both selected and not selected */ + text-align:center; + font-family: arial; + font-size:11px; + padding-top:2px; + margin: 0 auto; +} + +/* +DIV that indicates where the dragged image will be placed +*/ +#insertionMarker{ + height:150px; + width:6px; + position:absolute; +} + +#insertionMarkerLine{ + width:6px; /* No need to change this value */ + height:145px; /* To adjust the height of the div that indicates where the dragged image will be dropped */ + +} + +#insertionMarker img{ + float:left; +} + +/* +DIV that shows the image as you drag it +*/ +#dragDropContent{ + + opacity:0.4; /* 40 % opacity */ + filter:alpha(opacity=40); /* 40 % opacity */ + + /* + No need to change these three values + */ + position:absolute; + z-index:10; + display:none; + } \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/nggSorter.min.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/nggSorter.min.css new file mode 100644 index 0000000000000000000000000000000000000000..548f5ac5e50aac5745477e17584660b8bc0058ea --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/nggSorter.min.css @@ -0,0 +1 @@ +.imageBox,.imageBoxHighlighted{width:130px;height:160px;float:left}.imageBox_theImage{width:110px;height:125px;background-position:center;background-repeat:no-repeat;margin:0 auto;margin-bottom:2px}.imageBox .imageBox_theImage{border:1px solid #DDD;padding:2px}.imageBoxHighlighted .imageBox_theImage{border:3px solid #316ac5;padding:0}.imageBoxHighlighted span{background-color:#316ac5;color:#fff;padding:2px}.imageBox_label{text-align:center;font-family:arial;font-size:11px;padding-top:2px;margin:0 auto}#insertionMarker{height:150px;width:6px;position:absolute}#insertionMarkerLine{width:6px;height:145px}#insertionMarker img{float:left}#dragDropContent{opacity:.4;filter:alpha(opacity=40);position:absolute;z-index:10;display:none} \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/nggadmin.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/nggadmin.css index 415f6e4f1e5dc38790e2204e485690d871085e98..fdb0ca935e9c1b141a7eb0e4eac2961678e37325 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/nggadmin.css +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/nggadmin.css @@ -1,539 +1,556 @@ -/* -** NextGEN Gallery Style for Wordpress 3.3 -*/ - -#iframely h2.title { - display: none; -} - -/* SETTINGS FOR Overview Gallery */ - -#newversion { - border-color:#CCCCCC; - border-style:solid; - border-width:1px; - margin-right:7px; - margin-top:10px; - padding:2px; -} - -.ngg-dashboard-widget ul.settings span { - padding-left : 10px; - color:#2583AD; - font-weight:bold; -} - -.ngg-overview .postbox .handlediv { - float:right; - height:24px; - width:24px; -} - -.warning { - color: #9F6000; - background-color: #FEEFB3; - border: 1px solid; - margin: 5px 0px; - padding:5px; -} - -#donator_message { - margin:5px 0 15px; - background-color:#BDE5F8; - border-color:#00529B; - -moz-border-radius-bottomleft:3px; - -moz-border-radius-bottomright:3px; - -moz-border-radius-topleft:3px; - -moz-border-radius-topright:3px; - border-style:solid; - border-width:1px; - margin:5px 15px 2px; - padding:0 0.6em; -} - -#donator_message p{ - line-height:1; - margin:0.5em 0; - padding:2px; - padding-bottom:10px; -} - -#donator_message span{ - padding-top:10px; - float:right; -} - -#plugin_check img { - float: right; -} - -#plugin_check p.message { - font-size: 90%; - color: #666; -} -/* SETTING FOR FLASH UPLOAD BUTTON */ -.swfupload { - position:absolute; - z-index:1; - vertical-align:top; -} - -/* SETTINGS FOR THE OPTIONS TABLE */ -.ngg-options th { - width:22%; -} - -a.switch-expert { - text-decoration:none; -} - -/* WATERMARK */ -#wm-preview { - float:right; - font-size:90%; - width:35%; - border-color:#EBEBEB rgb(204, 204, 204) rgb(204, 204, 204) rgb(235, 235, 235); - border-style:solid; - border-width:1px; - margin-bottom:10px; - margin-left:10px; - margin-right:8px; - padding:2px; -} -#wm-preview h3{ - background:#F9F9F9 none repeat scroll 0%; - font-size:14px; - font-weight:bold; - margin:0pt 0pt 10px; - padding:8px 5px; -} - -#wm-position { - width:100%; - margin-left:40px; -} - -.wm-table { - border-collapse:collapse; - margin-top:1em; - width: 60%; - clear:none; -} -.wm-table td { - border-bottom:8px solid #FFFFFF; - line-height:20px; - margin-bottom:9px; - padding:10px; -} -.wm-table th { - border-bottom:8px solid #FFFFFF; - padding:10px; - text-align:left; -} -.wm-table tr { - background:#F9F9F9 none repeat scroll 0%; -} - -/* SETTINGS FOR MANAGE TABLE */ - -div#poststuff #gallerydiv { - cursor:pointer; -} - -p#ngg-inlinebutton { - float:right; - margin:0pt; - position:relative; - top:-25pt; -} - -#gallery_fields { - width: 100%; -} - -#gallery_fields td{ - padding: 5px; - min-width: 105px; -} - -#gallery_fields input[type=text], -#gallery_fields textarea, -#gallery_fields select { - min-width: 220px; - width: 99%; -} - -#ngg-listimages .row_actions, -#ngg-listimages .row_actions td { - border-top: none; - /* background-color: #F9F9F9; */ - padding-top: 0px; - padding-bottom: 0px; -} - -#ngg-listimages .row_actions.alternate, -#ngg-listimages .row_actions.alternate td { - /* background-color: #FCFCFC; */ -} - -#ngg-listimages .row-actions { - padding-left: 0px; - margin-bottom: -2px; - position: relative; - bottom: 4px; -} - -#ngg-listimages .iedit, -#ngg-listimages .iedit td, -#ngg-listimages .iedit th { - border: none; -} - -#ngg-listimages .iedit td { - padding-top: 8px; -} - -#ngg-listimages .column select { - width: 100%; -} - -#ngg-listimages .column-1 input { - margin: 0 0 0 8px; -} - -#ngg-listimages .column-1, -#ngg-listimages .column-2 { - width: 4%; - min-width: 33px; -} - -#ngg-listimages .column-3 { - min-width: 80px; - width: 10%; -} - -#ngg-listimages .column-3 .thumb { - max-height: 80px; - max-width: 80px; -} - -#ngg-listimages .column-4 { - width: 22%; - max-width: 220px; - -} - -#ngg-listimages .column-4 .meta { - font-size: 11px; -} - -#ngg-listimages .column-4 label input[type=checkbox] { - position: relative; - top: -2px; -} - -#ngg-listimages .column-5 input[type=text], -#ngg-listimages .column-5 textarea, -#ngg-listimages .column-6 textarea { - width: 100%; -} - -#ngg-listimages .column-5 textarea { - height: 57px; -} - -#ngg-listimages .column-6 textarea { - height: 80px; -} - -/* SETTINGS FOR PROGRESS BAR */ - -div .progressborder { - border:1px solid #DDDDDD; - display: block; - height: 30px; - background-color: #464646; - width: 100%; - margin-top: 15px; - margin-bottom: 15px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - border-radius: 5px; -} - -div .progressbar { - border: medium none ; - display: block; - height: 30px; - background-color: #D54E21; - width: 0%; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - border-radius: 5px; -} - -div .progressbar span { - display: inline; - position: absolute; - color: white; - font-weight: bold; - padding: 5px 0 0 5px; -} - -.show_details -{ - height: 16px; - line-height: 20px; - overflow: hidden; - min-width: 8em; - padding: 3px; - cursor:pointer; -} - -.show_details span -{ - border-bottom:1px solid #999; - white-space:pre; -} -.show_details:hover -{ - height: auto; - overflow: visible; - border: 1px solid #999; -} - - /* SETTINGS FOR ALBUM PAGE */ - -.albumnav select[name="act_album"] { - width:150px; -} - -.albumnav span { - padding-left: 50px; -} - -#editalbum select[name='pageid'] { - width: 95%; -} - -div .groupItem -{ - cursor: move; - width: 295px; - padding: 5px; - line-height: 1.5; -} - -div .innerhandle { - background-color:#FBFBFB; -} - -.groupItem .item_top -{ - background-color:#2683AE; - color: #FFFFFF; - font-weight:bold; - line-height: 28px; - height: 28px; - padding: 0 5px; - -moz-border-radius: 3px; - -khtml-border-radius: 3px; - -webkit-border-radius: 3px; - border-radius: 3px; -} - -.groupItem .album_obj -{ - background-color:#D54E21; -} - -.groupItem .item_top a -{ - color:#FFFFFF; - float:right; - text-decoration: none; -} - -.groupItem .item_top a:hover -{ - color:#FFFFFF; -} - -.itemContent { - border-color:#DFDFDF; - border-style:none solid solid; - border-width:0 1px 1px; - padding:2px 0 20px 2px; -} - -.itemContent p { - border: 0; - margin: 0; - padding: 0; -} - -.inlinepicture -{ - float:left; - display:inline; - margin:0pt; - padding:0pt 3px 1px; -} - -.inlinepicture img -{ - margin:3px; - max-height:60px; -} - -.sort_placeholder -{ - border:1px dashed #bba !important; - margin: 5px; - background: #F9F9F9; -} - -.container { - margin-top: 10px; -} - -.target-album { - margin:10px 685px 10px 10px; -} - -.widget-right { - float:right; - margin:0pt 10px; - width:315px; -} - -.widget-holder { - min-height: 400px; - padding-top:1px; -} - -.target { - background-color:#F1F1F1; -} - -div.widget-top h3 { - text-align:center; - line-height:25px; - margin: 0; - padding: 5px 12px; - font-size: 13px; -} - -div.widget-top { - text-shadow:0 1px 0 #FFFFFF; - background-repeat: repeat-x; - background-position: 0 0; - font-size: 13px; -} - -.ui-autocomplete-start { background-position: 99% center; } - -/* SETTINGS FOR SORT GALLERY */ - -#sortGallery { - position:relative; -} - -p#sortButton{ - margin:0; - position:absolute; - right:0; - top:0; -} - -.imageBox,.imageBoxHighlighted{ - width:130px; /* Total width of each image box */ - height:160px; /* Total height of each image box */ - float:left; - overflow: hidden; - text-overflow: ellipsis; - padding: 5px; -} -.imageBox_theImage{ - width:110px; /* Width of image */ - height:125px; /* Height of image */ - - background-position: center; - background-repeat: no-repeat; - margin: 0 auto; - margin-bottom:2px; -} - -.imageBox_label{ /* Title of images - both selected and not selected */ - text-align:center; - font-family: arial; - font-size:11px; - padding-top:2px; - margin: 0 auto; -} - -/* -DIV that indicates where the dragged image will be placed -*/ - -#insertionMarker{ - height:150px; - width:6px; - position:absolute; -} - -#insertionMarkerLine{ - width:6px; /* No need to change this value */ - height:145px; /* To adjust the height of the div that indicates where the dragged image will be dropped */ - -} - -#insertionMarker img{ - float:left; -} - -/* -DIV that shows the image as you drag it -*/ - -#dragDropContent{ - - opacity:0.4; /* 40 % opacity */ - filter:alpha(opacity=40); /* 40 % opacity */ - - /* - No need to change these three values - */ - position:absolute; - z-index:10; - display:none; - -} - -/* UPGRADE PAGE */ - -.error_inline { - background:#FFEBE8 none repeat scroll 0%; - border:1px solid #CC0000; - margin:5px auto; - padding:10px; -} - -/* ABOUT PAGE */ -.ngg-list { - font-size:11px; - margin-left:15px; - list-style-position:inside; - list-style-type:disc; -} - -#ngg-manage-images-items-per-page-label { - float: right; - line-height: 30px; - margin-right: 5px; -} - -#ngg-manage-images-items-per-page { - float: right; - margin-right: 5px; -} \ No newline at end of file +/* +** NextGEN Gallery Style for Wordpress 3.3 +*/ + +#iframely h2.title { + display: none; +} + +/* SETTINGS FOR Overview Gallery */ + +#newversion { + border-color:#CCCCCC; + border-style:solid; + border-width:1px; + margin-right:7px; + margin-top:10px; + padding:2px; +} + +.ngg-dashboard-widget ul.settings span { + padding-left : 10px; + color:#2583AD; + font-weight:bold; +} + +.ngg-overview .postbox .handlediv { + float:right; + height:24px; + width:24px; +} + +#gallerydiv h3 { + margin-left: 10px; +} + +#gallerydiv span.toggle-indicator { + font-size: 2em; + line-height: 2em; +} + +#gallerydiv span.toggle-indicator:hover { + cursor: pointer; +} + +.warning { + color: #9F6000; + background-color: #FEEFB3; + border: 1px solid; + margin: 5px 0px; + padding:5px; +} + +#donator_message { + margin:5px 0 15px; + background-color:#BDE5F8; + border-color:#00529B; + -moz-border-radius-bottomleft:3px; + -moz-border-radius-bottomright:3px; + -moz-border-radius-topleft:3px; + -moz-border-radius-topright:3px; + border-style:solid; + border-width:1px; + margin:5px 15px 2px; + padding:0 0.6em; +} + +#donator_message p{ + line-height:1; + margin:0.5em 0; + padding:2px; + padding-bottom:10px; +} + +#donator_message span{ + padding-top:10px; + float:right; +} + +#plugin_check img { + float: right; +} + +#plugin_check p.message { + font-size: 90%; + color: #666; +} +/* SETTING FOR FLASH UPLOAD BUTTON */ +.swfupload { + position:absolute; + z-index:1; + vertical-align:top; +} + +/* SETTINGS FOR THE OPTIONS TABLE */ +.ngg-options th { + width:22%; +} + +a.switch-expert { + text-decoration:none; +} + +/* WATERMARK */ +#wm-preview { + float:right; + font-size:90%; + width:35%; + border-color:#EBEBEB rgb(204, 204, 204) rgb(204, 204, 204) rgb(235, 235, 235); + border-style:solid; + border-width:1px; + margin-bottom:10px; + margin-left:10px; + margin-right:8px; + padding:2px; +} +#wm-preview h3{ + background:#F9F9F9 none repeat scroll 0%; + font-size:14px; + font-weight:bold; + margin:0pt 0pt 10px; + padding:8px 5px; +} + +#wm-position { + width:100%; + margin-left:40px; +} + +.wm-table { + border-collapse:collapse; + margin-top:1em; + width: 60%; + clear:none; +} +.wm-table td { + border-bottom:8px solid #FFFFFF; + line-height:20px; + margin-bottom:9px; + padding:10px; +} +.wm-table th { + border-bottom:8px solid #FFFFFF; + padding:10px; + text-align:left; +} +.wm-table tr { + background:#F9F9F9 none repeat scroll 0%; +} + +/* SETTINGS FOR MANAGE TABLE */ + +div#poststuff #gallerydiv { + cursor:pointer; +} + +p#ngg-inlinebutton { + float:right; + margin:0pt; + position:relative; + top:-25pt; +} + +#gallery_fields { + width: 100%; +} + +#gallery_fields td{ + padding: 5px; + min-width: 105px; +} + +#gallery_fields input[type=text], +#gallery_fields textarea, +#gallery_fields select { + min-width: 220px; + width: 99%; +} + +#ngg-listimages .row_actions, +#ngg-listimages .row_actions td { + border-top: none; + /* background-color: #F9F9F9; */ + padding-top: 0px; + padding-bottom: 0px; +} + +#ngg-listimages .row_actions.alternate, +#ngg-listimages .row_actions.alternate td { + /* background-color: #FCFCFC; */ +} + +#ngg-listimages .row-actions { + padding-left: 0px; + margin-bottom: -2px; + position: relative; + bottom: 4px; +} + +#ngg-listimages .iedit, +#ngg-listimages .iedit td, +#ngg-listimages .iedit th { + border: none; +} + +#ngg-listimages .iedit td { + padding-top: 8px; +} + +#ngg-listimages .column select { + width: 100%; +} + +#ngg-listimages .column-1 input { + margin: 0 0 0 8px; +} + +#ngg-listimages .column-1, +#ngg-listimages .column-2 { + width: 4%; + min-width: 33px; +} + +#ngg-listimages .column-3 { + min-width: 80px; + width: 10%; +} + +#ngg-listimages .column-3 .thumb { + max-height: 80px; + max-width: 80px; +} + +#ngg-listimages .column-4 { + width: 22%; + max-width: 220px; + +} + +#ngg-listimages .column-4 .meta { + font-size: 11px; +} + +#ngg-listimages .column-4 label input[type=checkbox] { + position: relative; + top: -2px; +} + +#ngg-listimages .column-5 input[type=text], +#ngg-listimages .column-5 textarea, +#ngg-listimages .column-6 textarea { + width: 100%; +} + +#ngg-listimages .column-5 textarea { + height: 57px; +} + +#ngg-listimages .column-6 textarea { + height: 80px; +} + +/* SETTINGS FOR PROGRESS BAR */ + +div .progressborder { + border:1px solid #DDDDDD; + display: block; + height: 30px; + background-color: #464646; + width: 100%; + margin-top: 15px; + margin-bottom: 15px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius: 5px; +} + +div .progressbar { + border: medium none ; + display: block; + height: 30px; + background-color: #D54E21; + width: 0%; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius: 5px; +} + +div .progressbar span { + display: inline; + position: absolute; + color: white; + font-weight: bold; + padding: 5px 0 0 5px; +} + +.show_details +{ + height: 16px; + line-height: 20px; + overflow: hidden; + min-width: 8em; + padding: 3px; + cursor:pointer; +} + +.show_details span +{ + border-bottom:1px solid #999; + white-space:pre; +} +.show_details:hover +{ + height: auto; + overflow: visible; + border: 1px solid #999; +} + + /* SETTINGS FOR ALBUM PAGE */ + +.albumnav select[name="act_album"] { + width:150px; +} + +.albumnav span { + padding-left: 50px; +} + +#editalbum select[name='pageid'] { + width: 95%; +} + +div .groupItem +{ + cursor: move; + width: 295px; + padding: 5px; + line-height: 1.5; +} + +div .innerhandle { + background-color:#FBFBFB; +} + +.groupItem .item_top +{ + background-color:#2683AE; + color: #FFFFFF; + font-weight:bold; + line-height: 28px; + height: 28px; + padding: 0 5px; + -moz-border-radius: 3px; + -khtml-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; +} + +.groupItem .album_obj +{ + background-color:#D54E21; +} + +.groupItem .item_top a +{ + color:#FFFFFF; + float:right; + text-decoration: none; +} + +.groupItem .item_top a:hover +{ + color:#FFFFFF; +} + +.itemContent { + border-color:#DFDFDF; + border-style:none solid solid; + border-width:0 1px 1px; + padding:2px 0 20px 2px; +} + +.itemContent p { + border: 0; + margin: 0; + padding: 0; +} + +.inlinepicture +{ + float:left; + display:inline; + margin:0pt; + padding:0pt 3px 1px; +} + +.inlinepicture img +{ + margin:3px; + max-height:60px; +} + +.sort_placeholder +{ + border:1px dashed #bba !important; + margin: 5px; + background: #F9F9F9; +} + +.container { + margin-top: 10px; +} + +.target-album { + margin:10px 685px 10px 10px; +} + +.widget-right { + float:right; + margin:0pt 10px; + width:315px; +} + +.widget-holder { + min-height: 400px; + padding-top:1px; +} + +.target { + background-color:#F1F1F1; +} + +div.widget-top h3 { + text-align:center; + line-height:25px; + margin: 0; + padding: 5px 12px; + font-size: 13px; +} + +div.widget-top { + text-shadow:0 1px 0 #FFFFFF; + background-repeat: repeat-x; + background-position: 0 0; + font-size: 13px; +} + +.ui-autocomplete-start { background-position: 99% center; } + +/* SETTINGS FOR SORT GALLERY */ + +#sortGallery { + position:relative; +} + +p#sortButton{ + margin:0; + position:absolute; + right:0; + top:0; +} + +.imageBox,.imageBoxHighlighted{ + width:130px; /* Total width of each image box */ + height:160px; /* Total height of each image box */ + float:left; + overflow: hidden; + text-overflow: ellipsis; + padding: 5px; +} +.imageBox_theImage{ + width:110px; /* Width of image */ + height:125px; /* Height of image */ + + background-position: center; + background-repeat: no-repeat; + margin: 0 auto; + margin-bottom:2px; +} + +.imageBox_label{ /* Title of images - both selected and not selected */ + text-align:center; + font-family: arial; + font-size:11px; + padding-top:2px; + margin: 0 auto; +} + +/* +DIV that indicates where the dragged image will be placed +*/ + +#insertionMarker{ + height:150px; + width:6px; + position:absolute; +} + +#insertionMarkerLine{ + width:6px; /* No need to change this value */ + height:145px; /* To adjust the height of the div that indicates where the dragged image will be dropped */ + +} + +#insertionMarker img{ + float:left; +} + +/* +DIV that shows the image as you drag it +*/ + +#dragDropContent{ + + opacity:0.4; /* 40 % opacity */ + filter:alpha(opacity=40); /* 40 % opacity */ + + /* + No need to change these three values + */ + position:absolute; + z-index:10; + display:none; + +} + +/* UPGRADE PAGE */ + +.error_inline { + background:#FFEBE8 none repeat scroll 0%; + border:1px solid #CC0000; + margin:5px auto; + padding:10px; +} + +/* ABOUT PAGE */ +.ngg-list { + font-size:11px; + margin-left:15px; + list-style-position:inside; + list-style-type:disc; +} + +#ngg-manage-images-items-per-page-label { + float: right; + line-height: 30px; + margin-right: 5px; +} + +#ngg-manage-images-items-per-page { + float: right; + margin-right: 5px; +} + +#adminmenu .wp-submenu a[href*=ngg_pro_upgrade] { + color: #76a934; +} diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/tags-admin.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/tags-admin.css index eec3fbe4109e5633babdc6aaef407dfd2ff6a5d9..a7f5e273e4c0de92a0c31cbfc026de0ded178103 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/tags-admin.css +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/css/tags-admin.css @@ -1,10 +1,10 @@ -.ngg_wrap .auto_list{width:98%;margin:3px 0;padding:3px 5px;} -.ngg_wrap .list_tags {width:240px;vertical-align:top;} -.ngg_wrap .forms_manage {vertical-align:top;} -.ngg_wrap .forms_manage h3 {margin-bottom:5px;} -.ngg_wrap .forms_manage .form-table {margin-top:0;} -.ngg_wrap .sort_order h3 {margin:0;} -.ngg_wrap #ajax_area_tagslist {} -.ngg_wrap #ajax_area_tagslist ul{list-style:square;margin:10px 0 10px 20px;padding:0;} -.ngg_wrap #ajax_area_tagslist ul li{margin:0;padding:0;line-height:1.4;} +.ngg_wrap .auto_list{width:98%;margin:3px 0;padding:3px 5px;} +.ngg_wrap .list_tags {width:240px;vertical-align:top;} +.ngg_wrap .forms_manage {vertical-align:top;} +.ngg_wrap .forms_manage h3 {margin-bottom:5px;} +.ngg_wrap .forms_manage .form-table {margin-top:0;} +.ngg_wrap .sort_order h3 {margin:0;} +.ngg_wrap #ajax_area_tagslist {} +.ngg_wrap #ajax_area_tagslist ul{list-style:square;margin:10px 0 10px 20px;padding:0;} +.ngg_wrap #ajax_area_tagslist ul li{margin:0;padding:0;line-height:1.4;} .ngg_wrap #ajax_area_tagslist ul li span{cursor:pointer;} \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/functions.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/functions.php index 0ee22f7f2b128852e3298b27b058f7e212f87146..4bcfe64856b0d3e83ddd2ff51922b4ecfea99adb 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/functions.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/functions.php @@ -115,14 +115,14 @@ class nggAdmin{ if ($output == false) return $galleryID; - if ($galleryID != false) { + if ($galleryID != false && !isset($_REQUEST['attach_to_post'])) { $message = __('Gallery ID %1$s successfully created. You can show this gallery in your post or page with the shortcode %2$s.<br/>','nggallery'); $message = sprintf($message, $galleryID, '<strong>[nggallery id=' . $galleryID . ']</strong>'); $message .= '<a href="' . admin_url() . 'admin.php?page=nggallery-manage-gallery&mode=edit&gid=' . $galleryID . '" >'; $message .= __('Edit gallery','nggallery'); $message .= '</a>'; - if ($output) nggGallery::show_message($message); + if ($output) nggGallery::show_message($message, 'gallery_created_msg'); } return true; } diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/js/Jcrop/css/jquery.Jcrop.min.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/js/Jcrop/css/jquery.Jcrop.min.css new file mode 100644 index 0000000000000000000000000000000000000000..d04dbd7b2f7b402db30f51a35b5b5e040b48b55f --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/js/Jcrop/css/jquery.Jcrop.min.css @@ -0,0 +1 @@ +.jcrop-holder{text-align:left}.jcrop-vline,.jcrop-hline{font-size:0;position:absolute;background:white url('Jcrop.gif') top left repeat}.jcrop-vline{height:100%;width:1px !important}.jcrop-hline{width:100%;height:1px !important}.jcrop-handle{font-size:1px;width:7px !important;height:7px !important;border:1px #eee solid;background-color:#333;*width:9px;*height:9px;}.jcrop-tracker{width:100%;height:100%}.custom .jcrop-vline,.custom .jcrop-hline{background:yellow}.custom .jcrop-handle{border-color:black;background-color:#c7bb00;-moz-border-radius:3px;-webkit-border-radius:3px} \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/js/Jcrop/js/jquery.Jcrop.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/js/Jcrop/js/jquery.Jcrop.min.js new file mode 100644 index 0000000000000000000000000000000000000000..2058c750b4c9f6c7cb21075c8caddb865f9840a0 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/js/Jcrop/js/jquery.Jcrop.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('(7($){$.1B=7(M,P){g M=M,P=P;d(1G(M)!==\'2P\')M=$(M)[0];d(1G(P)!==\'2P\')P={};d(!(\'2p\'1j P)){P.2p=$.1X.2b?O:F;d($.1X.2b&&$.1X.5r.5u(\'.\')[0]==\'8\')P.2p=F}d(!(\'2z\'1j P))P.2z=$.1X.2b?O:F;g 46={2p:O,4x:\'5z\',1p:3w,3g:\'5w\',3Q:.6,4g:.4,4c:.5,5y:5,4d:9,4b:5,5A:14,2I:0,2z:F,4h:F,4l:F,3J:F,4k:F,47:0,48:0,49:8,4J:20,4I:3,2Y:F,2V:F,3G:F,3B:[0,0],2v:[0,0],2i:[0,0],30:7(){},2W:7(){}};g j=46;2y(P);g $1t=$(M);g $J=$1t.5s().5B(\'5N\').B({1a:\'1c\'});$J.R($1t.R());$J.V($1t.V());$1t.5O($J).2l();4E($J,j.47,j.48);g L=$J.R(),K=$J.V(),$12=$(\'<12 />\').R(L).V(K).1p(2g(\'4Z\')).B({1a:\'52\',3i:j.3g}).4W($1t).1A($J);d(j.1p)$12.1p(j.1p);g $3k=$(\'<J />\').3q(\'2d\',$J.3q(\'2d\')).B(\'1a\',\'1c\').R(L).V(K);g $2S=$(\'<12 />\').R(1D(11)).V(1D(11)).B({1r:4T,1a:\'1c\',4O:\'4P\'}).1A($3k);g $1u=$(\'<12 />\').R(1D(11)).V(1D(11)).B(\'1r\',54);g $2n=$(\'<12 />\').B({1a:\'1c\',1r:5h}).4w($J).1A($2S,$1u);g 1Z=j.49;g $1i=3A().R(L+(1Z*2)).V(K+(1Z*2)).B({1a:\'1c\',T:E(-1Z),S:E(-1Z),1r:3T}).3e(4B);g 1W,1U,1S,1O;g 13,Z,5b=F;g 21=2D($J),1R,34,5t,3x,3b;g G=7(){g m=0,q=0,A=0,u=0,18,17;7 1z(z){g z=3M(z);A=m=z[0];u=q=z[1]};7 1s(z){g z=3M(z);18=z[0]-A;17=z[1]-u;A=z[0];u=z[1]};7 3c(){k[18,17]};7 1Y(2T){g 18=2T[0],17=2T[1];d(0>m+18)18-=18+m;d(0>q+17)17-=17+q;d(K<u+17)17+=K-(u+17);d(L<A+18)18+=L-(A+18);m+=18;A+=18;q+=17;u+=17};7 23(U){g c=Y();1K(U){D\'1w\':k[c.A,c.y];D\'16\':k[c.x,c.y];D\'2e\':k[c.A,c.u];D\'1M\':k[c.x,c.u]}};7 Y(){d(!j.2I)k 43();g 15=j.2I,24=j.2i[0]/13,5a=j.2i[1]/Z,1C=j.2v[0]/13,3y=j.2v[1]/Z,2a=A-m,28=u-q,3u=Q.1h(2a),3t=Q.1h(28),44=3u/3t,C,I;d(1C==0){1C=L*10}d(3y==0){3y=K*10}d(44<15){I=u;w=3t*15;C=2a<0?m-w:w+m;d(C<0){C=0;h=Q.1h((C-m)/15);I=28<0?q-h:h+q}X d(C>L){C=L;h=Q.1h((C-m)/15);I=28<0?q-h:h+q}}X{C=A;h=3u/15;I=28<0?q-h:q+h;d(I<0){I=0;w=Q.1h((I-q)*15);C=2a<0?m-w:w+m}X d(I>K){I=K;w=Q.1h(I-q)*15;C=2a<0?m-w:w+m}}d(C>m){d(C-m<24){C=m+24}X d(C-m>1C){C=m+1C}d(I>q){I=q+(C-m)/15}X{I=q-(C-m)/15}}X d(C<m){d(m-C<24){C=m-24}X d(m-C>1C){C=m-1C}d(I>q){I=q+(m-C)/15}X{I=q-(m-C)/15}}d(C<0){m-=C;C=0}X d(C>L){m-=C-L;C=L}d(I<0){q-=I;I=0}X d(I>K){q-=I-K;I=K}k 5i=3o(1N(m,q,C,I))};7 3M(p){d(p[0]<0)p[0]=0;d(p[1]<0)p[1]=0;d(p[0]>L)p[0]=L;d(p[1]>K)p[1]=K;k[p[0],p[1]]};7 1N(m,q,A,u){g 3O=m,3K=A,3N=q,3L=u;d(A<m){3O=A;3K=m}d(u<q){3N=u;3L=q}k[Q.1P(3O),Q.1P(3N),Q.1P(3K),Q.1P(3L)]};7 43(){g 2m=A-m;g 29=u-q;d(1W&&(Q.1h(2m)>1W))A=(2m>0)?(m+1W):(m-1W);d(1U&&(Q.1h(29)>1U))u=(29>0)?(q+1U):(q-1U);d(1O&&(Q.1h(29)<1O))u=(29>0)?(q+1O):(q-1O);d(1S&&(Q.1h(2m)<1S))A=(2m>0)?(m+1S):(m-1S);d(m<0){A-=m;m-=m}d(q<0){u-=q;q-=q}d(A<0){m-=A;A-=A}d(u<0){q-=u;u-=u}d(A>L){g 19=A-L;m-=19;A-=19}d(u>K){g 19=u-K;q-=19;u-=19}d(m>L){g 19=m-K;u-=19;q-=19}d(q>K){g 19=q-K;u-=19;q-=19}k 3o(1N(m,q,A,u))};7 3o(a){k{x:a[0],y:a[1],A:a[2],u:a[3],w:a[2]-a[0],h:a[3]-a[1]}};k{1N:1N,1z:1z,1s:1s,3c:3c,1Y:1Y,23:23,Y:Y}}();g H=7(){g 53,51,50,2r,3n=4X;g 2E={};g N={};g 1J=O;g 1k=j.4b;d(j.3J){2E={T:2t(\'4i\').B(\'T\',$.1X.2b?E(-1):E(0)),3V:2t(\'4i\'),S:2t(\'4j\'),3R:2t(\'4j\')}}d(j.4k){N.t=2o(\'n\');N.b=2o(\'s\');N.r=2o(\'e\');N.l=2o(\'w\')}j.4l&&3f([\'n\',\'s\',\'e\',\'w\']);j.4h&&3f([\'1M\',\'16\',\'1w\',\'2e\']);7 2t(1F){g 1L=$(\'<12 />\').B({1a:\'1c\',26:j.4g}).1p(2g(1F));$2S.1A(1L);k 1L};7 3r(U,3X){g 1L=$(\'<12 />\').3e(3E(U)).B({1I:U+\'-2J\',1a:\'1c\',1r:3X});$1u.1A(1L);k 1L};7 4e(U){k 3r(U,3n++).B({T:E(-1k+1),S:E(-1k+1),26:j.4c}).1p(2g(\'N\'))};7 2o(U){g s=j.4d,o=1k,h=s,w=s,t=o,l=o;1K(U){D\'n\':D\'s\':w=1D(11);W;D\'e\':D\'w\':h=1D(11);W}k 3r(U,3n++).R(w).V(h).B({T:E(-t+1),S:E(-l+1)})};7 3f(2F){5L(i 1j 2F)N[2F[i]]=4e(2F[i])};7 2C(c){g 3m=Q.1P((c.h/2)-1k),3l=Q.1P((c.w/2)-1k),5q=5p=-1k+1,2s=c.w-1k,2w=c.h-1k,x,y;\'e\'1j N&&N.e.B({T:E(3m),S:E(2s)})&&N.w.B({T:E(3m)})&&N.s.B({T:E(2w),S:E(3l)})&&N.n.B({S:E(3l)});\'1w\'1j N&&N.1w.B({S:E(2s)})&&N.2e.B({T:E(2w),S:E(2s)})&&N.1M.B({T:E(2w)});\'b\'1j N&&N.b.B({T:E(2w)})&&N.r.B({S:E(2s)})};7 4m(x,y){$3k.B({T:E(-y),S:E(-x)});$2n.B({T:E(y),S:E(x)})};7 2J(w,h){$2n.R(w).V(h)};7 2q(){g c=G.Y();G.1z([c.x,c.y]);G.1s([c.A,c.u]);2A()};7 2A(){d(2r)k 1m()};7 1m(){g c=G.Y();2J(c.w,c.h);4m(c.x,c.y);j.3J&&2E[\'3R\'].B({S:E(c.w-1)})&&2E[\'3V\'].B({T:E(c.h-1)});1J&&2C(c);2r||1y();j.30(31(c))};7 1y(){$2n.1y();$J.B(\'26\',j.3Q);2r=F};7 1E(){1l();$2n.2l();$J.B(\'26\',1);2r=O};7 3s(){d(1J){2C(G.Y());$1u.1y()}};7 1V(){1J=F;d(j.3G){2C(G.Y());$1u.1y();k F}};7 1l(){1J=O;$1u.2l()};7 25(v){(3x=v)?1l():1V()};7 1n(){25(O);2q()};g $3a=3A().3e(3E(\'1o\')).B({1I:\'1o\',1a:\'1c\',1r:5M})$2S.1A($3a);1l();k{2A:2A,1m:1m,1E:1E,2q:2q,1b:7(1I){$3a.B(\'1I\',1I)},1V:1V,4n:7(){1J=F},3s:3s,1l:1l,25:25,1n:1n}}();g 1d=7(){g 2R=7(){},2N=7(){},2O=j.2p;d(!2O){$1i.3v(2Q).3C(2j).4Y(2j)}7 4q(){$1i.B({1r:4R});d(2O){$(3U).3v(2Q).3C(2j)}}7 3S(){$1i.B({1r:3T});d(2O){$(3U).3W(\'3v\',2Q).3W(\'3C\',2j)}}7 2Q(e){2R(22(e))};7 2j(e){e.32();e.2H();d(1R){1R=O;2N(22(e));j.2W(31(G.Y()));3S();2R=7(){};2N=7(){}}k O};7 1x(1o,1n){1R=F;2R=1o;2N=1n;4q();k O};7 1b(t){$1i.B(\'1I\',t)};$J.5H($1i);k{1x:1x,1b:1b}}();g 2U=7(){g $2B=$(\'<57 1F="5d" />\').B({1a:\'1c\',S:\'-5j\'}).5g(4M).5m(4N),$4v=$(\'<12 />\').B({1a:\'1c\',4O:\'4P\'}).1A($2B);7 1Q(){d(j.2z){$2B.1y();$2B.45()}};7 4N(e){$2B.2l()};7 2h(e,x,y){d(j.2V){G.1Y([x,y]);H.2A()};e.32();e.2H()};7 4M(e){d(e.5x)k F;3b=e.4V?F:O;g 2x=3b?10:1;1K(e.5o){D 37:2h(e,-2x,0);W;D 39:2h(e,2x,0);W;D 38:2h(e,0,-2x);W;D 40:2h(e,0,2x);W;D 27:H.1E();W;D 9:k F}k 5v(e)};d(j.2z)$4v.4w($J);k{1Q:1Q}}();7 E(n){k\'\'+1q(n)+\'E\'};7 1D(n){k\'\'+1q(n)+\'%\'};7 2g(4t){k j.4x+\'-\'+4t};7 2D(M){g z=$(M).2T();k[z.S,z.T]};7 22(e){k[(e.5E-21[0]),(e.5D-21[1])]};7 4D(1F){d(1F!=34){1d.1b(1F);34=1F}};7 4F(1f,z){21=2D($J);1d.1b(1f==\'1o\'?1f:1f+\'-2J\');d(1f==\'1o\')k 1d.1x(4z(z),2G);g 4L=G.Y();g 3d=3F(1f);g 4p=G.23(3F(3d));G.1z(G.23(3d));G.1s(4p);1d.1x(4r(1f,4L),2G)};7 4r(1f,f){k 7(z){d(!j.2I)1K(1f){D\'e\':z[1]=f.u;W;D\'w\':z[1]=f.u;W;D\'n\':z[0]=f.A;W;D\'s\':z[0]=f.A;W}X 1K(1f){D\'e\':z[1]=f.y+1;W;D\'w\':z[1]=f.y+1;W;D\'n\':z[0]=f.x+1;W;D\'s\':z[0]=f.x+1;W}G.1s(z);H.1m()}};7 4z(z){g 2M=z;2U.1Q();k 7(z){G.1Y([z[0]-2M[0],z[1]-2M[1]]);2M=z;H.1m()}};7 3F(U){1K(U){D\'n\':k\'1M\';D\'s\':k\'16\';D\'e\':k\'16\';D\'w\':k\'1w\';D\'1w\':k\'1M\';D\'16\':k\'2e\';D\'2e\':k\'16\';D\'1M\':k\'1w\'}};7 3E(U){k 7(e){d(j.2Z)k O;d((U==\'1o\')&&!j.2V)k O;1R=F;4F(U,22(e));e.2H();e.32();k O}};7 4E($M,w,h){g 16=$M.R(),1T=$M.V();d((16>w)&&w>0){16=w;1T=(w/$M.R())*$M.V()}d((1T>h)&&h>0){1T=h;16=(h/$M.V())*$M.R()}13=$M.R()/16;Z=$M.V()/1T;$M.R(16).V(1T)};7 31(c){k{x:1q(c.x*13),y:1q(c.y*Z),A:1q(c.A*13),u:1q(c.u*Z),w:1q(c.w*13),h:1q(c.h*Z)}};7 2G(z){g c=G.Y();d(c.w>j.3B[0]&&c.h>j.3B[1]){H.1V();H.1n()}X{H.1E()}1d.1b(j.2Y?\'35\':\'2k\')};7 4B(e){d(j.2Z)k O;d(!j.2Y)k O;1R=F;21=2D($J);H.1l();4D(\'35\');g z=22(e);G.1z(z);1d.1x(4C,2G);2U.1Q();H.1m();e.2H();e.32();k O};7 4C(z){G.1s(z);H.1m()};7 3A(){g 1i=$(\'<12></12>\').1p(2g(\'5c\'));$.1X.2b&&1i.B({26:0,3i:\'59\'});k 1i};7 3D(a){g m=a[0]/13,q=a[1]/Z,A=a[2]/13,u=a[3]/Z;d(3x)k;g 2c=G.1N(m,q,A,u);g c=G.Y();g 1e=2f=[c.x,c.y,c.A,c.u];g 4K=j.4J;g x=1e[0];g y=1e[1];g A=1e[2];g u=1e[3];g 4G=2c[0]-2f[0];g 4y=2c[1]-2f[1];g 4o=2c[2]-2f[2];g 4s=2c[3]-2f[3];g 1g=0;g 4H=j.4I;H.25(F);g 4u=7(){k 7(){1g+=(11-1g)/4H;1e[0]=x+((1g/11)*4G);1e[1]=y+((1g/11)*4y);1e[2]=A+((1g/11)*4o);1e[3]=u+((1g/11)*4s);d(1g<11)3j();X H.1n();d(1g>=5J.8)1g=11;36(1e)}}();7 3j(){5K.5C(4u,4K)};3j()};7 1v(2u){36([2u[0]/13,2u[1]/Z,2u[2]/13,2u[3]/Z])};7 36(l){G.1z([l[0],l[1]]);G.1s([l[2],l[3]]);H.1m()};7 2y(P){d(1G(P)!=\'2P\')P={};j=$.4S(j,P);d(1G(j.30)!==\'7\')j.30=7(){};d(1G(j.2W)!==\'7\')j.2W=7(){}};7 3I(){k 31(G.Y())};7 3H(){k G.Y()};7 4a(P){2y(P);2X()};7 41(){j.2Z=F;H.1l();H.1b(\'2k\');1d.1b(\'2k\')};7 3Y(){j.2Z=O;2X()};7 3Z(){H.1n();1d.1x(3w,3w)};7 3p(){$12.4Q();$1t.1y()};7 2X(3P){j.3G?3P?H.4n():H.1V():H.1l();1d.1b(j.2Y?\'35\':\'2k\');H.1b(j.2V?\'1o\':\'2k\');$12.B(\'3i\',j.3g);d(\'1v\'1j j){1v(P.1v);H.1n();4f(j.1v)}d(\'3h\'1j j){13=j.3h[0]/L;Z=j.3h[1]/K}1W=j.2v[0]||0;1U=j.2v[1]||0;1S=j.2i[0]||0;1O=j.2i[1]||0;d(\'33\'1j j){$J.3q(\'2d\',j.33);4f(j.33)}H.2q()};$1u.2l();2X(F);g 2K={3D:3D,1v:1v,2y:4a,3I:3I,3H:3H,5f:41,5l:3Y,5e:3Z,45:2U.1Q,56:7(){k[L*13,K*Z]},5G:7(){k[L,K]},1E:H.1E,3p:3p};$1t.2L(\'1B\',2K);k 2K};$.5I.1B=7(j){7 42(3z){g 4A=j.5F||3z.2d;g J=5n 5k();J.58=7(){$.1B(3z,j)};J.2d=4A};d(1G(j)!==\'2P\')j={};1H.55(7(){d($(1H).2L(\'1B\')){d(j==\'2K\')k $(1H).2L(\'1B\');X $(1H).2L(\'1B\').2y(j)}X 42(1H)});k 1H}})(4U);',62,361,'|||||||function||||||if|||var|||options|return||x1||||y1||||y2|||||pos|x2|css|xx|case|px|true|Coords|Selection|yy|img|boundy|boundx|obj|handle|false|opt|Math|width|left|top|ord|height|break|else|getFixed|yscale||100|div|xscale||aspect|nw|oy|ox|delta|position|setCursor|absolute|Tracker|animat|mode|pcent|abs|trk|in|hhs|disableHandles|update|done|move|addClass|parseInt|zIndex|setCurrent|origimg|hdl_holder|setSelect|ne|activateHandlers|show|setPressed|append|Jcrop|max_x|pct|release|type|typeof|this|cursor|seehandles|switch|jq|sw|flipCoords|ymin|round|watchKeys|btndown|xmin|nh|ylimit|enableHandles|xlimit|browser|moveOffset|bound||docOffset|mouseAbs|getCorner|min_x|animMode|opacity||rh|ysize|rw|msie|animto|src|se|initcr|cssClass|doNudge|minSize|trackUp|default|hide|xsize|sel|insertDragbar|trackDocument|refresh|awake|east|insertBorder|rect|maxSize|south|nudge|setOptions|keySupport|updateVisible|keymgr|moveHandles|getPos|borders|li|doneSelect|stopPropagation|aspectRatio|resize|api|data|lloc|onDone|trackDoc|object|trackMove|onMove|img_holder|offset|KeyManager|allowMove|onSelect|interfaceUpdate|allowSelect|disabled|onChange|unscale|preventDefault|outerImage|lastcurs|crosshair|setSelectRaw||||track|shift_down|getOffset|opp|mousedown|createHandles|bgColor|trueSize|backgroundColor|animateStart|img2|midhoriz|midvert|hdep|makeObj|destroy|attr|dragDiv|showHandles|rha|rwa|mousemove|null|animating|max_y|from|newTracker|minSelect|mouseup|animateTo|createDragger|oppLockCorner|allowResize|tellScaled|tellSelect|drawBorders|xb|yb|rebound|ya|xa|alt|bgOpacity|right|toBack|290|document|bottom|unbind|zi|enableCrop|cancelCrop||disableCrop|attachWhenDone|getRect|real_ratio|focus|defaults|boxWidth|boxHeight|boundary|setOptionsNew|handleOffset|handleOpacity|handleSize|insertHandle|delete|borderOpacity|cornerHandles|hline|vline|dragEdges|sideHandles|moveto|enableOnly|ix2|opc|toFront|dragmodeHandler|iy2|cl|animator|keywrap|insertBefore|baseClass|iy1|createMover|loadsrc|newSelection|selectDrag|myCursor|presize|startDragMode|ix1|velocity|swingSpeed|animationDelay|interv|fc|parseKey|onBlur|overflow|hidden|remove|450|extend|310|jQuery|shiftKey|insertAfter|370|mouseout|holder|dragmode|end|relative|start|320|each|getBounds|input|onload|white|min_y|enabled|tracker|radio|cancel|disable|keypress|300|last|30px|Image|enable|blur|new|keyCode|west|north|version|clone|dimmed|split|nothing|black|ctrlKey|handlePad|jcrop|edgeMargin|removeAttr|setTimeout|pageY|pageX|useImg|getWidgetSize|before|fn|99|window|for|360|id|after'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/js/ngg.ajax.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/js/ngg.ajax.min.js new file mode 100644 index 0000000000000000000000000000000000000000..3e3228c2d4f6a2213343b8eabc573a26087f11aa --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/js/ngg.ajax.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('(a($){3={2:{h:e.h,y:"D",k:e.k,c:e.c,r:e.r,9:e.9,A:e.A,m:e.m,o:e.o,x:16,i:0,P:5,C:G},f:a(4){s=b.2;j J=$.K({y:"D",h:s.h,L:"k="+s.k+"&c="+s.c+"&Q="+s.r+"&W="+s.9[4]+"&i="+3.2.i,T:F,x:G,U:a(6){15(17(6)){z-1:7.l(3.2.A);w;z 0:7.l(3.2.m);w;z 1:w;14:7.l("<d>v "+3.2.9[4]+":</d> "+3.2.o,6);w}},m:a(E,t,u){3.2.u=u},X:a(E,t){4++;g(4<3.2.9.q){j f=O;g(t==\'m\'||t==\'Z\'){3.2.i+=1;g(3.2.i<=3.2.P){j B=3.2.C/13;4--;f=F;7.l("<d>v "+3.2.9[q]+":</d> "+"10 11 "+B+" B; 1b 1h 1m 1l.");1k(a(){3.f(4)},3.2.C)}p{j 6=E.N;g(6==\'\'){6=\'( \'+3.2.u+\' )\'}7.l("<d>v "+3.2.9[4]+":</d> "+3.2.o,6);7.I(4)}}p{3.2.i=0;7.I(4)}g(f)3.f(4)}p{7.1d()}}})},H:a(4){s=b.2;j J=$.K({y:"D",h:s.h,L:"k="+s.k+"&c="+s.c+"&Q="+s.r+"&W="+s.9[4],1e:"1c",T:F,x:G,U:a(6){n=n.18(6)},m:a(6){7.l("<d>v "+3.2.9[4]+":</d> "+3.2.o,6.N)},X:a(){4++;7.I(4);g(4<3.2.9.q)3.H(4);p{4=0;3.2.9=n;3.2.c=M;3.2.1j=n.q;7.V(3.2);3.f(4)}}})},V:a(s){g(b.R)1g;j 4=0;b.2=$.1f({},b.2,{},s||{});g(b.2.c.S(0,8)==\'1i\'){M=b.2.c.S(8);b.2.c=\'19\';n=12 1a();b.H(4)}p{b.f(4)}b.R=O}}}(Y));',62,85,'||settings|nggAjax|index||msg|nggProgressBar||ids|function|this|operation|strong|nggAjaxSetup|run|if|url|retries|var|action|addNote|error|imageIDS|failure|else|length|nonce||textStatus|errorThrown|ID|break|timeout|type|case|permission|seconds|retry_delay|POST|jqXHR|false|30000|readIDs|increase|req|ajax|data|nextOperation|responseText|true|max_retries|_wpnonce|inited|substring|cache|success|init|image|complete|jQuery|abort|Retrying|in|new|1000|default|switch|20000|parseInt|concat|get_image_ids|Array|host|json|finished|dataType|extend|return|might|gallery_|maxStep|setTimeout|throttling|be'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/js/ngg.progressbar.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/js/ngg.progressbar.min.js new file mode 100644 index 0000000000000000000000000000000000000000..742a576c12289dc0fd9e1e79f0e765fc313bbea1 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/js/ngg.progressbar.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('(6($){12={a:{2:\'11\',X:e,C:E,l:\'\',b:E},b:6(s){s=5.a=$.10({},5.a,{},s||{});d=R.K((e/s.X)*e)/e;7($("#"+s.2+"c").n==0){s.l=(s.l.n>0)?s.l:\'\';$("1i").i(\'<4 2="\'+s.2+\'c"><4 2="\'+s.2+\'" o="1e"><4 o="\'+s.2+\'"><9>0%</9></4></4></4>\');$("#"+s.2+"c").w({d:1d,1c:h,18:h,1f:s.l,1b:{1a:\'Q\',19:\'Q\',1h:5.u(q)}})}5.4=$(\'#\'+s.2+\'c\');s.b=h},u:6(M){8 f=M;1g{7(f&&f.y)f=f.y}17(15){}Z f},Y:6(F){s=5.a;7(!s.b)5.b();8 4=5.4;7(4.O("#"+s.2+"m").n==0)4.i(\'<4 o="\'+s.2+\'m"><9 16="14:13" 2="\'+s.2+\'m">\'+F+\'</9></4>\');k $("#"+s.2+"m").A(F)},W:6(x,I){s=5.a;7(!s.b)5.b();8 4=5.4;s.C=h;7(4.O("#"+s.2+"r").n==0)4.i(\'<P 2="\'+s.2+\'r">&1y;</P>\');7(I)$("#"+s.2+"r").i("<p>"+x+"<4 o=\'1w\'><9>[1B]</9><1G />"+I+"</4></p>");k $("#"+s.2+"r").i("<p>"+x+"</p>");4.w("1C","1D",1A)},1u:6(B){s=5.a;8 j=B*d+"%";8 L=R.K(B*d)+"%";$("#"+s.2+" 4").d(j);$("#"+s.2+" 9").A(L);$(5.u(q).1v).1m(0);8 t=$(5.u(q).1k).y();8 T=t.G(\'H\');D(6(){t.G(\'H\',0)},1);D(6(){t.G(\'H\',T)},3)},1p:6(){s=5.a;$("#"+s.2+" 4").d(\'e%\');$("#"+s.2+" 9").A(\'e%\');8 4=5.4;8 v=5;7(s.C){$("#"+s.2).g(U).1t("1s");v.W("1r!");4.1q(6(){v.z(E,0)})}k{q.D(6(){v.z(h,1)},U)}},z:6(g,j){7(g)$("#"+s.2+"c").g(N).w("V");k $("#"+s.2+"c").w("V");$("#"+s.2+"c").1o();$(\'.J\').1E("<1j 1F=\\"1x\\" 1z=\\"1n\\" j=\\""+j+"\\">");7(g)$(\'.J\').g(N).S();k $(\'.J\').S()}}})(1l);',62,105,'||id||div|this|function|if|var|span|settings|init|_dialog|width|100|retval|delay|true|append|value|else|header|_message|length|class|li|window|_note||tinymce_frame|find_parent|progressBar|dialog|note|parent|remove_dialog|html|step|wait|setTimeout|false|message|css|top|detail|nggform|round|rvalue|child|4000|find|ul|center|Math|submit|css_top|1000|destroy|addNote|maxStep|addMessage|return|extend|progressbar|nggProgressBar|block|display|Exception|style|catch|modal|at|my|position|resizable|640|progressborder|title|try|of|body|input|frameElement|jQuery|scrollTop|ajax_callback|remove|finished|click|Done|slow|hide|increase|document|show_details|hidden|nbsp|name|220|more|option|height|prepend|type|br'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/manage-images.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/manage-images.php index 2947798b01e6dc36ee32f8e9c7dd725af0cd8573..8597ee93dd10720b289b744c34a0b5f0eb5fa002 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/manage-images.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/manage-images.php @@ -12,18 +12,24 @@ function nggallery_picturelist($controller) { $wp_list_table = new _NGG_Images_List_Table('nggallery-manage-images'); - if ($is_search) { - + // look for pagination + $_GET['paged'] = isset($_GET['paged']) && ($_GET['paged'] > 0) ? absint($_GET['paged']) : 1; + $items_per_page = (!empty($_GET['items']) ? $_GET['items'] : apply_filters('ngg_manage_images_items_per_page', 50)); + if ($items_per_page == 'all') + $items_per_page = PHP_INT_MAX; + else + $items_per_page = (int)$items_per_page; + + if ($is_search) + { // fetch the imagelist $picturelist = $ngg->manage_page->search_result; + $total_number_of_images = count($picturelist); // we didn't set a gallery or a pagination - $act_gid = 0; - $_GET['paged'] = 1; - $page_links = false; - - } else { - + $act_gid = 0; + } + else { // GET variables $act_gid = $ngg->manage_page->gid; @@ -42,13 +48,6 @@ function nggallery_picturelist($controller) { return; } - // look for pagination - $_GET['paged'] = isset($_GET['paged']) && ($_GET['paged'] > 0) ? absint($_GET['paged']) : 1; - $items_per_page = (!empty($_GET['items']) ? $_GET['items'] : apply_filters('ngg_manage_images_items_per_page', 50)); - if ($items_per_page == 'all') - $items_per_page = PHP_INT_MAX; - else - $items_per_page = (int)$items_per_page; $start = ( $_GET['paged'] - 1 ) * $items_per_page; // get picture values @@ -333,8 +332,12 @@ jQuery(document).ready( function($) { <div id="poststuff" class="meta-box-sortables"> <?php wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false ); ?> <div id="gallerydiv" class="postbox <?php echo postbox_classes('gallerydiv', 'ngg-manage-gallery'); ?>" > - <div class="handlediv" title="<?php esc_attr_e('Click to toggle'); ?>"><br/></div> - <h3 class="hndl"><span><?php _e('Gallery settings', 'nggallery') ?><small> (<?php _e('Click here for more settings', 'nggallery') ?>)</small></span></h3> + <div class="handlediv" title="<?php esc_attr_e( 'Click to toggle' ); ?>"> + <span class="toggle-indicator"></span> + </div> + <h3> + <span> <?php _e('Gallery settings', 'nggallery'); ?></span> + </h3> <div class="inside"> <?php $controller->render_gallery_fields(); ?> diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/overview.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/overview.php index 121331e1d02e409e8687add122314c10f2f718fc..9980964b6bb5e4b6fdbbfffb6a124022ca776e2a 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/overview.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/overview.php @@ -2,262 +2,69 @@ if (preg_match('#' . basename(__FILE__) . '#', $_SERVER['PHP_SELF'])) { die('You are not allowed to call this page directly.'); } -/** - * nggallery_admin_overview() - * - * Add the admin overview the dashboard style - * @return mixed content - */ -function nggallery_admin_overview() -{ - ?> - <div class="wrap ngg-wrap"> - <?php screen_icon('nextgen-gallery'); ?> - <h2><?php _e('NextGEN Gallery Overview', 'nggallery'); ?></h2> - <div id="dashboard-widgets-container" class="ngg-overview"> - <div id="dashboard-widgets" class="metabox-holder"> - <div id="post-body"> - <div id="dashboard-widgets-main-content"> - <div class="postbox-container" id="main-container" style="width:75%;"> - <?php do_meta_boxes('ngg_overview', 'left', ''); ?> - </div> - <div class="postbox-container" id="side-container" style="width:24%;"> - <?php do_meta_boxes('ngg_overview', 'right', ''); ?> - </div> - </div> - </div> - </div> - </div> - </div> - <script type="text/javascript"> - jQuery(document).ready(function($) { - postboxes.add_postbox_toggles('ngg-overview'); - }); - </script> -<?php -} - class C_NGG_Admin_Overview { - public function __construct() - { - /** - * Load the meta boxes - * - */ - add_meta_box( - 'dashboard_right_now', - __('Welcome to NextGEN Gallery !', 'nggallery'), - array($this, 'overview_metabox'), - 'ngg_overview', - 'left', - 'core' - ); - - add_meta_box( - 'ngg_meta_box', - __('Do you like this Plugin?', 'nggallery'), - array($this, 'sharing_metabox'), - 'ngg_overview', - 'right', - 'core' - ); - - add_meta_box( - 'ngg_about_meta_box', - __('About', 'nggallery'), - array($this, 'about_metabox'), - 'ngg_overview', - 'left', - 'core' - ); - - if (!is_multisite() || is_super_admin()) - { - add_meta_box( - 'ngg_server', - __('Server Settings', 'nggallery'), - array($this, 'server_metabox'), - 'ngg_overview', - 'right', - 'core' - ); - } - } - - public function sharing_metabox() - { - echo '<p>'; - echo sprintf(__('This plugin is primarily developed, maintained, supported and documented by <a href="%s" target="_blank">Imagely</a> with a lot of love & effort. Any kind of contribution would be highly appreciated. Thanks!', 'nggallery'), 'https://www.imagely.com/'); - echo '</p><ul>'; - - $url = 'http://wordpress.org/plugins/nextgen-gallery/' ; - echo "<li style='padding-left: 38px; background:transparent url(" . NGGALLERY_URLPATH . "admin/images/icon-rating.png ) no-repeat scroll center left; background-position: 16px 50%; text-decoration: none;'><a href='{$url}' target='_blank'>"; - _e('Please click "Works" on WordPress.org', 'nggallery'); - echo "</a></li>"; - - $url = 'http://wordpress.org/plugins/nextgen-gallery/' ; - echo "<li style='padding-left: 38px; background:transparent url(" . NGGALLERY_URLPATH . "admin/images/icon-rating.png ) no-repeat scroll center left; background-position: 16px 50%; text-decoration: none;'><a href='{$url}' target='_blank'>"; - _e('Give it a good rating on WordPress.org', 'nggallery'); - echo "</a></li>"; - - $url = 'https://www.imagely.com/wordpress-gallery-plugin/nextgen-gallery/'; - echo "<li style='padding-left: 38px; background:transparent url(" . NGGALLERY_URLPATH . "admin/images/nextgen.png ) no-repeat scroll center left; background-position: 16px 50%; text-decoration: none;'><a href='{$url}' target='_blank'>"; - _e("Visit the plugin homepage", 'nggallery'); - echo "</a></li>"; - - $url = 'https://www.imagely.com/languages/'; - echo "<li style='padding-left: 38px; background:transparent url(" . NGGALLERY_URLPATH . "admin/images/icon-translate.png ) no-repeat scroll center left; background-position: 16px 50%; text-decoration: none;'><a href='{$url}' target='_blank'>"; - _e("Help translating it", 'nggallery'); - echo "</a></li>"; - - echo '</ul>'; - - echo ' - <div class="social" style="text-align:center;margin:15px 0 10px 0;"><span class="social" style="margin-right:5px;"><a target="_blank" href="http://twitter.com/NextGENGallery"><img title="Follow NextGEN on Twitter" alt="Twitter" src="' . NGGALLERY_URLPATH . 'admin/images/twitter.png"></a></span><span class="social" style="margin-right:5px;"><a target="_blank" href="http://www.facebook.com/NextGENGallery"><img title="Like NextGEN on Facebook" alt="Facebook" src="' . NGGALLERY_URLPATH . 'admin/images/facebook.png"></a></span><span class="social"><a target="_blank" href="http://plus.google.com/101643895780935290171"><img title="Add NextGEN to your circles" alt="GooglePlus" src="' . NGGALLERY_URLPATH . 'admin/images/googleplus.png"></a></span></div>'; - } - - /** - * Show a summary of the used images - * - * @return void - */ - public function overview_metabox() - { - global $wpdb; - $images = intval( $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->nggpictures") ); - $galleries = intval( $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->nggallery") ); - $albums = intval( $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->nggalbum") ); - ?> - <style type='text/css'> - #ngg_overview_right_now p { - padding: 0 0 6px 10px; - margin: 0; - } - #ngg_overview_right_now table { - margin-left: 10px; - } - #ngg_overview_right_now td { - padding: 4px; - } - #ngg_overview_right_now td:first-child { - font-size: 16px; - } - </style> - <div class="table table_content" id='ngg_overview_right_now'> - <p><?php _e('At a Glance', 'nggallery'); ?></p> - <table> - <tbody> - <tr class="first"> - <td class="first b"><a href="admin.php?page=ngg_addgallery"><?php echo $images; ?></a></td> - <td class="t"><a href="admin.php?page=ngg_addgallery"><?php echo _n( 'Image', 'Images', $images, 'nggallery' ); ?></a></td> - <td class="b"></td> - <td class="last"></td> - </tr> - <tr> - <td class="first b"><a href="admin.php?page=nggallery-manage-gallery"><?php echo $galleries; ?></a></td> - <td class="t"><a href="admin.php?page=nggallery-manage-gallery"><?php echo _n( 'Gallery', 'Galleries', $galleries, 'nggallery' ); ?></a></td> - <td class="b"></td> - <td class="last"></td> - </tr> - <tr> - <td class="first b"><a href="admin.php?page=nggallery-manage-album"><?php echo $albums; ?></a></td> - <td class="t"><a href="admin.php?page=nggallery-manage-album"><?php echo _n( 'Album', 'Albums', $albums, 'nggallery' ); ?></a></td> - <td class="b"></td> - <td class="last"></td> - </tr> - </tbody> - </table> - </div> - <div class="versions" style="padding-top:14px"> - <br class="clear" /> - </div> - <?php - if (is_multisite()) - $this->dashboard_quota(); - } - - public function about_metabox() - { - ?> - <div id="poststuff"> - <p><?php _e("NextGEN Gallery is one of the most popular WordPress plugins of all time with over 14 million downloads.", 'nggallery'); _e("It is developed and supported by Imagely. We'd like to offer a special thanks to Alex Rabe, who first developed the plugin and maintained it through 2011.", 'nggallery'); ?></p> - <p><?php _e("<strong>NEED HELP?</strong> If you need help or assistance please visit the <a href='http://wordpress.org/support/plugin/nextgen-gallery'>NextGEN Gallery forums on WordPress.org</a>. Please note that we actively monitor and participate in the forums, but given that NextGEN Gallery is a free product, we don't guarantee replies to support queries.", 'nggallery'); ?></p> - <p><?php _e("<strong>EXTENDING NEXTGEN?</strong> There are many third party plugins that add displays and functionality for NextGEN Gallery. See our <a href='http://www.nextgen-gallery.com/nextgen-gallery-extension-plugins/'>Complete List of NextGEN Extension Plugins</a>.", 'nggallery'); ?></p> - </div> - <?php - } - - /** - * Show the server settings in a dashboard widget - * - * @return void - */ - public function server_metabox() - { - ?> - <div id="dashboard_server_settings" class="dashboard-widget-holder wp_dashboard_empty"> - <div class="ngg-dashboard-widget"> - <div class="dashboard-widget-content"> - <ul class="settings"> - <?php $this->server_info(); ?> - </ul> - <p><strong><?php _e('Graphic Library', 'nggallery'); ?></strong></p> - <ul class="settings"> - <?php $this->gd_info(); ?> - </ul> - </div> - </div> - </div> - <?php - } /** - * Show up some server infor's + * Shows important server configuration details. * @author GamerZ (http://www.lesterchan.net) * * @return void */ + public function server_info() { global $wpdb, $ngg; + // Get MYSQL Version $sqlversion = $wpdb->get_var("SELECT VERSION() AS version"); + // GET SQL Mode $mysqlinfo = $wpdb->get_results("SHOW VARIABLES LIKE 'sql_mode'"); if (is_array($mysqlinfo)) $sql_mode = $mysqlinfo[0]->Value; if (empty($sql_mode)) $sql_mode = __('Not set', 'nggallery'); + // Get PHP Safe Mode if(ini_get('safe_mode')) $safe_mode = __('On', 'nggallery'); else $safe_mode = __('Off', 'nggallery'); + // Get PHP allow_url_fopen if(ini_get('allow_url_fopen')) $allow_url_fopen = __('On', 'nggallery'); else $allow_url_fopen = __('Off', 'nggallery'); + // Get PHP Max Upload Size - if (function_exists('wp_max_upload_size')) $upload_max = strval(round( (int) wp_max_upload_size() / (1024 * 1024) )) . 'M'; + if (function_exists('wp_max_upload_size')) $upload_max = strval(round((int) wp_max_upload_size() / (1024 * 1024))) . 'M'; else if(ini_get('upload_max_filesize')) $upload_max = ini_get('upload_max_filesize'); else $upload_max = __('N/A', 'nggallery'); + // Get PHP Output buffer Size if(ini_get('pcre.backtrack_limit')) $backtrack_limit = ini_get('pcre.backtrack_limit'); else $backtrack_limit = __('N/A', 'nggallery'); + // Get PHP Max Post Size if(ini_get('post_max_size')) $post_max = ini_get('post_max_size'); else $post_max = __('N/A', 'nggallery'); + // Get PHP Max execution time if(ini_get('max_execution_time')) $max_execute = ini_get('max_execution_time'); else $max_execute = __('N/A', 'nggallery'); + // Get PHP Memory Limit if(ini_get('memory_limit')) $memory_limit = $ngg->memory_limit; else $memory_limit = __('N/A', 'nggallery'); + // Get actual memory_get_usage if (function_exists('memory_get_usage')) $memory_usage = round(memory_get_usage() / 1024 / 1024, 2) . __(' MByte', 'nggallery'); else $memory_usage = __('N/A', 'nggallery'); + // required for EXIF read - if (is_callable('exif_read_data')) $exif = __('Yes', 'nggallery'). " ( V" . substr(phpversion('exif'),0,4) . ")" ; + if (is_callable('exif_read_data')) $exif = __('Yes', 'nggallery'). " (V" . substr(phpversion('exif'),0,4) . ")" ; else $exif = __('No', 'nggallery'); + // required for meta data if (is_callable('iptcparse')) $iptc = __('Yes', 'nggallery'); else $iptc = __('No', 'nggallery'); + // required for meta data if (is_callable('xml_parser_create')) $xml = __('Yes', 'nggallery'); else $xml = __('No', 'nggallery'); @@ -293,11 +100,11 @@ class C_NGG_Admin_Overview { $info = gd_info(); $keys = array_keys($info); - for($i=0; $i<count($keys); $i++) { - if(is_bool($info[$keys[$i]])) - echo "<li> " . $keys[$i] ." : <span>" . ($info[$keys[$i]] ? __('Yes', 'nggallery') : __('No', 'nggallery')) . "</span></li>\n"; + for ($i = 0; $i < count($keys); $i++) { + if (is_bool($info[$keys[$i]])) + echo "<li> " . $keys[$i] . " : <span>" . ($info[$keys[$i]] ? __('Yes', 'nggallery') : __('No', 'nggallery')) . "</span></li>\n"; else - echo "<li> " . $keys[$i] ." : <span>" . $info[$keys[$i]] . "</span></li>\n"; + echo "<li> " . $keys[$i] . " : <span>" . $info[$keys[$i]] . "</span></li>\n"; } } else { @@ -308,10 +115,10 @@ class C_NGG_Admin_Overview // Display File upload quota on dashboard function dashboard_quota() { - if ( get_site_option( 'upload_space_check_disabled' ) ) + if (get_site_option('upload_space_check_disabled')) return; - if ( !wpmu_enable_function('wpmuQuotaCheck') ) + if (!wpmu_enable_function('wpmuQuotaCheck')) return; $settings = C_NextGen_Settings::get_instance(); @@ -319,37 +126,278 @@ class C_NGG_Admin_Overview $dir = $fs->join_paths($fs->get_document_root('content'), $settings->gallerypath); $quota = get_space_allowed(); - $used = get_dirsize( $dir ) / 1024 / 1024; + $used = get_dirsize($dir) / 1024 / 1024; - if ( $used > $quota ) + if ($used > $quota) $percentused = '100'; else - $percentused = ( $used / $quota ) * 100; - $used_color = ( $percentused < 70 ) ? ( ( $percentused >= 40 ) ? 'waiting' : 'approved' ) : 'spam'; - $used = round( $used, 2 ); - $percentused = number_format( $percentused ); + $percentused = ($used / $quota) * 100; + + $used_color = ($percentused < 70) ? (($percentused >= 40) ? 'yellow' : 'green') : 'red'; + $used = round($used, 2); + $percentused = number_format($percentused); ?> - <p class="sub musub" style="position:static" ><?php _e( 'Storage Space' ); ?></p> - <div class="table table_content musubtable"> - <table> - <tr class="first"> - <td class="first b b-posts"><?php printf( __( '<a href="%1$s" title="Manage Uploads" class="musublink">%2$sMB</a>' ), nextgen_esc_url( admin_url( 'admin.php?page=nggallery-manage-gallery' ) ), $quota ); ?></td> - <td class="t posts"><?php _e( 'Space Allowed' ); ?></td> - </tr> - </table> - </div> - <div class="table table_discussion musubtable"> - <table> - <tr class="first"> - <td class="b b-comments"><?php printf( __( '<a href="%1$s" title="Manage Uploads" class="musublink">%2$sMB (%3$s%%)</a>' ), nextgen_esc_url( admin_url( 'admin.php?page=nggallery-manage-gallery' ) ), $used, $percentused ); ?></td> - <td class="last t comments <?php echo $used_color;?>"><?php _e( 'Space Used' );?></td> - </tr> - </table> - </div> - <br class="clear" /> + <p><?php print __('Storage Space'); ?></p> + <ul> + <li><?php printf(__('%1$sMB Allowed', 'nggallery'), $quota); ?></li> + <li class="<?php print $used_color; ?>"><?php printf(__('%1$sMB (%2$s%%) Used', 'nggallery'), $used, $percentused); ?></li> + </ul> <?php } + } -$NGG_Admin_Overview = new C_NGG_Admin_Overview(); \ No newline at end of file +/** + * nggallery_admin_overview() + * + * Add the admin overview the dashboard style + * @return mixed content + */ +function nggallery_admin_overview() +{ + $NGG_Admin_Overview = new C_NGG_Admin_Overview(); + + global $wpdb; + $images = intval($wpdb->get_var("SELECT COUNT(*) FROM $wpdb->nggpictures")); + $galleries = intval($wpdb->get_var("SELECT COUNT(*) FROM $wpdb->nggallery")); + $albums = intval($wpdb->get_var("SELECT COUNT(*) FROM $wpdb->nggalbum")); + + ?> + + <div class="wrap about-wrap"> + <h1><?php _e( 'Welcome to NextGEN Gallery', 'nggallery' ); ?></h1> + + <div class="about-text"><?php printf( __( "Congrats! You're now running the most popular WordPress gallery plugin of all time. So far you've added %s images, %s galleries, and %s albums." ), $images, $galleries, $albums); ?></div> + <div class="wp-badge"></div> + + <h2 class="nav-tab-wrapper wp-clearfix" id="ngg-tabs-wrapper"> + <a href="#top#welcome" class="nav-tab nav-tab-active" id="welcome-link"><?php _e( 'Welcome', 'nggallery' ); ?></a> + <a href="#top#videos" class="nav-tab" id="videos-link"><?php _e( 'More Videos' ); ?></a> + <a href="#top#pro" class="nav-tab" id="pro-link"><?php _e( 'NextGEN Pro' ); ?></a> + <a href="#top#genesis" class="nav-tab" id="genesis-link"><?php _e( 'Genesis Themes' ); ?></a> + <?php if (!is_multisite() || is_super_admin()) { ?> + <a href="#top#details" class="nav-tab" id="details-link"><?php _e( 'Site Details' ); ?></a> + <?php } ?> + <a href="#top#freedoms" class="nav-tab" id="freedoms-link"><?php _e( 'Freedoms' ); ?></a> + </h2> + + <div id="welcome" class="ngg-tab"> + + <div class="headline-feature feature-video"> + <iframe width="1050" height="590" src="https://www.youtube.com/embed/qwNr5ZNGavo?list=PL9cmsdHslD0vIcJjBggJ-XMjtwvqrRgoM" frameborder="0" allowfullscreen></iframe> + </div> + + <hr> + + <div class="feature-section three-col"> + <h2><?php _e( 'Meet the Imagely Product Ambassadors', 'nggallery' ); ?></h2> + <p class="about-text centered"><?php _e( "NextGEN Gallery and other Imagely products are used by some of the best photographers in the world. Meet some of the Imagely Ambassadors who are putting Imagely and NextGEN Gallery to work professionally.", 'nggallery' ); ?> + </p> + <div class="col"> + <a href="https://www.imagely.com/team-member/the-youngrens/" target="_blank"><img src="https://f001.backblaze.com/file/nextgen-gallery/theyoungrens-ngg.jpg" alt="The Youngrens"/></a> + <h3><?php _e( 'The Youngrens' ); ?></h3> + <p><?php _e( 'Jeff and Erin are a luxury husband and wife photography team who deeply love each other and their photography clients. They shoot weddings and engagements all over the U.S. and beyond. With three photography businesses that serve different clientele, they have unique insights into business strategies and are passionate about improving the day to day lives of other photographers.', 'nggallery' ); ?></p> + </div> + <div class="col"> + <a href="https://www.imagely.com/team-member/tamara-lackey/" target="_blank"><img src="https://f001.backblaze.com/file/nextgen-gallery/TamaraLackey-ngg.jpg" alt="Tamara Lackey" /></a> + <h3><?php _e( 'Tamara Lackey' ); ?></h3> + <p><?php _e( 'Tamara Lackey is a renowned professional photographer, speaker, and author. Her authentic lifestyle photography, from children’s portraits to celebrity portraits, is praised within her industry and published internationally. She is also founder of the charitable project, Beautiful Together.', 'nggallery' ); ?></p> + </div> + <div class="col"> + <a href="https://www.imagely.com/team-member/colby-brown/" target="_blank"><img src="https://f001.backblaze.com/file/nextgen-gallery/colby-brown-ngg.jpg" alt="Colby Brown" /></a> + <h3><?php _e( 'Colby Brown' ); ?></h3> + <p><?php _e( 'Colby is a photographer, photo educator, and author specializing in landscape, travel and humanitarian photography. With an audience reaching millions, Colby partners on social influencer marketing campaigns with some of the biggest companies and destinations in the world, including Sony, Samsung, Toshiba, Iceland Naturally, Jordan Tourism Board, Australia.com, Visit California and more.', 'nggallery' ); ?></p> + </div> + </div> + + <div class="feature-section three-col"> + <div class="col"> + <a href="https://www.imagely.com/team-member/jared-platt/" target="_blank"><img src="https://f001.backblaze.com/file/nextgen-gallery/jared-platt-ngg.jpg" alt="Jared Platt" /></a> + <h3><?php _e( 'Jared Platt' ); ?></h3> + <p><?php _e( 'Jared is a professional wedding and lifestyle photographer. He also travels the world giving lectures and workshops on photography, lighting, and post-production efficiency and workflow. His interactive style, and attention to detail and craft make him an entertaining and demanding photography instructor.', 'nggallery' ); ?></p> + </div> + <div class="col"> + <a href="https://www.imagely.com/team-member/brian-matiash/" target="_blank"><img src="https://f001.backblaze.com/file/nextgen-gallery/brian-matiash-ngg.jpeg" alt="" /></a> + <h3><?php _e( 'Brian Matiash' ); ?></h3> + <p><?php _e( 'Brian is a professional photographer, author, and educator. He fuses landscape & travel photography with experiential storytelling and practical instructing to help others grow creatively. He is also a Sony Artisan of Imagery, a Zeiss Lens Ambassador, a Formatt-Hitech Featured Photographer, and a member of G-Technology’s G-Team.', 'nggallery' ); ?></p> + </div> + <div class="col"> + <a href="https://www.imagely.com/team-member/christine-tremoulet/" target="_blank"><img src="https://f001.backblaze.com/file/nextgen-gallery/Christine-Tremoulet-ngg.jpg" alt="" /></a> + <h3><?php _e( 'Christine Tremoulet' ); ?></h3> + <p><?php _e( 'Christine famously coined the term WordPress. She is an author, speaker, business coach, and story strategist who specializes in helping creatives celebrate their story online through blogging and social media. When not offering actionable know-how to businesses, she can be found taking long road trips across North America in her Mini Cooper.', 'nggallery' ); ?></p> + </div> + </div> + + <div class="feature-section three-col"> + <div class="col"> + <a href="https://www.imagely.com/team-member/david-beckstead/" target="_blank"><img src="https://f001.backblaze.com/file/nextgen-gallery/david-beckstead-ngg.jpg" alt="David Beckstead" /></a> + <h3><?php _e( 'David Beckstead' ); ?></h3> + <p><?php _e( 'Named one of the Top 10 Wedding Photographers in the World by American Photo magazine, David is a celebrated photographer and educator. He is also a mountain man with a enviable lifestyle: from his base in rural Washington, he travels all over the world teaching workshops, while sharing lessons with 16,000 photographers in the Abstract Canvas Facebook group.', 'nggallery' ); ?></p> + </div> + </div> + + + </div> + + <div id="videos" class="ngg-tab"> + + <p class="about-text centered"><?php printf( __( 'We have a growing list of video tutorials to get you started. Watch some below or head over to <a href="%s" target="_blank">NextGEN Gallery University on YouTube</a> to see all available vidoes.', 'nggallery' ), esc_url( 'https://www.youtube.com/playlist?list=PL9cmsdHslD0vIcJjBggJ-XMjtwvqrRgoM' ) ); ?> + </p> + + <div class="headline-feature feature-video"> + <iframe width="1280" height="720" src="https://www.youtube.com/embed/c664fvAZ1nI?list=PL9cmsdHslD0vIcJjBggJ-XMjtwvqrRgoM" frameborder="0" allowfullscreen></iframe> + </div> + + <hr> + + <div class="feature-section two-col"> + <h2><?php _e( 'More Video Tutorials' ); ?></h2> + <div class="col"> + <div class="headline-feature feature-video"> + <iframe width="1280" height="720" src="https://www.youtube.com/embed/h_HrKpkI90w?list=PL9cmsdHslD0vIcJjBggJ-XMjtwvqrRgoM" frameborder="0" allowfullscreen></iframe> + </div> + </div> + <div class="col"> + <div class="headline-feature feature-video"> + <iframe width="1280" height="720" src="https://www.youtube.com/embed/58u9AjMJqJM?list=PL9cmsdHslD0vIcJjBggJ-XMjtwvqrRgoM" frameborder="0" allowfullscreen></iframe> + </div> + </div> + </div> + + <div class="feature-section two-col"> + <div class="col"> + <div class="headline-feature feature-video"> + <iframe width="1280" height="720" src="https://www.youtube.com/embed/OfxWM59fb_Y?list=PL9cmsdHslD0vIcJjBggJ-XMjtwvqrRgoM" frameborder="0" allowfullscreen></iframe> + </div> + </div> + <div class="col"> + <div class="headline-feature feature-video"> + <iframe width="1280" height="720" src="https://www.youtube.com/embed/BiFjDYIaZZw?list=PL9cmsdHslD0vIcJjBggJ-XMjtwvqrRgoM" frameborder="0" allowfullscreen></iframe> + </div> + </div> + </div> + + <p class="about-text centered"><?php printf( __( 'Want more? Head over to <a href="%s" target="_blank">NextGEN Gallery University on YouTube</a>.', 'nggallery' ), esc_url( 'https://www.youtube.com/playlist?list=PL9cmsdHslD0vIcJjBggJ-XMjtwvqrRgoM' ) ); ?> + </p> + + </div> + + <div id="pro" class="ngg-tab"> + + <h2><?php _e( 'Upgrade to NextGEN Pro!' ); ?></h2> + <p class="about-text centered"><?php _e( 'Gorgeous new gallery displays, image protection, full screen lightbox, commenting and social sharing for individual images, proofing, ecommerce, digital downloads, and more. Take your galleries to the next level with the Plus and Pro extensions for NextGEN Gallery. ', 'nggallery' ); ?></p> + <h3 class="about-text centered"><?php _e( 'CLICK TO LEARN MORE:', 'nggallery' ); ?></h3> + <div class="feature-section two-col"> + <div class="col"> + <a href="https://www.imagely.com/wordpress-gallery-plugin/nextgen-plus/" target="_blank"><img src="https://f001.backblaze.com/file/nextgen-gallery/nextgen-plus-ngg.jpg"></a> + </div> + <div class="col"> + <a href="https://www.imagely.com/wordpress-gallery-plugin/nextgen-pro/" target="_blank"><img src="https://f001.backblaze.com/file/nextgen-gallery/nextgen-pro-ngg.jpg"></a> + </div> + </div> + + </div> + + <div id="genesis" class="ngg-tab"> + + <h2><?php _e( 'Genesis Child Themes for Photographers' ); ?></h2> + <p class="about-text centered"><?php _e( 'Meet the new series of Genesis child themes by Imagely: gorgeous, responsive image-centric themes for photographers or anyone with visually rich websites.', 'nggallery' ); ?></p> + <h3 class="about-text centered"><?php _e( 'CLICK TO LEARN MORE:', 'nggallery' ); ?></h3> + <div class="feature-section two-col"> + <div class="col"> + <a href="https://www.imagely.com/wordpress-photography-themes/ansel/" target="_blank"><img src="https://f001.backblaze.com/file/nextgen-gallery/ansel-ngg.jpg" class="ngg-theme-image"></a> + </div> + <div class="col"> + <a href="https://www.imagely.com/wordpress-photography-themes/fearless/" target="_blank"><img src="https://f001.backblaze.com/file/nextgen-gallery/fearless-ngg.jpg" class="ngg-theme-image"></a> + </div> + </div> + <div class="feature-section two-col"> + <div class="col"> + <a href="https://www.imagely.com/wordpress-photography-themes/blush/" target="_blank"><img src="https://f001.backblaze.com/file/nextgen-gallery/blush-ngg.jpg" class="ngg-theme-image"></a> + </div> + <div class="col"> + <a href="https://www.imagely.com/wordpress-photography-themes/free-spirit/" target="_blank"><img src="https://f001.backblaze.com/file/nextgen-gallery/free-spirit-ngg.jpg" class="ngg-theme-image"></a> + </div> + </div> + <div class="feature-section two-col"> + <div class="col"> + <a href="https://www.imagely.com/wordpress-photography-themes/reportage/" target="_blank"><img src="https://f001.backblaze.com/file/nextgen-gallery/reportage-ngg.jpg" class="ngg-theme-image"></a> + </div> + <div class="col"> + <a href="https://www.imagely.com/wordpress-photography-themes/lightly/" target="_blank"><img src="https://f001.backblaze.com/file/nextgen-gallery/lightly-ngg.jpg" class="ngg-theme-image"></a> + </div> + </div> + <div class="feature-section two-col"> + <div class="col"> + <a href="https://www.imagely.com/wordpress-photography-themes/rebel/" target="_blank"><img src="https://f001.backblaze.com/file/nextgen-gallery/rebel-ngg.jpg" class="ngg-theme-image"></a> + </div> + <div class="col"> + <a href="https://www.imagely.com/wordpress-photography-themes/summerly/" target="_blank"><img src="https://f001.backblaze.com/file/nextgen-gallery/summerly-ngg.jpg" class="ngg-theme-image"></a> + </div> + </div> + <div class="feature-section two-col"> + <div class="col"> + <a href="https://www.imagely.com/wordpress-photography-themes/expedition/" target="_blank"><img src="https://f001.backblaze.com/file/nextgen-gallery/expedition-ngg.jpg" class="ngg-theme-image"></a> + </div> + <div class="col"> + <a href="https://www.imagely.com/wordpress-photography-themes/punk-bride/" target="_blank"><img src="https://f001.backblaze.com/file/nextgen-gallery/punk-bride-ngg.jpg" class="ngg-theme-image"></a> + </div> + </div> + <div class="feature-section two-col"> + <div class="col"> + <a href="https://www.imagely.com/wordpress-photography-themes/journal/" target="_blank"><img src="https://f001.backblaze.com/file/nextgen-gallery/journal-ngg.jpg" class="ngg-theme-image"></a> + </div> + <div class="col"> + <a href="https://www.imagely.com/wordpress-photography-themes/simplicity/" target="_blank"><img src="https://f001.backblaze.com/file/nextgen-gallery/simplicity-ngg.jpg" class="ngg-theme-image"></a> + </div> + </div> + + </div> + + <?php if (!is_multisite() || is_super_admin()) { ?> + <div id="details" class="ngg-tab"> + <h2><?php _e( 'Site Details' ); ?></h2> + <p class="about-text centered"><?php _e( 'When contacting support, consider copying and pasting this information in your support request. It helps us troubleshoot more quickly.', 'nggallery' ); ?> + </p> + <div class="two-col"> + <div class="col"> + <?php if (is_multisite()) $NGG_Admin_Overview->dashboard_quota(); ?> + </div> + <div class="col"> + <p><strong><?php print __('Server Settings', 'nggallery'); ?></strong></p> + <ul> + <?php $NGG_Admin_Overview->server_info(); ?> + </ul> + </div> + </div> + <div class="two-col"> + <div class="col"> + <p><strong><?php print __('Graphic Library', 'nggallery'); ?></strong></p> + <ul> + <?php $NGG_Admin_Overview->gd_info(); ?> + </ul> + </div> + </div> + </div> + <?php } ?> + + <div id="freedoms" class="ngg-tab"> + + <p class="about-description"><?php printf( __( 'NextGEN Gallery is Free and open source software, built by a small but dedicated team as well as community code contributions. It comes with awesome rights courtesy of its <a href="%s" target="_blank">license</a>, the GPL.' ), 'https://wordpress.org/about/license/' ); ?></p> + + <ol start="0"> + <li><p><?php _e( 'You have the freedom to run the program, for any purpose.' ); ?></p></li> + <li><p><?php _e( 'You have access to the source code, the freedom to study how the program works, and the freedom to change it to make it do what you wish.' ); ?></p></li> + <li><p><?php _e( 'You have the freedom to redistribute copies of the original program so you can help your neighbor.' ); ?></p></li> + <li><p><?php _e( 'You have the freedom to distribute copies of your modified versions to others. By doing this you can give the whole community a chance to benefit from your changes.' ); ?></p></li> + </ol> + + <p><?php _e( 'NextGEN Gallery grows because people like you tell your friends and website visitors about it. We thank you for doing so.' ); ?></p> + + </div> + + </div> + + <?php +} \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/publish.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/publish.php index cd8c9047640c0a874778e8e1503f727957066988..bd6b7ff79cfb29c36752de0fffbd0b86a6173d58 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/publish.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/admin/publish.php @@ -1,64 +1,64 @@ -<?php - -require_once( dirname( dirname(__FILE__) ) . '/ngg-config.php'); -require_once( NGGALLERY_ABSPATH . '/lib/image.php' ); - -if ( !is_user_logged_in() ) - die(__('Cheatin’ uh?')); - -if ( !current_user_can('NextGEN Manage gallery') ) - die(__('Cheatin’ uh?')); - -if ( !current_user_can( 'publish_posts' ) ) - die(__('Cheatin’ uh?')); - -global $wpdb; - -$id = (int) $_GET['id']; - -// let's get the image data -$picture = nggdb::find_image($id); - -// use defaults the first time -$width = empty ($ngg->options['publish_width']) ? $ngg->options['thumbwidth'] : $ngg->options['publish_width']; -$height = empty ($ngg->options['publish_height']) ? $ngg->options['thumbheight'] : $ngg->options['publish_height']; -$align = empty ($ngg->options['publish_align']) ? 'none' : $ngg->options['publish_align']; - -?> - -<form id="form-publish-post" method="POST" accept-charset="utf-8"> -<?php wp_nonce_field('publish-post') ?> -<input type="hidden" name="page" value="publish-post" /> -<input type="hidden" name="pid" value="<?php echo $picture->pid; ?>" /> -<table width="100%" border="0" cellspacing="3" cellpadding="3" > - <tr valign="top"> - <th align="left"><?php _e('Post title','nggallery') ?></th> - <td><input type="text" size="70" name="post_title" value="<?php echo esc_attr( $picture->alttext); ?>" /> - <br /><small><?php _e('Enter the post title ','nggallery') ?></small></td> - </tr> - <tr valign="top"> - <th align="left"><?php _e('Width x height (in pixel)','nggallery') ?></th> - <td><input type="text" size="5" maxlength="5" name="width" value="<?php echo $width; ?>" /> x <input type="text" size="5" maxlength="5" name="height" value="<?php echo $height; ?>" /> - <br /><small><?php _e('Size of the image','nggallery') ?></small></td> - </tr> - <tr valign="top"> - <th align="left"><?php _e('Alignment','nggallery') ?></th> - <td><input type="radio" value="none" <?php checked('none', $align); ?> id="image-align-none" name="align"/> - <label class="align" for="image-align-none"><?php _e('None','nggallery'); ?></label> - <input type="radio" value="left" <?php checked('left', $align); ?> id="image-align-left" name="align"/> - <label class="align" for="image-align-left"><?php _e('Left','nggallery'); ?></label> - <input type="radio" value="center" <?php checked('center', $align); ?> id="image-align-center" name="align"/> - <label class="align" for="image-align-center"><?php _e('Center','nggallery'); ?></label> - <input type="radio" value="right" <?php checked('right', $align); ?> id="image-align-right" name="align"/> - <label class="align" for="image-align-right"><?php _e('Right','nggallery'); ?></label> - </td> - </tr> - <tr align="right"> - <td colspan="2" class="submit"> - <input class="button-primary" type="submit" name="publish" value="<?php _e('Publish', 'nggallery');?>" /> - - <input class="button-secondary" type="submit" name="draft" value=" <?php _e('Draft', 'nggallery'); ?> " /> - </td> - </tr> -</table> +<?php + +require_once( dirname( dirname(__FILE__) ) . '/ngg-config.php'); +require_once( NGGALLERY_ABSPATH . '/lib/image.php' ); + +if ( !is_user_logged_in() ) + die(__('Cheatin’ uh?')); + +if ( !current_user_can('NextGEN Manage gallery') ) + die(__('Cheatin’ uh?')); + +if ( !current_user_can( 'publish_posts' ) ) + die(__('Cheatin’ uh?')); + +global $wpdb; + +$id = (int) $_GET['id']; + +// let's get the image data +$picture = nggdb::find_image($id); + +// use defaults the first time +$width = empty ($ngg->options['publish_width']) ? $ngg->options['thumbwidth'] : $ngg->options['publish_width']; +$height = empty ($ngg->options['publish_height']) ? $ngg->options['thumbheight'] : $ngg->options['publish_height']; +$align = empty ($ngg->options['publish_align']) ? 'none' : $ngg->options['publish_align']; + +?> + +<form id="form-publish-post" method="POST" accept-charset="utf-8"> +<?php wp_nonce_field('publish-post') ?> +<input type="hidden" name="page" value="publish-post" /> +<input type="hidden" name="pid" value="<?php echo $picture->pid; ?>" /> +<table width="100%" border="0" cellspacing="3" cellpadding="3" > + <tr valign="top"> + <th align="left"><?php _e('Post title','nggallery') ?></th> + <td><input type="text" size="70" name="post_title" value="<?php echo esc_attr( $picture->alttext); ?>" /> + <br /><small><?php _e('Enter the post title ','nggallery') ?></small></td> + </tr> + <tr valign="top"> + <th align="left"><?php _e('Width x height (in pixel)','nggallery') ?></th> + <td><input type="text" size="5" maxlength="5" name="width" value="<?php echo $width; ?>" /> x <input type="text" size="5" maxlength="5" name="height" value="<?php echo $height; ?>" /> + <br /><small><?php _e('Size of the image','nggallery') ?></small></td> + </tr> + <tr valign="top"> + <th align="left"><?php _e('Alignment','nggallery') ?></th> + <td><input type="radio" value="none" <?php checked('none', $align); ?> id="image-align-none" name="align"/> + <label class="align" for="image-align-none"><?php _e('None','nggallery'); ?></label> + <input type="radio" value="left" <?php checked('left', $align); ?> id="image-align-left" name="align"/> + <label class="align" for="image-align-left"><?php _e('Left','nggallery'); ?></label> + <input type="radio" value="center" <?php checked('center', $align); ?> id="image-align-center" name="align"/> + <label class="align" for="image-align-center"><?php _e('Center','nggallery'); ?></label> + <input type="radio" value="right" <?php checked('right', $align); ?> id="image-align-right" name="align"/> + <label class="align" for="image-align-right"><?php _e('Right','nggallery'); ?></label> + </td> + </tr> + <tr align="right"> + <td colspan="2" class="submit"> + <input class="button-primary" type="submit" name="publish" value="<?php _e('Publish', 'nggallery');?>" /> + + <input class="button-secondary" type="submit" name="draft" value=" <?php _e('Draft', 'nggallery'); ?> " /> + </td> + </tr> +</table> </form> \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/css/nggallery.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/css/nggallery.css index 84fae55fd03b3073c7d28fddcfb8d95760ed1b59..1402a8c8a0beac36339620dcf3233d49601d61c3 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/css/nggallery.css +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/css/nggallery.css @@ -1,8 +1,8 @@ -/* -CSS Name: Default Styles -Description: NextGEN Default Gallery Stylesheet -Author: Imagely -Version: 2.13 - -This stylesheet is provided to allow users the ability of overriding the default styles for all display types +/* +CSS Name: Default Styles +Description: NextGEN Default Gallery Stylesheet +Author: Imagely +Version: 2.13 + +This stylesheet is provided to allow users the ability of overriding the default styles for all display types */ \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/fonts/YanoneKaffeesatz-Bold.ttf b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/fonts/YanoneKaffeesatz-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..8542dab64e21b66e0e511e90ed74135b572f80ac Binary files /dev/null and b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/fonts/YanoneKaffeesatz-Bold.ttf differ diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/lib/core.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/lib/core.php index 2420daa25a43679f1fc644b35c3b0c9406122650..10d5bed1ecda744092bfe1af703705ede29b46a1 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/lib/core.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/lib/core.php @@ -18,8 +18,8 @@ class nggGallery { /** * Show a system messages */ - static function show_message($message) { - echo '<div class="wrap"><h2></h2><div class="updated fade" id="message"><p>' . $message . '</p></div></div>' . "\n"; + static function show_message($message, $message_id=NULL) { + echo '<div class="wrap"><h2></h2><div class="updated fade '.$message_id.'" id="message"><p>' . $message . '</p></div></div>' . "\n"; } /** diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/lib/meta.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/lib/meta.php index 3bcf4e101ab1572ab0ddb7593c76c2f72b49db6f..b02a741661f0320beabe5cb84d12707f797042c7 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/lib/meta.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/lib/meta.php @@ -121,7 +121,7 @@ class nggMeta{ $meta= array(); - $exif = isset($this->exif_array['EXIF']) ? $this->exif_array['EXIF'] : array(); + $exif = isset($this->exif_data['EXIF']) ? $this->exif_data['EXIF'] : array(); if (count($exif)) { if (!empty($exif['FNumber'])) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/lib/multisite.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/lib/multisite.php index e8f36a9893db4eaf6a4b4763470e9d49a31fcba5..96dd2bc17b8f2b7bf591727cebb43ee4e6acb9cb 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/lib/multisite.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/lib/multisite.php @@ -1,57 +1,57 @@ -<?php -/** -* Main PHP Class for Multisite setup -* -* @author Alex Rabe -* -* -*/ -class nggWPMU{ - - /** - * Check the Quota under WPMU. Only needed for this case - * - * @class nggWPMU - * @return bool $result - */ - function check_quota() { - if ( get_site_option( 'upload_space_check_disabled' ) ) - return false; - - if ( (is_multisite()) && nggWPMU::wpmu_enable_function('wpmuQuotaCheck')) - if( $error = upload_is_user_over_quota( false ) ) { - nggGallery::show_error( __( 'Sorry, you have used your space allocation. Please delete some files to upload more files.','nggallery' ) ); - return true; - } - return false; - } - - /** - * Check for site admin - * - * @return - */ - function wpmu_site_admin() { - - if ( function_exists('is_super_admin') ) - if ( is_super_admin() ) - return true; - - return false; - } - - /** - * Check for site wide options - * - * @param string $value - * @return value - */ - function wpmu_enable_function($value) { - if (is_multisite()) { - $ngg_options = get_site_option('ngg_options'); - return $ngg_options[$value]; - } - // if this is not WPMU, enable it ! - return true; - } -} +<?php +/** +* Main PHP Class for Multisite setup +* +* @author Alex Rabe +* +* +*/ +class nggWPMU{ + + /** + * Check the Quota under WPMU. Only needed for this case + * + * @class nggWPMU + * @return bool $result + */ + function check_quota() { + if ( get_site_option( 'upload_space_check_disabled' ) ) + return false; + + if ( (is_multisite()) && nggWPMU::wpmu_enable_function('wpmuQuotaCheck')) + if( $error = upload_is_user_over_quota( false ) ) { + nggGallery::show_error( __( 'Sorry, you have used your space allocation. Please delete some files to upload more files.','nggallery' ) ); + return true; + } + return false; + } + + /** + * Check for site admin + * + * @return + */ + function wpmu_site_admin() { + + if ( function_exists('is_super_admin') ) + if ( is_super_admin() ) + return true; + + return false; + } + + /** + * Check for site wide options + * + * @param string $value + * @return value + */ + function wpmu_enable_function($value) { + if (is_multisite()) { + $ngg_options = get_site_option('ngg_options'); + return $ngg_options[$value]; + } + // if this is not WPMU, enable it ! + return true; + } +} diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/lib/ngg-db.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/lib/ngg-db.php index ab6d9909bee1ded1c45dd943319cd2d62a595742..a1b3b23dd14bca99d044915ce22372f8fa6abd56 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/lib/ngg-db.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/lib/ngg-db.php @@ -750,7 +750,7 @@ class nggdb $searchand = ' AND '; } - $term = $wpdb->escape($request); + $term = esc_sql($request); if (count($search_terms) > 1 && $search_terms[0] != $request ) $search .= " OR (tt.description LIKE '{$n}{$term}{$n}') OR (tt.alttext LIKE '{$n}{$term}{$n}') OR (tt.filename LIKE '{$n}{$term}{$n}')"; diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/lib/tags.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/lib/tags.php index 31b1f3d20740128bd6a6d5ccedab0c2f7136f2b5..501badb269634fd394960963edfd1f9d6e19822f 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/lib/tags.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/lib/tags.php @@ -315,13 +315,13 @@ class nggTags { $taglist = array_map('trim', $taglist); $new_slugarray = array_map('sanitize_title', $taglist); - $sluglist = "'" . implode("', '", $new_slugarray) . "'"; + $sluglist = implode("', '", $new_slugarray); //Treat % as a litteral in the database, for unicode support - $sluglist=str_replace("%","%%",$sluglist); + $sluglist = str_replace("%","%%",$sluglist); // first get all $term_ids with this tag - $term_ids = $wpdb->get_col( $wpdb->prepare("SELECT term_id FROM $wpdb->terms WHERE slug IN ($sluglist) ORDER BY term_id ASC ", NULL)); + $term_ids = $wpdb->get_col( $wpdb->prepare("SELECT term_id FROM $wpdb->terms WHERE slug IN (%s) ORDER BY term_id ASC ", $sluglist)); $picids = get_objects_in_term($term_ids, 'ngg_tag'); if ($mode == 'RAND') diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/module.ngglegacy.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/module.ngglegacy.php index b369b7cc09b6e1333b03e9b29102d38d26a8067a..1467ccfe08a86a0212bb360b6f1dcf40ad88a18c 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/module.ngglegacy.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/module.ngglegacy.php @@ -22,7 +22,7 @@ class M_NggLegacy extends C_Base_Module 'photocrati-nextgen-legacy', 'NextGEN Legacy', 'Embeds the original version of NextGEN 1.9.3 by Alex Rabe', - '0.14', + '0.15', 'https://www.imagely.com/wordpress-gallery-plugin/nextgen-gallery/', 'Photocrati Media', 'https://www.imagely.com' diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/nggallery.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/nggallery.php index ce5d97d2550137a026098ce1172f62909cbbca21..36a4bf7f64991a22703a5390816ffe113a6bfa5f 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/nggallery.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/nggallery.php @@ -71,7 +71,7 @@ class nggLoader } else { // Add MRSS to wp_head - if ( $this->options['useMediaRSS'] ) + if ( isset( $this->options['useMediaRSS'] ) && $this->options['useMediaRSS'] ) add_action('wp_head', array('nggMediaRss', 'add_mrss_alternate_link')); } diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/Black_Minimalism.min.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/Black_Minimalism.min.css new file mode 100644 index 0000000000000000000000000000000000000000..b52d8328d79a44082734eddbe6614b3561405d29 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/Black_Minimalism.min.css @@ -0,0 +1 @@ +.ngg-thumbnail{margin:0 !important;margin-right:12px !important}.ngg-gallery-thumbnail-box{width:20%}.ngg-gallery-thumbnail{background:url('shadowAlpha.png') no-repeat bottom right !important;background:url('shadow.gif') no-repeat bottom right;margin:10px 0 0 10px !important}.ngg-gallery-thumbnail img{margin:-6px 6px 6px -6px}.ngg-navigation a.page-numbers,.ngg-navigation a.next,.ngg-navigation a.prev,.ngg-navigation span.page-numbers,.ngg-navigation span.next,.ngg-navigation span.prev{border:1px solid #600;padding:3px 7px}.ngg-related-gallery img{margin:0 2px} \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/default.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/default.css index 8f56f1cbe8a86e6777c8e2066425b73db951687a..c04e9602469d70669d85517c04ed6e4e64505be5 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/default.css +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/default.css @@ -1,32 +1,32 @@ -/* -CSS Name: Default Styles -Description: NextGEN Default Gallery Stylesheet -Author: Imagely -Version: 2.13 - -These are the default NextGEN rules and are loaded on each page. -*/ - -/* ----------- Related images -------------*/ - -.ngg-related-gallery { - background: #F9F9F9; - border: 1px solid #E0E0E0; - overflow: hidden; - margin-bottom: 1em; - margin-top: 1em; - padding: 5px; -} - -.ngg-related-gallery img { - border: 1px solid #DDDDDD; - float: left; - margin: 0pt 3px; - padding: 2px; - height: 50px; - width: 50px; -} - -.ngg-related-gallery img:hover { - border: 1px solid #000000; -} +/* +CSS Name: Default Styles +Description: NextGEN Default Gallery Stylesheet +Author: Imagely +Version: 2.13 + +These are the default NextGEN rules and are loaded on each page. +*/ + +/* ----------- Related images -------------*/ + +.ngg-related-gallery { + background: #F9F9F9; + border: 1px solid #E0E0E0; + overflow: hidden; + margin-bottom: 1em; + margin-top: 1em; + padding: 5px; +} + +.ngg-related-gallery img { + border: 1px solid #DDDDDD; + float: left; + margin: 0pt 3px; + padding: 2px; + height: 50px; + width: 50px; +} + +.ngg-related-gallery img:hover { + border: 1px solid #000000; +} diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/default.min.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/default.min.css new file mode 100644 index 0000000000000000000000000000000000000000..b5700d3788b66ab5e8276b1a3ead70da506c99e1 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/default.min.css @@ -0,0 +1 @@ +.ngg-related-gallery{background:#f9f9f9;border:1px solid #e0e0e0;overflow:hidden;margin-bottom:1em;margin-top:1em;padding:5px}.ngg-related-gallery img{border:1px solid #ddd;float:left;margin:0 3px;padding:2px;height:50px;width:50px}.ngg-related-gallery img:hover{border:1px solid #000} \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/hovereffect.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/hovereffect.css index 5eb14bfc1d05da7f716ea8de463adffc14afd917..2fc54bba040a2db59a5e3e9bdebb70674db948dc 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/hovereffect.css +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/hovereffect.css @@ -1,142 +1,142 @@ -/* -CSS Name: Hovereffect Styles -Description: Hover Stylesheet based on the idea of Hoverbox from http://host.sonspring.com/hoverbox/ -Author: Alex Rabe - Orginal by Nathan Smith -Version: 1.60 - -This applies a styling effect similiar to the Hoverbox style -*/ - -/* ----------- Album Styles Extend -------------*/ - -.ngg-albumtitle { - border-bottom: 1px dashed #AAAAAA; - padding-bottom: 3px; -} - -.ngg-thumbnail { - background: #EEEEEE none repeat scroll 0% 50%; - border-color: #DDDDDD rgb(187, 187, 187) rgb(170, 170, 170) rgb(204, 204, 204); - border-style: solid; - border-width: 1px; - color: inherit; - margin-right: 5px; - padding: 5px; -} - -.ngg-thumbnail img { - filter: alpha(opacity = 100); - -moz-opacity: .99; - opacity: .99; - background: #FFFFFF none repeat scroll 0%; - border-color: #AAAAAA rgb(204, 204, 204) rgb(221, 221, 221) rgb(187, 187, 187); - border-style: solid; - border-width: 1px; - color: inherit; - padding: 2px; - vertical-align: top; -} - -.ngg-thumbnail img:hover { - filter: alpha(opacity = 90); - -moz-opacity: .9; - opacity: .9; - border-color: #000000; -} - -/* ----------- Gallery style -------------*/ - -.ngg-galleryoverview { - overflow: hidden; - margin-top: 10px; - width: 100%; - clear: both; - display: block !important; -} - -.ngg-gallery-thumbnail-box { - background: #EEEEEE none repeat scroll 0% 50%; - border-color: #DDDDDD rgb(187, 187, 187) rgb(170, 170, 170) rgb(204, 204, 204); - border-style: solid; - border-width: 1px; - color: inherit; - display: inline; - margin: 3px; - padding: 5px; - position: relative; -} - -.ngg-gallery-thumbnail img { - filter: alpha(opacity = 100); - -moz-opacity: .99; - opacity: .99; - background: #FFFFFF none repeat scroll 0%; - border-color: #AAAAAA rgb(204, 204, 204) rgb(221, 221, 221) rgb(187, 187, 187); - border-style: solid; - border-width: 1px; - color: inherit; - padding: 2px; - vertical-align: top; -} - -.ngg-gallery-thumbnail img:hover { - filter: alpha(opacity = 90); - -moz-opacity: .9; - opacity: .9; - border-color: #000000; -} - -/* ----------- Gallery navigation -------------*/ - -.ngg-navigation a.page-numbers, -.ngg-navigation a.next, -.ngg-navigation a.prev, -.ngg-navigation span.page-numbers, -.ngg-navigation span.next, -.ngg-navigation span.prev { - padding: 3px 7px; -} - -/* ----------- Image browser style -------------*/ - -.ngg-imagebrowser h3 { - text-align: center; - padding-bottom: 10px; -} - -.ngg-imagebrowser .pic { - background: #EEEEEE none repeat scroll 0% 50%; - border-color: #DDDDDD rgb(187, 187, 187) rgb(170, 170, 170) rgb(204, 204, 204); - border-style: solid; - border-width: 1px; - color: inherit; - display: block; - padding: 10px; -} - -.ngg-imagebrowser img { - margin: -3px; - background: #FFFFFF none repeat scroll 0%; - border-color: #AAAAAA rgb(204, 204, 204) rgb(221, 221, 221) rgb(187, 187, 187); - border-style: solid; - border-width: 1px; - color: inherit; - padding: 2px; - vertical-align: top; -} - -.ngg-imagebrowser-nav { - padding: 10px; - -} - -.ngg-imagebrowser-nav .back:hover, -.ngg-imagebrowser-nav .next:hover { - border: 1px solid #000000; -} - -.ngg-imagebrowser-nav .back a:hover, -.ngg-imagebrowser-nav .next a:hover { - text-decoration: none !important; -} - +/* +CSS Name: Hovereffect Styles +Description: Hover Stylesheet based on the idea of Hoverbox from http://host.sonspring.com/hoverbox/ +Author: Alex Rabe - Orginal by Nathan Smith +Version: 1.60 + +This applies a styling effect similiar to the Hoverbox style +*/ + +/* ----------- Album Styles Extend -------------*/ + +.ngg-albumtitle { + border-bottom: 1px dashed #AAAAAA; + padding-bottom: 3px; +} + +.ngg-thumbnail { + background: #EEEEEE none repeat scroll 0% 50%; + border-color: #DDDDDD rgb(187, 187, 187) rgb(170, 170, 170) rgb(204, 204, 204); + border-style: solid; + border-width: 1px; + color: inherit; + margin-right: 5px; + padding: 5px; +} + +.ngg-thumbnail img { + filter: alpha(opacity = 100); + -moz-opacity: .99; + opacity: .99; + background: #FFFFFF none repeat scroll 0%; + border-color: #AAAAAA rgb(204, 204, 204) rgb(221, 221, 221) rgb(187, 187, 187); + border-style: solid; + border-width: 1px; + color: inherit; + padding: 2px; + vertical-align: top; +} + +.ngg-thumbnail img:hover { + filter: alpha(opacity = 90); + -moz-opacity: .9; + opacity: .9; + border-color: #000000; +} + +/* ----------- Gallery style -------------*/ + +.ngg-galleryoverview { + overflow: hidden; + margin-top: 10px; + width: 100%; + clear: both; + display: block !important; +} + +.ngg-gallery-thumbnail-box { + background: #EEEEEE none repeat scroll 0% 50%; + border-color: #DDDDDD rgb(187, 187, 187) rgb(170, 170, 170) rgb(204, 204, 204); + border-style: solid; + border-width: 1px; + color: inherit; + display: inline; + margin: 3px; + padding: 5px; + position: relative; +} + +.ngg-gallery-thumbnail img { + filter: alpha(opacity = 100); + -moz-opacity: .99; + opacity: .99; + background: #FFFFFF none repeat scroll 0%; + border-color: #AAAAAA rgb(204, 204, 204) rgb(221, 221, 221) rgb(187, 187, 187); + border-style: solid; + border-width: 1px; + color: inherit; + padding: 2px; + vertical-align: top; +} + +.ngg-gallery-thumbnail img:hover { + filter: alpha(opacity = 90); + -moz-opacity: .9; + opacity: .9; + border-color: #000000; +} + +/* ----------- Gallery navigation -------------*/ + +.ngg-navigation a.page-numbers, +.ngg-navigation a.next, +.ngg-navigation a.prev, +.ngg-navigation span.page-numbers, +.ngg-navigation span.next, +.ngg-navigation span.prev { + padding: 3px 7px; +} + +/* ----------- Image browser style -------------*/ + +.ngg-imagebrowser h3 { + text-align: center; + padding-bottom: 10px; +} + +.ngg-imagebrowser .pic { + background: #EEEEEE none repeat scroll 0% 50%; + border-color: #DDDDDD rgb(187, 187, 187) rgb(170, 170, 170) rgb(204, 204, 204); + border-style: solid; + border-width: 1px; + color: inherit; + display: block; + padding: 10px; +} + +.ngg-imagebrowser img { + margin: -3px; + background: #FFFFFF none repeat scroll 0%; + border-color: #AAAAAA rgb(204, 204, 204) rgb(221, 221, 221) rgb(187, 187, 187); + border-style: solid; + border-width: 1px; + color: inherit; + padding: 2px; + vertical-align: top; +} + +.ngg-imagebrowser-nav { + padding: 10px; + +} + +.ngg-imagebrowser-nav .back:hover, +.ngg-imagebrowser-nav .next:hover { + border: 1px solid #000000; +} + +.ngg-imagebrowser-nav .back a:hover, +.ngg-imagebrowser-nav .next a:hover { + text-decoration: none !important; +} + diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/hovereffect.min.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/hovereffect.min.css new file mode 100644 index 0000000000000000000000000000000000000000..668ad6e6810ad3299016d50be347b3246c0c16b6 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/hovereffect.min.css @@ -0,0 +1 @@ +.ngg-albumtitle{border-bottom:1px dashed #aaa;padding-bottom:3px}.ngg-thumbnail{background:#eee none repeat scroll 0 50%;border-color:#ddd #bbb #aaa #ccc;border-style:solid;border-width:1px;color:inherit;margin-right:5px;padding:5px}.ngg-thumbnail img{filter:alpha(opacity=100);-moz-opacity:.99;opacity:.99;background:#fff none repeat scroll 0;border-color:#aaa #ccc #ddd #bbb;border-style:solid;border-width:1px;color:inherit;padding:2px;vertical-align:top}.ngg-thumbnail img:hover{filter:alpha(opacity=90);-moz-opacity:.9;opacity:.9;border-color:#000}.ngg-galleryoverview{overflow:hidden;margin-top:10px;width:100%;clear:both;display:block !important}.ngg-gallery-thumbnail-box{background:#eee none repeat scroll 0 50%;border-color:#ddd #bbb #aaa #ccc;border-style:solid;border-width:1px;color:inherit;display:inline;margin:3px;padding:5px;position:relative}.ngg-gallery-thumbnail img{filter:alpha(opacity=100);-moz-opacity:.99;opacity:.99;background:#fff none repeat scroll 0;border-color:#aaa #ccc #ddd #bbb;border-style:solid;border-width:1px;color:inherit;padding:2px;vertical-align:top}.ngg-gallery-thumbnail img:hover{filter:alpha(opacity=90);-moz-opacity:.9;opacity:.9;border-color:#000}.ngg-navigation a.page-numbers,.ngg-navigation a.next,.ngg-navigation a.prev,.ngg-navigation span.page-numbers,.ngg-navigation span.next,.ngg-navigation span.prev{padding:3px 7px}.ngg-imagebrowser h3{text-align:center;padding-bottom:10px}.ngg-imagebrowser .pic{background:#eee none repeat scroll 0 50%;border-color:#ddd #bbb #aaa #ccc;border-style:solid;border-width:1px;color:inherit;display:block;padding:10px}.ngg-imagebrowser img{margin:-3px;background:#fff none repeat scroll 0;border-color:#aaa #ccc #ddd #bbb;border-style:solid;border-width:1px;color:inherit;padding:2px;vertical-align:top}.ngg-imagebrowser-nav{padding:10px}.ngg-imagebrowser-nav .back:hover,.ngg-imagebrowser-nav .next:hover{border:1px solid #000}.ngg-imagebrowser-nav .back a:hover,.ngg-imagebrowser-nav .next a:hover{text-decoration:none !important} \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/ngg_dkret3.min.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/ngg_dkret3.min.css new file mode 100644 index 0000000000000000000000000000000000000000..f0dfe257672abe78d3639b0de1e826250b343f2d --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/ngg_dkret3.min.css @@ -0,0 +1 @@ +.ngg-gallery-thumbnail{background:url('shadowAlpha.png') no-repeat bottom right !important;background:url('shadow.gif') no-repeat bottom right;margin:10px 0 0 10px !important}.ngg-gallery-thumbnail img{margin:-6px 6px 6px -6px}.ngg-gallery-thumbnail span{display:none}.ngg-navigation a.page-numbers,.ngg-navigation a.next,.ngg-navigation a.prev,.ngg-navigation span.page-numbers,.ngg-navigation span.next,.ngg-navigation span.prev{padding:3px 7px}.ngg-widget,.ngg-widget-slideshow{text-align:center} \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/ngg_k2.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/ngg_k2.css index b6dac58b0f620056cf30a48d9cb85e0b9c510f85..36d6ddcc4bca75b5146306dea84f54cb6250eeb8 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/ngg_k2.css +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/ngg_k2.css @@ -1,84 +1,84 @@ -/* -CSS Name: K2 Theme -Description: NextGEN Style for K2 Theme -Author: Alex Rabe -Version: 1.60 - -This stylesheet modifies the NextGEN defaults to be more compatible with the K2 theme -*/ - -/* ----------- Album Styles Extend -------------*/ - -.ngg-albumoverview { - margin: 10px 0px 0px 0px !important; -} - -.ngg-album { - margin: 0px 0px 5px !important; -} - -.ngg-albumtitle { - margin: 0px 0px 10px 0px !important; -} - -.ngg-albumcontent { - margin: 0px !important; -} - -.ngg-thumbnail { - float: left; - margin: 0px 12px 0px 0px !important; -} - -.ngg-thumbnail img { - margin: 4px 0px 4px 5px !important; -} - -/* ----------- Album Styles Compact -------------*/ - -.ngg-album-link { - margin: 0px !important; -} - -.ngg-album-compact h4 { - margin-bottom: 0px !important; - margin-top: 0px !important; - padding: 0px !important; -} - -/* ----------- Gallery style -------------*/ - -.ngg-gallery-thumbnail-box { - margin: 0px !important; -} - -.ngg-gallery-thumbnail { - background: url('shadowAlpha.png') no-repeat bottom right !important; - background: url('shadow.gif') no-repeat bottom right; - margin: 10px 0 0 10px !important; -} - -.ngg-gallery-thumbnail img { - margin: -6px 6px 6px -6px !important; -} - -/* ----------- Gallery navigation -------------*/ - -.ngg-navigation a.page-numbers, -.ngg-navigation a.next, -.ngg-navigation a.prev, -.ngg-navigation span.page-numbers, -.ngg-navigation span.next, -.ngg-navigation span.prev { - padding: 3px 7px; -} - -/* ----------- Related images -------------*/ - -.ngg-related-gallery img { - margin: 0pt 2px; -} - -.ngg-related-gallery img:hover { - border: 1px solid #000000; -} +/* +CSS Name: K2 Theme +Description: NextGEN Style for K2 Theme +Author: Alex Rabe +Version: 1.60 + +This stylesheet modifies the NextGEN defaults to be more compatible with the K2 theme +*/ + +/* ----------- Album Styles Extend -------------*/ + +.ngg-albumoverview { + margin: 10px 0px 0px 0px !important; +} + +.ngg-album { + margin: 0px 0px 5px !important; +} + +.ngg-albumtitle { + margin: 0px 0px 10px 0px !important; +} + +.ngg-albumcontent { + margin: 0px !important; +} + +.ngg-thumbnail { + float: left; + margin: 0px 12px 0px 0px !important; +} + +.ngg-thumbnail img { + margin: 4px 0px 4px 5px !important; +} + +/* ----------- Album Styles Compact -------------*/ + +.ngg-album-link { + margin: 0px !important; +} + +.ngg-album-compact h4 { + margin-bottom: 0px !important; + margin-top: 0px !important; + padding: 0px !important; +} + +/* ----------- Gallery style -------------*/ + +.ngg-gallery-thumbnail-box { + margin: 0px !important; +} + +.ngg-gallery-thumbnail { + background: url('shadowAlpha.png') no-repeat bottom right !important; + background: url('shadow.gif') no-repeat bottom right; + margin: 10px 0 0 10px !important; +} + +.ngg-gallery-thumbnail img { + margin: -6px 6px 6px -6px !important; +} + +/* ----------- Gallery navigation -------------*/ + +.ngg-navigation a.page-numbers, +.ngg-navigation a.next, +.ngg-navigation a.prev, +.ngg-navigation span.page-numbers, +.ngg-navigation span.next, +.ngg-navigation span.prev { + padding: 3px 7px; +} + +/* ----------- Related images -------------*/ + +.ngg-related-gallery img { + margin: 0pt 2px; +} + +.ngg-related-gallery img:hover { + border: 1px solid #000000; +} diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/ngg_k2.min.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/ngg_k2.min.css new file mode 100644 index 0000000000000000000000000000000000000000..d7417232712bffb79527ef96a0c0d2a241f7df8f --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/ngg_k2.min.css @@ -0,0 +1 @@ +.ngg-albumoverview{margin:10px 0 0 0 !important}.ngg-album{margin:0 0 5px !important}.ngg-albumtitle{margin:0 0 10px 0 !important}.ngg-albumcontent{margin:0 !important}.ngg-thumbnail{float:left;margin:0 12px 0 0 !important}.ngg-thumbnail img{margin:4px 0 4px 5px !important}.ngg-album-link{margin:0 !important}.ngg-album-compact h4{margin-bottom:0 !important;margin-top:0 !important;padding:0 !important}.ngg-gallery-thumbnail-box{margin:0 !important}.ngg-gallery-thumbnail{background:url('shadowAlpha.png') no-repeat bottom right !important;background:url('shadow.gif') no-repeat bottom right;margin:10px 0 0 10px !important}.ngg-gallery-thumbnail img{margin:-6px 6px 6px -6px !important}.ngg-navigation a.page-numbers,.ngg-navigation a.next,.ngg-navigation a.prev,.ngg-navigation span.page-numbers,.ngg-navigation span.next,.ngg-navigation span.prev{padding:3px 7px}.ngg-related-gallery img{margin:0 2px}.ngg-related-gallery img:hover{border:1px solid #000} \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/ngg_shadow.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/ngg_shadow.css index ebab00b867d3bf7c5a514483eddde9a47570789c..a345fe18c9c87ced09d86fa9e856facd2b5660d8 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/ngg_shadow.css +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/ngg_shadow.css @@ -1,24 +1,24 @@ -/* -CSS Name: Shadow Effect -Description: NextGEN Default Style with a Shadow effect -Author: Alex Rabe -Version: 1.60 - -Applies a shadow effect to gallery thumbnails and enables display of their description text -*/ - -/* ----------- Gallery style -------------*/ - -.ngg-gallery-thumbnail { - background: url('shadowAlpha.png') no-repeat bottom right !important; - background: url('shadow.gif') no-repeat bottom right; - margin: 10px 0 0 10px !important; -} - -.ngg-gallery-thumbnail img { - margin: -6px 6px 6px -6px; -} - -.ngg-gallery-thumbnail span { - display: none; -} +/* +CSS Name: Shadow Effect +Description: NextGEN Default Style with a Shadow effect +Author: Alex Rabe +Version: 1.60 + +Applies a shadow effect to gallery thumbnails and enables display of their description text +*/ + +/* ----------- Gallery style -------------*/ + +.ngg-gallery-thumbnail { + background: url('shadowAlpha.png') no-repeat bottom right !important; + background: url('shadow.gif') no-repeat bottom right; + margin: 10px 0 0 10px !important; +} + +.ngg-gallery-thumbnail img { + margin: -6px 6px 6px -6px; +} + +.ngg-gallery-thumbnail span { + display: none; +} diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/ngg_shadow.min.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/ngg_shadow.min.css new file mode 100644 index 0000000000000000000000000000000000000000..f545d4688d146ebd494794b220c3d49a337b8fa8 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/ngg_shadow.min.css @@ -0,0 +1 @@ +.ngg-gallery-thumbnail{background:url('shadowAlpha.png') no-repeat bottom right !important;background:url('shadow.gif') no-repeat bottom right;margin:10px 0 0 10px !important}.ngg-gallery-thumbnail img{margin:-6px 6px 6px -6px}.ngg-gallery-thumbnail span{display:none} \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/ngg_shadow2.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/ngg_shadow2.css index 290fa1c1133bced1cf1e22060a116bd163865ea9..3a5a3e555e7b9a321105f495580d2da8da3ba179 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/ngg_shadow2.css +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/ngg_shadow2.css @@ -1,30 +1,30 @@ -/* -CSS Name: Shadow Effect with Description text -Description: NextGEN Default Style with a Shadow effect and description text below the thumbnail -Author: Alex Rabe -Version: 1.60 - -Applies a shadow effect to gallery thumbnails and enables display of their description text -*/ - -/* ----------- Gallery style -------------*/ - -.ngg-gallery-thumbnail { - background: url('shadowAlpha.png') no-repeat bottom right !important; - background: url('shadow.gif') no-repeat bottom right; - margin: 10px 0 0 10px !important; - padding: 10px 15px 10px 15px; - border-color: #EEEEEE; - border-style: solid none none solid; - border-width: 1px medium medium 1px; -} - -.ngg-gallery-thumbnail img { - margin: -6px 6px 6px -6px; -} - -.ngg-gallery-thumbnail span { - margin: -6px 6px 6px -6px; - text-align: center; - color: #808080; -} +/* +CSS Name: Shadow Effect with Description text +Description: NextGEN Default Style with a Shadow effect and description text below the thumbnail +Author: Alex Rabe +Version: 1.60 + +Applies a shadow effect to gallery thumbnails and enables display of their description text +*/ + +/* ----------- Gallery style -------------*/ + +.ngg-gallery-thumbnail { + background: url('shadowAlpha.png') no-repeat bottom right !important; + background: url('shadow.gif') no-repeat bottom right; + margin: 10px 0 0 10px !important; + padding: 10px 15px 10px 15px; + border-color: #EEEEEE; + border-style: solid none none solid; + border-width: 1px medium medium 1px; +} + +.ngg-gallery-thumbnail img { + margin: -6px 6px 6px -6px; +} + +.ngg-gallery-thumbnail span { + margin: -6px 6px 6px -6px; + text-align: center; + color: #808080; +} diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/ngg_shadow2.min.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/ngg_shadow2.min.css new file mode 100644 index 0000000000000000000000000000000000000000..4913b2e69b78171629d0e03fe908b93246c9235b --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/ngg_shadow2.min.css @@ -0,0 +1 @@ +.ngg-gallery-thumbnail{background:url('shadowAlpha.png') no-repeat bottom right !important;background:url('shadow.gif') no-repeat bottom right;margin:10px 0 0 10px !important;padding:10px 15px 10px 15px;border-color:#eee;border-style:solid none none solid;border-width:1px medium medium 1px}.ngg-gallery-thumbnail img{margin:-6px 6px 6px -6px}.ngg-gallery-thumbnail span{margin:-6px 6px 6px -6px;text-align:center;color:gray} \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/overview.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/overview.css new file mode 100644 index 0000000000000000000000000000000000000000..ba8e79f58705b9c8873ebc022ed58192adae2ee3 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/overview.css @@ -0,0 +1,51 @@ +.toplevel_page_nextgen-gallery .wp-badge { + border: none; + background: url( 'https://www.imagely.com/wp-content/uploads/2016/06/on-white-icon.png' ) no-repeat; + background-size: 140px 140px; + box-shadow: none; +} + +.ngg-tab { + display: none; +} + +.ngg-tab.active { + display: block; +} + +#ngg-server-settings { + float: left; +} + +#ngg-server-settings p { + margin: 0 0 0.5em 0; +} + +#ngg-server-settings:nth-of-type(2) { + margin-left: 20px; +} + +.about-text.centered { + text-align: center; + margin: 1em; +} + +.feature-video iframe, +.feature-video object, +.feature-video embed { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +.ngg-theme-image { + box-shadow: 0 0 8px #888888; +} + +@media only screen and (max-width: 700px) { + #ngg-server-settings:nth-of-type(2) { + margin-left: 0; + } +} \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/overview.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/overview.js new file mode 100644 index 0000000000000000000000000000000000000000..3ce4e439de3459cdadd6accf9df399a24f3a45cf --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/overview.js @@ -0,0 +1,25 @@ +/* + * Overview Page JS for NextGEN Gallery: Provides JS for + * navigating tabs on the NextGEN Overview page. + * + */ + +jQuery(document).ready(function($) { + $('#ngg-tabs-wrapper').find('a').click(function() { + $('#ngg-tabs-wrapper').find('a').removeClass('nav-tab-active'); + $('.ngg-tab').removeClass('active'); + + var id = jQuery(this).attr('id').replace('-link', ''); + $('#' + id).addClass('active'); + $(this).addClass('nav-tab-active'); + }); + + var activeTab = window.location.hash.replace('#top#', ''); + if ('' === activeTab) { + activeTab = $('.ngg-tab').attr('id'); + } + + $('#' + activeTab).addClass('active'); + $('#' + activeTab + '-tab').addClass('nav-tab-active'); + $('.nav-tab-active').click(); +}); \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/overview.min.css b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/overview.min.css new file mode 100644 index 0000000000000000000000000000000000000000..28d8dc1c8c2b472bed52e9622c4dc7454fc84965 --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/overview.min.css @@ -0,0 +1 @@ +.toplevel_page_nextgen-gallery .wp-badge{border:0;background:url('https://www.imagely.com/wp-content/uploads/2016/06/on-white-icon.png') no-repeat;background-size:140px 140px;box-shadow:none}.ngg-tab{display:none}.ngg-tab.active{display:block}#ngg-server-settings{float:left}#ngg-server-settings p{margin:0 0 .5em 0}#ngg-server-settings:nth-of-type(2){margin-left:20px}.about-text.centered{text-align:center;margin:1em}.feature-video iframe,.feature-video object,.feature-video embed{position:absolute;top:0;left:0;width:100%;height:100%}.ngg-theme-image{box-shadow:0 0 8px #888}@media only screen and (max-width:700px){#ngg-server-settings:nth-of-type(2){margin-left:0}} \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/overview.min.js b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/overview.min.js new file mode 100644 index 0000000000000000000000000000000000000000..f1d9983bff1380436b658bcfb4cca3464d77951b --- /dev/null +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/static/overview.min.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return c.toString(36)};if(!''.replace(/^/,String)){while(c--){d[c.toString(a)]=k[c]||c.toString(a)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('f(j).k(i($){$(\'#4-7-b\').g(\'a\').c(i(){$(\'#4-7-b\').g(\'a\').h(\'6-0-1\');$(\'.4-0\').h(\'1\');8 3=f(9).e(\'3\').d(\'-q\',\'\');$(\'#\'+3).5(\'1\');$(9).5(\'6-0-1\')});8 2=p.l.o.d(\'#m#\',\'\');n(\'\'===2){2=$(\'.4-0\').e(\'3\')}$(\'#\'+2).5(\'1\');$(\'#\'+2+\'-0\').5(\'6-0-1\');$(\'.6-0-1\').c()});',27,27,'tab|active|activeTab|id|ngg|addClass|nav|tabs|var|this||wrapper|click|replace|attr|jQuery|find|removeClass|function|document|ready|location|top|if|hash|window|link'.split('|'),0,{})) diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/simplehtmldom/simplehtmldom/simple_html_dom.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/simplehtmldom/simplehtmldom/simple_html_dom.php index a92a94a46783953fb1801a736d17d30260b22f58..ad492da891ab7bc93e26f2c71b4682170102b88d 100644 --- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/simplehtmldom/simplehtmldom/simple_html_dom.php +++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/simplehtmldom/simplehtmldom/simple_html_dom.php @@ -1,1742 +1,1742 @@ -<?php -/** - * Website: http://sourceforge.net/projects/simplehtmldom/ - * Additional projects that may be used: http://sourceforge.net/projects/debugobject/ - * Acknowledge: Jose Solorzano (https://sourceforge.net/projects/php-html/) - * Contributions by: - * Yousuke Kumakura (Attribute filters) - * Vadim Voituk (Negative indexes supports of "find" method) - * Antcs (Constructor with automatically load contents either text or file/url) - * - * all affected sections have comments starting with "PaperG" - * - * Paperg - Added case insensitive testing of the value of the selector. - * Paperg - Added tag_start for the starting index of tags - NOTE: This works but not accurately. - * This tag_start gets counted AFTER \r\n have been crushed out, and after the remove_noice calls so it will not reflect the REAL position of the tag in the source, - * it will almost always be smaller by some amount. - * We use this to determine how far into the file the tag in question is. This "percentage will never be accurate as the $dom->size is the "real" number of bytes the dom was created from. - * but for most purposes, it's a really good estimation. - * Paperg - Added the forceTagsClosed to the dom constructor. Forcing tags closed is great for malformed html, but it CAN lead to parsing errors. - * Allow the user to tell us how much they trust the html. - * Paperg add the text and plaintext to the selectors for the find syntax. plaintext implies text in the innertext of a node. text implies that the tag is a text node. - * This allows for us to find tags based on the text they contain. - * Create find_ancestor_tag to see if a tag is - at any level - inside of another specific tag. - * Paperg: added parse_charset so that we know about the character set of the source document. - * NOTE: If the user's system has a routine called get_last_retrieve_url_contents_content_type availalbe, we will assume it's returning the content-type header from the - * last transfer or curl_exec, and we will parse that and use it in preference to any other method of charset detection. - * - * Found infinite loop in the case of broken html in restore_noise. Rewrote to protect from that. - * PaperG (John Schlick) Added get_display_size for "IMG" tags. - * - * Licensed under The MIT License - * Redistributions of files must retain the above copyright notice. - * - * @author S.C. Chen <me578022@gmail.com> - * @author John Schlick - * @author Rus Carroll - * @version 1.5 ($Rev: 208 $) - * @package PlaceLocalInclude - * @subpackage simple_html_dom - */ - -/** - * All of the Defines for the classes below. - * @author S.C. Chen <me578022@gmail.com> - */ -define('HDOM_TYPE_ELEMENT', 1); -define('HDOM_TYPE_COMMENT', 2); -define('HDOM_TYPE_TEXT', 3); -define('HDOM_TYPE_ENDTAG', 4); -define('HDOM_TYPE_ROOT', 5); -define('HDOM_TYPE_UNKNOWN', 6); -define('HDOM_QUOTE_DOUBLE', 0); -define('HDOM_QUOTE_SINGLE', 1); -define('HDOM_QUOTE_NO', 3); -define('HDOM_INFO_BEGIN', 0); -define('HDOM_INFO_END', 1); -define('HDOM_INFO_QUOTE', 2); -define('HDOM_INFO_SPACE', 3); -define('HDOM_INFO_TEXT', 4); -define('HDOM_INFO_INNER', 5); -define('HDOM_INFO_OUTER', 6); -define('HDOM_INFO_ENDSPACE',7); -define('DEFAULT_TARGET_CHARSET', 'UTF-8'); -define('DEFAULT_BR_TEXT', "\r\n"); -define('DEFAULT_SPAN_TEXT', " "); -define('MAX_FILE_SIZE', 600000); -// helper functions -// ----------------------------------------------------------------------------- -// get html dom from file -// $maxlen is defined in the code as PHP_STREAM_COPY_ALL which is defined as -1. -function file_get_html($url, $use_include_path = false, $context=null, $offset = -1, $maxLen=-1, $lowercase = true, $forceTagsClosed=true, $target_charset = DEFAULT_TARGET_CHARSET, $stripRN=true, $defaultBRText=DEFAULT_BR_TEXT, $defaultSpanText=DEFAULT_SPAN_TEXT) -{ - // We DO force the tags to be terminated. - $dom = new simple_html_dom(null, $lowercase, $forceTagsClosed, $target_charset, $stripRN, $defaultBRText, $defaultSpanText); - // For sourceforge users: uncomment the next line and comment the retreive_url_contents line 2 lines down if it is not already done. - $contents = file_get_contents($url, $use_include_path, $context, $offset); - // Paperg - use our own mechanism for getting the contents as we want to control the timeout. - //$contents = retrieve_url_contents($url); - if (empty($contents) || strlen($contents) > MAX_FILE_SIZE) - { - return false; - } - // The second parameter can force the selectors to all be lowercase. - $dom->load($contents, $lowercase, $stripRN); - return $dom; -} - -// get html dom from string -function str_get_html($str, $lowercase=true, $forceTagsClosed=true, $target_charset = DEFAULT_TARGET_CHARSET, $stripRN=true, $defaultBRText=DEFAULT_BR_TEXT, $defaultSpanText=DEFAULT_SPAN_TEXT) -{ - $dom = new simple_html_dom(null, $lowercase, $forceTagsClosed, $target_charset, $stripRN, $defaultBRText, $defaultSpanText); - if (empty($str) || strlen($str) > MAX_FILE_SIZE) - { - $dom->clear(); - return false; - } - $dom->load($str, $lowercase, $stripRN); - return $dom; -} - -// dump html dom tree -function dump_html_tree($node, $show_attr=true, $deep=0) -{ - $node->dump($node); -} - - -/** - * simple html dom node - * PaperG - added ability for "find" routine to lowercase the value of the selector. - * PaperG - added $tag_start to track the start position of the tag in the total byte index - * - * @package PlaceLocalInclude - */ -class simple_html_dom_node -{ - public $nodetype = HDOM_TYPE_TEXT; - public $tag = 'text'; - public $attr = array(); - public $children = array(); - public $nodes = array(); - public $parent = null; - // The "info" array - see HDOM_INFO_... for what each element contains. - public $_ = array(); - public $tag_start = 0; - private $dom = null; - - function __construct($dom) - { - $this->dom = $dom; - $dom->nodes[] = $this; - } - - function __destruct() - { - $this->clear(); - } - - function __toString() - { - return $this->outertext(); - } - - // clean up memory due to php5 circular references memory leak... - function clear() - { - $this->dom = null; - $this->nodes = null; - $this->parent = null; - $this->children = null; - } - - // dump node's tree - function dump($show_attr=true, $deep=0) - { - $lead = str_repeat(' ', $deep); - - echo $lead.$this->tag; - if ($show_attr && count($this->attr)>0) - { - echo '('; - foreach ($this->attr as $k=>$v) - echo "[$k]=>\"".$this->$k.'", '; - echo ')'; - } - echo "\n"; - - if ($this->nodes) - { - foreach ($this->nodes as $c) - { - $c->dump($show_attr, $deep+1); - } - } - } - - - // Debugging function to dump a single dom node with a bunch of information about it. - function dump_node($echo=true) - { - - $string = $this->tag; - if (count($this->attr)>0) - { - $string .= '('; - foreach ($this->attr as $k=>$v) - { - $string .= "[$k]=>\"".$this->$k.'", '; - } - $string .= ')'; - } - if (count($this->_)>0) - { - $string .= ' $_ ('; - foreach ($this->_ as $k=>$v) - { - if (is_array($v)) - { - $string .= "[$k]=>("; - foreach ($v as $k2=>$v2) - { - $string .= "[$k2]=>\"".$v2.'", '; - } - $string .= ")"; - } else { - $string .= "[$k]=>\"".$v.'", '; - } - } - $string .= ")"; - } - - if (isset($this->text)) - { - $string .= " text: (" . $this->text . ")"; - } - - $string .= " HDOM_INNER_INFO: '"; - if (isset($node->_[HDOM_INFO_INNER])) - { - $string .= $node->_[HDOM_INFO_INNER] . "'"; - } - else - { - $string .= ' NULL '; - } - - $string .= " children: " . count($this->children); - $string .= " nodes: " . count($this->nodes); - $string .= " tag_start: " . $this->tag_start; - $string .= "\n"; - - if ($echo) - { - echo $string; - return; - } - else - { - return $string; - } - } - - // returns the parent of node - // If a node is passed in, it will reset the parent of the current node to that one. - function parent($parent=null) - { - // I am SURE that this doesn't work properly. - // It fails to unset the current node from it's current parents nodes or children list first. - if ($parent !== null) - { - $this->parent = $parent; - $this->parent->nodes[] = $this; - $this->parent->children[] = $this; - } - - return $this->parent; - } - - // verify that node has children - function has_child() - { - return !empty($this->children); - } - - // returns children of node - function children($idx=-1) - { - if ($idx===-1) - { - return $this->children; - } - if (isset($this->children[$idx])) - { - return $this->children[$idx]; - } - return null; - } - - // returns the first child of node - function first_child() - { - if (count($this->children)>0) - { - return $this->children[0]; - } - return null; - } - - // returns the last child of node - function last_child() - { - if (($count=count($this->children))>0) - { - return $this->children[$count-1]; - } - return null; - } - - // returns the next sibling of node - function next_sibling() - { - if ($this->parent===null) - { - return null; - } - - $idx = 0; - $count = count($this->parent->children); - while ($idx<$count && $this!==$this->parent->children[$idx]) - { - ++$idx; - } - if (++$idx>=$count) - { - return null; - } - return $this->parent->children[$idx]; - } - - // returns the previous sibling of node - function prev_sibling() - { - if ($this->parent===null) return null; - $idx = 0; - $count = count($this->parent->children); - while ($idx<$count && $this!==$this->parent->children[$idx]) - ++$idx; - if (--$idx<0) return null; - return $this->parent->children[$idx]; - } - - // function to locate a specific ancestor tag in the path to the root. - function find_ancestor_tag($tag) - { - global $debug_object; - if (is_object($debug_object)) { $debug_object->debug_log_entry(1); } - - // Start by including ourselves in the comparison. - $returnDom = $this; - - while (!is_null($returnDom)) - { - if (is_object($debug_object)) { $debug_object->debug_log(2, "Current tag is: " . $returnDom->tag); } - - if ($returnDom->tag == $tag) - { - break; - } - $returnDom = $returnDom->parent; - } - return $returnDom; - } - - // get dom node's inner html - function innertext() - { - if (isset($this->_[HDOM_INFO_INNER])) return $this->_[HDOM_INFO_INNER]; - if (isset($this->_[HDOM_INFO_TEXT])) return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); - - $ret = ''; - foreach ($this->nodes as $n) - $ret .= $n->outertext(); - return $ret; - } - - // get dom node's outer text (with tag) - function outertext() - { - global $debug_object; - if (is_object($debug_object)) - { - $text = ''; - if ($this->tag == 'text') - { - if (!empty($this->text)) - { - $text = " with text: " . $this->text; - } - } - $debug_object->debug_log(1, 'Innertext of tag: ' . $this->tag . $text); - } - - if ($this->tag==='root') return $this->innertext(); - - // trigger callback - if ($this->dom && $this->dom->callback!==null) - { - call_user_func_array($this->dom->callback, array($this)); - } - - if (isset($this->_[HDOM_INFO_OUTER])) return $this->_[HDOM_INFO_OUTER]; - if (isset($this->_[HDOM_INFO_TEXT])) return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); - - // render begin tag - if ($this->dom && $this->dom->nodes[$this->_[HDOM_INFO_BEGIN]]) - { - $ret = $this->dom->nodes[$this->_[HDOM_INFO_BEGIN]]->makeup(); - } else { - $ret = ""; - } - - // render inner text - if (isset($this->_[HDOM_INFO_INNER])) - { - // If it's a br tag... don't return the HDOM_INNER_INFO that we may or may not have added. - if ($this->tag != "br") - { - $ret .= $this->_[HDOM_INFO_INNER]; - } - } else { - if ($this->nodes) - { - foreach ($this->nodes as $n) - { - $ret .= $this->convert_text($n->outertext()); - } - } - } - - // render end tag - if (isset($this->_[HDOM_INFO_END]) && $this->_[HDOM_INFO_END]!=0) - $ret .= '</'.$this->tag.'>'; - return $ret; - } - - // get dom node's plain text - function text() - { - if (isset($this->_[HDOM_INFO_INNER])) return $this->_[HDOM_INFO_INNER]; - switch ($this->nodetype) - { - case HDOM_TYPE_TEXT: return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); - case HDOM_TYPE_COMMENT: return ''; - case HDOM_TYPE_UNKNOWN: return ''; - } - if (strcasecmp($this->tag, 'script')===0) return ''; - if (strcasecmp($this->tag, 'style')===0) return ''; - - $ret = ''; - // In rare cases, (always node type 1 or HDOM_TYPE_ELEMENT - observed for some span tags, and some p tags) $this->nodes is set to NULL. - // NOTE: This indicates that there is a problem where it's set to NULL without a clear happening. - // WHY is this happening? - if (!is_null($this->nodes)) - { - foreach ($this->nodes as $n) - { - $ret .= $this->convert_text($n->text()); - } - - // If this node is a span... add a space at the end of it so multiple spans don't run into each other. This is plaintext after all. - if ($this->tag == "span") - { - $ret .= $this->dom->default_span_text; - } - - - } - return $ret; - } - - function xmltext() - { - $ret = $this->innertext(); - $ret = str_ireplace('<![CDATA[', '', $ret); - $ret = str_replace(']]>', '', $ret); - return $ret; - } - - // build node's text with tag - function makeup() - { - // text, comment, unknown - if (isset($this->_[HDOM_INFO_TEXT])) return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); - - $ret = '<'.$this->tag; - $i = -1; - - foreach ($this->attr as $key=>$val) - { - ++$i; - - // skip removed attribute - if ($val===null || $val===false) - continue; - - $ret .= $this->_[HDOM_INFO_SPACE][$i][0]; - //no value attr: nowrap, checked selected... - if ($val===true) - $ret .= $key; - else { - switch ($this->_[HDOM_INFO_QUOTE][$i]) - { - case HDOM_QUOTE_DOUBLE: $quote = '"'; break; - case HDOM_QUOTE_SINGLE: $quote = '\''; break; - default: $quote = ''; - } - $ret .= $key.$this->_[HDOM_INFO_SPACE][$i][1].'='.$this->_[HDOM_INFO_SPACE][$i][2].$quote.$val.$quote; - } - } - $ret = $this->dom->restore_noise($ret); - return $ret . $this->_[HDOM_INFO_ENDSPACE] . '>'; - } - - // find elements by css selector - //PaperG - added ability for find to lowercase the value of the selector. - function find($selector, $idx=null, $lowercase=false) - { - $selectors = $this->parse_selector($selector); - if (($count=count($selectors))===0) return array(); - $found_keys = array(); - - // find each selector - for ($c=0; $c<$count; ++$c) - { - // The change on the below line was documented on the sourceforge code tracker id 2788009 - // used to be: if (($levle=count($selectors[0]))===0) return array(); - if (($levle=count($selectors[$c]))===0) return array(); - if (!isset($this->_[HDOM_INFO_BEGIN])) return array(); - - $head = array($this->_[HDOM_INFO_BEGIN]=>1); - - // handle descendant selectors, no recursive! - for ($l=0; $l<$levle; ++$l) - { - $ret = array(); - foreach ($head as $k=>$v) - { - $n = ($k===-1) ? $this->dom->root : $this->dom->nodes[$k]; - //PaperG - Pass this optional parameter on to the seek function. - $n->seek($selectors[$c][$l], $ret, $lowercase); - } - $head = $ret; - } - - foreach ($head as $k=>$v) - { - if (!isset($found_keys[$k])) - { - $found_keys[$k] = 1; - } - } - } - - // sort keys - ksort($found_keys); - - $found = array(); - foreach ($found_keys as $k=>$v) - $found[] = $this->dom->nodes[$k]; - - // return nth-element or array - if (is_null($idx)) return $found; - else if ($idx<0) $idx = count($found) + $idx; - return (isset($found[$idx])) ? $found[$idx] : null; - } - - // seek for given conditions - // PaperG - added parameter to allow for case insensitive testing of the value of a selector. - protected function seek($selector, &$ret, $lowercase=false) - { - global $debug_object; - if (is_object($debug_object)) { $debug_object->debug_log_entry(1); } - - list($tag, $key, $val, $exp, $no_key) = $selector; - - // xpath index - if ($tag && $key && is_numeric($key)) - { - $count = 0; - foreach ($this->children as $c) - { - if ($tag==='*' || $tag===$c->tag) { - if (++$count==$key) { - $ret[$c->_[HDOM_INFO_BEGIN]] = 1; - return; - } - } - } - return; - } - - $end = (!empty($this->_[HDOM_INFO_END])) ? $this->_[HDOM_INFO_END] : 0; - if ($end==0) { - $parent = $this->parent; - while (!isset($parent->_[HDOM_INFO_END]) && $parent!==null) { - $end -= 1; - $parent = $parent->parent; - } - $end += $parent->_[HDOM_INFO_END]; - } - - for ($i=$this->_[HDOM_INFO_BEGIN]+1; $i<$end; ++$i) { - $node = $this->dom->nodes[$i]; - - $pass = true; - - if ($tag==='*' && !$key) { - if (in_array($node, $this->children, true)) - $ret[$i] = 1; - continue; - } - - // compare tag - if ($tag && $tag!=$node->tag && $tag!=='*') {$pass=false;} - // compare key - if ($pass && $key) { - if ($no_key) { - if (isset($node->attr[$key])) $pass=false; - } else { - if (($key != "plaintext") && !isset($node->attr[$key])) $pass=false; - } - } - // compare value - if ($pass && $key && $val && $val!=='*') { - // If they have told us that this is a "plaintext" search then we want the plaintext of the node - right? - if ($key == "plaintext") { - // $node->plaintext actually returns $node->text(); - $nodeKeyValue = $node->text(); - } else { - // this is a normal search, we want the value of that attribute of the tag. - $nodeKeyValue = $node->attr[$key]; - } - if (is_object($debug_object)) {$debug_object->debug_log(2, "testing node: " . $node->tag . " for attribute: " . $key . $exp . $val . " where nodes value is: " . $nodeKeyValue);} - - //PaperG - If lowercase is set, do a case insensitive test of the value of the selector. - if ($lowercase) { - $check = $this->match($exp, strtolower($val), strtolower($nodeKeyValue)); - } else { - $check = $this->match($exp, $val, $nodeKeyValue); - } - if (is_object($debug_object)) {$debug_object->debug_log(2, "after match: " . ($check ? "true" : "false"));} - - // handle multiple class - if (!$check && strcasecmp($key, 'class')===0) { - foreach (explode(' ',$node->attr[$key]) as $k) { - // Without this, there were cases where leading, trailing, or double spaces lead to our comparing blanks - bad form. - if (!empty($k)) { - if ($lowercase) { - $check = $this->match($exp, strtolower($val), strtolower($k)); - } else { - $check = $this->match($exp, $val, $k); - } - if ($check) break; - } - } - } - if (!$check) $pass = false; - } - if ($pass) $ret[$i] = 1; - unset($node); - } - // It's passed by reference so this is actually what this function returns. - if (is_object($debug_object)) {$debug_object->debug_log(1, "EXIT - ret: ", $ret);} - } - - protected function match($exp, $pattern, $value) { - global $debug_object; - if (is_object($debug_object)) {$debug_object->debug_log_entry(1);} - - switch ($exp) { - case '=': - return ($value===$pattern); - case '!=': - return ($value!==$pattern); - case '^=': - return preg_match("/^".preg_quote($pattern,'/')."/", $value); - case '$=': - return preg_match("/".preg_quote($pattern,'/')."$/", $value); - case '*=': - if ($pattern[0]=='/') { - return preg_match($pattern, $value); - } - return preg_match("/".$pattern."/i", $value); - } - return false; - } - - protected function parse_selector($selector_string) { - global $debug_object; - if (is_object($debug_object)) {$debug_object->debug_log_entry(1);} - - // pattern of CSS selectors, modified from mootools - // Paperg: Add the colon to the attrbute, so that it properly finds <tag attr:ibute="something" > like google does. - // Note: if you try to look at this attribute, yo MUST use getAttribute since $dom->x:y will fail the php syntax check. -// Notice the \[ starting the attbute? and the @? following? This implies that an attribute can begin with an @ sign that is not captured. -// This implies that an html attribute specifier may start with an @ sign that is NOT captured by the expression. -// farther study is required to determine of this should be documented or removed. -// $pattern = "/([\w-:\*]*)(?:\#([\w-]+)|\.([\w-]+))?(?:\[@?(!?[\w-]+)(?:([!*^$]?=)[\"']?(.*?)[\"']?)?\])?([\/, ]+)/is"; - $pattern = "/([\w-:\*]*)(?:\#([\w-]+)|\.([\w-]+))?(?:\[@?(!?[\w-:]+)(?:([!*^$]?=)[\"']?(.*?)[\"']?)?\])?([\/, ]+)/is"; - preg_match_all($pattern, trim($selector_string).' ', $matches, PREG_SET_ORDER); - if (is_object($debug_object)) {$debug_object->debug_log(2, "Matches Array: ", $matches);} - - $selectors = array(); - $result = array(); - //print_r($matches); - - foreach ($matches as $m) { - $m[0] = trim($m[0]); - if ($m[0]==='' || $m[0]==='/' || $m[0]==='//') continue; - // for browser generated xpath - if ($m[1]==='tbody') continue; - - list($tag, $key, $val, $exp, $no_key) = array($m[1], null, null, '=', false); - if (!empty($m[2])) {$key='id'; $val=$m[2];} - if (!empty($m[3])) {$key='class'; $val=$m[3];} - if (!empty($m[4])) {$key=$m[4];} - if (!empty($m[5])) {$exp=$m[5];} - if (!empty($m[6])) {$val=$m[6];} - - // convert to lowercase - if ($this->dom->lowercase) {$tag=strtolower($tag); $key=strtolower($key);} - //elements that do NOT have the specified attribute - if (isset($key[0]) && $key[0]==='!') {$key=substr($key, 1); $no_key=true;} - - $result[] = array($tag, $key, $val, $exp, $no_key); - if (trim($m[7])===',') { - $selectors[] = $result; - $result = array(); - } - } - if (count($result)>0) - $selectors[] = $result; - return $selectors; - } - - function __get($name) - { - if (isset($this->attr[$name])) - { - return $this->convert_text($this->attr[$name]); - } - switch ($name) - { - case 'outertext': return $this->outertext(); - case 'innertext': return $this->innertext(); - case 'plaintext': return $this->text(); - case 'xmltext': return $this->xmltext(); - default: return array_key_exists($name, $this->attr); - } - } - - function __set($name, $value) - { - global $debug_object; - if (is_object($debug_object)) {$debug_object->debug_log_entry(1);} - - switch ($name) - { - case 'outertext': return $this->_[HDOM_INFO_OUTER] = $value; - case 'innertext': - if (isset($this->_[HDOM_INFO_TEXT])) return $this->_[HDOM_INFO_TEXT] = $value; - return $this->_[HDOM_INFO_INNER] = $value; - } - if (!isset($this->attr[$name])) - { - $this->_[HDOM_INFO_SPACE][] = array(' ', '', ''); - $this->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_DOUBLE; - } - $this->attr[$name] = $value; - } - - function __isset($name) - { - switch ($name) - { - case 'outertext': return true; - case 'innertext': return true; - case 'plaintext': return true; - } - //no value attr: nowrap, checked selected... - return (array_key_exists($name, $this->attr)) ? true : isset($this->attr[$name]); - } - - function __unset($name) { - if (isset($this->attr[$name])) - unset($this->attr[$name]); - } - - // PaperG - Function to convert the text from one character set to another if the two sets are not the same. - function convert_text($text) - { - global $debug_object; - if (is_object($debug_object)) {$debug_object->debug_log_entry(1);} - - $converted_text = $text; - - $sourceCharset = ""; - $targetCharset = ""; - - if ($this->dom) - { - $sourceCharset = strtoupper($this->dom->_charset); - $targetCharset = strtoupper($this->dom->_target_charset); - } - if (is_object($debug_object)) {$debug_object->debug_log(3, "source charset: " . $sourceCharset . " target charaset: " . $targetCharset);} - - if (!empty($sourceCharset) && !empty($targetCharset) && (strcasecmp($sourceCharset, $targetCharset) != 0)) - { - // Check if the reported encoding could have been incorrect and the text is actually already UTF-8 - if ((strcasecmp($targetCharset, 'UTF-8') == 0) && ($this->is_utf8($text))) - { - $converted_text = $text; - } - else - { - $converted_text = iconv($sourceCharset, $targetCharset, $text); - } - } - - // Lets make sure that we don't have that silly BOM issue with any of the utf-8 text we output. - if ($targetCharset == 'UTF-8') - { - if (substr($converted_text, 0, 3) == "\xef\xbb\xbf") - { - $converted_text = substr($converted_text, 3); - } - if (substr($converted_text, -3) == "\xef\xbb\xbf") - { - $converted_text = substr($converted_text, 0, -3); - } - } - - return $converted_text; - } - - /** - * Returns true if $string is valid UTF-8 and false otherwise. - * - * @param mixed $str String to be tested - * @return boolean - */ - static function is_utf8($str) - { - $c=0; $b=0; - $bits=0; - $len=strlen($str); - for($i=0; $i<$len; $i++) - { - $c=ord($str[$i]); - if($c > 128) - { - if(($c >= 254)) return false; - elseif($c >= 252) $bits=6; - elseif($c >= 248) $bits=5; - elseif($c >= 240) $bits=4; - elseif($c >= 224) $bits=3; - elseif($c >= 192) $bits=2; - else return false; - if(($i+$bits) > $len) return false; - while($bits > 1) - { - $i++; - $b=ord($str[$i]); - if($b < 128 || $b > 191) return false; - $bits--; - } - } - } - return true; - } - /* - function is_utf8($string) - { - //this is buggy - return (utf8_encode(utf8_decode($string)) == $string); - } - */ - - /** - * Function to try a few tricks to determine the displayed size of an img on the page. - * NOTE: This will ONLY work on an IMG tag. Returns FALSE on all other tag types. - * - * @author John Schlick - * @version April 19 2012 - * @return array an array containing the 'height' and 'width' of the image on the page or -1 if we can't figure it out. - */ - function get_display_size() - { - global $debug_object; - - $width = -1; - $height = -1; - - if ($this->tag !== 'img') - { - return false; - } - - // See if there is aheight or width attribute in the tag itself. - if (isset($this->attr['width'])) - { - $width = $this->attr['width']; - } - - if (isset($this->attr['height'])) - { - $height = $this->attr['height']; - } - - // Now look for an inline style. - if (isset($this->attr['style'])) - { - // Thanks to user gnarf from stackoverflow for this regular expression. - $attributes = array(); - preg_match_all("/([\w-]+)\s*:\s*([^;]+)\s*;?/", $this->attr['style'], $matches, PREG_SET_ORDER); - foreach ($matches as $match) { - $attributes[$match[1]] = $match[2]; - } - - // If there is a width in the style attributes: - if (isset($attributes['width']) && $width == -1) - { - // check that the last two characters are px (pixels) - if (strtolower(substr($attributes['width'], -2)) == 'px') - { - $proposed_width = substr($attributes['width'], 0, -2); - // Now make sure that it's an integer and not something stupid. - if (filter_var($proposed_width, FILTER_VALIDATE_INT)) - { - $width = $proposed_width; - } - } - } - - // If there is a width in the style attributes: - if (isset($attributes['height']) && $height == -1) - { - // check that the last two characters are px (pixels) - if (strtolower(substr($attributes['height'], -2)) == 'px') - { - $proposed_height = substr($attributes['height'], 0, -2); - // Now make sure that it's an integer and not something stupid. - if (filter_var($proposed_height, FILTER_VALIDATE_INT)) - { - $height = $proposed_height; - } - } - } - - } - - // Future enhancement: - // Look in the tag to see if there is a class or id specified that has a height or width attribute to it. - - // Far future enhancement - // Look at all the parent tags of this image to see if they specify a class or id that has an img selector that specifies a height or width - // Note that in this case, the class or id will have the img subselector for it to apply to the image. - - // ridiculously far future development - // If the class or id is specified in a SEPARATE css file thats not on the page, go get it and do what we were just doing for the ones on the page. - - $result = array('height' => $height, - 'width' => $width); - return $result; - } - - // camel naming conventions - function getAllAttributes() {return $this->attr;} - function getAttribute($name) {return $this->__get($name);} - function setAttribute($name, $value) {$this->__set($name, $value);} - function hasAttribute($name) {return $this->__isset($name);} - function removeAttribute($name) {$this->__set($name, null);} - function getElementById($id) {return $this->find("#$id", 0);} - function getElementsById($id, $idx=null) {return $this->find("#$id", $idx);} - function getElementByTagName($name) {return $this->find($name, 0);} - function getElementsByTagName($name, $idx=null) {return $this->find($name, $idx);} - function parentNode() {return $this->parent();} - function childNodes($idx=-1) {return $this->children($idx);} - function firstChild() {return $this->first_child();} - function lastChild() {return $this->last_child();} - function nextSibling() {return $this->next_sibling();} - function previousSibling() {return $this->prev_sibling();} - function hasChildNodes() {return $this->has_child();} - function nodeName() {return $this->tag;} - function appendChild($node) {$node->parent($this); return $node;} - -} - -/** - * simple html dom parser - * Paperg - in the find routine: allow us to specify that we want case insensitive testing of the value of the selector. - * Paperg - change $size from protected to public so we can easily access it - * Paperg - added ForceTagsClosed in the constructor which tells us whether we trust the html or not. Default is to NOT trust it. - * - * @package PlaceLocalInclude - */ -class simple_html_dom -{ - public $root = null; - public $nodes = array(); - public $callback = null; - public $lowercase = false; - // Used to keep track of how large the text was when we started. - public $original_size; - public $size; - protected $pos; - protected $doc; - protected $char; - protected $cursor; - protected $parent; - protected $noise = array(); - protected $token_blank = " \t\r\n"; - protected $token_equal = ' =/>'; - protected $token_slash = " />\r\n\t"; - protected $token_attr = ' >'; - // Note that this is referenced by a child node, and so it needs to be public for that node to see this information. - public $_charset = ''; - public $_target_charset = ''; - protected $default_br_text = ""; - public $default_span_text = ""; - - // use isset instead of in_array, performance boost about 30%... - protected $self_closing_tags = array('img'=>1, 'br'=>1, 'input'=>1, 'meta'=>1, 'link'=>1, 'hr'=>1, 'base'=>1, 'embed'=>1, 'spacer'=>1); - protected $block_tags = array('root'=>1, 'body'=>1, 'form'=>1, 'div'=>1, 'span'=>1, 'table'=>1); - // Known sourceforge issue #2977341 - // B tags that are not closed cause us to return everything to the end of the document. - protected $optional_closing_tags = array( - 'tr'=>array('tr'=>1, 'td'=>1, 'th'=>1), - 'th'=>array('th'=>1), - 'td'=>array('td'=>1), - 'li'=>array('li'=>1), - 'dt'=>array('dt'=>1, 'dd'=>1), - 'dd'=>array('dd'=>1, 'dt'=>1), - 'dl'=>array('dd'=>1, 'dt'=>1), - 'p'=>array('p'=>1), - 'nobr'=>array('nobr'=>1), - 'b'=>array('b'=>1), - 'option'=>array('option'=>1), - ); - - function __construct($str=null, $lowercase=true, $forceTagsClosed=true, $target_charset=DEFAULT_TARGET_CHARSET, $stripRN=true, $defaultBRText=DEFAULT_BR_TEXT, $defaultSpanText=DEFAULT_SPAN_TEXT) - { - if ($str) - { - if (preg_match("/^http:\/\//i",$str) || is_file($str)) - { - $this->load_file($str); - } - else - { - $this->load($str, $lowercase, $stripRN, $defaultBRText, $defaultSpanText); - } - } - // Forcing tags to be closed implies that we don't trust the html, but it can lead to parsing errors if we SHOULD trust the html. - if (!$forceTagsClosed) { - $this->optional_closing_array=array(); - } - $this->_target_charset = $target_charset; - } - - function __destruct() - { - $this->clear(); - } - - // load html from string - function load($str, $lowercase=true, $stripRN=true, $defaultBRText=DEFAULT_BR_TEXT, $defaultSpanText=DEFAULT_SPAN_TEXT) - { - global $debug_object; - - // prepare - $this->prepare($str, $lowercase, $stripRN, $defaultBRText, $defaultSpanText); - // strip out cdata - $this->remove_noise("'<!\[CDATA\[(.*?)\]\]>'is", true); - // strip out comments - $this->remove_noise("'<!--(.*?)-->'is"); - // Per sourceforge http://sourceforge.net/tracker/?func=detail&aid=2949097&group_id=218559&atid=1044037 - // Script tags removal now preceeds style tag removal. - // strip out <script> tags - $this->remove_noise("'<\s*script[^>]*[^/]>(.*?)<\s*/\s*script\s*>'is"); - $this->remove_noise("'<\s*script\s*>(.*?)<\s*/\s*script\s*>'is"); - // strip out <style> tags - $this->remove_noise("'<\s*style[^>]*[^/]>(.*?)<\s*/\s*style\s*>'is"); - $this->remove_noise("'<\s*style\s*>(.*?)<\s*/\s*style\s*>'is"); - // strip out preformatted tags - $this->remove_noise("'<\s*(?:code)[^>]*>(.*?)<\s*/\s*(?:code)\s*>'is"); - // strip out server side scripts - $this->remove_noise("'(<\?)(.*?)(\?>)'s", true); - // strip smarty scripts - $this->remove_noise("'(\{\w)(.*?)(\})'s", true); - - // parsing - while ($this->parse()); - // end - $this->root->_[HDOM_INFO_END] = $this->cursor; - $this->parse_charset(); - - // make load function chainable - return $this; - - } - - // load html from file - function load_file() - { - $args = func_get_args(); - $this->load(call_user_func_array('file_get_contents', $args), true); - // Throw an error if we can't properly load the dom. - if (($error=error_get_last())!==null) { - $this->clear(); - return false; - } - } - - // set callback function - function set_callback($function_name) - { - $this->callback = $function_name; - } - - // remove callback function - function remove_callback() - { - $this->callback = null; - } - - // save dom as string - function save($filepath='') - { - $ret = $this->root->innertext(); - if ($filepath!=='') file_put_contents($filepath, $ret, LOCK_EX); - return $ret; - } - - // find dom node by css selector - // Paperg - allow us to specify that we want case insensitive testing of the value of the selector. - function find($selector, $idx=null, $lowercase=false) - { - return $this->root->find($selector, $idx, $lowercase); - } - - // clean up memory due to php5 circular references memory leak... - function clear() - { - foreach ($this->nodes as $n) {$n->clear(); $n = null;} - // This add next line is documented in the sourceforge repository. 2977248 as a fix for ongoing memory leaks that occur even with the use of clear. - if (isset($this->children)) foreach ($this->children as $n) {$n->clear(); $n = null;} - if (isset($this->parent)) {$this->parent->clear(); unset($this->parent);} - if (isset($this->root)) {$this->root->clear(); unset($this->root);} - unset($this->doc); - unset($this->noise); - } - - function dump($show_attr=true) - { - $this->root->dump($show_attr); - } - - // prepare HTML data and init everything - protected function prepare($str, $lowercase=true, $stripRN=true, $defaultBRText=DEFAULT_BR_TEXT, $defaultSpanText=DEFAULT_SPAN_TEXT) - { - $this->clear(); - - // set the length of content before we do anything to it. - $this->size = strlen($str); - // Save the original size of the html that we got in. It might be useful to someone. - $this->original_size = $this->size; - - //before we save the string as the doc... strip out the \r \n's if we are told to. - if ($stripRN) { - $str = str_replace("\r", " ", $str); - $str = str_replace("\n", " ", $str); - - // set the length of content since we have changed it. - $this->size = strlen($str); - } - - $this->doc = $str; - $this->pos = 0; - $this->cursor = 1; - $this->noise = array(); - $this->nodes = array(); - $this->lowercase = $lowercase; - $this->default_br_text = $defaultBRText; - $this->default_span_text = $defaultSpanText; - $this->root = new simple_html_dom_node($this); - $this->root->tag = 'root'; - $this->root->_[HDOM_INFO_BEGIN] = -1; - $this->root->nodetype = HDOM_TYPE_ROOT; - $this->parent = $this->root; - if ($this->size>0) $this->char = $this->doc[0]; - } - - // parse html content - protected function parse() - { - if (($s = $this->copy_until_char('<'))==='') - { - return $this->read_tag(); - } - - // text - $node = new simple_html_dom_node($this); - ++$this->cursor; - $node->_[HDOM_INFO_TEXT] = $s; - $this->link_nodes($node, false); - return true; - } - - // PAPERG - dkchou - added this to try to identify the character set of the page we have just parsed so we know better how to spit it out later. - // NOTE: IF you provide a routine called get_last_retrieve_url_contents_content_type which returns the CURLINFO_CONTENT_TYPE from the last curl_exec - // (or the content_type header from the last transfer), we will parse THAT, and if a charset is specified, we will use it over any other mechanism. - protected function parse_charset() - { - global $debug_object; - - $charset = null; - - if (function_exists('get_last_retrieve_url_contents_content_type')) - { - $contentTypeHeader = get_last_retrieve_url_contents_content_type(); - $success = preg_match('/charset=(.+)/', $contentTypeHeader, $matches); - if ($success) - { - $charset = $matches[1]; - if (is_object($debug_object)) {$debug_object->debug_log(2, 'header content-type found charset of: ' . $charset);} - } - - } - - if (empty($charset)) - { - $el = $this->root->find('meta[http-equiv=Content-Type]',0); - if (!empty($el)) - { - $fullvalue = $el->content; - if (is_object($debug_object)) {$debug_object->debug_log(2, 'meta content-type tag found' . $fullvalue);} - - if (!empty($fullvalue)) - { - $success = preg_match('/charset=(.+)/', $fullvalue, $matches); - if ($success) - { - $charset = $matches[1]; - } - else - { - // If there is a meta tag, and they don't specify the character set, research says that it's typically ISO-8859-1 - if (is_object($debug_object)) {$debug_object->debug_log(2, 'meta content-type tag couldn\'t be parsed. using iso-8859 default.');} - $charset = 'ISO-8859-1'; - } - } - } - } - - // If we couldn't find a charset above, then lets try to detect one based on the text we got... - if (empty($charset)) - { - // Use this in case mb_detect_charset isn't installed/loaded on this machine. - $charset = false; - if (function_exists('mb_detect_encoding')) - { - // Have php try to detect the encoding from the text given to us. - $charset = mb_detect_encoding($this->root->plaintext . "ascii", $encoding_list = array( "UTF-8", "CP1252" ) ); - if (is_object($debug_object)) {$debug_object->debug_log(2, 'mb_detect found: ' . $charset);} - } - - // and if this doesn't work... then we need to just wrongheadedly assume it's UTF-8 so that we can move on - cause this will usually give us most of what we need... - if ($charset === false) - { - if (is_object($debug_object)) {$debug_object->debug_log(2, 'since mb_detect failed - using default of utf-8');} - $charset = 'UTF-8'; - } - } - - // Since CP1252 is a superset, if we get one of it's subsets, we want it instead. - if ((strtolower($charset) == strtolower('ISO-8859-1')) || (strtolower($charset) == strtolower('Latin1')) || (strtolower($charset) == strtolower('Latin-1'))) - { - if (is_object($debug_object)) {$debug_object->debug_log(2, 'replacing ' . $charset . ' with CP1252 as its a superset');} - $charset = 'CP1252'; - } - - if (is_object($debug_object)) {$debug_object->debug_log(1, 'EXIT - ' . $charset);} - - return $this->_charset = $charset; - } - - // read tag info - protected function read_tag() - { - if ($this->char!=='<') - { - $this->root->_[HDOM_INFO_END] = $this->cursor; - return false; - } - $begin_tag_pos = $this->pos; - $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next - - // end tag - if ($this->char==='/') - { - $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next - // This represents the change in the simple_html_dom trunk from revision 180 to 181. - // $this->skip($this->token_blank_t); - $this->skip($this->token_blank); - $tag = $this->copy_until_char('>'); - - // skip attributes in end tag - if (($pos = strpos($tag, ' '))!==false) - $tag = substr($tag, 0, $pos); - - $parent_lower = strtolower($this->parent->tag); - $tag_lower = strtolower($tag); - - if ($parent_lower!==$tag_lower) - { - if (isset($this->optional_closing_tags[$parent_lower]) && isset($this->block_tags[$tag_lower])) - { - $this->parent->_[HDOM_INFO_END] = 0; - $org_parent = $this->parent; - - while (($this->parent->parent) && strtolower($this->parent->tag)!==$tag_lower) - $this->parent = $this->parent->parent; - - if (strtolower($this->parent->tag)!==$tag_lower) { - $this->parent = $org_parent; // restore origonal parent - if ($this->parent->parent) $this->parent = $this->parent->parent; - $this->parent->_[HDOM_INFO_END] = $this->cursor; - return $this->as_text_node($tag); - } - } - else if (($this->parent->parent) && isset($this->block_tags[$tag_lower])) - { - $this->parent->_[HDOM_INFO_END] = 0; - $org_parent = $this->parent; - - while (($this->parent->parent) && strtolower($this->parent->tag)!==$tag_lower) - $this->parent = $this->parent->parent; - - if (strtolower($this->parent->tag)!==$tag_lower) - { - $this->parent = $org_parent; // restore origonal parent - $this->parent->_[HDOM_INFO_END] = $this->cursor; - return $this->as_text_node($tag); - } - } - else if (($this->parent->parent) && strtolower($this->parent->parent->tag)===$tag_lower) - { - $this->parent->_[HDOM_INFO_END] = 0; - $this->parent = $this->parent->parent; - } - else - return $this->as_text_node($tag); - } - - $this->parent->_[HDOM_INFO_END] = $this->cursor; - if ($this->parent->parent) $this->parent = $this->parent->parent; - - $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next - return true; - } - - $node = new simple_html_dom_node($this); - $node->_[HDOM_INFO_BEGIN] = $this->cursor; - ++$this->cursor; - $tag = $this->copy_until($this->token_slash); - $node->tag_start = $begin_tag_pos; - - // doctype, cdata & comments... - if (isset($tag[0]) && $tag[0]==='!') { - $node->_[HDOM_INFO_TEXT] = '<' . $tag . $this->copy_until_char('>'); - - if (isset($tag[2]) && $tag[1]==='-' && $tag[2]==='-') { - $node->nodetype = HDOM_TYPE_COMMENT; - $node->tag = 'comment'; - } else { - $node->nodetype = HDOM_TYPE_UNKNOWN; - $node->tag = 'unknown'; - } - if ($this->char==='>') $node->_[HDOM_INFO_TEXT].='>'; - $this->link_nodes($node, true); - $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next - return true; - } - - // text - if ($pos=strpos($tag, '<')!==false) { - $tag = '<' . substr($tag, 0, -1); - $node->_[HDOM_INFO_TEXT] = $tag; - $this->link_nodes($node, false); - $this->char = $this->doc[--$this->pos]; // prev - return true; - } - - if (!preg_match("/^[\w-:]+$/", $tag)) { - $node->_[HDOM_INFO_TEXT] = '<' . $tag . $this->copy_until('<>'); - if ($this->char==='<') { - $this->link_nodes($node, false); - return true; - } - - if ($this->char==='>') $node->_[HDOM_INFO_TEXT].='>'; - $this->link_nodes($node, false); - $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next - return true; - } - - // begin tag - $node->nodetype = HDOM_TYPE_ELEMENT; - $tag_lower = strtolower($tag); - $node->tag = ($this->lowercase) ? $tag_lower : $tag; - - // handle optional closing tags - if (isset($this->optional_closing_tags[$tag_lower]) ) - { - while (isset($this->optional_closing_tags[$tag_lower][strtolower($this->parent->tag)])) - { - $this->parent->_[HDOM_INFO_END] = 0; - $this->parent = $this->parent->parent; - } - $node->parent = $this->parent; - } - - $guard = 0; // prevent infinity loop - $space = array($this->copy_skip($this->token_blank), '', ''); - - // attributes - do - { - if ($this->char!==null && $space[0]==='') - { - break; - } - $name = $this->copy_until($this->token_equal); - if ($guard===$this->pos) - { - $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next - continue; - } - $guard = $this->pos; - - // handle endless '<' - if ($this->pos>=$this->size-1 && $this->char!=='>') { - $node->nodetype = HDOM_TYPE_TEXT; - $node->_[HDOM_INFO_END] = 0; - $node->_[HDOM_INFO_TEXT] = '<'.$tag . $space[0] . $name; - $node->tag = 'text'; - $this->link_nodes($node, false); - return true; - } - - // handle mismatch '<' - if ($this->doc[$this->pos-1]=='<') { - $node->nodetype = HDOM_TYPE_TEXT; - $node->tag = 'text'; - $node->attr = array(); - $node->_[HDOM_INFO_END] = 0; - $node->_[HDOM_INFO_TEXT] = substr($this->doc, $begin_tag_pos, $this->pos-$begin_tag_pos-1); - $this->pos -= 2; - $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next - $this->link_nodes($node, false); - return true; - } - - if ($name!=='/' && $name!=='') { - $space[1] = $this->copy_skip($this->token_blank); - $name = $this->restore_noise($name); - if ($this->lowercase) $name = strtolower($name); - if ($this->char==='=') { - $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next - $this->parse_attr($node, $name, $space); - } - else { - //no value attr: nowrap, checked selected... - $node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_NO; - $node->attr[$name] = true; - if ($this->char!='>') $this->char = $this->doc[--$this->pos]; // prev - } - $node->_[HDOM_INFO_SPACE][] = $space; - $space = array($this->copy_skip($this->token_blank), '', ''); - } - else - break; - } while ($this->char!=='>' && $this->char!=='/'); - - $this->link_nodes($node, true); - $node->_[HDOM_INFO_ENDSPACE] = $space[0]; - - // check self closing - if ($this->copy_until_char_escape('>')==='/') - { - $node->_[HDOM_INFO_ENDSPACE] .= '/'; - $node->_[HDOM_INFO_END] = 0; - } - else - { - // reset parent - if (!isset($this->self_closing_tags[strtolower($node->tag)])) $this->parent = $node; - } - $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next - - // If it's a BR tag, we need to set it's text to the default text. - // This way when we see it in plaintext, we can generate formatting that the user wants. - // since a br tag never has sub nodes, this works well. - if ($node->tag == "br") - { - $node->_[HDOM_INFO_INNER] = $this->default_br_text; - } - - return true; - } - - // parse attributes - protected function parse_attr($node, $name, &$space) - { - // Per sourceforge: http://sourceforge.net/tracker/?func=detail&aid=3061408&group_id=218559&atid=1044037 - // If the attribute is already defined inside a tag, only pay atetntion to the first one as opposed to the last one. - if (isset($node->attr[$name])) - { - return; - } - - $space[2] = $this->copy_skip($this->token_blank); - switch ($this->char) { - case '"': - $node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_DOUBLE; - $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next - $node->attr[$name] = $this->restore_noise($this->copy_until_char_escape('"')); - $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next - break; - case '\'': - $node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_SINGLE; - $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next - $node->attr[$name] = $this->restore_noise($this->copy_until_char_escape('\'')); - $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next - break; - default: - $node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_NO; - $node->attr[$name] = $this->restore_noise($this->copy_until($this->token_attr)); - } - // PaperG: Attributes should not have \r or \n in them, that counts as html whitespace. - $node->attr[$name] = str_replace("\r", "", $node->attr[$name]); - $node->attr[$name] = str_replace("\n", "", $node->attr[$name]); - // PaperG: If this is a "class" selector, lets get rid of the preceeding and trailing space since some people leave it in the multi class case. - if ($name == "class") { - $node->attr[$name] = trim($node->attr[$name]); - } - } - - // link node's parent - protected function link_nodes(&$node, $is_child) - { - $node->parent = $this->parent; - $this->parent->nodes[] = $node; - if ($is_child) - { - $this->parent->children[] = $node; - } - } - - // as a text node - protected function as_text_node($tag) - { - $node = new simple_html_dom_node($this); - ++$this->cursor; - $node->_[HDOM_INFO_TEXT] = '</' . $tag . '>'; - $this->link_nodes($node, false); - $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next - return true; - } - - protected function skip($chars) - { - $this->pos += strspn($this->doc, $chars, $this->pos); - $this->char = ($this->pos<$this->size) ? $this->doc[$this->pos] : null; // next - } - - protected function copy_skip($chars) - { - $pos = $this->pos; - $len = strspn($this->doc, $chars, $pos); - $this->pos += $len; - $this->char = ($this->pos<$this->size) ? $this->doc[$this->pos] : null; // next - if ($len===0) return ''; - return substr($this->doc, $pos, $len); - } - - protected function copy_until($chars) - { - $pos = $this->pos; - $len = strcspn($this->doc, $chars, $pos); - $this->pos += $len; - $this->char = ($this->pos<$this->size) ? $this->doc[$this->pos] : null; // next - return substr($this->doc, $pos, $len); - } - - protected function copy_until_char($char) - { - if ($this->char===null) return ''; - - if (($pos = strpos($this->doc, $char, $this->pos))===false) { - $ret = substr($this->doc, $this->pos, $this->size-$this->pos); - $this->char = null; - $this->pos = $this->size; - return $ret; - } - - if ($pos===$this->pos) return ''; - $pos_old = $this->pos; - $this->char = $this->doc[$pos]; - $this->pos = $pos; - return substr($this->doc, $pos_old, $pos-$pos_old); - } - - protected function copy_until_char_escape($char) - { - if ($this->char===null) return ''; - - $start = $this->pos; - while (1) - { - if (($pos = strpos($this->doc, $char, $start))===false) - { - $ret = substr($this->doc, $this->pos, $this->size-$this->pos); - $this->char = null; - $this->pos = $this->size; - return $ret; - } - - if ($pos===$this->pos) return ''; - - if ($this->doc[$pos-1]==='\\') { - $start = $pos+1; - continue; - } - - $pos_old = $this->pos; - $this->char = $this->doc[$pos]; - $this->pos = $pos; - return substr($this->doc, $pos_old, $pos-$pos_old); - } - } - - // remove noise from html content - // save the noise in the $this->noise array. - protected function remove_noise($pattern, $remove_tag=false) - { - global $debug_object; - if (is_object($debug_object)) { $debug_object->debug_log_entry(1); } - - $count = preg_match_all($pattern, $this->doc, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE); - - for ($i=$count-1; $i>-1; --$i) - { - $key = '___noise___'.sprintf('% 5d', count($this->noise)+1000); - if (is_object($debug_object)) { $debug_object->debug_log(2, 'key is: ' . $key); } - $idx = ($remove_tag) ? 0 : 1; - $this->noise[$key] = $matches[$i][$idx][0]; - $this->doc = substr_replace($this->doc, $key, $matches[$i][$idx][1], strlen($matches[$i][$idx][0])); - } - - // reset the length of content - $this->size = strlen($this->doc); - if ($this->size>0) - { - $this->char = $this->doc[0]; - } - } - - // restore noise to html content - function restore_noise($text) - { - global $debug_object; - if (is_object($debug_object)) { $debug_object->debug_log_entry(1); } - - while (($pos=strpos($text, '___noise___'))!==false) - { - // Sometimes there is a broken piece of markup, and we don't GET the pos+11 etc... token which indicates a problem outside of us... - if (strlen($text) > $pos+15) - { - $key = '___noise___'.$text[$pos+11].$text[$pos+12].$text[$pos+13].$text[$pos+14].$text[$pos+15]; - if (is_object($debug_object)) { $debug_object->debug_log(2, 'located key of: ' . $key); } - - if (isset($this->noise[$key])) - { - $text = substr($text, 0, $pos).$this->noise[$key].substr($text, $pos+16); - } - else - { - // do this to prevent an infinite loop. - $text = substr($text, 0, $pos).'UNDEFINED NOISE FOR KEY: '.$key . substr($text, $pos+16); - } - } - else - { - // There is no valid key being given back to us... We must get rid of the ___noise___ or we will have a problem. - $text = substr($text, 0, $pos).'NO NUMERIC NOISE KEY' . substr($text, $pos+11); - } - } - return $text; - } - - // Sometimes we NEED one of the noise elements. - function search_noise($text) - { - global $debug_object; - if (is_object($debug_object)) { $debug_object->debug_log_entry(1); } - - foreach($this->noise as $noiseElement) - { - if (strpos($noiseElement, $text)!==false) - { - return $noiseElement; - } - } - } - function __toString() - { - return $this->root->innertext(); - } - - function __get($name) - { - switch ($name) - { - case 'outertext': - return $this->root->innertext(); - case 'innertext': - return $this->root->innertext(); - case 'plaintext': - return $this->root->text(); - case 'charset': - return $this->_charset; - case 'target_charset': - return $this->_target_charset; - } - } - - // camel naming conventions - function childNodes($idx=-1) {return $this->root->childNodes($idx);} - function firstChild() {return $this->root->first_child();} - function lastChild() {return $this->root->last_child();} - function createElement($name, $value=null) {return @str_get_html("<$name>$value</$name>")->first_child();} - function createTextNode($value) {return @end(str_get_html($value)->nodes);} - function getElementById($id) {return $this->find("#$id", 0);} - function getElementsById($id, $idx=null) {return $this->find("#$id", $idx);} - function getElementByTagName($name) {return $this->find($name, 0);} - function getElementsByTagName($name, $idx=-1) {return $this->find($name, $idx);} - function loadFile() {$args = func_get_args();$this->load_file($args);} -} - +<?php +/** + * Website: http://sourceforge.net/projects/simplehtmldom/ + * Additional projects that may be used: http://sourceforge.net/projects/debugobject/ + * Acknowledge: Jose Solorzano (https://sourceforge.net/projects/php-html/) + * Contributions by: + * Yousuke Kumakura (Attribute filters) + * Vadim Voituk (Negative indexes supports of "find" method) + * Antcs (Constructor with automatically load contents either text or file/url) + * + * all affected sections have comments starting with "PaperG" + * + * Paperg - Added case insensitive testing of the value of the selector. + * Paperg - Added tag_start for the starting index of tags - NOTE: This works but not accurately. + * This tag_start gets counted AFTER \r\n have been crushed out, and after the remove_noice calls so it will not reflect the REAL position of the tag in the source, + * it will almost always be smaller by some amount. + * We use this to determine how far into the file the tag in question is. This "percentage will never be accurate as the $dom->size is the "real" number of bytes the dom was created from. + * but for most purposes, it's a really good estimation. + * Paperg - Added the forceTagsClosed to the dom constructor. Forcing tags closed is great for malformed html, but it CAN lead to parsing errors. + * Allow the user to tell us how much they trust the html. + * Paperg add the text and plaintext to the selectors for the find syntax. plaintext implies text in the innertext of a node. text implies that the tag is a text node. + * This allows for us to find tags based on the text they contain. + * Create find_ancestor_tag to see if a tag is - at any level - inside of another specific tag. + * Paperg: added parse_charset so that we know about the character set of the source document. + * NOTE: If the user's system has a routine called get_last_retrieve_url_contents_content_type availalbe, we will assume it's returning the content-type header from the + * last transfer or curl_exec, and we will parse that and use it in preference to any other method of charset detection. + * + * Found infinite loop in the case of broken html in restore_noise. Rewrote to protect from that. + * PaperG (John Schlick) Added get_display_size for "IMG" tags. + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @author S.C. Chen <me578022@gmail.com> + * @author John Schlick + * @author Rus Carroll + * @version 1.5 ($Rev: 208 $) + * @package PlaceLocalInclude + * @subpackage simple_html_dom + */ + +/** + * All of the Defines for the classes below. + * @author S.C. Chen <me578022@gmail.com> + */ +define('HDOM_TYPE_ELEMENT', 1); +define('HDOM_TYPE_COMMENT', 2); +define('HDOM_TYPE_TEXT', 3); +define('HDOM_TYPE_ENDTAG', 4); +define('HDOM_TYPE_ROOT', 5); +define('HDOM_TYPE_UNKNOWN', 6); +define('HDOM_QUOTE_DOUBLE', 0); +define('HDOM_QUOTE_SINGLE', 1); +define('HDOM_QUOTE_NO', 3); +define('HDOM_INFO_BEGIN', 0); +define('HDOM_INFO_END', 1); +define('HDOM_INFO_QUOTE', 2); +define('HDOM_INFO_SPACE', 3); +define('HDOM_INFO_TEXT', 4); +define('HDOM_INFO_INNER', 5); +define('HDOM_INFO_OUTER', 6); +define('HDOM_INFO_ENDSPACE',7); +define('DEFAULT_TARGET_CHARSET', 'UTF-8'); +define('DEFAULT_BR_TEXT', "\r\n"); +define('DEFAULT_SPAN_TEXT', " "); +define('MAX_FILE_SIZE', 600000); +// helper functions +// ----------------------------------------------------------------------------- +// get html dom from file +// $maxlen is defined in the code as PHP_STREAM_COPY_ALL which is defined as -1. +function file_get_html($url, $use_include_path = false, $context=null, $offset = -1, $maxLen=-1, $lowercase = true, $forceTagsClosed=true, $target_charset = DEFAULT_TARGET_CHARSET, $stripRN=true, $defaultBRText=DEFAULT_BR_TEXT, $defaultSpanText=DEFAULT_SPAN_TEXT) +{ + // We DO force the tags to be terminated. + $dom = new simple_html_dom(null, $lowercase, $forceTagsClosed, $target_charset, $stripRN, $defaultBRText, $defaultSpanText); + // For sourceforge users: uncomment the next line and comment the retreive_url_contents line 2 lines down if it is not already done. + $contents = file_get_contents($url, $use_include_path, $context, $offset); + // Paperg - use our own mechanism for getting the contents as we want to control the timeout. + //$contents = retrieve_url_contents($url); + if (empty($contents) || strlen($contents) > MAX_FILE_SIZE) + { + return false; + } + // The second parameter can force the selectors to all be lowercase. + $dom->load($contents, $lowercase, $stripRN); + return $dom; +} + +// get html dom from string +function str_get_html($str, $lowercase=true, $forceTagsClosed=true, $target_charset = DEFAULT_TARGET_CHARSET, $stripRN=true, $defaultBRText=DEFAULT_BR_TEXT, $defaultSpanText=DEFAULT_SPAN_TEXT) +{ + $dom = new simple_html_dom(null, $lowercase, $forceTagsClosed, $target_charset, $stripRN, $defaultBRText, $defaultSpanText); + if (empty($str) || strlen($str) > MAX_FILE_SIZE) + { + $dom->clear(); + return false; + } + $dom->load($str, $lowercase, $stripRN); + return $dom; +} + +// dump html dom tree +function dump_html_tree($node, $show_attr=true, $deep=0) +{ + $node->dump($node); +} + + +/** + * simple html dom node + * PaperG - added ability for "find" routine to lowercase the value of the selector. + * PaperG - added $tag_start to track the start position of the tag in the total byte index + * + * @package PlaceLocalInclude + */ +class simple_html_dom_node +{ + public $nodetype = HDOM_TYPE_TEXT; + public $tag = 'text'; + public $attr = array(); + public $children = array(); + public $nodes = array(); + public $parent = null; + // The "info" array - see HDOM_INFO_... for what each element contains. + public $_ = array(); + public $tag_start = 0; + private $dom = null; + + function __construct($dom) + { + $this->dom = $dom; + $dom->nodes[] = $this; + } + + function __destruct() + { + $this->clear(); + } + + function __toString() + { + return $this->outertext(); + } + + // clean up memory due to php5 circular references memory leak... + function clear() + { + $this->dom = null; + $this->nodes = null; + $this->parent = null; + $this->children = null; + } + + // dump node's tree + function dump($show_attr=true, $deep=0) + { + $lead = str_repeat(' ', $deep); + + echo $lead.$this->tag; + if ($show_attr && count($this->attr)>0) + { + echo '('; + foreach ($this->attr as $k=>$v) + echo "[$k]=>\"".$this->$k.'", '; + echo ')'; + } + echo "\n"; + + if ($this->nodes) + { + foreach ($this->nodes as $c) + { + $c->dump($show_attr, $deep+1); + } + } + } + + + // Debugging function to dump a single dom node with a bunch of information about it. + function dump_node($echo=true) + { + + $string = $this->tag; + if (count($this->attr)>0) + { + $string .= '('; + foreach ($this->attr as $k=>$v) + { + $string .= "[$k]=>\"".$this->$k.'", '; + } + $string .= ')'; + } + if (count($this->_)>0) + { + $string .= ' $_ ('; + foreach ($this->_ as $k=>$v) + { + if (is_array($v)) + { + $string .= "[$k]=>("; + foreach ($v as $k2=>$v2) + { + $string .= "[$k2]=>\"".$v2.'", '; + } + $string .= ")"; + } else { + $string .= "[$k]=>\"".$v.'", '; + } + } + $string .= ")"; + } + + if (isset($this->text)) + { + $string .= " text: (" . $this->text . ")"; + } + + $string .= " HDOM_INNER_INFO: '"; + if (isset($node->_[HDOM_INFO_INNER])) + { + $string .= $node->_[HDOM_INFO_INNER] . "'"; + } + else + { + $string .= ' NULL '; + } + + $string .= " children: " . count($this->children); + $string .= " nodes: " . count($this->nodes); + $string .= " tag_start: " . $this->tag_start; + $string .= "\n"; + + if ($echo) + { + echo $string; + return; + } + else + { + return $string; + } + } + + // returns the parent of node + // If a node is passed in, it will reset the parent of the current node to that one. + function parent($parent=null) + { + // I am SURE that this doesn't work properly. + // It fails to unset the current node from it's current parents nodes or children list first. + if ($parent !== null) + { + $this->parent = $parent; + $this->parent->nodes[] = $this; + $this->parent->children[] = $this; + } + + return $this->parent; + } + + // verify that node has children + function has_child() + { + return !empty($this->children); + } + + // returns children of node + function children($idx=-1) + { + if ($idx===-1) + { + return $this->children; + } + if (isset($this->children[$idx])) + { + return $this->children[$idx]; + } + return null; + } + + // returns the first child of node + function first_child() + { + if (count($this->children)>0) + { + return $this->children[0]; + } + return null; + } + + // returns the last child of node + function last_child() + { + if (($count=count($this->children))>0) + { + return $this->children[$count-1]; + } + return null; + } + + // returns the next sibling of node + function next_sibling() + { + if ($this->parent===null) + { + return null; + } + + $idx = 0; + $count = count($this->parent->children); + while ($idx<$count && $this!==$this->parent->children[$idx]) + { + ++$idx; + } + if (++$idx>=$count) + { + return null; + } + return $this->parent->children[$idx]; + } + + // returns the previous sibling of node + function prev_sibling() + { + if ($this->parent===null) return null; + $idx = 0; + $count = count($this->parent->children); + while ($idx<$count && $this!==$this->parent->children[$idx]) + ++$idx; + if (--$idx<0) return null; + return $this->parent->children[$idx]; + } + + // function to locate a specific ancestor tag in the path to the root. + function find_ancestor_tag($tag) + { + global $debug_object; + if (is_object($debug_object)) { $debug_object->debug_log_entry(1); } + + // Start by including ourselves in the comparison. + $returnDom = $this; + + while (!is_null($returnDom)) + { + if (is_object($debug_object)) { $debug_object->debug_log(2, "Current tag is: " . $returnDom->tag); } + + if ($returnDom->tag == $tag) + { + break; + } + $returnDom = $returnDom->parent; + } + return $returnDom; + } + + // get dom node's inner html + function innertext() + { + if (isset($this->_[HDOM_INFO_INNER])) return $this->_[HDOM_INFO_INNER]; + if (isset($this->_[HDOM_INFO_TEXT])) return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); + + $ret = ''; + foreach ($this->nodes as $n) + $ret .= $n->outertext(); + return $ret; + } + + // get dom node's outer text (with tag) + function outertext() + { + global $debug_object; + if (is_object($debug_object)) + { + $text = ''; + if ($this->tag == 'text') + { + if (!empty($this->text)) + { + $text = " with text: " . $this->text; + } + } + $debug_object->debug_log(1, 'Innertext of tag: ' . $this->tag . $text); + } + + if ($this->tag==='root') return $this->innertext(); + + // trigger callback + if ($this->dom && $this->dom->callback!==null) + { + call_user_func_array($this->dom->callback, array($this)); + } + + if (isset($this->_[HDOM_INFO_OUTER])) return $this->_[HDOM_INFO_OUTER]; + if (isset($this->_[HDOM_INFO_TEXT])) return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); + + // render begin tag + if ($this->dom && $this->dom->nodes[$this->_[HDOM_INFO_BEGIN]]) + { + $ret = $this->dom->nodes[$this->_[HDOM_INFO_BEGIN]]->makeup(); + } else { + $ret = ""; + } + + // render inner text + if (isset($this->_[HDOM_INFO_INNER])) + { + // If it's a br tag... don't return the HDOM_INNER_INFO that we may or may not have added. + if ($this->tag != "br") + { + $ret .= $this->_[HDOM_INFO_INNER]; + } + } else { + if ($this->nodes) + { + foreach ($this->nodes as $n) + { + $ret .= $this->convert_text($n->outertext()); + } + } + } + + // render end tag + if (isset($this->_[HDOM_INFO_END]) && $this->_[HDOM_INFO_END]!=0) + $ret .= '</'.$this->tag.'>'; + return $ret; + } + + // get dom node's plain text + function text() + { + if (isset($this->_[HDOM_INFO_INNER])) return $this->_[HDOM_INFO_INNER]; + switch ($this->nodetype) + { + case HDOM_TYPE_TEXT: return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); + case HDOM_TYPE_COMMENT: return ''; + case HDOM_TYPE_UNKNOWN: return ''; + } + if (strcasecmp($this->tag, 'script')===0) return ''; + if (strcasecmp($this->tag, 'style')===0) return ''; + + $ret = ''; + // In rare cases, (always node type 1 or HDOM_TYPE_ELEMENT - observed for some span tags, and some p tags) $this->nodes is set to NULL. + // NOTE: This indicates that there is a problem where it's set to NULL without a clear happening. + // WHY is this happening? + if (!is_null($this->nodes)) + { + foreach ($this->nodes as $n) + { + $ret .= $this->convert_text($n->text()); + } + + // If this node is a span... add a space at the end of it so multiple spans don't run into each other. This is plaintext after all. + if ($this->tag == "span") + { + $ret .= $this->dom->default_span_text; + } + + + } + return $ret; + } + + function xmltext() + { + $ret = $this->innertext(); + $ret = str_ireplace('<![CDATA[', '', $ret); + $ret = str_replace(']]>', '', $ret); + return $ret; + } + + // build node's text with tag + function makeup() + { + // text, comment, unknown + if (isset($this->_[HDOM_INFO_TEXT])) return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); + + $ret = '<'.$this->tag; + $i = -1; + + foreach ($this->attr as $key=>$val) + { + ++$i; + + // skip removed attribute + if ($val===null || $val===false) + continue; + + $ret .= $this->_[HDOM_INFO_SPACE][$i][0]; + //no value attr: nowrap, checked selected... + if ($val===true) + $ret .= $key; + else { + switch ($this->_[HDOM_INFO_QUOTE][$i]) + { + case HDOM_QUOTE_DOUBLE: $quote = '"'; break; + case HDOM_QUOTE_SINGLE: $quote = '\''; break; + default: $quote = ''; + } + $ret .= $key.$this->_[HDOM_INFO_SPACE][$i][1].'='.$this->_[HDOM_INFO_SPACE][$i][2].$quote.$val.$quote; + } + } + $ret = $this->dom->restore_noise($ret); + return $ret . $this->_[HDOM_INFO_ENDSPACE] . '>'; + } + + // find elements by css selector + //PaperG - added ability for find to lowercase the value of the selector. + function find($selector, $idx=null, $lowercase=false) + { + $selectors = $this->parse_selector($selector); + if (($count=count($selectors))===0) return array(); + $found_keys = array(); + + // find each selector + for ($c=0; $c<$count; ++$c) + { + // The change on the below line was documented on the sourceforge code tracker id 2788009 + // used to be: if (($levle=count($selectors[0]))===0) return array(); + if (($levle=count($selectors[$c]))===0) return array(); + if (!isset($this->_[HDOM_INFO_BEGIN])) return array(); + + $head = array($this->_[HDOM_INFO_BEGIN]=>1); + + // handle descendant selectors, no recursive! + for ($l=0; $l<$levle; ++$l) + { + $ret = array(); + foreach ($head as $k=>$v) + { + $n = ($k===-1) ? $this->dom->root : $this->dom->nodes[$k]; + //PaperG - Pass this optional parameter on to the seek function. + $n->seek($selectors[$c][$l], $ret, $lowercase); + } + $head = $ret; + } + + foreach ($head as $k=>$v) + { + if (!isset($found_keys[$k])) + { + $found_keys[$k] = 1; + } + } + } + + // sort keys + ksort($found_keys); + + $found = array(); + foreach ($found_keys as $k=>$v) + $found[] = $this->dom->nodes[$k]; + + // return nth-element or array + if (is_null($idx)) return $found; + else if ($idx<0) $idx = count($found) + $idx; + return (isset($found[$idx])) ? $found[$idx] : null; + } + + // seek for given conditions + // PaperG - added parameter to allow for case insensitive testing of the value of a selector. + protected function seek($selector, &$ret, $lowercase=false) + { + global $debug_object; + if (is_object($debug_object)) { $debug_object->debug_log_entry(1); } + + list($tag, $key, $val, $exp, $no_key) = $selector; + + // xpath index + if ($tag && $key && is_numeric($key)) + { + $count = 0; + foreach ($this->children as $c) + { + if ($tag==='*' || $tag===$c->tag) { + if (++$count==$key) { + $ret[$c->_[HDOM_INFO_BEGIN]] = 1; + return; + } + } + } + return; + } + + $end = (!empty($this->_[HDOM_INFO_END])) ? $this->_[HDOM_INFO_END] : 0; + if ($end==0) { + $parent = $this->parent; + while (!isset($parent->_[HDOM_INFO_END]) && $parent!==null) { + $end -= 1; + $parent = $parent->parent; + } + $end += $parent->_[HDOM_INFO_END]; + } + + for ($i=$this->_[HDOM_INFO_BEGIN]+1; $i<$end; ++$i) { + $node = $this->dom->nodes[$i]; + + $pass = true; + + if ($tag==='*' && !$key) { + if (in_array($node, $this->children, true)) + $ret[$i] = 1; + continue; + } + + // compare tag + if ($tag && $tag!=$node->tag && $tag!=='*') {$pass=false;} + // compare key + if ($pass && $key) { + if ($no_key) { + if (isset($node->attr[$key])) $pass=false; + } else { + if (($key != "plaintext") && !isset($node->attr[$key])) $pass=false; + } + } + // compare value + if ($pass && $key && $val && $val!=='*') { + // If they have told us that this is a "plaintext" search then we want the plaintext of the node - right? + if ($key == "plaintext") { + // $node->plaintext actually returns $node->text(); + $nodeKeyValue = $node->text(); + } else { + // this is a normal search, we want the value of that attribute of the tag. + $nodeKeyValue = $node->attr[$key]; + } + if (is_object($debug_object)) {$debug_object->debug_log(2, "testing node: " . $node->tag . " for attribute: " . $key . $exp . $val . " where nodes value is: " . $nodeKeyValue);} + + //PaperG - If lowercase is set, do a case insensitive test of the value of the selector. + if ($lowercase) { + $check = $this->match($exp, strtolower($val), strtolower($nodeKeyValue)); + } else { + $check = $this->match($exp, $val, $nodeKeyValue); + } + if (is_object($debug_object)) {$debug_object->debug_log(2, "after match: " . ($check ? "true" : "false"));} + + // handle multiple class + if (!$check && strcasecmp($key, 'class')===0) { + foreach (explode(' ',$node->attr[$key]) as $k) { + // Without this, there were cases where leading, trailing, or double spaces lead to our comparing blanks - bad form. + if (!empty($k)) { + if ($lowercase) { + $check = $this->match($exp, strtolower($val), strtolower($k)); + } else { + $check = $this->match($exp, $val, $k); + } + if ($check) break; + } + } + } + if (!$check) $pass = false; + } + if ($pass) $ret[$i] = 1; + unset($node); + } + // It's passed by reference so this is actually what this function returns. + if (is_object($debug_object)) {$debug_object->debug_log(1, "EXIT - ret: ", $ret);} + } + + protected function match($exp, $pattern, $value) { + global $debug_object; + if (is_object($debug_object)) {$debug_object->debug_log_entry(1);} + + switch ($exp) { + case '=': + return ($value===$pattern); + case '!=': + return ($value!==$pattern); + case '^=': + return preg_match("/^".preg_quote($pattern,'/')."/", $value); + case '$=': + return preg_match("/".preg_quote($pattern,'/')."$/", $value); + case '*=': + if ($pattern[0]=='/') { + return preg_match($pattern, $value); + } + return preg_match("/".$pattern."/i", $value); + } + return false; + } + + protected function parse_selector($selector_string) { + global $debug_object; + if (is_object($debug_object)) {$debug_object->debug_log_entry(1);} + + // pattern of CSS selectors, modified from mootools + // Paperg: Add the colon to the attrbute, so that it properly finds <tag attr:ibute="something" > like google does. + // Note: if you try to look at this attribute, yo MUST use getAttribute since $dom->x:y will fail the php syntax check. +// Notice the \[ starting the attbute? and the @? following? This implies that an attribute can begin with an @ sign that is not captured. +// This implies that an html attribute specifier may start with an @ sign that is NOT captured by the expression. +// farther study is required to determine of this should be documented or removed. +// $pattern = "/([\w-:\*]*)(?:\#([\w-]+)|\.([\w-]+))?(?:\[@?(!?[\w-]+)(?:([!*^$]?=)[\"']?(.*?)[\"']?)?\])?([\/, ]+)/is"; + $pattern = "/([\w-:\*]*)(?:\#([\w-]+)|\.([\w-]+))?(?:\[@?(!?[\w-:]+)(?:([!*^$]?=)[\"']?(.*?)[\"']?)?\])?([\/, ]+)/is"; + preg_match_all($pattern, trim($selector_string).' ', $matches, PREG_SET_ORDER); + if (is_object($debug_object)) {$debug_object->debug_log(2, "Matches Array: ", $matches);} + + $selectors = array(); + $result = array(); + //print_r($matches); + + foreach ($matches as $m) { + $m[0] = trim($m[0]); + if ($m[0]==='' || $m[0]==='/' || $m[0]==='//') continue; + // for browser generated xpath + if ($m[1]==='tbody') continue; + + list($tag, $key, $val, $exp, $no_key) = array($m[1], null, null, '=', false); + if (!empty($m[2])) {$key='id'; $val=$m[2];} + if (!empty($m[3])) {$key='class'; $val=$m[3];} + if (!empty($m[4])) {$key=$m[4];} + if (!empty($m[5])) {$exp=$m[5];} + if (!empty($m[6])) {$val=$m[6];} + + // convert to lowercase + if ($this->dom->lowercase) {$tag=strtolower($tag); $key=strtolower($key);} + //elements that do NOT have the specified attribute + if (isset($key[0]) && $key[0]==='!') {$key=substr($key, 1); $no_key=true;} + + $result[] = array($tag, $key, $val, $exp, $no_key); + if (trim($m[7])===',') { + $selectors[] = $result; + $result = array(); + } + } + if (count($result)>0) + $selectors[] = $result; + return $selectors; + } + + function __get($name) + { + if (isset($this->attr[$name])) + { + return $this->convert_text($this->attr[$name]); + } + switch ($name) + { + case 'outertext': return $this->outertext(); + case 'innertext': return $this->innertext(); + case 'plaintext': return $this->text(); + case 'xmltext': return $this->xmltext(); + default: return array_key_exists($name, $this->attr); + } + } + + function __set($name, $value) + { + global $debug_object; + if (is_object($debug_object)) {$debug_object->debug_log_entry(1);} + + switch ($name) + { + case 'outertext': return $this->_[HDOM_INFO_OUTER] = $value; + case 'innertext': + if (isset($this->_[HDOM_INFO_TEXT])) return $this->_[HDOM_INFO_TEXT] = $value; + return $this->_[HDOM_INFO_INNER] = $value; + } + if (!isset($this->attr[$name])) + { + $this->_[HDOM_INFO_SPACE][] = array(' ', '', ''); + $this->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_DOUBLE; + } + $this->attr[$name] = $value; + } + + function __isset($name) + { + switch ($name) + { + case 'outertext': return true; + case 'innertext': return true; + case 'plaintext': return true; + } + //no value attr: nowrap, checked selected... + return (array_key_exists($name, $this->attr)) ? true : isset($this->attr[$name]); + } + + function __unset($name) { + if (isset($this->attr[$name])) + unset($this->attr[$name]); + } + + // PaperG - Function to convert the text from one character set to another if the two sets are not the same. + function convert_text($text) + { + global $debug_object; + if (is_object($debug_object)) {$debug_object->debug_log_entry(1);} + + $converted_text = $text; + + $sourceCharset = ""; + $targetCharset = ""; + + if ($this->dom) + { + $sourceCharset = strtoupper($this->dom->_charset); + $targetCharset = strtoupper($this->dom->_target_charset); + } + if (is_object($debug_object)) {$debug_object->debug_log(3, "source charset: " . $sourceCharset . " target charaset: " . $targetCharset);} + + if (!empty($sourceCharset) && !empty($targetCharset) && (strcasecmp($sourceCharset, $targetCharset) != 0)) + { + // Check if the reported encoding could have been incorrect and the text is actually already UTF-8 + if ((strcasecmp($targetCharset, 'UTF-8') == 0) && ($this->is_utf8($text))) + { + $converted_text = $text; + } + else + { + $converted_text = iconv($sourceCharset, $targetCharset, $text); + } + } + + // Lets make sure that we don't have that silly BOM issue with any of the utf-8 text we output. + if ($targetCharset == 'UTF-8') + { + if (substr($converted_text, 0, 3) == "\xef\xbb\xbf") + { + $converted_text = substr($converted_text, 3); + } + if (substr($converted_text, -3) == "\xef\xbb\xbf") + { + $converted_text = substr($converted_text, 0, -3); + } + } + + return $converted_text; + } + + /** + * Returns true if $string is valid UTF-8 and false otherwise. + * + * @param mixed $str String to be tested + * @return boolean + */ + static function is_utf8($str) + { + $c=0; $b=0; + $bits=0; + $len=strlen($str); + for($i=0; $i<$len; $i++) + { + $c=ord($str[$i]); + if($c > 128) + { + if(($c >= 254)) return false; + elseif($c >= 252) $bits=6; + elseif($c >= 248) $bits=5; + elseif($c >= 240) $bits=4; + elseif($c >= 224) $bits=3; + elseif($c >= 192) $bits=2; + else return false; + if(($i+$bits) > $len) return false; + while($bits > 1) + { + $i++; + $b=ord($str[$i]); + if($b < 128 || $b > 191) return false; + $bits--; + } + } + } + return true; + } + /* + function is_utf8($string) + { + //this is buggy + return (utf8_encode(utf8_decode($string)) == $string); + } + */ + + /** + * Function to try a few tricks to determine the displayed size of an img on the page. + * NOTE: This will ONLY work on an IMG tag. Returns FALSE on all other tag types. + * + * @author John Schlick + * @version April 19 2012 + * @return array an array containing the 'height' and 'width' of the image on the page or -1 if we can't figure it out. + */ + function get_display_size() + { + global $debug_object; + + $width = -1; + $height = -1; + + if ($this->tag !== 'img') + { + return false; + } + + // See if there is aheight or width attribute in the tag itself. + if (isset($this->attr['width'])) + { + $width = $this->attr['width']; + } + + if (isset($this->attr['height'])) + { + $height = $this->attr['height']; + } + + // Now look for an inline style. + if (isset($this->attr['style'])) + { + // Thanks to user gnarf from stackoverflow for this regular expression. + $attributes = array(); + preg_match_all("/([\w-]+)\s*:\s*([^;]+)\s*;?/", $this->attr['style'], $matches, PREG_SET_ORDER); + foreach ($matches as $match) { + $attributes[$match[1]] = $match[2]; + } + + // If there is a width in the style attributes: + if (isset($attributes['width']) && $width == -1) + { + // check that the last two characters are px (pixels) + if (strtolower(substr($attributes['width'], -2)) == 'px') + { + $proposed_width = substr($attributes['width'], 0, -2); + // Now make sure that it's an integer and not something stupid. + if (filter_var($proposed_width, FILTER_VALIDATE_INT)) + { + $width = $proposed_width; + } + } + } + + // If there is a width in the style attributes: + if (isset($attributes['height']) && $height == -1) + { + // check that the last two characters are px (pixels) + if (strtolower(substr($attributes['height'], -2)) == 'px') + { + $proposed_height = substr($attributes['height'], 0, -2); + // Now make sure that it's an integer and not something stupid. + if (filter_var($proposed_height, FILTER_VALIDATE_INT)) + { + $height = $proposed_height; + } + } + } + + } + + // Future enhancement: + // Look in the tag to see if there is a class or id specified that has a height or width attribute to it. + + // Far future enhancement + // Look at all the parent tags of this image to see if they specify a class or id that has an img selector that specifies a height or width + // Note that in this case, the class or id will have the img subselector for it to apply to the image. + + // ridiculously far future development + // If the class or id is specified in a SEPARATE css file thats not on the page, go get it and do what we were just doing for the ones on the page. + + $result = array('height' => $height, + 'width' => $width); + return $result; + } + + // camel naming conventions + function getAllAttributes() {return $this->attr;} + function getAttribute($name) {return $this->__get($name);} + function setAttribute($name, $value) {$this->__set($name, $value);} + function hasAttribute($name) {return $this->__isset($name);} + function removeAttribute($name) {$this->__set($name, null);} + function getElementById($id) {return $this->find("#$id", 0);} + function getElementsById($id, $idx=null) {return $this->find("#$id", $idx);} + function getElementByTagName($name) {return $this->find($name, 0);} + function getElementsByTagName($name, $idx=null) {return $this->find($name, $idx);} + function parentNode() {return $this->parent();} + function childNodes($idx=-1) {return $this->children($idx);} + function firstChild() {return $this->first_child();} + function lastChild() {return $this->last_child();} + function nextSibling() {return $this->next_sibling();} + function previousSibling() {return $this->prev_sibling();} + function hasChildNodes() {return $this->has_child();} + function nodeName() {return $this->tag;} + function appendChild($node) {$node->parent($this); return $node;} + +} + +/** + * simple html dom parser + * Paperg - in the find routine: allow us to specify that we want case insensitive testing of the value of the selector. + * Paperg - change $size from protected to public so we can easily access it + * Paperg - added ForceTagsClosed in the constructor which tells us whether we trust the html or not. Default is to NOT trust it. + * + * @package PlaceLocalInclude + */ +class simple_html_dom +{ + public $root = null; + public $nodes = array(); + public $callback = null; + public $lowercase = false; + // Used to keep track of how large the text was when we started. + public $original_size; + public $size; + protected $pos; + protected $doc; + protected $char; + protected $cursor; + protected $parent; + protected $noise = array(); + protected $token_blank = " \t\r\n"; + protected $token_equal = ' =/>'; + protected $token_slash = " />\r\n\t"; + protected $token_attr = ' >'; + // Note that this is referenced by a child node, and so it needs to be public for that node to see this information. + public $_charset = ''; + public $_target_charset = ''; + protected $default_br_text = ""; + public $default_span_text = ""; + + // use isset instead of in_array, performance boost about 30%... + protected $self_closing_tags = array('img'=>1, 'br'=>1, 'input'=>1, 'meta'=>1, 'link'=>1, 'hr'=>1, 'base'=>1, 'embed'=>1, 'spacer'=>1); + protected $block_tags = array('root'=>1, 'body'=>1, 'form'=>1, 'div'=>1, 'span'=>1, 'table'=>1); + // Known sourceforge issue #2977341 + // B tags that are not closed cause us to return everything to the end of the document. + protected $optional_closing_tags = array( + 'tr'=>array('tr'=>1, 'td'=>1, 'th'=>1), + 'th'=>array('th'=>1), + 'td'=>array('td'=>1), + 'li'=>array('li'=>1), + 'dt'=>array('dt'=>1, 'dd'=>1), + 'dd'=>array('dd'=>1, 'dt'=>1), + 'dl'=>array('dd'=>1, 'dt'=>1), + 'p'=>array('p'=>1), + 'nobr'=>array('nobr'=>1), + 'b'=>array('b'=>1), + 'option'=>array('option'=>1), + ); + + function __construct($str=null, $lowercase=true, $forceTagsClosed=true, $target_charset=DEFAULT_TARGET_CHARSET, $stripRN=true, $defaultBRText=DEFAULT_BR_TEXT, $defaultSpanText=DEFAULT_SPAN_TEXT) + { + if ($str) + { + if (preg_match("/^http:\/\//i",$str) || is_file($str)) + { + $this->load_file($str); + } + else + { + $this->load($str, $lowercase, $stripRN, $defaultBRText, $defaultSpanText); + } + } + // Forcing tags to be closed implies that we don't trust the html, but it can lead to parsing errors if we SHOULD trust the html. + if (!$forceTagsClosed) { + $this->optional_closing_array=array(); + } + $this->_target_charset = $target_charset; + } + + function __destruct() + { + $this->clear(); + } + + // load html from string + function load($str, $lowercase=true, $stripRN=true, $defaultBRText=DEFAULT_BR_TEXT, $defaultSpanText=DEFAULT_SPAN_TEXT) + { + global $debug_object; + + // prepare + $this->prepare($str, $lowercase, $stripRN, $defaultBRText, $defaultSpanText); + // strip out cdata + $this->remove_noise("'<!\[CDATA\[(.*?)\]\]>'is", true); + // strip out comments + $this->remove_noise("'<!--(.*?)-->'is"); + // Per sourceforge http://sourceforge.net/tracker/?func=detail&aid=2949097&group_id=218559&atid=1044037 + // Script tags removal now preceeds style tag removal. + // strip out <script> tags + $this->remove_noise("'<\s*script[^>]*[^/]>(.*?)<\s*/\s*script\s*>'is"); + $this->remove_noise("'<\s*script\s*>(.*?)<\s*/\s*script\s*>'is"); + // strip out <style> tags + $this->remove_noise("'<\s*style[^>]*[^/]>(.*?)<\s*/\s*style\s*>'is"); + $this->remove_noise("'<\s*style\s*>(.*?)<\s*/\s*style\s*>'is"); + // strip out preformatted tags + $this->remove_noise("'<\s*(?:code)[^>]*>(.*?)<\s*/\s*(?:code)\s*>'is"); + // strip out server side scripts + $this->remove_noise("'(<\?)(.*?)(\?>)'s", true); + // strip smarty scripts + $this->remove_noise("'(\{\w)(.*?)(\})'s", true); + + // parsing + while ($this->parse()); + // end + $this->root->_[HDOM_INFO_END] = $this->cursor; + $this->parse_charset(); + + // make load function chainable + return $this; + + } + + // load html from file + function load_file() + { + $args = func_get_args(); + $this->load(call_user_func_array('file_get_contents', $args), true); + // Throw an error if we can't properly load the dom. + if (($error=error_get_last())!==null) { + $this->clear(); + return false; + } + } + + // set callback function + function set_callback($function_name) + { + $this->callback = $function_name; + } + + // remove callback function + function remove_callback() + { + $this->callback = null; + } + + // save dom as string + function save($filepath='') + { + $ret = $this->root->innertext(); + if ($filepath!=='') file_put_contents($filepath, $ret, LOCK_EX); + return $ret; + } + + // find dom node by css selector + // Paperg - allow us to specify that we want case insensitive testing of the value of the selector. + function find($selector, $idx=null, $lowercase=false) + { + return $this->root->find($selector, $idx, $lowercase); + } + + // clean up memory due to php5 circular references memory leak... + function clear() + { + foreach ($this->nodes as $n) {$n->clear(); $n = null;} + // This add next line is documented in the sourceforge repository. 2977248 as a fix for ongoing memory leaks that occur even with the use of clear. + if (isset($this->children)) foreach ($this->children as $n) {$n->clear(); $n = null;} + if (isset($this->parent)) {$this->parent->clear(); unset($this->parent);} + if (isset($this->root)) {$this->root->clear(); unset($this->root);} + unset($this->doc); + unset($this->noise); + } + + function dump($show_attr=true) + { + $this->root->dump($show_attr); + } + + // prepare HTML data and init everything + protected function prepare($str, $lowercase=true, $stripRN=true, $defaultBRText=DEFAULT_BR_TEXT, $defaultSpanText=DEFAULT_SPAN_TEXT) + { + $this->clear(); + + // set the length of content before we do anything to it. + $this->size = strlen($str); + // Save the original size of the html that we got in. It might be useful to someone. + $this->original_size = $this->size; + + //before we save the string as the doc... strip out the \r \n's if we are told to. + if ($stripRN) { + $str = str_replace("\r", " ", $str); + $str = str_replace("\n", " ", $str); + + // set the length of content since we have changed it. + $this->size = strlen($str); + } + + $this->doc = $str; + $this->pos = 0; + $this->cursor = 1; + $this->noise = array(); + $this->nodes = array(); + $this->lowercase = $lowercase; + $this->default_br_text = $defaultBRText; + $this->default_span_text = $defaultSpanText; + $this->root = new simple_html_dom_node($this); + $this->root->tag = 'root'; + $this->root->_[HDOM_INFO_BEGIN] = -1; + $this->root->nodetype = HDOM_TYPE_ROOT; + $this->parent = $this->root; + if ($this->size>0) $this->char = $this->doc[0]; + } + + // parse html content + protected function parse() + { + if (($s = $this->copy_until_char('<'))==='') + { + return $this->read_tag(); + } + + // text + $node = new simple_html_dom_node($this); + ++$this->cursor; + $node->_[HDOM_INFO_TEXT] = $s; + $this->link_nodes($node, false); + return true; + } + + // PAPERG - dkchou - added this to try to identify the character set of the page we have just parsed so we know better how to spit it out later. + // NOTE: IF you provide a routine called get_last_retrieve_url_contents_content_type which returns the CURLINFO_CONTENT_TYPE from the last curl_exec + // (or the content_type header from the last transfer), we will parse THAT, and if a charset is specified, we will use it over any other mechanism. + protected function parse_charset() + { + global $debug_object; + + $charset = null; + + if (function_exists('get_last_retrieve_url_contents_content_type')) + { + $contentTypeHeader = get_last_retrieve_url_contents_content_type(); + $success = preg_match('/charset=(.+)/', $contentTypeHeader, $matches); + if ($success) + { + $charset = $matches[1]; + if (is_object($debug_object)) {$debug_object->debug_log(2, 'header content-type found charset of: ' . $charset);} + } + + } + + if (empty($charset)) + { + $el = $this->root->find('meta[http-equiv=Content-Type]',0); + if (!empty($el)) + { + $fullvalue = $el->content; + if (is_object($debug_object)) {$debug_object->debug_log(2, 'meta content-type tag found' . $fullvalue);} + + if (!empty($fullvalue)) + { + $success = preg_match('/charset=(.+)/', $fullvalue, $matches); + if ($success) + { + $charset = $matches[1]; + } + else + { + // If there is a meta tag, and they don't specify the character set, research says that it's typically ISO-8859-1 + if (is_object($debug_object)) {$debug_object->debug_log(2, 'meta content-type tag couldn\'t be parsed. using iso-8859 default.');} + $charset = 'ISO-8859-1'; + } + } + } + } + + // If we couldn't find a charset above, then lets try to detect one based on the text we got... + if (empty($charset)) + { + // Use this in case mb_detect_charset isn't installed/loaded on this machine. + $charset = false; + if (function_exists('mb_detect_encoding')) + { + // Have php try to detect the encoding from the text given to us. + $charset = mb_detect_encoding($this->root->plaintext . "ascii", $encoding_list = array( "UTF-8", "CP1252" ) ); + if (is_object($debug_object)) {$debug_object->debug_log(2, 'mb_detect found: ' . $charset);} + } + + // and if this doesn't work... then we need to just wrongheadedly assume it's UTF-8 so that we can move on - cause this will usually give us most of what we need... + if ($charset === false) + { + if (is_object($debug_object)) {$debug_object->debug_log(2, 'since mb_detect failed - using default of utf-8');} + $charset = 'UTF-8'; + } + } + + // Since CP1252 is a superset, if we get one of it's subsets, we want it instead. + if ((strtolower($charset) == strtolower('ISO-8859-1')) || (strtolower($charset) == strtolower('Latin1')) || (strtolower($charset) == strtolower('Latin-1'))) + { + if (is_object($debug_object)) {$debug_object->debug_log(2, 'replacing ' . $charset . ' with CP1252 as its a superset');} + $charset = 'CP1252'; + } + + if (is_object($debug_object)) {$debug_object->debug_log(1, 'EXIT - ' . $charset);} + + return $this->_charset = $charset; + } + + // read tag info + protected function read_tag() + { + if ($this->char!=='<') + { + $this->root->_[HDOM_INFO_END] = $this->cursor; + return false; + } + $begin_tag_pos = $this->pos; + $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next + + // end tag + if ($this->char==='/') + { + $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next + // This represents the change in the simple_html_dom trunk from revision 180 to 181. + // $this->skip($this->token_blank_t); + $this->skip($this->token_blank); + $tag = $this->copy_until_char('>'); + + // skip attributes in end tag + if (($pos = strpos($tag, ' '))!==false) + $tag = substr($tag, 0, $pos); + + $parent_lower = strtolower($this->parent->tag); + $tag_lower = strtolower($tag); + + if ($parent_lower!==$tag_lower) + { + if (isset($this->optional_closing_tags[$parent_lower]) && isset($this->block_tags[$tag_lower])) + { + $this->parent->_[HDOM_INFO_END] = 0; + $org_parent = $this->parent; + + while (($this->parent->parent) && strtolower($this->parent->tag)!==$tag_lower) + $this->parent = $this->parent->parent; + + if (strtolower($this->parent->tag)!==$tag_lower) { + $this->parent = $org_parent; // restore origonal parent + if ($this->parent->parent) $this->parent = $this->parent->parent; + $this->parent->_[HDOM_INFO_END] = $this->cursor; + return $this->as_text_node($tag); + } + } + else if (($this->parent->parent) && isset($this->block_tags[$tag_lower])) + { + $this->parent->_[HDOM_INFO_END] = 0; + $org_parent = $this->parent; + + while (($this->parent->parent) && strtolower($this->parent->tag)!==$tag_lower) + $this->parent = $this->parent->parent; + + if (strtolower($this->parent->tag)!==$tag_lower) + { + $this->parent = $org_parent; // restore origonal parent + $this->parent->_[HDOM_INFO_END] = $this->cursor; + return $this->as_text_node($tag); + } + } + else if (($this->parent->parent) && strtolower($this->parent->parent->tag)===$tag_lower) + { + $this->parent->_[HDOM_INFO_END] = 0; + $this->parent = $this->parent->parent; + } + else + return $this->as_text_node($tag); + } + + $this->parent->_[HDOM_INFO_END] = $this->cursor; + if ($this->parent->parent) $this->parent = $this->parent->parent; + + $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next + return true; + } + + $node = new simple_html_dom_node($this); + $node->_[HDOM_INFO_BEGIN] = $this->cursor; + ++$this->cursor; + $tag = $this->copy_until($this->token_slash); + $node->tag_start = $begin_tag_pos; + + // doctype, cdata & comments... + if (isset($tag[0]) && $tag[0]==='!') { + $node->_[HDOM_INFO_TEXT] = '<' . $tag . $this->copy_until_char('>'); + + if (isset($tag[2]) && $tag[1]==='-' && $tag[2]==='-') { + $node->nodetype = HDOM_TYPE_COMMENT; + $node->tag = 'comment'; + } else { + $node->nodetype = HDOM_TYPE_UNKNOWN; + $node->tag = 'unknown'; + } + if ($this->char==='>') $node->_[HDOM_INFO_TEXT].='>'; + $this->link_nodes($node, true); + $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next + return true; + } + + // text + if ($pos=strpos($tag, '<')!==false) { + $tag = '<' . substr($tag, 0, -1); + $node->_[HDOM_INFO_TEXT] = $tag; + $this->link_nodes($node, false); + $this->char = $this->doc[--$this->pos]; // prev + return true; + } + + if (!preg_match("/^[\w-:]+$/", $tag)) { + $node->_[HDOM_INFO_TEXT] = '<' . $tag . $this->copy_until('<>'); + if ($this->char==='<') { + $this->link_nodes($node, false); + return true; + } + + if ($this->char==='>') $node->_[HDOM_INFO_TEXT].='>'; + $this->link_nodes($node, false); + $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next + return true; + } + + // begin tag + $node->nodetype = HDOM_TYPE_ELEMENT; + $tag_lower = strtolower($tag); + $node->tag = ($this->lowercase) ? $tag_lower : $tag; + + // handle optional closing tags + if (isset($this->optional_closing_tags[$tag_lower]) ) + { + while (isset($this->optional_closing_tags[$tag_lower][strtolower($this->parent->tag)])) + { + $this->parent->_[HDOM_INFO_END] = 0; + $this->parent = $this->parent->parent; + } + $node->parent = $this->parent; + } + + $guard = 0; // prevent infinity loop + $space = array($this->copy_skip($this->token_blank), '', ''); + + // attributes + do + { + if ($this->char!==null && $space[0]==='') + { + break; + } + $name = $this->copy_until($this->token_equal); + if ($guard===$this->pos) + { + $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next + continue; + } + $guard = $this->pos; + + // handle endless '<' + if ($this->pos>=$this->size-1 && $this->char!=='>') { + $node->nodetype = HDOM_TYPE_TEXT; + $node->_[HDOM_INFO_END] = 0; + $node->_[HDOM_INFO_TEXT] = '<'.$tag . $space[0] . $name; + $node->tag = 'text'; + $this->link_nodes($node, false); + return true; + } + + // handle mismatch '<' + if ($this->doc[$this->pos-1]=='<') { + $node->nodetype = HDOM_TYPE_TEXT; + $node->tag = 'text'; + $node->attr = array(); + $node->_[HDOM_INFO_END] = 0; + $node->_[HDOM_INFO_TEXT] = substr($this->doc, $begin_tag_pos, $this->pos-$begin_tag_pos-1); + $this->pos -= 2; + $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next + $this->link_nodes($node, false); + return true; + } + + if ($name!=='/' && $name!=='') { + $space[1] = $this->copy_skip($this->token_blank); + $name = $this->restore_noise($name); + if ($this->lowercase) $name = strtolower($name); + if ($this->char==='=') { + $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next + $this->parse_attr($node, $name, $space); + } + else { + //no value attr: nowrap, checked selected... + $node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_NO; + $node->attr[$name] = true; + if ($this->char!='>') $this->char = $this->doc[--$this->pos]; // prev + } + $node->_[HDOM_INFO_SPACE][] = $space; + $space = array($this->copy_skip($this->token_blank), '', ''); + } + else + break; + } while ($this->char!=='>' && $this->char!=='/'); + + $this->link_nodes($node, true); + $node->_[HDOM_INFO_ENDSPACE] = $space[0]; + + // check self closing + if ($this->copy_until_char_escape('>')==='/') + { + $node->_[HDOM_INFO_ENDSPACE] .= '/'; + $node->_[HDOM_INFO_END] = 0; + } + else + { + // reset parent + if (!isset($this->self_closing_tags[strtolower($node->tag)])) $this->parent = $node; + } + $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next + + // If it's a BR tag, we need to set it's text to the default text. + // This way when we see it in plaintext, we can generate formatting that the user wants. + // since a br tag never has sub nodes, this works well. + if ($node->tag == "br") + { + $node->_[HDOM_INFO_INNER] = $this->default_br_text; + } + + return true; + } + + // parse attributes + protected function parse_attr($node, $name, &$space) + { + // Per sourceforge: http://sourceforge.net/tracker/?func=detail&aid=3061408&group_id=218559&atid=1044037 + // If the attribute is already defined inside a tag, only pay atetntion to the first one as opposed to the last one. + if (isset($node->attr[$name])) + { + return; + } + + $space[2] = $this->copy_skip($this->token_blank); + switch ($this->char) { + case '"': + $node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_DOUBLE; + $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next + $node->attr[$name] = $this->restore_noise($this->copy_until_char_escape('"')); + $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next + break; + case '\'': + $node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_SINGLE; + $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next + $node->attr[$name] = $this->restore_noise($this->copy_until_char_escape('\'')); + $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next + break; + default: + $node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_NO; + $node->attr[$name] = $this->restore_noise($this->copy_until($this->token_attr)); + } + // PaperG: Attributes should not have \r or \n in them, that counts as html whitespace. + $node->attr[$name] = str_replace("\r", "", $node->attr[$name]); + $node->attr[$name] = str_replace("\n", "", $node->attr[$name]); + // PaperG: If this is a "class" selector, lets get rid of the preceeding and trailing space since some people leave it in the multi class case. + if ($name == "class") { + $node->attr[$name] = trim($node->attr[$name]); + } + } + + // link node's parent + protected function link_nodes(&$node, $is_child) + { + $node->parent = $this->parent; + $this->parent->nodes[] = $node; + if ($is_child) + { + $this->parent->children[] = $node; + } + } + + // as a text node + protected function as_text_node($tag) + { + $node = new simple_html_dom_node($this); + ++$this->cursor; + $node->_[HDOM_INFO_TEXT] = '</' . $tag . '>'; + $this->link_nodes($node, false); + $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next + return true; + } + + protected function skip($chars) + { + $this->pos += strspn($this->doc, $chars, $this->pos); + $this->char = ($this->pos<$this->size) ? $this->doc[$this->pos] : null; // next + } + + protected function copy_skip($chars) + { + $pos = $this->pos; + $len = strspn($this->doc, $chars, $pos); + $this->pos += $len; + $this->char = ($this->pos<$this->size) ? $this->doc[$this->pos] : null; // next + if ($len===0) return ''; + return substr($this->doc, $pos, $len); + } + + protected function copy_until($chars) + { + $pos = $this->pos; + $len = strcspn($this->doc, $chars, $pos); + $this->pos += $len; + $this->char = ($this->pos<$this->size) ? $this->doc[$this->pos] : null; // next + return substr($this->doc, $pos, $len); + } + + protected function copy_until_char($char) + { + if ($this->char===null) return ''; + + if (($pos = strpos($this->doc, $char, $this->pos))===false) { + $ret = substr($this->doc, $this->pos, $this->size-$this->pos); + $this->char = null; + $this->pos = $this->size; + return $ret; + } + + if ($pos===$this->pos) return ''; + $pos_old = $this->pos; + $this->char = $this->doc[$pos]; + $this->pos = $pos; + return substr($this->doc, $pos_old, $pos-$pos_old); + } + + protected function copy_until_char_escape($char) + { + if ($this->char===null) return ''; + + $start = $this->pos; + while (1) + { + if (($pos = strpos($this->doc, $char, $start))===false) + { + $ret = substr($this->doc, $this->pos, $this->size-$this->pos); + $this->char = null; + $this->pos = $this->size; + return $ret; + } + + if ($pos===$this->pos) return ''; + + if ($this->doc[$pos-1]==='\\') { + $start = $pos+1; + continue; + } + + $pos_old = $this->pos; + $this->char = $this->doc[$pos]; + $this->pos = $pos; + return substr($this->doc, $pos_old, $pos-$pos_old); + } + } + + // remove noise from html content + // save the noise in the $this->noise array. + protected function remove_noise($pattern, $remove_tag=false) + { + global $debug_object; + if (is_object($debug_object)) { $debug_object->debug_log_entry(1); } + + $count = preg_match_all($pattern, $this->doc, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE); + + for ($i=$count-1; $i>-1; --$i) + { + $key = '___noise___'.sprintf('% 5d', count($this->noise)+1000); + if (is_object($debug_object)) { $debug_object->debug_log(2, 'key is: ' . $key); } + $idx = ($remove_tag) ? 0 : 1; + $this->noise[$key] = $matches[$i][$idx][0]; + $this->doc = substr_replace($this->doc, $key, $matches[$i][$idx][1], strlen($matches[$i][$idx][0])); + } + + // reset the length of content + $this->size = strlen($this->doc); + if ($this->size>0) + { + $this->char = $this->doc[0]; + } + } + + // restore noise to html content + function restore_noise($text) + { + global $debug_object; + if (is_object($debug_object)) { $debug_object->debug_log_entry(1); } + + while (($pos=strpos($text, '___noise___'))!==false) + { + // Sometimes there is a broken piece of markup, and we don't GET the pos+11 etc... token which indicates a problem outside of us... + if (strlen($text) > $pos+15) + { + $key = '___noise___'.$text[$pos+11].$text[$pos+12].$text[$pos+13].$text[$pos+14].$text[$pos+15]; + if (is_object($debug_object)) { $debug_object->debug_log(2, 'located key of: ' . $key); } + + if (isset($this->noise[$key])) + { + $text = substr($text, 0, $pos).$this->noise[$key].substr($text, $pos+16); + } + else + { + // do this to prevent an infinite loop. + $text = substr($text, 0, $pos).'UNDEFINED NOISE FOR KEY: '.$key . substr($text, $pos+16); + } + } + else + { + // There is no valid key being given back to us... We must get rid of the ___noise___ or we will have a problem. + $text = substr($text, 0, $pos).'NO NUMERIC NOISE KEY' . substr($text, $pos+11); + } + } + return $text; + } + + // Sometimes we NEED one of the noise elements. + function search_noise($text) + { + global $debug_object; + if (is_object($debug_object)) { $debug_object->debug_log_entry(1); } + + foreach($this->noise as $noiseElement) + { + if (strpos($noiseElement, $text)!==false) + { + return $noiseElement; + } + } + } + function __toString() + { + return $this->root->innertext(); + } + + function __get($name) + { + switch ($name) + { + case 'outertext': + return $this->root->innertext(); + case 'innertext': + return $this->root->innertext(); + case 'plaintext': + return $this->root->text(); + case 'charset': + return $this->_charset; + case 'target_charset': + return $this->_target_charset; + } + } + + // camel naming conventions + function childNodes($idx=-1) {return $this->root->childNodes($idx);} + function firstChild() {return $this->root->first_child();} + function lastChild() {return $this->root->last_child();} + function createElement($name, $value=null) {return @str_get_html("<$name>$value</$name>")->first_child();} + function createTextNode($value) {return @end(str_get_html($value)->nodes);} + function getElementById($id) {return $this->find("#$id", 0);} + function getElementsById($id, $idx=null) {return $this->find("#$id", $idx);} + function getElementByTagName($name) {return $this->find($name, 0);} + function getElementsByTagName($name, $idx=-1) {return $this->find($name, $idx);} + function loadFile() {$args = func_get_args();$this->load_file($args);} +} + ?> \ No newline at end of file diff --git a/wp-content/plugins/nextgen-gallery/readme.txt b/wp-content/plugins/nextgen-gallery/readme.txt index 309908d5c9c01b7b9ec36617929c5ed73f7e6b7a..9e781fae018363dd5d1981772aeb5a2fdc9ca4b1 100644 --- a/wp-content/plugins/nextgen-gallery/readme.txt +++ b/wp-content/plugins/nextgen-gallery/readme.txt @@ -2,11 +2,11 @@ Contributors: photocrati, imagely Tags: nextgen, nextgen gallery, gallery, galleries, image, images, image gallery, photo, photos, photo gallery, picture, pictures, picture gallery, album, albums, photo albums, image album, media, media gallery, thumbnails, thumbnail gallery, thumbnail galleries, slideshow, slideshows, slideshow gallery, slideshow galleries, fancybox, lightbox, responsive, responsive gallery, responsive galleries, wordpress responsive gallery, nextcellent, wordpress gallery plugin, wordpress photo gallery plugin, wp gallery, wp gallery plugins, best gallery plugin, free photo gallery, singlepic, image captions imagebrowser, watermarks, watermarking, photography, photographer Requires at least: 4.0.0 -Stable tag: 2.1.43 -Tested up to: 4.5.2 +Stable tag: 2.1.49 +Tested up to: 4.6.0 License: GPLv2 -The most popular WordPress gallery plugin and one of the most popular plugins of all time with over 14 million downloads. +The most popular WordPress gallery plugin and one of the most popular plugins of all time with over 15 million downloads. == Description == @@ -187,6 +187,43 @@ For more information, feel free to visit the official website for the NextGEN Ga == Changelog == += V2.1.49 - 07.26.2016 = +* NEW: Add a "Default" template option to override ATP settings when a global setting is used +* NEW: Added "generic" error reporting back during image upload. +* NEW: Added notice for deprecating PHP 5.2 +* NEW: Option to display child gallery and album descriptions when viewing albums +* Changed: ATP preview images are smaller with tighter margins to show more images +* Changed: Content of Upgrade to Pro page +* Changed: New NextGEN Overview page +* Changed: Replicate gallery name sanitation of NG legacy for gallery paths +* Fixed: Resolved all found PHP warnings/notices/deprecations and strict errors +* Fixed: Compatibility on Windows servers with network mounted document roots +* Fixed: Ensure EXIF meta data is loaded from the appropriate exif_data array instead of exif_array +* Fixed: Gallery Settings toggle not functioning +* Fixed: Uploading breaking when thumbnail or image resizing fails due to lack of specific format support for image libraries +* Fixed: Warning generated in nggallery.php checking useMediaRSS option + += V2.1.46 - 06.23.2016 = +* Fixed: Remove inner nextgen-gallery folder due to build issue + += V2.1.45 - 06.22.2016 = +* Fixed: Freemius assets should not be minified + += V2.1.44 - 06.22.2016 = +* NEW: "Add Gallery" button added next to "Add Media" button on Create/Edit Post screen +* NEW: IGW placeholder images are watermarked +* NEW: Added API for communicating with Lightroom plugin +* NEW: Gulp build system +* NEW: Added "ngg_igw_placeholder_line_2_settings" and "ngg_igw_placeholder_line_1_settings" filters +* NEW: Added "ngg_settings_during_image_generation" filter to adjust image generation +* NEW: Added "ngg_before_save_thumbnail" filter for image manipulation abilities +* NEW: Added the ability to apply GD filters during image generation +* NEW: Integrated with WordPress SEO sitemaps to show include NGG images in image counts +* Changed: Links to manage a gallery after it's been created don't appear in the IGW +* Fixed: Freemius code shouldn't be minified +* Fixed: When a datamapper entity is saved, it's corresponding cache should be cleared +* Fixed: IGW placeholder images aren't used by WordPress SEO's OpenGraph analysis + = V2.1.43 - 05.25.2016 = * NEW: Added Freemius integration * NEW: Added actions actions ngg_updated_image_meta, ngg_recovered_image, ngg_generated_image, ngg_moved_images, and ngg_copied_images