Version Description
(2019-08-14) =
Added - New link to the custom feed in the "Custom Feed" settings page.
Changed - Updated the logging system to no longer cause VaultPress to trigger false positive warnings. - The date format in the custom feed now uses the "RFC3339 Extended" format.
Fixed
- Items with the same title were not being imported even when "Unique titles only" was turned off.
- Items with future dates where marked as "scheduled" by WordPress.
- The custom feed's "Content-Type" header was set for RSS 2.0 instead of Atom.
- Imported images were not being deleted from the media library when the imported item is deleted.
- PHP notice for "undefined index enclosure" when a feed cannot be fetched.
- Deprecation notice on PHP 7.2 or later for "each" function.
- Warnings when the wprss_log
function is used incorrectly.
- PHP notice for "property of non-object" when using YoastSEO.
- After using the Templates add-on, images would continue to be imported after the add-on was deactivated.
Release Info
Developer | Mekku |
Plugin | WP RSS Aggregator |
Version | 4.15.1 |
Comparing to | |
See all releases |
Code changes from version 4.15 to 4.15.1
- CHANGELOG.md +19 -0
- README.md +24 -0
- css/admin-3.8.css +0 -0
- css/admin-editor.css +0 -0
- css/admin-styles.css +1 -1
- css/admin-tracking-styles.css +0 -0
- css/colorbox.css +0 -0
- css/font-awesome.min.css +0 -0
- css/src/common/index.scss +3 -0
- css/src/common/info-box.scss +16 -0
- css/src/common/notice-block.scss +64 -0
- css/src/gutenberg-block/index.scss +14 -0
- css/src/intro/animation.scss +48 -0
- css/src/intro/expander.scss +26 -0
- css/src/intro/loading.scss +131 -0
- css/src/intro/steps.scss +647 -0
- css/src/mixins.scss +32 -0
- css/src/pagination/index.scss +10 -0
- css/src/plugins/form.scss +48 -0
- css/src/plugins/index.scss +25 -0
- css/src/plugins/modal.scss +173 -0
- css/src/templates/bottom-panel.scss +15 -0
- css/src/templates/grid.scss +18 -0
- css/src/templates/index.scss +216 -0
- css/src/templates/loading.scss +220 -0
- css/src/templates/notifications.scss +28 -0
- css/src/update/index.scss +149 -0
- fonts/FontAwesome.otf +0 -0
- fonts/fontawesome-webfont.eot +0 -0
- fonts/fontawesome-webfont.svg +0 -0
- fonts/fontawesome-webfont.ttf +0 -0
- fonts/fontawesome-webfont.woff +0 -0
- images/add-ons/wprss.jpg +0 -0
- images/colorbox/border.png +0 -0
- images/colorbox/controls.png +0 -0
- images/colorbox/ie6/borderBottomCenter.png +0 -0
- images/colorbox/ie6/borderBottomLeft.png +0 -0
- images/colorbox/ie6/borderBottomRight.png +0 -0
- images/colorbox/ie6/borderMiddleLeft.png +0 -0
- images/colorbox/ie6/borderMiddleRight.png +0 -0
- images/colorbox/ie6/borderTopCenter.png +0 -0
- images/colorbox/ie6/borderTopLeft.png +0 -0
- images/colorbox/ie6/borderTopRight.png +0 -0
- images/colorbox/loading.gif +0 -0
- images/colorbox/loading_background.png +0 -0
- images/colorbox/overlay.png +0 -0
- images/facebook.png +0 -0
- images/icon-adminmenu16-sprite.png +0 -0
- images/icon-adminpage32.png +0 -0
- images/twitter.png +0 -0
- includes/Aventura/Wprss/Core/Model/Regex/HtmlEncoder.php +10 -3
- includes/OPML.php +0 -0
- includes/admin-addons.php +0 -137
- includes/admin-ajax-notice.php +0 -0
- includes/admin-debugging.php +0 -57
- includes/admin-display.php +6 -2
- includes/admin-editor.php +0 -0
- includes/admin-heartbeat.php +0 -0
- includes/admin-help-metaboxes.php +0 -0
- includes/admin-help-settings.php +2 -2
- includes/admin-help.php +1 -0
- includes/admin-import-export.php +0 -0
- includes/admin-log.php +14 -12
- includes/admin-metaboxes.php +1 -9
- includes/admin-options.php +43 -25
- includes/admin.php +0 -4
- includes/cpt-feeds.php +0 -0
- includes/cron-jobs.php +0 -0
- includes/fallback-mbstring.php +0 -0
- includes/feed-access.php +0 -0
- includes/feed-blacklist.php +0 -0
- includes/feed-importing-images.php +92 -69
- includes/feed-importing.php +50 -30
- includes/feed-processing.php +0 -0
- includes/feed-states.php +0 -0
- includes/functions.php +98 -2
- includes/image-caching.php +9 -2
- includes/libraries/WordPress-Readme-Parser/ReadmeParser.php +0 -0
- includes/libraries/browser.php +0 -0
- includes/libraries/php-markdown/markdown.php +0 -0
- includes/licensing.php +0 -0
- includes/misc-functions.php +0 -0
- includes/opml-importer.php +0 -0
- includes/readme.php +0 -0
- includes/roles-capabilities.php +0 -0
- includes/scripts.php +0 -5
- includes/system-info.php +141 -117
- includes/update.php +1 -1
- js/admin-addon-ajax.js +0 -0
- js/admin-custom-bulk-actions-feed-item.js +0 -16
- js/admin-custom-bulk-actions.js +0 -0
- js/admin-custom.js +0 -0
- js/admin-help.js +0 -0
- js/admin-license-manager.js +0 -0
- js/admin-licensing.js +0 -0
- js/custom.js +0 -0
- js/editor.js +0 -0
- js/heartbeat.js +0 -0
- js/jquery-ui-timepicker-addon.js +0 -0
- js/jquery.colorbox-min.js +0 -0
- js/pointers.js +0 -0
- js/src/components/BottomPanel.vue +9 -0
- js/src/components/Button.js +14 -0
- js/src/components/Expander.vue +36 -0
- js/src/components/Input.js +100 -0
- js/src/components/Layout.js +11 -0
- js/src/components/Main.js +11 -0
- js/src/components/MediaInput.js +96 -0
- js/src/components/Modal.vue +114 -0
- js/src/components/NoticeBlock.js +143 -0
- js/src/components/Postbox.vue +44 -0
- js/src/components/RouteLink.js +27 -0
- js/src/components/RouterApp.js +47 -0
- js/src/components/SerializedForm.vue +89 -0
- js/src/components/Sidebar.js +11 -0
- js/src/components/TransitionExpand.vue +66 -0
- js/src/components/index.js +15 -0
- js/src/libs/NotificationCenter.js +45 -0
- js/src/libs/Router.js +122 -0
- js/src/mixins/DataChangesAware.js +47 -0
- js/src/modules/gutenberg-block/components/MultipleSelectControl.js +85 -0
- js/src/modules/gutenberg-block/index.js +209 -0
- js/src/modules/intro/Wizard.vue +440 -0
- js/src/modules/intro/index.js +11 -0
- js/src/modules/pagination/index.js +47 -0
- js/src/modules/plugins/PluginDisablePoll.vue +122 -0
- js/src/modules/plugins/index.js +10 -0
- js/src/modules/templates/Edit.js +491 -0
- js/src/modules/templates/List.js +350 -0
- js/src/modules/templates/app.js +117 -0
- js/src/modules/templates/index.js +36 -0
- js/src/modules/templates/store/actions.js +1 -0
- js/src/modules/templates/store/getters.js +7 -0
- js/src/modules/templates/store/index.js +12 -0
- js/src/modules/templates/store/mutations.js +10 -0
- js/src/modules/templates/store/state.js +18 -0
- js/src/utils/Collection.js +178 -0
- js/src/utils/base64.js +133 -0
- js/src/utils/copy.js +43 -0
- js/src/utils/deepmerge.js +72 -0
- js/src/utils/fetch.js +26 -0
- js/src/utils/jsonClone.js +3 -0
- languages/default.mo +0 -0
- languages/default.po +0 -0
- languages/wprss-it.mo +0 -0
- languages/wprss-it.po +0 -0
- languages/wprss-nl_NL.mo +0 -0
- languages/wprss-nl_NL.po +0 -0
- languages/wprss-pt_BR.mo +0 -0
- languages/wprss-pt_BR.po +0 -0
- languages/wprss-ru_RU.mo +0 -0
- languages/wprss-ru_RU.po +0 -0
- readme.txt +14 -15
- src/Database/TableInterface.php +5 -0
- src/Entities/Feeds/Sources/WpPostFeedSource.php +0 -9
- src/Handlers/CustomFeed/RenderCustomFeedHandler.php +1 -1
- src/Handlers/FeedTemplates/RenderTemplateContentHandler.php +4 -0
- src/Handlers/Images/DeleteImagesHandler.php +8 -5
- src/Logger/ConditionalLogger.php +0 -54
- src/Logger/FeedLoggerInterface.php +24 -0
- src/Logger/ProblemLogger.php +53 -0
- src/Logger/WpdbLogger.php +20 -12
- src/Logger/WpraLogger.php +81 -0
- src/Modules/ImagesModule.php +7 -49
- src/Modules/LoggerModule.php +21 -43
- src/Modules/LoremModule.php +123 -0
- src/Modules/UpsellModule.php +284 -0
- src/Util/NullFunction.php +20 -0
- templates/admin/upsell/add-on-list.twig +10 -0
- templates/admin/upsell/more-features-page/add-on.twig +32 -0
- templates/admin/upsell/more-features-page/lorem.twig +2 -0
- templates/admin/upsell/more-features-page/main.twig +21 -0
- templates/custom-feed/entry.twig +1 -1
- templates/help-footer-js.php +0 -0
- templates/help-tooltip-content.php +0 -0
- templates/help-tooltip-handle.php +0 -0
- templates/wprss.css +0 -0
- uninstall.php +0 -0
- vendor/autoload.php +1 -1
- vendor/composer/ClassLoader.php +0 -0
- vendor/composer/LICENSE +0 -0
- vendor/composer/autoload_classmap.php +6 -1
- vendor/composer/autoload_namespaces.php +0 -0
- vendor/composer/autoload_psr4.php +0 -0
- vendor/composer/autoload_real.php +7 -7
- vendor/composer/autoload_static.php +11 -6
- vendor/composer/installed.json +0 -0
- vendor/dhii/collections-abstract-base/composer.json +0 -0
- vendor/dhii/collections-abstract-base/composer.lock +0 -0
- vendor/dhii/collections-abstract-base/src/AbstractCollection.php +0 -0
- vendor/dhii/collections-abstract-base/src/AbstractHasher.php +0 -0
- vendor/dhii/collections-abstract-base/src/AbstractIterableCollection.php +0 -0
- vendor/dhii/collections-abstract/composer.json +0 -0
- vendor/dhii/collections-abstract/composer.lock +0 -0
- vendor/dhii/collections-abstract/src/AbstractCallbackCollection.php +0 -0
- vendor/dhii/collections-abstract/src/AbstractCallbackCollectionBase.php +0 -0
- vendor/dhii/collections-abstract/src/AbstractCallbackIterator.php +0 -0
- vendor/dhii/collections-abstract/src/AbstractGenericAccessibleCollection.php +0 -0
- vendor/dhii/collections-abstract/src/AbstractGenericCollection.php +0 -0
- vendor/dhii/collections-abstract/src/AbstractGenericMutableCollection.php +0 -0
- vendor/dhii/collections-abstract/src/AbstractSearchableCollection.php +0 -0
- vendor/dhii/collections-abstract/src/AppendIterator.php +0 -0
- vendor/dhii/collections-abstract/src/CallbackIterator.php +0 -0
- vendor/dhii/collections-interface/composer.json +0 -0
- vendor/dhii/collections-interface/composer.lock +0 -0
- vendor/dhii/collections-interface/src/AccessibleCollectionInterface.php +0 -0
- vendor/dhii/collections-interface/src/CallbackIterableInterface.php +0 -0
- vendor/dhii/collections-interface/src/CallbackIteratorInterface.php +0 -0
- vendor/dhii/collections-interface/src/CollectionInterface.php +0 -0
- vendor/dhii/collections-interface/src/MutableCollectionInterface.php +0 -0
- vendor/dhii/collections-interface/src/SearchableCollectionInterface.php +0 -0
- vendor/dhii/collections-interface/src/SequenceIteratorIteratorInterface.php +0 -0
- vendor/dhii/collections-interface/src/SetInterface.php +0 -0
- vendor/dhii/stats-abstract/composer.json +0 -0
- vendor/dhii/stats-abstract/composer.lock +0 -0
- vendor/dhii/stats-abstract/src/AbstractAggregatableCollection.php +0 -0
- vendor/dhii/stats-abstract/src/AbstractAggregator.php +0 -0
- vendor/dhii/stats-interface/composer.json +0 -0
- vendor/dhii/stats-interface/composer.lock +0 -0
- vendor/dhii/stats-interface/src/AggregatorInterface.php +0 -0
- wp-rss-aggregator.php +6 -5
@@ -4,6 +4,25 @@ All notable changes to this project will be documented in this file.
|
|
4 |
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
5 |
and this project adheres to [Semantic Versioning](http://semver.org/).
|
6 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
## [4.15] - 2019-07-16
|
8 |
### Added
|
9 |
* New error handling for catchable PHP7 `Throwable` errors.
|
4 |
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
5 |
and this project adheres to [Semantic Versioning](http://semver.org/).
|
6 |
|
7 |
+
## [4.15.1] - 2019-08-14
|
8 |
+
### Added
|
9 |
+
* New link to the custom feed in the "Custom Feed" settings page.
|
10 |
+
|
11 |
+
### Changed
|
12 |
+
* Updated the logging system to no longer cause VaultPress to trigger false positive warnings.
|
13 |
+
* The date format in the custom feed now uses the "RFC3339 Extended" format.
|
14 |
+
|
15 |
+
### Fixed
|
16 |
+
* Items with the same title were not being imported even when "Unique titles only" was turned off.
|
17 |
+
* Items with future dates where marked as "scheduled" by WordPress.
|
18 |
+
* The custom feed's "Content-Type" header was set for RSS 2.0 instead of Atom.
|
19 |
+
* Imported images were not being deleted from the media library when the imported item is deleted.
|
20 |
+
* PHP notice for "undefined index enclosure" when a feed cannot be fetched.
|
21 |
+
* Deprecation notice on PHP 7.2 or later for "each" function.
|
22 |
+
* Warnings when the `wprss_log` function is used incorrectly.
|
23 |
+
* PHP notice for "property of non-object" when using YoastSEO.
|
24 |
+
* After using the Templates add-on, images would continue to be imported after the add-on was deactivated.
|
25 |
+
|
26 |
## [4.15] - 2019-07-16
|
27 |
### Added
|
28 |
* New error handling for catchable PHP7 `Throwable` errors.
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
![](https://repository-images.githubusercontent.com/15269888/73ca9400-669f-11e9-9e18-5662f7b5bd68)
|
2 |
+
|
3 |
+
## Requirements
|
4 |
+
|
5 |
+
**Recommended**
|
6 |
+
* PHP 7+
|
7 |
+
* PHP `curl` extension
|
8 |
+
* PHP `simplexml` extension
|
9 |
+
* PHP `mbstring` extension
|
10 |
+
* PHP `gd` extension
|
11 |
+
* WordPress 5.0+
|
12 |
+
|
13 |
+
**Minimum**
|
14 |
+
* PHP 5.4+
|
15 |
+
* PHP `curl` extension
|
16 |
+
* PHP `simplexml` extension
|
17 |
+
* WordPress 4.8+
|
18 |
+
|
19 |
+
## Links
|
20 |
+
|
21 |
+
* [Website](https://wprssaggregator.com)
|
22 |
+
* [Premium Addons](https://wprssaggregator.com/pricing)
|
23 |
+
* [Knowledge Base](https://kb.wprssaggregator.com)
|
24 |
+
* [WordPress.org Page](https://wordpress.org/plugins/wp-rss-aggregator)
|
File without changes
|
File without changes
|
@@ -738,7 +738,7 @@ i.wprss-updating-feed-icon.wprss-show {
|
|
738 |
border: 1px solid #E5E5E5;
|
739 |
position: relative;
|
740 |
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
|
741 |
-
|
742 |
}
|
743 |
|
744 |
#add-ons .add-on h3 {
|
738 |
border: 1px solid #E5E5E5;
|
739 |
position: relative;
|
740 |
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
|
741 |
+
min-height: 320px;
|
742 |
}
|
743 |
|
744 |
#add-ons .add-on h3 {
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
@import "./../mixins";
|
2 |
+
@import "notice-block";
|
3 |
+
@import "info-box";
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.wpra-info-box {
|
2 |
+
background: #daf4ff;
|
3 |
+
padding: 8px 12px;
|
4 |
+
border-radius: 3px;
|
5 |
+
display: flex;
|
6 |
+
|
7 |
+
&__icon {
|
8 |
+
opacity: .4;
|
9 |
+
flex-shrink: 0;
|
10 |
+
}
|
11 |
+
|
12 |
+
&__text {
|
13 |
+
flex-grow: 1;
|
14 |
+
padding-left: 8px;
|
15 |
+
}
|
16 |
+
}
|
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.wpra-notice-block {
|
2 |
+
background-color: white;
|
3 |
+
box-shadow: 0 1px 1px 0 rgba(0,0,0,0.1);
|
4 |
+
padding: 12px 16px;
|
5 |
+
margin-top: .5rem;
|
6 |
+
margin-bottom: .15rem;
|
7 |
+
//border-left: 4px solid #ff792b;
|
8 |
+
|
9 |
+
&.postbox {
|
10 |
+
margin-top: 0;
|
11 |
+
margin-bottom: 20px;
|
12 |
+
box-shadow: 0;
|
13 |
+
|
14 |
+
.wpra-notice-block__body {
|
15 |
+
font-size: 14px;
|
16 |
+
opacity: .8;
|
17 |
+
}
|
18 |
+
}
|
19 |
+
|
20 |
+
&__title {
|
21 |
+
font-size: 22px;
|
22 |
+
padding: .5rem 0 1rem;
|
23 |
+
max-width: 65rem;
|
24 |
+
}
|
25 |
+
|
26 |
+
&__body {
|
27 |
+
line-height: 1.5;
|
28 |
+
font-size: 16px;
|
29 |
+
opacity: .7;
|
30 |
+
max-width: 65rem;
|
31 |
+
}
|
32 |
+
|
33 |
+
&__buttons {
|
34 |
+
padding: 1rem 0 .5rem;
|
35 |
+
|
36 |
+
.button {
|
37 |
+
height: 34px;
|
38 |
+
line-height: 32px;
|
39 |
+
padding: 0 16px 2px;
|
40 |
+
|
41 |
+
.dashicons {
|
42 |
+
font-size: 16px;
|
43 |
+
vertical-align: middle;
|
44 |
+
opacity: .75;
|
45 |
+
margin-left: 2px;
|
46 |
+
}
|
47 |
+
|
48 |
+
&-clear {
|
49 |
+
margin-left: 8px;
|
50 |
+
font-weight: 500;
|
51 |
+
color: #0085ba;
|
52 |
+
border: none;
|
53 |
+
background: none;
|
54 |
+
box-shadow: none;
|
55 |
+
|
56 |
+
&:hover, &:active, &:focus {
|
57 |
+
border: none;
|
58 |
+
background: none;
|
59 |
+
box-shadow: none;
|
60 |
+
}
|
61 |
+
}
|
62 |
+
}
|
63 |
+
}
|
64 |
+
}
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.wpra-gutenberg-block, [data-type="wpra-shortcode/wpra-shortcode"] {
|
2 |
+
.wpra-item {
|
3 |
+
// Prevent clicking on feed item links.
|
4 |
+
a {
|
5 |
+
pointer-events: none !important;
|
6 |
+
}
|
7 |
+
}
|
8 |
+
}
|
9 |
+
|
10 |
+
.nav-links::after {
|
11 |
+
display: block;
|
12 |
+
content: '';
|
13 |
+
clear: both;
|
14 |
+
}
|
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.wrpa-expander {
|
2 |
+
will-change: height;
|
3 |
+
transform: translateZ(0);
|
4 |
+
backface-visibility: hidden;
|
5 |
+
perspective: 1000px;
|
6 |
+
}
|
7 |
+
|
8 |
+
.expand-enter-active,
|
9 |
+
.expand-leave-active {
|
10 |
+
transition: height .35s ease;
|
11 |
+
overflow: hidden;
|
12 |
+
}
|
13 |
+
|
14 |
+
.expand-enter,
|
15 |
+
.expand-leave-to {
|
16 |
+
height: 0;
|
17 |
+
}
|
18 |
+
|
19 |
+
.fade-enter, .fade-leave-to {
|
20 |
+
opacity: 0;
|
21 |
+
}
|
22 |
+
.fade-enter-active, .fade-leave-active {
|
23 |
+
transition: opacity .3s ease;
|
24 |
+
}
|
25 |
+
|
26 |
+
.slide-up-enter {
|
27 |
+
transform: translateY(10px);
|
28 |
+
opacity: 0;
|
29 |
+
}
|
30 |
+
.slide-up-leave-to {
|
31 |
+
transform: translateY(-10px);
|
32 |
+
opacity: 0;
|
33 |
+
}
|
34 |
+
.slide-up-enter-active, .slide-up-leave-active {
|
35 |
+
transition: all .3s ease;
|
36 |
+
}
|
37 |
+
|
38 |
+
.slide-down-enter {
|
39 |
+
transform: translateY(-10px);
|
40 |
+
opacity: 0;
|
41 |
+
}
|
42 |
+
.slide-down-leave-to {
|
43 |
+
transform: translateY(10px);
|
44 |
+
opacity: 0;
|
45 |
+
}
|
46 |
+
.slide-down-enter-active, .slide-down-leave-active {
|
47 |
+
transition: all .3s ease;
|
48 |
+
}
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.wpra-expander {
|
2 |
+
&__title {
|
3 |
+
cursor: pointer;
|
4 |
+
user-select: none;
|
5 |
+
span {
|
6 |
+
opacity: .5;
|
7 |
+
vertical-align: bottom;
|
8 |
+
transition: transform .3s ease;
|
9 |
+
}
|
10 |
+
}
|
11 |
+
&__content {
|
12 |
+
padding: 0 .5rem;
|
13 |
+
opacity: 0;
|
14 |
+
transition: opacity .3s ease;
|
15 |
+
}
|
16 |
+
&--expanded {
|
17 |
+
.wpra-expander__content {
|
18 |
+
opacity: 1;
|
19 |
+
}
|
20 |
+
.wpra-expander__title {
|
21 |
+
span {
|
22 |
+
transform: rotate(180deg);
|
23 |
+
}
|
24 |
+
}
|
25 |
+
}
|
26 |
+
}
|
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
[v-cloak] {
|
2 |
+
.vcloak {
|
3 |
+
&--visible {
|
4 |
+
display: block;
|
5 |
+
}
|
6 |
+
&--hidden {
|
7 |
+
display: none;
|
8 |
+
}
|
9 |
+
}
|
10 |
+
}
|
11 |
+
.vcloak {
|
12 |
+
&--visible {
|
13 |
+
min-height: 60px;
|
14 |
+
display: none;
|
15 |
+
}
|
16 |
+
}
|
17 |
+
|
18 |
+
.loading-container {
|
19 |
+
position: relative;
|
20 |
+
&:before {
|
21 |
+
display: block;
|
22 |
+
content: '';
|
23 |
+
position: absolute;
|
24 |
+
left: calc(50% - 20px);
|
25 |
+
top: calc(50% - 20px);
|
26 |
+
box-sizing: border-box;
|
27 |
+
height: 40px;
|
28 |
+
width: 40px;
|
29 |
+
border: 0px solid #d0d0d0;
|
30 |
+
border-radius: 50%;
|
31 |
+
box-shadow: 0 -12px 0 16px #d0d0d0 inset;
|
32 |
+
animation: rotate 1s infinite linear;
|
33 |
+
z-index: 3;
|
34 |
+
}
|
35 |
+
&:after {
|
36 |
+
display: block;
|
37 |
+
content: '';
|
38 |
+
position: absolute;
|
39 |
+
z-index: 2;
|
40 |
+
background-color: rgba(241, 241, 241, 0.5);
|
41 |
+
width: 100%;
|
42 |
+
height: 100%;
|
43 |
+
left: 0;
|
44 |
+
top: 0;
|
45 |
+
}
|
46 |
+
&--white {
|
47 |
+
&:after {
|
48 |
+
background-color: white;
|
49 |
+
}
|
50 |
+
}
|
51 |
+
}
|
52 |
+
|
53 |
+
|
54 |
+
.loading-button {
|
55 |
+
pointer-events: none;
|
56 |
+
position: relative;
|
57 |
+
&:before {
|
58 |
+
display: block;
|
59 |
+
content: '';
|
60 |
+
position: absolute;
|
61 |
+
left: calc(50% - 8px);
|
62 |
+
top: calc(50% - 8px);
|
63 |
+
box-sizing: border-box;
|
64 |
+
height: 16px;
|
65 |
+
width: 16px;
|
66 |
+
border: 0px solid #fff;
|
67 |
+
border-radius: 50%;
|
68 |
+
box-shadow: 0 -4px 0 6px #fff inset;
|
69 |
+
animation: rotate 1s infinite linear;
|
70 |
+
z-index: 3;
|
71 |
+
}
|
72 |
+
&:after {
|
73 |
+
display: block;
|
74 |
+
content: '';
|
75 |
+
position: absolute;
|
76 |
+
z-index: 2;
|
77 |
+
background-color: inherit;
|
78 |
+
width: 100%;
|
79 |
+
height: 100%;
|
80 |
+
left: 0;
|
81 |
+
top: 0;
|
82 |
+
}
|
83 |
+
}
|
84 |
+
|
85 |
+
.button-default {
|
86 |
+
&.loading-button:before {
|
87 |
+
box-shadow: inset 0 -4px 0 6px #6f6f6f;
|
88 |
+
}
|
89 |
+
}
|
90 |
+
|
91 |
+
.loading-inline {
|
92 |
+
display: inline-block;
|
93 |
+
pointer-events: none;
|
94 |
+
position: relative;
|
95 |
+
&:before {
|
96 |
+
display: block;
|
97 |
+
content: '';
|
98 |
+
position: absolute;
|
99 |
+
left: calc(50% + 1px);
|
100 |
+
top: calc(50% - 11px);
|
101 |
+
box-sizing: border-box;
|
102 |
+
height: 14px;
|
103 |
+
width: 14px;
|
104 |
+
border: 0px solid #d0d0d0;
|
105 |
+
border-radius: 50%;
|
106 |
+
box-shadow: 0 -3px 0 5px #d0d0d0 inset;
|
107 |
+
animation: rotate 1s infinite linear;
|
108 |
+
z-index: 3;
|
109 |
+
}
|
110 |
+
&:after {
|
111 |
+
display: block;
|
112 |
+
content: '';
|
113 |
+
position: absolute;
|
114 |
+
z-index: 2;
|
115 |
+
background-color: inherit;
|
116 |
+
width: 100%;
|
117 |
+
height: 100%;
|
118 |
+
left: 0;
|
119 |
+
top: 0;
|
120 |
+
}
|
121 |
+
}
|
122 |
+
|
123 |
+
|
124 |
+
@keyframes rotate {
|
125 |
+
0% {
|
126 |
+
transform: rotate(0deg);
|
127 |
+
}
|
128 |
+
100% {
|
129 |
+
transform: rotate(360deg);
|
130 |
+
}
|
131 |
+
}
|
@@ -0,0 +1,647 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
$dark-gray: transparentize(#000, .25);
|
2 |
+
$medium-gray: transparentize(#000, .5);
|
3 |
+
$deep-gray: transparentize(#000, .95);
|
4 |
+
$light-gray: transparentize(#000, .95);
|
5 |
+
$borderColor: transparentize(#000, .95);
|
6 |
+
$white: #fff;
|
7 |
+
$button-radius: 4px;
|
8 |
+
|
9 |
+
$wizard-width: 42rem;
|
10 |
+
|
11 |
+
$success-color: #00b479;
|
12 |
+
$primary-color: #1a53e6;
|
13 |
+
|
14 |
+
@import "animation";
|
15 |
+
@import "expander";
|
16 |
+
@import "loading";
|
17 |
+
|
18 |
+
@mixin clear() {
|
19 |
+
&:after {
|
20 |
+
clear: both;
|
21 |
+
display: block;
|
22 |
+
content: '';
|
23 |
+
}
|
24 |
+
}
|
25 |
+
|
26 |
+
@mixin breakpoint($point) {
|
27 |
+
@if $point == desktop {
|
28 |
+
@media (min-width: 70em) { @content ; }
|
29 |
+
}
|
30 |
+
@else if $point == laptop {
|
31 |
+
@media (min-width: 64em) { @content ; }
|
32 |
+
}
|
33 |
+
@else if $point == tablet {
|
34 |
+
@media (max-width: 50em) { @content ; }
|
35 |
+
}
|
36 |
+
@else if $point == phablet {
|
37 |
+
@media (min-width: 37.5em) { @content ; }
|
38 |
+
}
|
39 |
+
@else if $point == mobileonly {
|
40 |
+
@media (max-width: 37.5em) { @content ; }
|
41 |
+
|
42 |
+
}
|
43 |
+
}
|
44 |
+
|
45 |
+
.wpra-wizard-head {
|
46 |
+
display: flex;
|
47 |
+
padding-bottom: 1.5rem;
|
48 |
+
padding-top: .75rem;
|
49 |
+
&__logo {
|
50 |
+
flex-shrink: 0;
|
51 |
+
img {
|
52 |
+
width: 57px;
|
53 |
+
}
|
54 |
+
}
|
55 |
+
&__copy {
|
56 |
+
flex-grow: 1;
|
57 |
+
padding-left: 1rem;
|
58 |
+
display: flex;
|
59 |
+
flex-direction: column;
|
60 |
+
justify-content: center;
|
61 |
+
}
|
62 |
+
&__title {
|
63 |
+
font-size: 1.25rem;
|
64 |
+
font-weight: 500;
|
65 |
+
padding-bottom: 12px;
|
66 |
+
}
|
67 |
+
&__subtitle {
|
68 |
+
font-size: 1rem;
|
69 |
+
opacity: .85;
|
70 |
+
}
|
71 |
+
}
|
72 |
+
|
73 |
+
.wpra-cols {
|
74 |
+
&-title {
|
75 |
+
font-weight: normal;
|
76 |
+
font-size: 1rem;
|
77 |
+
padding-bottom: 1rem;
|
78 |
+
}
|
79 |
+
|
80 |
+
display: flex;
|
81 |
+
margin: 0 -.5rem;
|
82 |
+
border-top: 2px solid rgba(0,0,0,.05);
|
83 |
+
padding-top: 1.45rem;
|
84 |
+
|
85 |
+
@include breakpoint(tablet) {
|
86 |
+
flex-wrap: wrap;
|
87 |
+
}
|
88 |
+
.col {
|
89 |
+
flex-basis: 50%;
|
90 |
+
padding: 0 .5rem;
|
91 |
+
|
92 |
+
@include breakpoint(tablet) {
|
93 |
+
flex-basis: 100%;
|
94 |
+
padding-bottom: 1rem;
|
95 |
+
}
|
96 |
+
|
97 |
+
img {
|
98 |
+
max-width: 100%;
|
99 |
+
}
|
100 |
+
|
101 |
+
p {
|
102 |
+
font-size: 14px;
|
103 |
+
line-height: 1.6;
|
104 |
+
}
|
105 |
+
p:first-child {
|
106 |
+
margin-top: 0;
|
107 |
+
}
|
108 |
+
}
|
109 |
+
}
|
110 |
+
|
111 |
+
.wpra-feed-input {
|
112 |
+
width: 26rem;
|
113 |
+
padding: 6px 10px;
|
114 |
+
max-width: 100%;
|
115 |
+
}
|
116 |
+
|
117 |
+
.wpra-feedback {
|
118 |
+
display: flex;
|
119 |
+
&__photo {
|
120 |
+
flex-shrink: 0;
|
121 |
+
img {
|
122 |
+
width: 70px;
|
123 |
+
border-radius: 100%;
|
124 |
+
}
|
125 |
+
}
|
126 |
+
&__copy {
|
127 |
+
padding-left: .5rem;
|
128 |
+
flex-grow: 1;
|
129 |
+
}
|
130 |
+
&__text {
|
131 |
+
font-size: 1rem;
|
132 |
+
font-family: Georgia, serif;
|
133 |
+
font-style: italic;
|
134 |
+
line-height: 1.5;
|
135 |
+
}
|
136 |
+
&__rating {
|
137 |
+
padding: .25rem 0 .45rem;
|
138 |
+
span {
|
139 |
+
color: #f8ca29;
|
140 |
+
}
|
141 |
+
}
|
142 |
+
&__by {
|
143 |
+
opacity: .85;
|
144 |
+
a {
|
145 |
+
color: #617181;
|
146 |
+
}
|
147 |
+
}
|
148 |
+
}
|
149 |
+
|
150 |
+
.wpra-demo-photo {
|
151 |
+
margin-bottom: 1rem;
|
152 |
+
border-radius: 4px;
|
153 |
+
border: 1px solid rgba(0, 0, 0, 0.15);
|
154 |
+
}
|
155 |
+
|
156 |
+
.wpra-feed-items {
|
157 |
+
padding-left: .5rem;
|
158 |
+
margin-bottom: 1rem;
|
159 |
+
border-left: 4px solid #ff792b;
|
160 |
+
.wpra-feed-item {
|
161 |
+
padding: .75rem;
|
162 |
+
&__link {
|
163 |
+
padding-bottom: 4px;
|
164 |
+
}
|
165 |
+
}
|
166 |
+
}
|
167 |
+
|
168 |
+
.step-items {
|
169 |
+
$size: 35px;
|
170 |
+
|
171 |
+
display: flex;
|
172 |
+
position: relative;
|
173 |
+
|
174 |
+
flex-direction: column;
|
175 |
+
align-items: flex-end;
|
176 |
+
|
177 |
+
.step-progress {
|
178 |
+
position: absolute;
|
179 |
+
width: 3px;
|
180 |
+
height: 0;
|
181 |
+
background-color: $success-color;
|
182 |
+
left: $size / 2;
|
183 |
+
top: 0;
|
184 |
+
transition: height .3s ease;
|
185 |
+
z-index: -1;
|
186 |
+
&--1 {
|
187 |
+
height: 50%;
|
188 |
+
}
|
189 |
+
&--2 {
|
190 |
+
height: 100%;
|
191 |
+
}
|
192 |
+
|
193 |
+
@include breakpoint(tablet) {
|
194 |
+
display: none;
|
195 |
+
}
|
196 |
+
}
|
197 |
+
|
198 |
+
@include breakpoint(tablet) {
|
199 |
+
padding: .625rem;
|
200 |
+
flex-direction: row;
|
201 |
+
align-items: flex-start;
|
202 |
+
}
|
203 |
+
|
204 |
+
.step-item {
|
205 |
+
font-size: 16px;
|
206 |
+
width: 15rem;
|
207 |
+
margin-bottom: 2.25rem;
|
208 |
+
display: flex;
|
209 |
+
background-color: #f1f1f1;
|
210 |
+
|
211 |
+
&:last-child {
|
212 |
+
margin-bottom: 0;
|
213 |
+
}
|
214 |
+
|
215 |
+
@include breakpoint(tablet) {
|
216 |
+
flex-direction: column;
|
217 |
+
margin-bottom: 0;
|
218 |
+
align-items: center;
|
219 |
+
}
|
220 |
+
|
221 |
+
&_active {
|
222 |
+
.step-item__info {
|
223 |
+
opacity: 1;
|
224 |
+
}
|
225 |
+
.step-item__status {
|
226 |
+
opacity: 1;
|
227 |
+
}
|
228 |
+
opacity: 1;
|
229 |
+
@include breakpoint(tablet) {
|
230 |
+
flex-grow: 1;
|
231 |
+
}
|
232 |
+
}
|
233 |
+
&__title {
|
234 |
+
}
|
235 |
+
&__description {
|
236 |
+
//color: $dark-gray;
|
237 |
+
font-size: 14px;
|
238 |
+
}
|
239 |
+
|
240 |
+
&__info {
|
241 |
+
display: flex;
|
242 |
+
align-items: center;
|
243 |
+
padding-left: .75rem;
|
244 |
+
opacity: .5;
|
245 |
+
@include breakpoint(tablet) {
|
246 |
+
padding-left: 0;
|
247 |
+
padding-top: .3rem;
|
248 |
+
display: none;
|
249 |
+
}
|
250 |
+
}
|
251 |
+
|
252 |
+
&__status {
|
253 |
+
width: $size;
|
254 |
+
height: $size;
|
255 |
+
border-radius: 50%;
|
256 |
+
border: 2px dashed $medium-gray;
|
257 |
+
flex-shrink: 0;
|
258 |
+
opacity: .5;
|
259 |
+
|
260 |
+
text-align: center;
|
261 |
+
font-size: 1.25rem;
|
262 |
+
line-height: 2.375rem;
|
263 |
+
|
264 |
+
color: $success-color;
|
265 |
+
|
266 |
+
span {
|
267 |
+
display: block;
|
268 |
+
margin: 0 !important;
|
269 |
+
width: 100%;
|
270 |
+
line-height: 35px;
|
271 |
+
font-size: 26px;
|
272 |
+
}
|
273 |
+
}
|
274 |
+
|
275 |
+
&_completed {
|
276 |
+
opacity: 1;
|
277 |
+
.step-item {
|
278 |
+
&__status {
|
279 |
+
border-style: solid;
|
280 |
+
border-color: $success-color;
|
281 |
+
opacity: 1;
|
282 |
+
|
283 |
+
span {
|
284 |
+
position: relative;
|
285 |
+
}
|
286 |
+
}
|
287 |
+
&__info {
|
288 |
+
opacity: .5;
|
289 |
+
}
|
290 |
+
}
|
291 |
+
}
|
292 |
+
}
|
293 |
+
}
|
294 |
+
|
295 |
+
.wizard {
|
296 |
+
width: 100%;
|
297 |
+
margin-left: 1rem;
|
298 |
+
|
299 |
+
@include breakpoint(tablet) {
|
300 |
+
margin-left: 0;
|
301 |
+
}
|
302 |
+
|
303 |
+
ol {
|
304 |
+
margin-left: 1.5rem;
|
305 |
+
line-height: 1.5;
|
306 |
+
font-size: 13px;
|
307 |
+
ul {
|
308 |
+
margin-bottom: 1rem;
|
309 |
+
}
|
310 |
+
}
|
311 |
+
|
312 |
+
.form-group {
|
313 |
+
display: flex;
|
314 |
+
align-items: center;
|
315 |
+
@include breakpoint(tablet) {
|
316 |
+
display: block;
|
317 |
+
align-items: unset;
|
318 |
+
input {
|
319 |
+
margin-bottom: 8px;
|
320 |
+
}
|
321 |
+
}
|
322 |
+
input {
|
323 |
+
flex-shrink: 0;
|
324 |
+
}
|
325 |
+
.warning-icon {
|
326 |
+
padding-left: 4px;
|
327 |
+
color: #ee5a65;
|
328 |
+
}
|
329 |
+
a {
|
330 |
+
flex-shrink: 0;
|
331 |
+
margin-left: 6px;
|
332 |
+
}
|
333 |
+
}
|
334 |
+
|
335 |
+
.button-clear {
|
336 |
+
background-color: transparent;
|
337 |
+
border: none;
|
338 |
+
cursor: pointer;
|
339 |
+
height: 30px;
|
340 |
+
line-height: 28px;
|
341 |
+
padding: 0 12px 2px;
|
342 |
+
vertical-align: baseline;
|
343 |
+
|
344 |
+
opacity: .55;
|
345 |
+
&:hover {
|
346 |
+
opacity: .8;
|
347 |
+
}
|
348 |
+
}
|
349 |
+
|
350 |
+
.button {
|
351 |
+
vertical-align: baseline !important;
|
352 |
+
}
|
353 |
+
|
354 |
+
.pad {
|
355 |
+
display: flex;
|
356 |
+
&-item {
|
357 |
+
&--grow {
|
358 |
+
flex-grow: 1;
|
359 |
+
}
|
360 |
+
&--no-shrink {
|
361 |
+
flex-shrink: 0;
|
362 |
+
}
|
363 |
+
}
|
364 |
+
}
|
365 |
+
|
366 |
+
.wpra-success {
|
367 |
+
padding-right: 1rem;
|
368 |
+
font-size: 14px;
|
369 |
+
}
|
370 |
+
|
371 |
+
&_content {
|
372 |
+
padding: 1rem;
|
373 |
+
font-size: 14px;
|
374 |
+
max-width: $wizard-width;
|
375 |
+
min-height: 16rem;
|
376 |
+
padding-top: 12px;
|
377 |
+
|
378 |
+
@include breakpoint(tablet) {
|
379 |
+
padding: 0;
|
380 |
+
}
|
381 |
+
}
|
382 |
+
|
383 |
+
&-holder {
|
384 |
+
width: 100%;
|
385 |
+
position: relative;
|
386 |
+
display: flex;
|
387 |
+
//align-items: center;
|
388 |
+
//justify-content: center;
|
389 |
+
|
390 |
+
@include breakpoint(tablet) {
|
391 |
+
flex-direction: column;
|
392 |
+
}
|
393 |
+
|
394 |
+
.connect-steps {
|
395 |
+
flex-shrink: 0;
|
396 |
+
max-width: 450px;
|
397 |
+
padding: 1rem;
|
398 |
+
|
399 |
+
@include breakpoint(tablet) {
|
400 |
+
max-width: 100%;
|
401 |
+
flex-basis: auto;
|
402 |
+
padding: .5rem;
|
403 |
+
}
|
404 |
+
}
|
405 |
+
|
406 |
+
.wizard {
|
407 |
+
//background-color: #00aced;
|
408 |
+
|
409 |
+
flex-grow: 1;
|
410 |
+
}
|
411 |
+
}
|
412 |
+
|
413 |
+
&_text {
|
414 |
+
padding: 0 0 25px 0;
|
415 |
+
max-width: 480px;
|
416 |
+
font-size: 14px;
|
417 |
+
}
|
418 |
+
|
419 |
+
&_more {
|
420 |
+
user-select: none;
|
421 |
+
display: inline-block;
|
422 |
+
color: $medium-gray;
|
423 |
+
font-size: 12px;
|
424 |
+
margin-top: 20px;
|
425 |
+
|
426 |
+
&:hover {
|
427 |
+
cursor: pointer;
|
428 |
+
text-decoration: underline;
|
429 |
+
}
|
430 |
+
}
|
431 |
+
|
432 |
+
&_hello {
|
433 |
+
font-size: 18px;
|
434 |
+
margin: 15px 0 10px 0;
|
435 |
+
img {
|
436 |
+
height: 26px;
|
437 |
+
vertical-align: sub;
|
438 |
+
margin-right: 3px;
|
439 |
+
}
|
440 |
+
}
|
441 |
+
|
442 |
+
&_button {
|
443 |
+
min-width: 137px;
|
444 |
+
margin: 0 .3rem 1rem .3rem;
|
445 |
+
}
|
446 |
+
|
447 |
+
&_buttons {
|
448 |
+
margin: 0 -.5rem;
|
449 |
+
display: flex;
|
450 |
+
|
451 |
+
@include breakpoint(tablet) {
|
452 |
+
flex-direction: row;
|
453 |
+
flex-wrap: wrap;
|
454 |
+
}
|
455 |
+
}
|
456 |
+
&_network {
|
457 |
+
//flex-shrink: 1;
|
458 |
+
//width: 33%;
|
459 |
+
padding: 0 .5rem;
|
460 |
+
margin-bottom: .35rem;
|
461 |
+
//text-align: center;
|
462 |
+
|
463 |
+
.button {
|
464 |
+
min-width: 145px;
|
465 |
+
text-align: center;
|
466 |
+
i {
|
467 |
+
margin-left: 4px;
|
468 |
+
}
|
469 |
+
}
|
470 |
+
|
471 |
+
.button-transparent {
|
472 |
+
margin-bottom: 10px;
|
473 |
+
}
|
474 |
+
|
475 |
+
&-icon {
|
476 |
+
width: 50px;
|
477 |
+
height: 50px;
|
478 |
+
border-radius: 100%;
|
479 |
+
background-color: lighten($light-gray, 7);
|
480 |
+
margin: 0 auto .8rem auto;
|
481 |
+
i {
|
482 |
+
font-size: 22px;
|
483 |
+
line-height: 50px;
|
484 |
+
}
|
485 |
+
}
|
486 |
+
}
|
487 |
+
|
488 |
+
&_list {
|
489 |
+
padding: 10px 0;
|
490 |
+
display: flex;
|
491 |
+
flex-wrap: wrap;
|
492 |
+
margin: 0 -0.3125rem;
|
493 |
+
max-width: 49rem;
|
494 |
+
}
|
495 |
+
|
496 |
+
&_item {
|
497 |
+
padding: 5px;
|
498 |
+
margin: 5px;
|
499 |
+
border: 1px solid $borderColor;
|
500 |
+
display: flex;
|
501 |
+
|
502 |
+
width: 31%;
|
503 |
+
align-items: center;
|
504 |
+
|
505 |
+
@include breakpoint(tablet) {
|
506 |
+
width: 100%;
|
507 |
+
margin: 0;
|
508 |
+
margin-bottom: .625rem;
|
509 |
+
}
|
510 |
+
|
511 |
+
vertical-align: middle;
|
512 |
+
border-radius: $button-radius;
|
513 |
+
text-align: left;
|
514 |
+
|
515 |
+
.description {
|
516 |
+
font-size: 12px;
|
517 |
+
color: $dark-gray;
|
518 |
+
margin-top: 2px;
|
519 |
+
}
|
520 |
+
|
521 |
+
.account-item_picture {
|
522 |
+
float: none;
|
523 |
+
margin-right: 10px;
|
524 |
+
flex-shrink: 0;
|
525 |
+
}
|
526 |
+
}
|
527 |
+
|
528 |
+
/*
|
529 |
+
* This is form
|
530 |
+
*/
|
531 |
+
&_info {
|
532 |
+
max-width: 20rem;
|
533 |
+
text-align: left;
|
534 |
+
|
535 |
+
.form-group {
|
536 |
+
margin-bottom: 1rem;
|
537 |
+
}
|
538 |
+
}
|
539 |
+
|
540 |
+
&_label {
|
541 |
+
font-size: 1rem;
|
542 |
+
padding-top: .2rem;
|
543 |
+
padding-bottom: .75rem;
|
544 |
+
}
|
545 |
+
}
|
546 |
+
|
547 |
+
.wrpa-shortcode {
|
548 |
+
display: flex;
|
549 |
+
&-form, &-preview {
|
550 |
+
padding-bottom: 10px;
|
551 |
+
padding-right: 75px;
|
552 |
+
flex-basis: 50%;
|
553 |
+
.wrpa-shortcode-label {
|
554 |
+
font-size: 1rem;
|
555 |
+
padding-bottom: 12px;
|
556 |
+
line-height: 1.5;
|
557 |
+
}
|
558 |
+
.button.loading-button {
|
559 |
+
&::before {
|
560 |
+
box-shadow: inset 0 -4px 0 6px #797979 !important;
|
561 |
+
}
|
562 |
+
}
|
563 |
+
}
|
564 |
+
.wrpa-shortcode-form {
|
565 |
+
cursor: pointer;
|
566 |
+
.wrpa-shortcode-form__shortcode {
|
567 |
+
display: inline-block;
|
568 |
+
}
|
569 |
+
.wrpa-shortcode-form__button {
|
570 |
+
display: inline-block;
|
571 |
+
opacity: .65;
|
572 |
+
font-size: 11px;
|
573 |
+
font-style: italic;
|
574 |
+
padding-right: 3px;
|
575 |
+
}
|
576 |
+
}
|
577 |
+
}
|
578 |
+
|
579 |
+
.connect {
|
580 |
+
&_progress {
|
581 |
+
position: absolute;
|
582 |
+
left: calc(50% - 22px);
|
583 |
+
top: 30px;
|
584 |
+
|
585 |
+
@include clear;
|
586 |
+
|
587 |
+
&-point {
|
588 |
+
display: block;
|
589 |
+
float: left;
|
590 |
+
margin-left: 5px;
|
591 |
+
width: 8px;
|
592 |
+
height: 8px;
|
593 |
+
border-radius: 100%;
|
594 |
+
background-color: transparentize($primary-color, .7);
|
595 |
+
|
596 |
+
&__active {
|
597 |
+
border: 1px solid $primary-color;
|
598 |
+
}
|
599 |
+
|
600 |
+
&__done {
|
601 |
+
background-color: $primary-color;
|
602 |
+
}
|
603 |
+
}
|
604 |
+
}
|
605 |
+
}
|
606 |
+
|
607 |
+
.connect-actions {
|
608 |
+
width: 100%;
|
609 |
+
max-width: $wizard-width;
|
610 |
+
border-top: 2px solid $light-gray;
|
611 |
+
padding: 1rem 0;
|
612 |
+
|
613 |
+
.button {
|
614 |
+
margin: 0;
|
615 |
+
}
|
616 |
+
|
617 |
+
@include breakpoint(tablet) {
|
618 |
+
padding-bottom: 2rem;
|
619 |
+
}
|
620 |
+
|
621 |
+
.fa-animated {
|
622 |
+
font-size: 2rem;
|
623 |
+
color: transparentize($primary-color, .35);
|
624 |
+
vertical-align: middle;
|
625 |
+
margin-right: 5px;
|
626 |
+
}
|
627 |
+
}
|
628 |
+
|
629 |
+
@keyframes moveRightLeftLoop {
|
630 |
+
0% {
|
631 |
+
transform: translateX(-10px);
|
632 |
+
}
|
633 |
+
|
634 |
+
50% {
|
635 |
+
transform: translateX(0);
|
636 |
+
}
|
637 |
+
|
638 |
+
100% {
|
639 |
+
transform: translateX(-10px);
|
640 |
+
}
|
641 |
+
}
|
642 |
+
|
643 |
+
.moveRightLeftLoop {
|
644 |
+
animation-iteration-count: infinite;
|
645 |
+
animation-name: moveRightLeftLoop;
|
646 |
+
animation-duration: 1000ms;
|
647 |
+
}
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// grid
|
2 |
+
$breakpoint-small: 782px; // 540px
|
3 |
+
$breakpoint-med: 60em; // 720px
|
4 |
+
$breakpoint-large: 68em; // 960px
|
5 |
+
|
6 |
+
@mixin breakpoint($point) {
|
7 |
+
@if $point == desktop {
|
8 |
+
@media (min-width: $breakpoint-large) { @content ; }
|
9 |
+
}
|
10 |
+
@else if $point == mobile {
|
11 |
+
@media (max-width: $breakpoint-small) { @content ; }
|
12 |
+
}
|
13 |
+
@else if $point == not-mobile {
|
14 |
+
@media (min-width: $breakpoint-small) { @content ; }
|
15 |
+
}
|
16 |
+
}
|
17 |
+
|
18 |
+
.mobile-collapsed {
|
19 |
+
display: inherit;
|
20 |
+
}
|
21 |
+
.mobile-only {
|
22 |
+
display: none !important;
|
23 |
+
}
|
24 |
+
|
25 |
+
@include breakpoint(mobile) {
|
26 |
+
.mobile-only {
|
27 |
+
display: inherit !important;
|
28 |
+
}
|
29 |
+
.mobile-collapsed {
|
30 |
+
display: none !important;
|
31 |
+
}
|
32 |
+
}
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.wpra-loading {
|
2 |
+
animation: pulse 1s infinite ease-in-out;
|
3 |
+
pointer-events: none;
|
4 |
+
}
|
5 |
+
|
6 |
+
@keyframes pulse {
|
7 |
+
0% { opacity: .25; }
|
8 |
+
50% { opacity: .6; }
|
9 |
+
100% { opacity: .25; }
|
10 |
+
}
|
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.form {
|
2 |
+
&-check {
|
3 |
+
input {
|
4 |
+
display: inline-block !important;
|
5 |
+
width: auto !important;
|
6 |
+
margin: 0 4px 0 0;
|
7 |
+
}
|
8 |
+
label {
|
9 |
+
display: inline-block !important;
|
10 |
+
}
|
11 |
+
padding: 4px 0;
|
12 |
+
}
|
13 |
+
&-group {
|
14 |
+
padding-bottom: 8px;
|
15 |
+
label {
|
16 |
+
display: block;
|
17 |
+
}
|
18 |
+
& > label {
|
19 |
+
margin-bottom: 2px;
|
20 |
+
}
|
21 |
+
input, textarea {
|
22 |
+
display: block;
|
23 |
+
width: 100%;
|
24 |
+
}
|
25 |
+
&:last-child {
|
26 |
+
padding-bottom: 0;
|
27 |
+
}
|
28 |
+
p {
|
29 |
+
&:first-child {
|
30 |
+
margin-top: 0;
|
31 |
+
}
|
32 |
+
&:last-child {
|
33 |
+
margin-bottom: 0;
|
34 |
+
}
|
35 |
+
}
|
36 |
+
.error {
|
37 |
+
margin: 0 !important;
|
38 |
+
}
|
39 |
+
}
|
40 |
+
}
|
41 |
+
|
42 |
+
.wpra-plugin-disable-poll {
|
43 |
+
&__logo {
|
44 |
+
img {
|
45 |
+
max-height: 40px;
|
46 |
+
}
|
47 |
+
}
|
48 |
+
}
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
$white: #fff;
|
2 |
+
$radius: 4px;
|
3 |
+
|
4 |
+
@mixin breakpoint($point) {
|
5 |
+
@if $point == desktop {
|
6 |
+
@media (min-width: 70em) { @content ; }
|
7 |
+
}
|
8 |
+
@else if $point == laptop {
|
9 |
+
@media (min-width: 64em) { @content ; }
|
10 |
+
}
|
11 |
+
@else if $point == tablet {
|
12 |
+
@media (max-width: 50em) { @content ; }
|
13 |
+
}
|
14 |
+
@else if $point == phablet {
|
15 |
+
@media (min-width: 37.5em) { @content ; }
|
16 |
+
}
|
17 |
+
@else if $point == mobileonly {
|
18 |
+
@media (max-width: 37.5em) { @content ; }
|
19 |
+
|
20 |
+
}
|
21 |
+
}
|
22 |
+
|
23 |
+
@import "./../intro/loading";
|
24 |
+
@import "modal";
|
25 |
+
@import "form";
|
@@ -0,0 +1,173 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.modal {
|
2 |
+
&-opened {
|
3 |
+
overflow: hidden;
|
4 |
+
}
|
5 |
+
|
6 |
+
position: fixed;
|
7 |
+
background-color: rgba(0, 0, 0, 0.65);
|
8 |
+
width: 100%;
|
9 |
+
height: 100%;
|
10 |
+
left: 0;
|
11 |
+
top: 0;
|
12 |
+
z-index: 9999;
|
13 |
+
overflow-y: auto;
|
14 |
+
|
15 |
+
@include breakpoint(mobile) {
|
16 |
+
z-index: 100000;
|
17 |
+
}
|
18 |
+
|
19 |
+
&__body {
|
20 |
+
width: 100%;
|
21 |
+
max-width: 30rem;
|
22 |
+
margin: 5rem auto;
|
23 |
+
|
24 |
+
background-color: $white;
|
25 |
+
border-radius: $radius;
|
26 |
+
|
27 |
+
&--no-content-padding {
|
28 |
+
.modal__content {
|
29 |
+
padding: 0;
|
30 |
+
}
|
31 |
+
}
|
32 |
+
|
33 |
+
&--wide {
|
34 |
+
max-width: 50rem;
|
35 |
+
}
|
36 |
+
|
37 |
+
@include breakpoint(mobile) {
|
38 |
+
min-height: 100vh;
|
39 |
+
margin: 0;
|
40 |
+
border-radius: 0;
|
41 |
+
}
|
42 |
+
}
|
43 |
+
|
44 |
+
&__header {
|
45 |
+
padding: .5rem 1rem;
|
46 |
+
font-size: 20px;
|
47 |
+
font-weight: bold;
|
48 |
+
line-height: 1.5;
|
49 |
+
border-bottom: 1px solid #eee;
|
50 |
+
|
51 |
+
&.invisible-header {
|
52 |
+
border: none;
|
53 |
+
font-size: unset;
|
54 |
+
font-weight: unset;
|
55 |
+
padding-top: 12px !important;
|
56 |
+
h3 {
|
57 |
+
margin-top: 0;
|
58 |
+
line-height: 1.5;
|
59 |
+
margin-bottom: 0;
|
60 |
+
}
|
61 |
+
p {
|
62 |
+
margin-top: .25rem;
|
63 |
+
font-size: 14px;
|
64 |
+
opacity: .6;
|
65 |
+
margin-bottom: 0;
|
66 |
+
}
|
67 |
+
& + .modal__content {
|
68 |
+
padding-top: 6px !important;
|
69 |
+
}
|
70 |
+
}
|
71 |
+
|
72 |
+
@include breakpoint(mobile) {
|
73 |
+
position: relative;
|
74 |
+
|
75 |
+
.modal--right {
|
76 |
+
position: absolute;
|
77 |
+
top: 0;
|
78 |
+
padding: 6px 1rem 0 1rem;
|
79 |
+
right: 0;
|
80 |
+
background-color: white;
|
81 |
+
}
|
82 |
+
}
|
83 |
+
|
84 |
+
&-buttons {
|
85 |
+
font-weight: normal;
|
86 |
+
}
|
87 |
+
}
|
88 |
+
|
89 |
+
&__close {
|
90 |
+
opacity: .5;
|
91 |
+
cursor: pointer;
|
92 |
+
&:hover {
|
93 |
+
opacity: .8;
|
94 |
+
}
|
95 |
+
}
|
96 |
+
|
97 |
+
&--right {
|
98 |
+
float: right;
|
99 |
+
}
|
100 |
+
|
101 |
+
&__content {
|
102 |
+
padding: 1rem;
|
103 |
+
}
|
104 |
+
|
105 |
+
&__footer {
|
106 |
+
padding: 1rem;
|
107 |
+
border-top: 1px solid #eee;
|
108 |
+
text-align: right;
|
109 |
+
|
110 |
+
.button {
|
111 |
+
display: inline-block !important;
|
112 |
+
margin-left: 4px !important;
|
113 |
+
}
|
114 |
+
.footer-confirm {
|
115 |
+
margin: 0;
|
116 |
+
padding: 0;
|
117 |
+
display: flex;
|
118 |
+
align-items: center;
|
119 |
+
|
120 |
+
@include breakpoint(mobile) {
|
121 |
+
display: block;
|
122 |
+
&__message {
|
123 |
+
padding-right: 0;
|
124 |
+
padding-bottom: 10px;
|
125 |
+
}
|
126 |
+
}
|
127 |
+
|
128 |
+
&__buttons {
|
129 |
+
flex-shrink: 0;
|
130 |
+
|
131 |
+
&--left {
|
132 |
+
margin-right: auto;
|
133 |
+
flex-grow: 1;
|
134 |
+
text-align: left;
|
135 |
+
}
|
136 |
+
}
|
137 |
+
|
138 |
+
&__message {
|
139 |
+
margin-right: auto;
|
140 |
+
&.__right {
|
141 |
+
flex-grow: 1;
|
142 |
+
padding-right: 10px;
|
143 |
+
text-align: right;
|
144 |
+
}
|
145 |
+
}
|
146 |
+
}
|
147 |
+
}
|
148 |
+
}
|
149 |
+
|
150 |
+
.modal-transition {
|
151 |
+
&-enter, &-leave-to {
|
152 |
+
opacity: 0;
|
153 |
+
|
154 |
+
.modal__body {
|
155 |
+
opacity: 0;
|
156 |
+
transform: scaleX(.8) scaleY(.7);
|
157 |
+
}
|
158 |
+
}
|
159 |
+
|
160 |
+
&-enter-active, &-leave-active {
|
161 |
+
transition: opacity 0.25s ease-out;
|
162 |
+
|
163 |
+
.modal__body {
|
164 |
+
transition: all .25s cubic-bezier(.665,1.65,0,.845);
|
165 |
+
}
|
166 |
+
}
|
167 |
+
}
|
168 |
+
|
169 |
+
.button-clear {
|
170 |
+
border: none !important;
|
171 |
+
background: transparent !important;
|
172 |
+
box-shadow: none !important;
|
173 |
+
}
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.wpra-bottom-panel {
|
2 |
+
position: sticky;
|
3 |
+
bottom: 0;
|
4 |
+
z-index: 9;
|
5 |
+
background-color: #fffce9;
|
6 |
+
padding: 1rem;
|
7 |
+
border: 1px solid #e5e5e5;
|
8 |
+
box-shadow: 0 1px 1px rgba(0,0,0,0.04);
|
9 |
+
|
10 |
+
&__title {
|
11 |
+
font-size: 1rem;
|
12 |
+
font-weight: 500;
|
13 |
+
padding-bottom: 8px;
|
14 |
+
}
|
15 |
+
}
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.flex {
|
2 |
+
&-row {
|
3 |
+
display: flex;
|
4 |
+
}
|
5 |
+
&-col {
|
6 |
+
box-sizing: border-box;
|
7 |
+
padding: 0 10px;
|
8 |
+
flex: 1 1 0;
|
9 |
+
|
10 |
+
&:first-child {
|
11 |
+
padding-left: 0;
|
12 |
+
}
|
13 |
+
|
14 |
+
&:last-child {
|
15 |
+
padding-right: 0;
|
16 |
+
}
|
17 |
+
}
|
18 |
+
}
|
@@ -0,0 +1,216 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
@import "./../mixins";
|
2 |
+
@import "bottom-panel";
|
3 |
+
@import "loading";
|
4 |
+
@import "notifications";
|
5 |
+
@import "grid";
|
6 |
+
|
7 |
+
.wpra-postbox {
|
8 |
+
.hndle {
|
9 |
+
cursor: unset !important;
|
10 |
+
}
|
11 |
+
}
|
12 |
+
|
13 |
+
.wpra-shortcode-copy {
|
14 |
+
font-size: 13px;
|
15 |
+
background-color: #fff;
|
16 |
+
margin-left: auto;
|
17 |
+
padding: 9px 14px;
|
18 |
+
box-shadow: 0 1px 1px 0 rgba(0,0,0,0.1);
|
19 |
+
|
20 |
+
border-left: 4px solid #0085ba;
|
21 |
+
|
22 |
+
display: flex;
|
23 |
+
align-items: center;
|
24 |
+
|
25 |
+
@include breakpoint (mobile) {
|
26 |
+
display: block;
|
27 |
+
}
|
28 |
+
|
29 |
+
&__icon {
|
30 |
+
padding-left: 16px;
|
31 |
+
|
32 |
+
@include breakpoint (mobile) {
|
33 |
+
padding-left: 0;
|
34 |
+
margin-top: 1rem;
|
35 |
+
}
|
36 |
+
}
|
37 |
+
}
|
38 |
+
|
39 |
+
.page-title {
|
40 |
+
display: flex;
|
41 |
+
align-items: center;
|
42 |
+
padding: 9px 0 4px 0;
|
43 |
+
|
44 |
+
@include breakpoint (mobile) {
|
45 |
+
display: block;
|
46 |
+
}
|
47 |
+
|
48 |
+
a {
|
49 |
+
&:focus {
|
50 |
+
text-decoration: none;
|
51 |
+
}
|
52 |
+
}
|
53 |
+
|
54 |
+
h1 {
|
55 |
+
margin-left: 6px;
|
56 |
+
padding: 0;
|
57 |
+
}
|
58 |
+
}
|
59 |
+
|
60 |
+
.back-button {
|
61 |
+
opacity: .75;
|
62 |
+
text-decoration: none;
|
63 |
+
font-size: 20px;
|
64 |
+
display: flex;
|
65 |
+
align-items: center;
|
66 |
+
padding-right: 10px;
|
67 |
+
margin-right: 4px;
|
68 |
+
border-right: 1px solid #b4b4b4;
|
69 |
+
|
70 |
+
@include breakpoint (mobile) {
|
71 |
+
border-right: none;
|
72 |
+
margin-bottom: .5rem;
|
73 |
+
}
|
74 |
+
|
75 |
+
.dashicons {
|
76 |
+
margin-right: 8px;
|
77 |
+
}
|
78 |
+
}
|
79 |
+
|
80 |
+
.tippy-tooltip.light-theme {
|
81 |
+
font-size: 13px !important;
|
82 |
+
font-family: unset !important;
|
83 |
+
text-align: left !important;
|
84 |
+
|
85 |
+
hr {
|
86 |
+
border: none;
|
87 |
+
height: 1px;
|
88 |
+
background-color: #efefef;
|
89 |
+
}
|
90 |
+
}
|
91 |
+
|
92 |
+
.form-input {
|
93 |
+
display: flex;
|
94 |
+
margin: .75rem 0;
|
95 |
+
&--disabled {
|
96 |
+
pointer-events: none;
|
97 |
+
.form-input__label {
|
98 |
+
*:not(.disable-ignored) {
|
99 |
+
opacity: .5;
|
100 |
+
user-select: none;
|
101 |
+
}
|
102 |
+
}
|
103 |
+
}
|
104 |
+
.disable-ignored {
|
105 |
+
opacity: 1;
|
106 |
+
}
|
107 |
+
&--vertical {
|
108 |
+
flex-direction: column;
|
109 |
+
.form-input__label {
|
110 |
+
padding-right: 0;
|
111 |
+
padding-bottom: 4px;
|
112 |
+
flex-basis: 100%;
|
113 |
+
}
|
114 |
+
}
|
115 |
+
|
116 |
+
@include breakpoint(mobile) {
|
117 |
+
flex-direction: column;
|
118 |
+
.form-input__label {
|
119 |
+
padding-right: 0;
|
120 |
+
padding-bottom: 4px;
|
121 |
+
flex-basis: 100%;
|
122 |
+
}
|
123 |
+
}
|
124 |
+
|
125 |
+
&:last-child {
|
126 |
+
margin-bottom: 0;
|
127 |
+
}
|
128 |
+
&__tip {
|
129 |
+
cursor: pointer;
|
130 |
+
display: inline-block;
|
131 |
+
margin-left: 4px;
|
132 |
+
opacity: .25;
|
133 |
+
vertical-align: middle;
|
134 |
+
&:hover {
|
135 |
+
opacity: .85;
|
136 |
+
}
|
137 |
+
.dashicons {
|
138 |
+
font-size: 18px;
|
139 |
+
}
|
140 |
+
}
|
141 |
+
&__label {
|
142 |
+
padding-right: 12px;
|
143 |
+
flex-basis: 260px;
|
144 |
+
&-description {
|
145 |
+
padding-top: 2px;
|
146 |
+
padding-right: 10px;
|
147 |
+
line-height: 1.65;
|
148 |
+
opacity: .6;
|
149 |
+
font-size: 12px;
|
150 |
+
|
151 |
+
a {
|
152 |
+
pointer-events: auto !important;
|
153 |
+
}
|
154 |
+
}
|
155 |
+
}
|
156 |
+
&__field {
|
157 |
+
flex-grow: 1;
|
158 |
+
input:not([type="checkbox"]), textarea, select {
|
159 |
+
width: 100%;
|
160 |
+
max-width: 325px;
|
161 |
+
}
|
162 |
+
}
|
163 |
+
}
|
164 |
+
|
165 |
+
.built-in {
|
166 |
+
background: #f1f1f1;
|
167 |
+
|
168 |
+
[type="checkbox"] {
|
169 |
+
display: none;
|
170 |
+
}
|
171 |
+
}
|
172 |
+
|
173 |
+
.wpra-preview-link {
|
174 |
+
vertical-align: middle;
|
175 |
+
|
176 |
+
span.dashicons {
|
177 |
+
opacity: .75;
|
178 |
+
font-size: 16px;
|
179 |
+
vertical-align: middle;
|
180 |
+
}
|
181 |
+
}
|
182 |
+
|
183 |
+
.wpra-no-cb {
|
184 |
+
.column-cb {
|
185 |
+
input[type="checkbox"] {
|
186 |
+
display: none;
|
187 |
+
}
|
188 |
+
}
|
189 |
+
}
|
190 |
+
|
191 |
+
.column.name {
|
192 |
+
small {
|
193 |
+
@include breakpoint (mobile) {
|
194 |
+
display: block;
|
195 |
+
}
|
196 |
+
}
|
197 |
+
}
|
198 |
+
|
199 |
+
.inside {
|
200 |
+
.wpra-preview-link {
|
201 |
+
@include breakpoint (mobile) {
|
202 |
+
float: none;
|
203 |
+
}
|
204 |
+
}
|
205 |
+
}
|
206 |
+
|
207 |
+
.wpra-postbox-container {
|
208 |
+
@include breakpoint (mobile) {
|
209 |
+
display: flex;
|
210 |
+
flex-direction: column;
|
211 |
+
|
212 |
+
.wpra-postbox-last {
|
213 |
+
order: 100;
|
214 |
+
}
|
215 |
+
}
|
216 |
+
}
|
@@ -0,0 +1,220 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
a.disabled {
|
2 |
+
color: #9c9c9c;
|
3 |
+
pointer-events: none;
|
4 |
+
}
|
5 |
+
|
6 |
+
[v-cloak] {
|
7 |
+
.vcloak {
|
8 |
+
&--visible {
|
9 |
+
display: block;
|
10 |
+
}
|
11 |
+
&--hidden {
|
12 |
+
display: none;
|
13 |
+
}
|
14 |
+
}
|
15 |
+
}
|
16 |
+
.vcloak {
|
17 |
+
&--visible {
|
18 |
+
min-height: 60px;
|
19 |
+
display: none;
|
20 |
+
}
|
21 |
+
}
|
22 |
+
|
23 |
+
.loading-container {
|
24 |
+
min-height: 5rem;
|
25 |
+
position: relative;
|
26 |
+
&:before {
|
27 |
+
display: block;
|
28 |
+
content: '';
|
29 |
+
position: absolute;
|
30 |
+
left: calc(50% - 20px);
|
31 |
+
top: calc(50% - 20px);
|
32 |
+
box-sizing: border-box;
|
33 |
+
height: 40px;
|
34 |
+
width: 40px;
|
35 |
+
border: 0px solid #d0d0d0;
|
36 |
+
border-radius: 50%;
|
37 |
+
box-shadow: 0 -12px 0 16px #d0d0d0 inset;
|
38 |
+
animation: rotate 1s infinite linear;
|
39 |
+
z-index: 3;
|
40 |
+
}
|
41 |
+
&:after {
|
42 |
+
display: block;
|
43 |
+
content: '';
|
44 |
+
position: absolute;
|
45 |
+
z-index: 2;
|
46 |
+
background-color: rgba(241, 241, 241, 0.5);
|
47 |
+
width: 100%;
|
48 |
+
height: 100%;
|
49 |
+
left: 0;
|
50 |
+
top: 0;
|
51 |
+
}
|
52 |
+
&--white {
|
53 |
+
&:after {
|
54 |
+
background-color: white;
|
55 |
+
}
|
56 |
+
}
|
57 |
+
}
|
58 |
+
|
59 |
+
|
60 |
+
.loading-button {
|
61 |
+
pointer-events: none;
|
62 |
+
position: relative;
|
63 |
+
&:before {
|
64 |
+
display: block;
|
65 |
+
content: '';
|
66 |
+
position: absolute;
|
67 |
+
left: calc(50% - 8px);
|
68 |
+
top: calc(50% - 8px);
|
69 |
+
box-sizing: border-box;
|
70 |
+
height: 16px;
|
71 |
+
width: 16px;
|
72 |
+
border: 0px solid #fff;
|
73 |
+
border-radius: 50%;
|
74 |
+
box-shadow: 0 -4px 0 6px #fff inset;
|
75 |
+
animation: rotate 1s infinite linear;
|
76 |
+
z-index: 3;
|
77 |
+
}
|
78 |
+
&:after {
|
79 |
+
display: block;
|
80 |
+
content: '';
|
81 |
+
position: absolute;
|
82 |
+
z-index: 2;
|
83 |
+
background-color: inherit;
|
84 |
+
width: 100%;
|
85 |
+
height: 100%;
|
86 |
+
left: 0;
|
87 |
+
top: 0;
|
88 |
+
}
|
89 |
+
}
|
90 |
+
|
91 |
+
.button-default {
|
92 |
+
&.loading-button:before {
|
93 |
+
box-shadow: inset 0 -4px 0 6px #6f6f6f;
|
94 |
+
}
|
95 |
+
}
|
96 |
+
|
97 |
+
.loading-inline {
|
98 |
+
display: inline-block;
|
99 |
+
pointer-events: none;
|
100 |
+
position: relative;
|
101 |
+
&:before {
|
102 |
+
display: block;
|
103 |
+
content: '';
|
104 |
+
position: absolute;
|
105 |
+
left: calc(50% + 1px);
|
106 |
+
top: calc(50% - 11px);
|
107 |
+
box-sizing: border-box;
|
108 |
+
height: 14px;
|
109 |
+
width: 14px;
|
110 |
+
border: 0px solid #d0d0d0;
|
111 |
+
border-radius: 50%;
|
112 |
+
box-shadow: 0 -3px 0 5px #d0d0d0 inset;
|
113 |
+
animation: rotate 1s infinite linear;
|
114 |
+
z-index: 3;
|
115 |
+
}
|
116 |
+
&:after {
|
117 |
+
display: block;
|
118 |
+
content: '';
|
119 |
+
position: absolute;
|
120 |
+
z-index: 2;
|
121 |
+
background-color: inherit;
|
122 |
+
width: 100%;
|
123 |
+
height: 100%;
|
124 |
+
left: 0;
|
125 |
+
top: 0;
|
126 |
+
}
|
127 |
+
}
|
128 |
+
|
129 |
+
|
130 |
+
@keyframes rotate {
|
131 |
+
0% {
|
132 |
+
transform: rotate(0deg);
|
133 |
+
}
|
134 |
+
100% {
|
135 |
+
transform: rotate(360deg);
|
136 |
+
}
|
137 |
+
}
|
138 |
+
|
139 |
+
.table-loading {
|
140 |
+
position: relative;
|
141 |
+
}
|
142 |
+
.table-loading .table-loader-wrap {
|
143 |
+
position: absolute;
|
144 |
+
width: 100%;
|
145 |
+
height: 100%;
|
146 |
+
z-index: 9;
|
147 |
+
}
|
148 |
+
.table-loading .table-loader-wrap .table-loader-center {
|
149 |
+
position: absolute;
|
150 |
+
top: 50%;
|
151 |
+
transform: translateY(-50%);
|
152 |
+
width: 100%;
|
153 |
+
}
|
154 |
+
.table-loading .wp-list-table,
|
155 |
+
.table-loading .tablenav {
|
156 |
+
opacity: 0.4;
|
157 |
+
}
|
158 |
+
.table-loader {
|
159 |
+
font-size: 10px;
|
160 |
+
margin: 50px auto;
|
161 |
+
text-indent: -9999em;
|
162 |
+
width: 11em;
|
163 |
+
height: 11em;
|
164 |
+
border-radius: 50%;
|
165 |
+
background: #ffffff;
|
166 |
+
background: -moz-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
|
167 |
+
background: -webkit-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
|
168 |
+
background: -o-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
|
169 |
+
background: -ms-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
|
170 |
+
background: linear-gradient(to right, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
|
171 |
+
position: relative;
|
172 |
+
-webkit-animation: tableLoading 1s infinite linear;
|
173 |
+
animation: tableLoading 1s infinite linear;
|
174 |
+
-webkit-transform: translateZ(0);
|
175 |
+
-ms-transform: translateZ(0);
|
176 |
+
transform: translateZ(0);
|
177 |
+
}
|
178 |
+
.table-loader:before {
|
179 |
+
width: 50%;
|
180 |
+
height: 50%;
|
181 |
+
background: #ffffff;
|
182 |
+
border-radius: 100% 0 0 0;
|
183 |
+
position: absolute;
|
184 |
+
top: 0;
|
185 |
+
left: 0;
|
186 |
+
content: '';
|
187 |
+
}
|
188 |
+
.table-loader:after {
|
189 |
+
background: #f4f4f4;
|
190 |
+
width: 75%;
|
191 |
+
height: 75%;
|
192 |
+
border-radius: 50%;
|
193 |
+
content: '';
|
194 |
+
margin: auto;
|
195 |
+
position: absolute;
|
196 |
+
top: 0;
|
197 |
+
left: 0;
|
198 |
+
bottom: 0;
|
199 |
+
right: 0;
|
200 |
+
}
|
201 |
+
@-webkit-keyframes tableLoading {
|
202 |
+
0% {
|
203 |
+
-webkit-transform: rotate(0deg);
|
204 |
+
transform: rotate(0deg);
|
205 |
+
}
|
206 |
+
100% {
|
207 |
+
-webkit-transform: rotate(360deg);
|
208 |
+
transform: rotate(360deg);
|
209 |
+
}
|
210 |
+
}
|
211 |
+
@keyframes tableLoading {
|
212 |
+
0% {
|
213 |
+
-webkit-transform: rotate(0deg);
|
214 |
+
transform: rotate(0deg);
|
215 |
+
}
|
216 |
+
100% {
|
217 |
+
-webkit-transform: rotate(360deg);
|
218 |
+
transform: rotate(360deg);
|
219 |
+
}
|
220 |
+
}
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.toasted-container.top-center {
|
2 |
+
top: 44px !important;
|
3 |
+
}
|
4 |
+
|
5 |
+
.toasted {
|
6 |
+
background: #23282d !important;
|
7 |
+
color: #e5e5e5 !important;
|
8 |
+
font-size: inherit !important;
|
9 |
+
font-weight: inherit !important;
|
10 |
+
|
11 |
+
justify-content: start !important;
|
12 |
+
border-left: none !important;
|
13 |
+
|
14 |
+
&.success {}
|
15 |
+
|
16 |
+
&.error {
|
17 |
+
.dashicons {
|
18 |
+
color: #ff7781;
|
19 |
+
}
|
20 |
+
}
|
21 |
+
|
22 |
+
.dashicons {
|
23 |
+
margin-right: 12px;
|
24 |
+
margin-left: -8px;
|
25 |
+
display: inline-block;
|
26 |
+
opacity: .65;
|
27 |
+
}
|
28 |
+
}
|
@@ -0,0 +1,149 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
@import "./../mixins";
|
2 |
+
|
3 |
+
.wrap--wpra-update {
|
4 |
+
padding-top: 1rem;
|
5 |
+
|
6 |
+
@include breakpoint(not-mobile) {
|
7 |
+
width: 100%;
|
8 |
+
max-width: 1400px;
|
9 |
+
margin: 0 auto;
|
10 |
+
padding-right: 20px;
|
11 |
+
box-sizing: border-box;
|
12 |
+
}
|
13 |
+
}
|
14 |
+
|
15 |
+
.wpra-text-center {
|
16 |
+
text-align: center;
|
17 |
+
}
|
18 |
+
|
19 |
+
.wpra-updates ul {
|
20 |
+
list-style: disc;
|
21 |
+
padding: 0 1.25rem;
|
22 |
+
}
|
23 |
+
|
24 |
+
.wpra-inline-form {
|
25 |
+
display: flex;
|
26 |
+
align-items: baseline;
|
27 |
+
|
28 |
+
button {
|
29 |
+
margin-right: 12px !important;
|
30 |
+
}
|
31 |
+
|
32 |
+
small {
|
33 |
+
font-size: 12px;
|
34 |
+
opacity: .75;
|
35 |
+
}
|
36 |
+
}
|
37 |
+
|
38 |
+
|
39 |
+
.wpra-update-head__title {
|
40 |
+
font-size: 24px;
|
41 |
+
font-weight: 500;
|
42 |
+
padding: 1.5rem 0 1.5rem;
|
43 |
+
line-height: 1.4;
|
44 |
+
}
|
45 |
+
|
46 |
+
.wpra-update__logo img {
|
47 |
+
width: 56px;
|
48 |
+
}
|
49 |
+
|
50 |
+
.button-icon span {
|
51 |
+
vertical-align: baseline;
|
52 |
+
margin-right: -7px;
|
53 |
+
opacity: .6;
|
54 |
+
font-size: 16px;
|
55 |
+
top: 4px;
|
56 |
+
position: relative;
|
57 |
+
}
|
58 |
+
|
59 |
+
.wpra-links {
|
60 |
+
padding-top: .5rem;
|
61 |
+
}
|
62 |
+
|
63 |
+
.wpra-update-head__link {
|
64 |
+
font-size: 1rem;
|
65 |
+
padding-bottom: 1.5rem;
|
66 |
+
line-height: 1.5;
|
67 |
+
}
|
68 |
+
|
69 |
+
.wpra-update-feature {
|
70 |
+
display: flex;
|
71 |
+
padding: 0 18px 12px !important;
|
72 |
+
|
73 |
+
@include breakpoint(mobile) {
|
74 |
+
flex-direction: column-reverse;
|
75 |
+
}
|
76 |
+
}
|
77 |
+
|
78 |
+
.wpra-update-feature__text {
|
79 |
+
@include breakpoint(not-mobile) {
|
80 |
+
padding-right: 12px;
|
81 |
+
}
|
82 |
+
|
83 |
+
h3 {
|
84 |
+
margin-top: 8px;
|
85 |
+
@include breakpoint(mobile) {
|
86 |
+
margin-top: 16px;
|
87 |
+
}
|
88 |
+
}
|
89 |
+
|
90 |
+
p {
|
91 |
+
font-size: 14px;
|
92 |
+
}
|
93 |
+
}
|
94 |
+
|
95 |
+
.wpra-update-feature__image {
|
96 |
+
flex-shrink: 0;
|
97 |
+
width: 30rem;
|
98 |
+
overflow: hidden;
|
99 |
+
min-height: 336px;
|
100 |
+
position: relative;
|
101 |
+
margin: -11px -18px -23px 0;
|
102 |
+
cursor: pointer;
|
103 |
+
transition-duration: 0.5s;
|
104 |
+
|
105 |
+
&:hover {
|
106 |
+
transition-duration: 0.2s;
|
107 |
+
background-color: #111;
|
108 |
+
|
109 |
+
img {
|
110 |
+
opacity: 0.95;
|
111 |
+
|
112 |
+
}
|
113 |
+
|
114 |
+
&::before {
|
115 |
+
content: "\f177";
|
116 |
+
display: block;
|
117 |
+
position: absolute;
|
118 |
+
top: calc(50% - 45px);
|
119 |
+
width: 100%;
|
120 |
+
height: 90px;
|
121 |
+
font-size: 5em;
|
122 |
+
font-family: dashicons;
|
123 |
+
text-align: center;
|
124 |
+
z-index: 100;
|
125 |
+
opacity: 0.5;
|
126 |
+
}
|
127 |
+
}
|
128 |
+
|
129 |
+
@include breakpoint(mobile) {
|
130 |
+
flex-shrink: unset;
|
131 |
+
width: unset;
|
132 |
+
min-height: unset;
|
133 |
+
|
134 |
+
max-height: 15rem;
|
135 |
+
margin: -11px -18px 0px;
|
136 |
+
}
|
137 |
+
|
138 |
+
img {
|
139 |
+
max-height: 29rem;
|
140 |
+
position: absolute;
|
141 |
+
|
142 |
+
@include breakpoint(mobile) {
|
143 |
+
max-height: unset;
|
144 |
+
position: unset;
|
145 |
+
|
146 |
+
max-width: 100%;
|
147 |
+
}
|
148 |
+
}
|
149 |
+
}
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -555,11 +555,18 @@ class HtmlEncoder extends AbstractRegex
|
|
555 |
$symPrefix = $this->getSymPrefix();
|
556 |
}
|
557 |
|
|
|
|
|
|
|
|
|
558 |
/**
|
559 |
* Iterating through all matches.
|
560 |
* http://php.net/manual/en/control-structures.foreach.php#88578
|
561 |
*/
|
562 |
-
|
|
|
|
|
|
|
563 |
// Is this a symmetrical char match key?
|
564 |
if (!$this->isSymKey($key, $symPrefix)) {
|
565 |
continue;
|
@@ -577,7 +584,7 @@ class HtmlEncoder extends AbstractRegex
|
|
577 |
}
|
578 |
// Remove the symmetric char match
|
579 |
unset($matches[$key]);
|
580 |
-
}
|
581 |
|
582 |
$matches = array_merge($matches);
|
583 |
return $matches;
|
@@ -618,4 +625,4 @@ class HtmlEncoder extends AbstractRegex
|
|
618 |
$startLength = strlen($start);
|
619 |
return ($actualStart = substr($string, 0, $startLength)) === $start;
|
620 |
}
|
621 |
-
}
|
555 |
$symPrefix = $this->getSymPrefix();
|
556 |
}
|
557 |
|
558 |
+
if (count($matches) === 0) {
|
559 |
+
return $matches;
|
560 |
+
}
|
561 |
+
|
562 |
/**
|
563 |
* Iterating through all matches.
|
564 |
* http://php.net/manual/en/control-structures.foreach.php#88578
|
565 |
*/
|
566 |
+
reset($matches);
|
567 |
+
do {
|
568 |
+
$key = key($matches);
|
569 |
+
$value = current($matches);
|
570 |
// Is this a symmetrical char match key?
|
571 |
if (!$this->isSymKey($key, $symPrefix)) {
|
572 |
continue;
|
584 |
}
|
585 |
// Remove the symmetric char match
|
586 |
unset($matches[$key]);
|
587 |
+
} while (next($matches) !== false && key($matches) !== null);
|
588 |
|
589 |
$matches = array_merge($matches);
|
590 |
return $matches;
|
625 |
$startLength = strlen($start);
|
626 |
return ($actualStart = substr($string, 0, $startLength)) === $start;
|
627 |
}
|
628 |
+
}
|
File without changes
|
@@ -1,137 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Build the Add-ons page (Code borrowed from the ACF plugin)
|
4 |
-
*
|
5 |
-
* @since 4.2
|
6 |
-
* @link http://www.advancedcustomfields.com/
|
7 |
-
*
|
8 |
-
*/
|
9 |
-
function wprss_addons_page_display() {
|
10 |
-
|
11 |
-
$premium = wprss_addons_get_extra();
|
12 |
-
|
13 |
-
?>
|
14 |
-
<div class="wrap">
|
15 |
-
<h2><?php _e( 'More Features With Our Premium Add-Ons', WPRSS_TEXT_DOMAIN ); ?></h2>
|
16 |
-
<p><?php echo sprintf(__( 'The following <a href="%1$s" target="_blank">add-ons</a> are available to increase the functionality of the WP RSS Aggregator plugin.', WPRSS_TEXT_DOMAIN ), 'https://www.wprssaggregator.com/extensions') ?></p>
|
17 |
-
<p>
|
18 |
-
<?php
|
19 |
-
$pricingLink = sprintf(
|
20 |
-
'<a href="%s" target="_blank">%s</a>',
|
21 |
-
'https://www.wprssaggregator.com/pricing',
|
22 |
-
_x('pricing plans', 'Check out our pricing plans for bigger savings!', 'wprss')
|
23 |
-
);
|
24 |
-
|
25 |
-
printf(_x('Check out our %s for bigger savings!', '%s = "pricing plans"', 'wprss'), $pricingLink);
|
26 |
-
?>
|
27 |
-
</p>
|
28 |
-
|
29 |
-
<div id="add-ons" class="clearfix">
|
30 |
-
|
31 |
-
<div class="add-on-group clearfix">
|
32 |
-
<?php foreach( $premium as $_code => $addon ): ?>
|
33 |
-
<?php $isActive = is_plugin_active($addon['basename']) ?>
|
34 |
-
<?php $isInstalledInactive = wprss_is_plugin_inactive($addon['basename']) ?>
|
35 |
-
<div class="add-on wp-box<?php if( $isActive ): ?> add-on-active<?php endif; ?> <?php echo sprintf('add-on-code-%1$s', $_code) ?>">
|
36 |
-
<!-- <a target="_blank" href="<?php echo $addon['url']; ?>">
|
37 |
-
<img src="<?php echo $addon['thumbnail']; ?>" />
|
38 |
-
</a> -->
|
39 |
-
<div class="inner">
|
40 |
-
<h3><a target="_blank" href="<?php echo $addon['url']; ?>"><?php echo $addon['title']; ?></a></h3>
|
41 |
-
<p><?php echo $addon['description']; ?></p>
|
42 |
-
</div>
|
43 |
-
<div class="footer">
|
44 |
-
<?php if( $isActive ): ?>
|
45 |
-
<a class="button button-disabled"><span class="wprss-sprite-tick"></span><?php _e( "Installed", WPRSS_TEXT_DOMAIN ); ?></a>
|
46 |
-
<?php elseif( $isInstalledInactive ): ?>
|
47 |
-
<a class="button" href="<?php echo wp_nonce_url('plugins.php?action=activate&plugin='.$addon['basename'], 'activate-plugin_'.$addon['basename'] ) ?>"><?php _e( "Activate", WPRSS_TEXT_DOMAIN ); ?></a>
|
48 |
-
<?php else: ?>
|
49 |
-
<a target="_blank" href="<?php echo $addon['url']; ?>" class="button"><?php _e( "Purchase & Install", WPRSS_TEXT_DOMAIN ); ?></a>
|
50 |
-
<?php endif; ?>
|
51 |
-
</div>
|
52 |
-
</div>
|
53 |
-
<?php endforeach; ?>
|
54 |
-
</div>
|
55 |
-
|
56 |
-
</div>
|
57 |
-
|
58 |
-
</div>
|
59 |
-
|
60 |
-
<?php
|
61 |
-
|
62 |
-
}
|
63 |
-
|
64 |
-
function wprss_addons_get_extra()
|
65 |
-
{
|
66 |
-
return apply_filters('wprss_extra_addons', array(
|
67 |
-
'ftp' => array(
|
68 |
-
'title' => 'Feed to Post',
|
69 |
-
'description' => __("An advanced importer that lets you import RSS feed items as WordPress posts or any other custom post type. You can use it to populate a website in minutes (auto-blog). This is the most popular and feature-filled extension.", WPRSS_TEXT_DOMAIN),
|
70 |
-
'thumbnail' => WPRSS_IMG . 'add-ons/wprss.jpg',
|
71 |
-
'basename' => 'wp-rss-feed-to-post/wp-rss-feed-to-post.php',
|
72 |
-
'url' => 'https://www.wprssaggregator.com/extension/feed-to-post/'
|
73 |
-
),
|
74 |
-
'ftr' => array(
|
75 |
-
'title' => 'Full Text RSS Feeds',
|
76 |
-
'description' => __("An extension for Feed to Post that adds connectivity to our premium full text service, which allows you to import the full post content for an unlimited number of feed items per feed source, even when the feed itself doesn't provide it", WPRSS_TEXT_DOMAIN),
|
77 |
-
'thumbnail' => WPRSS_IMG . 'add-ons/wprss.jpg',
|
78 |
-
'basename' => 'wp-rss-full-text-feeds/wp-rss-full-text.php',
|
79 |
-
'url' => 'https://www.wprssaggregator.com/extension/full-text-rss-feeds/'
|
80 |
-
),
|
81 |
-
'tmp' => array(
|
82 |
-
'title' => 'Templates',
|
83 |
-
'description' => __('Premium templates to display images and excerpts in various ways. It includes a fully customisable grid template and a list template that includes excerpts & thumbnails, both of which will spruce up your site!', WPRSS_TEXT_DOMAIN),
|
84 |
-
'thumbnail' => WPRSS_IMG . 'add-ons/wprss.jpg',
|
85 |
-
'basename' => 'wp-rss-templates/wp-rss-templates.php',
|
86 |
-
'url' => 'https://www.wprssaggregator.com/extension/templates/'
|
87 |
-
),
|
88 |
-
'kf' => array(
|
89 |
-
'title' => 'Keyword Filtering',
|
90 |
-
'description' => __("Filters the feed items to be imported based on your own keywords, key phrases, or tags; you only get the items you're interested in. It is compatible with all other add-ons.", WPRSS_TEXT_DOMAIN),
|
91 |
-
'thumbnail' => WPRSS_IMG . 'add-ons/wprss.jpg',
|
92 |
-
'basename' => 'wp-rss-keyword-filtering/wp-rss-keyword-filtering.php',
|
93 |
-
'url' => 'https://www.wprssaggregator.com/extension/keyword-filtering/'
|
94 |
-
),
|
95 |
-
'c' => array(
|
96 |
-
'title' => 'Source Categories',
|
97 |
-
'description' => __("Categorises your feed sources and allows you to display feed items from a particular category within your site using the shortcode parameters.", WPRSS_TEXT_DOMAIN),
|
98 |
-
'thumbnail' => WPRSS_IMG . 'add-ons/wprss.jpg',
|
99 |
-
'basename' => 'wp-rss-categories/wp-rss-categories.php',
|
100 |
-
'url' => 'https://www.wprssaggregator.com/extension/categories/'
|
101 |
-
),
|
102 |
-
'wai' => array(
|
103 |
-
'title' => 'WordAi',
|
104 |
-
'description' => __("An extension for Feed to Post that allows you to integrate the WordAi article spinner so that the imported content is both completely unique and completely readable.", WPRSS_TEXT_DOMAIN),
|
105 |
-
'thumbnail' => WPRSS_IMG . 'add-ons/wprss.jpg',
|
106 |
-
'basename' => 'wp-rss-wordai/wp-rss-wordai.php',
|
107 |
-
'url' => 'https://www.wprssaggregator.com/extension/wordai/'
|
108 |
-
),
|
109 |
-
'spc' => array(
|
110 |
-
'title' => 'SpinnerChief',
|
111 |
-
'description' => __("An extension for Feed to Post that allows you to integrate the SpinnerChief article spinner so that the imported content is both completely unique and completely readable.", WPRSS_TEXT_DOMAIN),
|
112 |
-
'thumbnail' => WPRSS_IMG . 'add-ons/wprss.jpg',
|
113 |
-
'basename' => 'wp-rss-spinnerchief/wp-rss-spinnerchief.php',
|
114 |
-
'url' => 'https://www.wprssaggregator.com/extension/spinnerchief/'
|
115 |
-
),
|
116 |
-
));
|
117 |
-
}
|
118 |
-
|
119 |
-
/**
|
120 |
-
* Check if plugin file exists but plugin is inactive
|
121 |
-
* @param $path Path to plugin file
|
122 |
-
* @since 4.7.3
|
123 |
-
* @return bool TRUE if plugin file found but plugin inactive. False otherwise
|
124 |
-
*/
|
125 |
-
function wprss_is_plugin_inactive( $path ){
|
126 |
-
|
127 |
-
if( ! isset( $path ) ){
|
128 |
-
return FALSE;
|
129 |
-
}
|
130 |
-
|
131 |
-
if( file_exists( WP_PLUGIN_DIR . '/' . $path ) && is_plugin_inactive( $path ) ){
|
132 |
-
return TRUE; // plugin found but inactive
|
133 |
-
}
|
134 |
-
|
135 |
-
return FALSE;
|
136 |
-
|
137 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
File without changes
|
@@ -167,63 +167,6 @@ use Psr\Log\LogLevel;
|
|
167 |
<?php
|
168 |
}
|
169 |
|
170 |
-
/**
|
171 |
-
* Renders the debug log.
|
172 |
-
*/
|
173 |
-
function wprss_debug_render_error_log() {
|
174 |
-
$num = 200;
|
175 |
-
$logs = wpra_get_logger()->getLogs($num, 1);
|
176 |
-
?>
|
177 |
-
|
178 |
-
<h3><?= __( 'Debug Log', 'wprss' ); ?></h3>
|
179 |
-
<p><i><?= sprintf(__( 'Showing the most recent %d log messages', 'wprss' ), $num); ?></i></p>
|
180 |
-
|
181 |
-
<?php if (count($logs) === 0) : ?>
|
182 |
-
<section class="notice notice-success notice-inline wpra-empty-log-notice">
|
183 |
-
<p><?= __('The log is empty', 'wprss'); ?></p>
|
184 |
-
</section>
|
185 |
-
<?php else: ?>
|
186 |
-
<div class="wpra-log">
|
187 |
-
<p>
|
188 |
-
<strong><?= __('Filters:', 'wprss') ?></strong>
|
189 |
-
|
190 |
-
<span class="wpra-toggle-logs" data-level="all">
|
191 |
-
<a href="#"><?= __('All', 'wprss') ?></a>
|
192 |
-
</span>
|
193 |
-
<span class="wpra-toggle-logs wpra-selected" data-level="error">
|
194 |
-
<a href="#"><?= __('Errors', 'wprss') ?></a>
|
195 |
-
</span>
|
196 |
-
<span class="wpra-toggle-logs wpra-selected" data-level="info">
|
197 |
-
<a href="#"><?= __('Info', 'wprss') ?></a>
|
198 |
-
</span>
|
199 |
-
<span class="wpra-toggle-logs" data-level="notice">
|
200 |
-
<a href="#"><?= __('Notice', 'wprss') ?></a>
|
201 |
-
</span>
|
202 |
-
<span class="wpra-toggle-logs" data-level="warning">
|
203 |
-
<a href="#"><?= __('Warnings', 'wprss') ?></a>
|
204 |
-
</span>
|
205 |
-
<span class="wpra-toggle-logs" data-level="debug">
|
206 |
-
<a href="#"><?= __('Debug', 'wprss') ?></a>
|
207 |
-
</span>
|
208 |
-
</p>
|
209 |
-
<div class="wpra-log-container">
|
210 |
-
<table>
|
211 |
-
<tbody>
|
212 |
-
<?php foreach ($logs as $log) : ?>
|
213 |
-
<tr class="wpra-log-<?= $log['level'] ?>">
|
214 |
-
<td class="wpra-log-date"><?= $log['date'] ?></td>
|
215 |
-
<td class="wpra-log-level"><?= ucfirst($log['level']) ?></td>
|
216 |
-
<td class="wpra-log-feed"><?= get_the_title(ucfirst($log['feed_id'])) ?></td>
|
217 |
-
<td class="wpra-log-message"><?= htmlentities($log['message']) ?></td>
|
218 |
-
</tr>
|
219 |
-
<?php endforeach; ?>
|
220 |
-
</tbody>
|
221 |
-
</table>
|
222 |
-
</div>
|
223 |
-
</div>
|
224 |
-
<?php endif;
|
225 |
-
}
|
226 |
-
|
227 |
/**
|
228 |
* Renders the "Clear log" button
|
229 |
*
|
167 |
<?php
|
168 |
}
|
169 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
170 |
/**
|
171 |
* Renders the "Clear log" button
|
172 |
*
|
@@ -395,7 +395,7 @@
|
|
395 |
|
396 |
$page = isset( $_GET['paged'] )? '&paged=' . $_GET['paged'] : '';
|
397 |
if ( get_post_type($post) === 'wprss_feed_item' ) {
|
398 |
-
if (
|
399 |
unset($actions['edit']);
|
400 |
}
|
401 |
unset( $actions[ 'view' ] );
|
@@ -657,7 +657,11 @@
|
|
657 |
*
|
658 |
* @since 2.0
|
659 |
*/
|
660 |
-
function wprss_custom_feed_item_bulk_actions( $actions ){
|
|
|
|
|
|
|
|
|
661 |
return apply_filters( 'wprss_custom_feed_item_bulk_actions', $actions );
|
662 |
}
|
663 |
|
395 |
|
396 |
$page = isset( $_GET['paged'] )? '&paged=' . $_GET['paged'] : '';
|
397 |
if ( get_post_type($post) === 'wprss_feed_item' ) {
|
398 |
+
if (!wpra_is_dev_mode()) {
|
399 |
unset($actions['edit']);
|
400 |
}
|
401 |
unset( $actions[ 'view' ] );
|
657 |
*
|
658 |
* @since 2.0
|
659 |
*/
|
660 |
+
function wprss_custom_feed_item_bulk_actions( $actions ) {
|
661 |
+
if (!wpra_is_dev_mode()) {
|
662 |
+
unset($actions['edit']);
|
663 |
+
}
|
664 |
+
|
665 |
return apply_filters( 'wprss_custom_feed_item_bulk_actions', $actions );
|
666 |
}
|
667 |
|
File without changes
|
File without changes
|
File without changes
|
@@ -164,7 +164,7 @@ function wprss_settings_add_tooltips() {
|
|
164 |
|
165 |
'. 'Some servers react in unexpected ways to the default value. In such cases, try changing this to something else.
|
166 |
|
167 |
-
'. 'The default value is
|
168 |
'feed_cache_enabled' => __( 'Tick this box to enable caching for a small performance gain.
|
169 |
|
170 |
'. 'When enabled, websites may ignore the plugin if their RSS feed did not change. So we suggest testing it out first to ensure that your RSS feeds work well with this option enabled.
|
@@ -185,7 +185,7 @@ function wprss_settings_add_tooltips() {
|
|
185 |
|
186 |
'. 'Some servers react in unexpected ways to the default value. In such cases, try changing this to something else.
|
187 |
|
188 |
-
'. 'The default value is
|
189 |
$wprss->getName()))
|
190 |
), $prefix);
|
191 |
}
|
164 |
|
165 |
'. 'Some servers react in unexpected ways to the default value. In such cases, try changing this to something else.
|
166 |
|
167 |
+
'. 'The default value is the useragent that the Chrome Browser uses.'),
|
168 |
'feed_cache_enabled' => __( 'Tick this box to enable caching for a small performance gain.
|
169 |
|
170 |
'. 'When enabled, websites may ignore the plugin if their RSS feed did not change. So we suggest testing it out first to ensure that your RSS feeds work well with this option enabled.
|
185 |
|
186 |
'. 'Some servers react in unexpected ways to the default value. In such cases, try changing this to something else.
|
187 |
|
188 |
+
'. 'The default value is the useragent that the Chrome browser uses.',
|
189 |
$wprss->getName()))
|
190 |
), $prefix);
|
191 |
}
|
@@ -23,6 +23,7 @@
|
|
23 |
|
24 |
<div class="wrap">
|
25 |
<h2><?php _e( 'Help & Support', WPRSS_TEXT_DOMAIN ); ?></h2>
|
|
|
26 |
<h3><?php _e( 'Knowledge Base', WPRSS_TEXT_DOMAIN ) ?></h3>
|
27 |
<?php
|
28 |
printf(
|
23 |
|
24 |
<div class="wrap">
|
25 |
<h2><?php _e( 'Help & Support', WPRSS_TEXT_DOMAIN ); ?></h2>
|
26 |
+
<?php do_action('wpra/help_page/after_title') ?>
|
27 |
<h3><?php _e( 'Knowledge Base', WPRSS_TEXT_DOMAIN ) ?></h3>
|
28 |
<?php
|
29 |
printf(
|
File without changes
|
@@ -3,6 +3,7 @@
|
|
3 |
use Psr\Log\LoggerInterface;
|
4 |
use Psr\Log\LogLevel;
|
5 |
use RebelCode\Wpra\Core\Logger\ClearableLoggerInterface;
|
|
|
6 |
use RebelCode\Wpra\Core\Logger\LogReaderInterface;
|
7 |
|
8 |
define('WPRSS_OPTION_CODE_LOG_LEVEL', 'log_level');
|
@@ -26,14 +27,11 @@ define('WPRSS_LOG_LEVEL_DEFAULT', WPRSS_LOG_LEVEL_NONE);
|
|
26 |
*/
|
27 |
function wpra_get_logger($feed_id = null)
|
28 |
{
|
29 |
-
|
30 |
-
return wpra_container()->get('wpra/logging/logger');
|
31 |
-
}
|
32 |
-
|
33 |
-
$dataset = wpra_container()->get('wpra/logging/feed_logger_dataset');
|
34 |
-
$logger = $dataset[$feed_id];
|
35 |
|
36 |
-
return $logger
|
|
|
|
|
37 |
}
|
38 |
|
39 |
/**
|
@@ -54,7 +52,9 @@ function wpra_get_logger($feed_id = null)
|
|
54 |
*/
|
55 |
function wprss_log_read($length = null, $start = null)
|
56 |
{
|
57 |
-
|
|
|
|
|
58 |
|
59 |
$output = '';
|
60 |
foreach ($logs as $log) {
|
@@ -81,7 +81,9 @@ function wprss_get_log()
|
|
81 |
*/
|
82 |
function wprss_clear_log()
|
83 |
{
|
84 |
-
|
|
|
|
|
85 |
}
|
86 |
|
87 |
/**
|
@@ -101,11 +103,11 @@ function wprss_reset_log()
|
|
101 |
*
|
102 |
* @since 3.9.6
|
103 |
*/
|
104 |
-
function wprss_log($message, $src = null, $log_level =
|
105 |
{
|
106 |
-
|
107 |
|
108 |
-
|
109 |
}
|
110 |
|
111 |
/**
|
3 |
use Psr\Log\LoggerInterface;
|
4 |
use Psr\Log\LogLevel;
|
5 |
use RebelCode\Wpra\Core\Logger\ClearableLoggerInterface;
|
6 |
+
use RebelCode\Wpra\Core\Logger\FeedLoggerInterface;
|
7 |
use RebelCode\Wpra\Core\Logger\LogReaderInterface;
|
8 |
|
9 |
define('WPRSS_OPTION_CODE_LOG_LEVEL', 'log_level');
|
27 |
*/
|
28 |
function wpra_get_logger($feed_id = null)
|
29 |
{
|
30 |
+
$logger = wpra_container()->get('wpra/logging/logger');
|
|
|
|
|
|
|
|
|
|
|
31 |
|
32 |
+
return ($feed_id !== null && $logger instanceof FeedLoggerInterface)
|
33 |
+
? $logger->forFeedSource($feed_id)
|
34 |
+
: $logger;
|
35 |
}
|
36 |
|
37 |
/**
|
52 |
*/
|
53 |
function wprss_log_read($length = null, $start = null)
|
54 |
{
|
55 |
+
/* @var $reader LogReaderInterface */
|
56 |
+
$reader = wpra_container()->get('wpra/logging/reader');
|
57 |
+
$logs = $reader->getLogs($length, $start);
|
58 |
|
59 |
$output = '';
|
60 |
foreach ($logs as $log) {
|
81 |
*/
|
82 |
function wprss_clear_log()
|
83 |
{
|
84 |
+
/* @var $clearer ClearableLoggerInterface */
|
85 |
+
$clearer = wpra_container()->get('wpra/logging/clearer');
|
86 |
+
$clearer->clearLogs();
|
87 |
}
|
88 |
|
89 |
/**
|
103 |
*
|
104 |
* @since 3.9.6
|
105 |
*/
|
106 |
+
function wprss_log($message, $src = null, $log_level = null)
|
107 |
{
|
108 |
+
$log_level = ($log_level) ? LogLevel::ERROR : $log_level;
|
109 |
|
110 |
+
wpra_get_logger()->log($log_level, $message);
|
111 |
}
|
112 |
|
113 |
/**
|
@@ -694,16 +694,8 @@
|
|
694 |
<ul>
|
695 |
<li><a href="https://wordpress.org/support/view/plugin-reviews/wp-rss-aggregator?rate=5#postform" target="_blank"><?php _e( 'Give it a 5 star rating on WordPress.org', WPRSS_TEXT_DOMAIN ) ?></a></li>
|
696 |
</ul>
|
697 |
-
<p><strong><?php _e( 'Add functionality with our premium extensions:', WPRSS_TEXT_DOMAIN ) ?></strong></p>
|
698 |
-
<?php $addons = wprss_addons_get_extra() ?>
|
699 |
-
<?php if (count($addons)): ?>
|
700 |
-
<ul class="add-on-list">
|
701 |
-
<?php foreach ($addons as $_code => $_addon): ?>
|
702 |
-
<li class="add-on <?php echo sprintf('add-on-code-%1$s', $_code) ?>"><a href="<?php echo $_addon['url'] ?>"><?php echo $_addon['title'] ?></a></li>
|
703 |
-
<?php endforeach ?>
|
704 |
-
</ul>
|
705 |
-
<?php endif ?>
|
706 |
<?php
|
|
|
707 |
}
|
708 |
|
709 |
|
694 |
<ul>
|
695 |
<li><a href="https://wordpress.org/support/view/plugin-reviews/wp-rss-aggregator?rate=5#postform" target="_blank"><?php _e( 'Give it a 5 star rating on WordPress.org', WPRSS_TEXT_DOMAIN ) ?></a></li>
|
696 |
</ul>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
697 |
<?php
|
698 |
+
do_action('wpra_share_the_love_metabox');
|
699 |
}
|
700 |
|
701 |
|
@@ -190,7 +190,6 @@
|
|
190 |
/**
|
191 |
* Register and define options and settings
|
192 |
* @since 2.0
|
193 |
-
* @todo add option for cron frequency
|
194 |
*
|
195 |
* Note: In the future might change to
|
196 |
* the way EDD builds the settings pages, cleaner method.
|
@@ -507,9 +506,9 @@
|
|
507 |
*/
|
508 |
function wprss_setting_unique_titles( $field ) {
|
509 |
$unique_titles = wprss_get_general_setting( 'unique_titles' );
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
}
|
514 |
|
515 |
|
@@ -518,16 +517,24 @@
|
|
518 |
* @since 3.3
|
519 |
*/
|
520 |
function wprss_settings_custom_feed_url_callback( $field ) {
|
521 |
-
$siteUrl = get_site_url();
|
522 |
$custom_feed_url = wprss_get_general_setting( 'custom_feed_url' );
|
|
|
523 |
?>
|
524 |
-
<code><?= $siteUrl
|
525 |
<input id="<?php echo $field['field_id'] ?>"
|
526 |
name="wprss_settings_general[custom_feed_url]"
|
527 |
type="text"
|
528 |
value="<?php echo $custom_feed_url ?>" />
|
529 |
|
530 |
-
<?php echo wprss_settings_inline_help( $field['field_id'], $field['tooltip'] );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
531 |
}
|
532 |
|
533 |
/**
|
@@ -558,9 +565,8 @@
|
|
558 |
*/
|
559 |
function wprss_setting_styles_disable_callback( $field ) {
|
560 |
$styles_disable = wprss_get_general_setting( 'styles_disable' );
|
561 |
-
|
562 |
-
|
563 |
-
<?php echo wprss_settings_inline_help( $field['field_id'], $field['tooltip'] );
|
564 |
}
|
565 |
|
566 |
/**
|
@@ -650,21 +656,6 @@
|
|
650 |
}
|
651 |
|
652 |
|
653 |
-
/**
|
654 |
-
* Tracking checkbox
|
655 |
-
* @since 3.6
|
656 |
-
*/
|
657 |
-
function wprss_tracking_callback( $field ) {
|
658 |
-
$tracking = wprss_get_general_setting( 'tracking' );
|
659 |
-
?>
|
660 |
-
<input type="checkbox" id="<?php echo $field['field_id'] ?>" name="wprss_settings_general[tracking]" value="1" <?php echo checked( 1, $tracking, false ) ?> />
|
661 |
-
<?php echo wprss_settings_inline_help( $field['field_id'], $field['tooltip'] ) ?>
|
662 |
-
<label class="description" for="<?php echo $field['field_id'] ?>">
|
663 |
-
<?php _e( 'Please help us improve WP RSS Aggregator by allowing us to gather anonymous usage statistics. No sensitive data is collected.', WPRSS_TEXT_DOMAIN ) ?>
|
664 |
-
</label>
|
665 |
-
<?php
|
666 |
-
}
|
667 |
-
|
668 |
/**
|
669 |
* Gets options that should go in a dropdown which represents a
|
670 |
* feed-source-specific boolean setting.
|
@@ -982,3 +973,30 @@
|
|
982 |
)
|
983 |
);
|
984 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
190 |
/**
|
191 |
* Register and define options and settings
|
192 |
* @since 2.0
|
|
|
193 |
*
|
194 |
* Note: In the future might change to
|
195 |
* the way EDD builds the settings pages, cleaner method.
|
506 |
*/
|
507 |
function wprss_setting_unique_titles( $field ) {
|
508 |
$unique_titles = wprss_get_general_setting( 'unique_titles' );
|
509 |
+
|
510 |
+
echo wprss_options_render_checkbox( $field['field_id'], 'unique_titles', $unique_titles );
|
511 |
+
echo wprss_settings_inline_help( $field['field_id'], $field['tooltip'] );
|
512 |
}
|
513 |
|
514 |
|
517 |
* @since 3.3
|
518 |
*/
|
519 |
function wprss_settings_custom_feed_url_callback( $field ) {
|
520 |
+
$siteUrl = trailingslashit(get_site_url());
|
521 |
$custom_feed_url = wprss_get_general_setting( 'custom_feed_url' );
|
522 |
+
$fullUrl = $siteUrl . $custom_feed_url;
|
523 |
?>
|
524 |
+
<code><?= $siteUrl ?></code>
|
525 |
<input id="<?php echo $field['field_id'] ?>"
|
526 |
name="wprss_settings_general[custom_feed_url]"
|
527 |
type="text"
|
528 |
value="<?php echo $custom_feed_url ?>" />
|
529 |
|
530 |
+
<?php echo wprss_settings_inline_help( $field['field_id'], $field['tooltip'] ); ?>
|
531 |
+
|
532 |
+
<p style="font-style: normal">
|
533 |
+
<a href="<?php echo esc_attr($fullUrl); ?>" target="_blank">
|
534 |
+
<?php _e('Open custom feed', 'wprss') ?>
|
535 |
+
</a>
|
536 |
+
</p>
|
537 |
+
<?php
|
538 |
}
|
539 |
|
540 |
/**
|
565 |
*/
|
566 |
function wprss_setting_styles_disable_callback( $field ) {
|
567 |
$styles_disable = wprss_get_general_setting( 'styles_disable' );
|
568 |
+
echo wprss_options_render_checkbox( $field['field_id'], 'styles_disable', $styles_disable );
|
569 |
+
echo wprss_settings_inline_help( $field['field_id'], $field['tooltip'] );
|
|
|
570 |
}
|
571 |
|
572 |
/**
|
656 |
}
|
657 |
|
658 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
659 |
/**
|
660 |
* Gets options that should go in a dropdown which represents a
|
661 |
* feed-source-specific boolean setting.
|
973 |
)
|
974 |
);
|
975 |
}
|
976 |
+
|
977 |
+
/**
|
978 |
+
* Renders a checkbox with a hidden field for the default value (when unchecked).
|
979 |
+
*
|
980 |
+
* @param string $id
|
981 |
+
* @param string $name
|
982 |
+
* @param string $value
|
983 |
+
* @param string $checked_value
|
984 |
+
* @param string $default_value
|
985 |
+
*
|
986 |
+
* @return string
|
987 |
+
*/
|
988 |
+
function wprss_options_render_checkbox($id, $name, $value, $checked_value = '1', $default_value = '0') {
|
989 |
+
$nameAttr = esc_attr(sprintf('wprss_settings_general[%s]', $name));
|
990 |
+
ob_start();
|
991 |
+
|
992 |
+
?>
|
993 |
+
<input type="hidden" name="<?= $nameAttr; ?>" value="<?= esc_attr($default_value) ?>"/>
|
994 |
+
<input type="checkbox"
|
995 |
+
id="<?= $id ?>"
|
996 |
+
name="<?= $nameAttr ?>"
|
997 |
+
value="<?= esc_attr($checked_value) ?>"
|
998 |
+
<?= checked( $checked_value, $value, false ) ?> />
|
999 |
+
<?php
|
1000 |
+
|
1001 |
+
return ob_get_clean();
|
1002 |
+
}
|
@@ -37,10 +37,6 @@
|
|
37 |
add_submenu_page( 'edit.php?post_type=wprss_feed', __( 'Debugging', WPRSS_TEXT_DOMAIN ), __( 'Debugging', WPRSS_TEXT_DOMAIN ), apply_filters( 'wprss_capability', 'manage_feed_settings'), 'wprss-debugging', 'wprss_debugging_page_display' );
|
38 |
}, 40);
|
39 |
|
40 |
-
add_action('admin_menu', function () {
|
41 |
-
add_submenu_page( 'edit.php?post_type=wprss_feed', __( 'More Features', WPRSS_TEXT_DOMAIN ), __( 'More Features', WPRSS_TEXT_DOMAIN ) . '<span class="dashicons dashicons-star-filled wprss-more-features-glyph"></span>', apply_filters( 'wprss_capability', 'manage_feed_settings'), 'wprss-addons', 'wprss_addons_page_display' );
|
42 |
-
}, 50);
|
43 |
-
|
44 |
add_action('admin_menu', function () {
|
45 |
add_submenu_page( 'edit.php?post_type=wprss_feed', __( 'Help & Support', WPRSS_TEXT_DOMAIN ), __( 'Help & Support', WPRSS_TEXT_DOMAIN ), apply_filters( 'wprss_capability', 'manage_feed_settings'), 'wprss-help', 'wprss_help_page_display' );
|
46 |
}, 60);
|
37 |
add_submenu_page( 'edit.php?post_type=wprss_feed', __( 'Debugging', WPRSS_TEXT_DOMAIN ), __( 'Debugging', WPRSS_TEXT_DOMAIN ), apply_filters( 'wprss_capability', 'manage_feed_settings'), 'wprss-debugging', 'wprss_debugging_page_display' );
|
38 |
}, 40);
|
39 |
|
|
|
|
|
|
|
|
|
40 |
add_action('admin_menu', function () {
|
41 |
add_submenu_page( 'edit.php?post_type=wprss_feed', __( 'Help & Support', WPRSS_TEXT_DOMAIN ), __( 'Help & Support', WPRSS_TEXT_DOMAIN ), apply_filters( 'wprss_capability', 'manage_feed_settings'), 'wprss-help', 'wprss_help_page_display' );
|
42 |
}, 60);
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -3,6 +3,7 @@
|
|
3 |
// Save item image info during import
|
4 |
use Psr\Log\LoggerInterface;
|
5 |
use RebelCode\Wpra\Core\Data\DataSetInterface;
|
|
|
6 |
|
7 |
class Wpra_Rss_Namespace {
|
8 |
const ITUNES = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
|
@@ -45,6 +46,24 @@ function wpra_detect_item_type($itemId, $item, $sourceId)
|
|
45 |
}
|
46 |
}
|
47 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
/**
|
49 |
* Imports images for a feed item.
|
50 |
*
|
@@ -61,10 +80,8 @@ function wpra_import_item_images($itemId, $item, $sourceId)
|
|
61 |
update_post_meta($itemId, 'wprss_images', []);
|
62 |
update_post_meta($itemId, 'wprss_best_image', '');
|
63 |
|
64 |
-
/* @var $logger
|
65 |
-
$
|
66 |
-
$loggerDataSet = $container->get('wpra/images/logging/feed_logger_dataset');
|
67 |
-
$logger = $loggerDataSet[$sourceId];
|
68 |
|
69 |
$title = $item->get_title();
|
70 |
$logger->debug('Importing images for item "{title}"', ['title' => $title]);
|
@@ -91,82 +108,88 @@ function wpra_import_item_images($itemId, $item, $sourceId)
|
|
91 |
// Process the images, removing duds, and find the best image
|
92 |
$images = wpra_process_images($allImages, $source, $bestImage);
|
93 |
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
|
|
|
|
102 |
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
|
133 |
-
|
134 |
-
|
135 |
-
if ($ftImageOpt !== 'default' && wpra_image_feature_enabled('must_have_ft_image') && $source['must_have_ft_image']) {
|
136 |
-
$logger->debug('Rejecting item "{title}" due to a lack of a featured image.', [
|
137 |
-
'title' => get_post($itemId)->post_title,
|
138 |
-
]);
|
139 |
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
// - the user did NOT explicitly want to use the default
|
149 |
-
$usedDefault = $defaultSuccessful && $ftImageOpt !== 'default';
|
150 |
-
|
151 |
-
if ($usedDefault) {
|
152 |
-
update_post_meta($itemId, 'wprss_item_is_using_def_image', '1');
|
153 |
-
$logger->notice('Used the feed source\'s default featured image for "{title}"', ['title' => $title]);
|
154 |
} else {
|
155 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
156 |
}
|
157 |
-
}
|
158 |
-
|
159 |
-
|
160 |
-
wpra_set_featured_image_from_url($itemId, $ftImageUrl);
|
161 |
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
|
|
170 |
}
|
171 |
}
|
172 |
|
3 |
// Save item image info during import
|
4 |
use Psr\Log\LoggerInterface;
|
5 |
use RebelCode\Wpra\Core\Data\DataSetInterface;
|
6 |
+
use RebelCode\Wpra\Core\Logger\FeedLoggerInterface;
|
7 |
|
8 |
class Wpra_Rss_Namespace {
|
9 |
const ITUNES = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
|
46 |
}
|
47 |
}
|
48 |
|
49 |
+
/**
|
50 |
+
* Retrieves the logger instance to use for image importing.
|
51 |
+
*
|
52 |
+
* @since 4.15.1
|
53 |
+
*
|
54 |
+
* @param int $feedId Optional feed source ID to log messages specifically for that feed source.
|
55 |
+
*
|
56 |
+
* @return LoggerInterface
|
57 |
+
*/
|
58 |
+
function wpra_get_images_logger($feedId = null)
|
59 |
+
{
|
60 |
+
$logger = wpra_container()->get('wpra/images/logging/logger');
|
61 |
+
|
62 |
+
return ($feedId !== null && $logger instanceof FeedLoggerInterface)
|
63 |
+
? $logger->forFeedSource($feedId)
|
64 |
+
: $logger;
|
65 |
+
}
|
66 |
+
|
67 |
/**
|
68 |
* Imports images for a feed item.
|
69 |
*
|
80 |
update_post_meta($itemId, 'wprss_images', []);
|
81 |
update_post_meta($itemId, 'wprss_best_image', '');
|
82 |
|
83 |
+
/* @var $logger FeedLoggerInterface */
|
84 |
+
$logger = wpra_get_images_logger($sourceId);
|
|
|
|
|
85 |
|
86 |
$title = $item->get_title();
|
87 |
$logger->debug('Importing images for item "{title}"', ['title' => $title]);
|
108 |
// Process the images, removing duds, and find the best image
|
109 |
$images = wpra_process_images($allImages, $source, $bestImage);
|
110 |
|
111 |
+
// If the featured image importing feature is enabled, import the featured image
|
112 |
+
if (wpra_image_feature_enabled('import_ft_images')) {
|
113 |
+
$ftImageUrl = null;
|
114 |
+
switch ($ftImageOpt)
|
115 |
+
{
|
116 |
+
case 'auto':
|
117 |
+
if (!empty($bestImage)) {
|
118 |
+
$ftImageUrl = $bestImage;
|
119 |
+
}
|
120 |
+
break;
|
121 |
|
122 |
+
case 'media':
|
123 |
+
if (isset($images['media'])) {
|
124 |
+
$ftImageUrl = $images['media'];
|
125 |
+
}
|
126 |
+
break;
|
127 |
|
128 |
+
case 'enclosure':
|
129 |
+
if (isset($images['enclosure']) && !empty($images['enclosure'])) {
|
130 |
+
$ftImageUrl = reset($images['enclosure']);
|
131 |
+
}
|
132 |
+
break;
|
133 |
|
134 |
+
case 'content':
|
135 |
+
if (isset($images['content']) && !empty($images['content'])) {
|
136 |
+
$ftImageUrl = reset($images['content']);
|
137 |
+
}
|
138 |
+
break;
|
139 |
|
140 |
+
case 'itunes':
|
141 |
+
if (isset($images['itunes']) && !empty($images['itunes'])) {
|
142 |
+
$ftImageUrl = reset($images['itunes']);
|
143 |
+
}
|
144 |
+
break;
|
145 |
|
146 |
+
case 'default':
|
147 |
+
default:
|
148 |
+
$ftImageUrl = '';
|
149 |
+
break;
|
150 |
+
}
|
151 |
|
152 |
+
// Filter the featured image URL
|
153 |
+
$ftImageUrl = apply_filters('wpra/importer/images/ft_image_url', $ftImageUrl, $item, $sourceId);
|
|
|
|
|
|
|
|
|
154 |
|
155 |
+
if (empty($ftImageUrl)) {
|
156 |
+
// If not always using the default image, and items must have an image, delete the item
|
157 |
+
if ($ftImageOpt !== 'default' && wpra_image_feature_enabled('must_have_ft_image') && $source['must_have_ft_image']) {
|
158 |
+
$logger->debug('Rejecting item "{title}" due to a lack of a featured image.', [
|
159 |
+
'title' => get_post($itemId)->post_title,
|
160 |
+
]);
|
161 |
+
|
162 |
+
wp_delete_post($itemId, true);
|
|
|
|
|
|
|
|
|
|
|
|
|
163 |
} else {
|
164 |
+
// Get the feed source's default featured image
|
165 |
+
$defaultFtImage = get_post_thumbnail_id($sourceId);
|
166 |
+
// Assign it to the feed item
|
167 |
+
$defaultSuccessful = set_post_thumbnail($itemId, $defaultFtImage);
|
168 |
+
// The feed item is classified as using the default image if:
|
169 |
+
// - the default image was successfully assigned
|
170 |
+
// - the user did NOT explicitly want to use the default
|
171 |
+
$usedDefault = $defaultSuccessful && $ftImageOpt !== 'default';
|
172 |
+
|
173 |
+
if ($usedDefault) {
|
174 |
+
update_post_meta($itemId, 'wprss_item_is_using_def_image', '1');
|
175 |
+
$logger->notice('Used the feed source\'s default featured image for "{title}"', ['title' => $title]);
|
176 |
+
} else {
|
177 |
+
$logger->notice('No featured image was found for item "{title}"', ['title' => $title]);
|
178 |
+
}
|
179 |
}
|
180 |
+
} else {
|
181 |
+
$logger->info('Set featured image from URL: "{url}"', ['url' => $ftImageUrl]);
|
182 |
+
wpra_set_featured_image_from_url($itemId, $ftImageUrl);
|
|
|
183 |
|
184 |
+
if (wpra_image_feature_enabled('siphon_ft_image') && $source['siphon_ft_image']) {
|
185 |
+
$content = get_post($itemId)->post_content;
|
186 |
+
$newContent = wpra_remove_image_from_content($content, $ftImageUrl);
|
187 |
|
188 |
+
wp_update_post([
|
189 |
+
'ID' => $itemId,
|
190 |
+
'post_content' => $newContent
|
191 |
+
]);
|
192 |
+
}
|
193 |
}
|
194 |
}
|
195 |
|
@@ -6,9 +6,7 @@
|
|
6 |
* @package WPRSSAggregator
|
7 |
*/
|
8 |
|
9 |
-
|
10 |
-
|
11 |
-
// Warning: Order may be important
|
12 |
add_filter('wprss_normalize_permalink', 'wprss_google_news_url_fix', 8);
|
13 |
add_filter('wprss_normalize_permalink', 'wprss_bing_news_url_fix', 9);
|
14 |
add_filter('wprss_normalize_permalink', 'wprss_google_alerts_url_fix', 10);
|
@@ -100,11 +98,18 @@
|
|
100 |
}
|
101 |
}
|
102 |
|
103 |
-
|
104 |
-
$
|
|
|
|
|
|
|
105 |
// Gather the titles of the items that are imported
|
|
|
106 |
$existing_titles = [];
|
107 |
|
|
|
|
|
|
|
108 |
// Generate a list of items fetched, that are not already in the DB
|
109 |
$new_items = array();
|
110 |
foreach ( $items_to_insert as $item ) {
|
@@ -113,31 +118,33 @@
|
|
113 |
$permalink = wprss_normalize_permalink( $item->get_permalink(), $item, $feed_ID );
|
114 |
$logger->debug('Checking item "{0}"', [$item_title]);
|
115 |
|
116 |
-
// Check if
|
117 |
-
|
118 |
-
$permalink_exists = array_key_exists( $permalink, $existing_permalinks );
|
119 |
-
$title_exists_db = wprss_item_title_exists( $item->get_title() );
|
120 |
-
$title_exists_feed = array_key_exists($item_title, $existing_titles);
|
121 |
-
$title_exists = $title_exists_db || $title_exists_feed;
|
122 |
-
|
123 |
-
$existing_titles[$item_title] = 1;
|
124 |
-
|
125 |
-
if ($is_blacklisted) {
|
126 |
$logger->debug('Item "{0}" is blacklisted', [$item_title]);
|
127 |
|
128 |
continue;
|
129 |
}
|
130 |
|
131 |
-
if
|
|
|
132 |
$logger->debug('Item "{0}" already exists in the database', [$item_title]);
|
133 |
|
134 |
continue;
|
135 |
}
|
136 |
|
137 |
-
if (
|
138 |
-
|
|
|
|
|
|
|
|
|
|
|
139 |
|
140 |
-
|
|
|
|
|
|
|
|
|
141 |
}
|
142 |
|
143 |
$new_items[] = $item;
|
@@ -231,6 +238,9 @@
|
|
231 |
/* Fetch the feed from the soure URL specified */
|
232 |
$feed = wprss_fetch_feed( $feed_url, $source, $force_feed );
|
233 |
|
|
|
|
|
|
|
234 |
// Remove previously added filters and actions
|
235 |
remove_filter( 'wp_feed_cache_transient_lifetime' , 'wprss_feed_cache_lifetime' );
|
236 |
|
@@ -547,7 +557,7 @@ function wprss_get_feed_cache_dir()
|
|
547 |
// Count of items inserted
|
548 |
$items_inserted = 0;
|
549 |
|
550 |
-
foreach ( $items as $item ) {
|
551 |
|
552 |
// Normalize the URL
|
553 |
$permalink = $item->get_permalink(); // Link or enclosure URL
|
@@ -590,8 +600,13 @@ function wprss_get_feed_cache_dir()
|
|
590 |
$format = 'Y-m-d H:i:s';
|
591 |
$has_date = $item->get_date( 'U' ) ? TRUE : FALSE;
|
592 |
$timestamp = $has_date ? $item->get_date( 'U' ) : date( 'U' );
|
593 |
-
|
594 |
-
|
|
|
|
|
|
|
|
|
|
|
595 |
|
596 |
// Do not let WordPress sanitize the excerpt
|
597 |
// WordPress sanitizes the excerpt because it's expected to be typed by a user and sent in a POST
|
@@ -665,15 +680,20 @@ function wprss_get_feed_cache_dir()
|
|
665 |
update_post_meta( $feed_ID, 'wprss_last_update_items', $items_inserted );
|
666 |
}
|
667 |
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
|
|
|
|
|
|
|
|
676 |
function wprss_items_insert_post_meta( $inserted_ID, $item, $feed_ID, $permalink, $enclosure_url ) {
|
|
|
677 |
update_post_meta( $inserted_ID, 'wprss_item_permalink', $permalink );
|
678 |
update_post_meta( $inserted_ID, 'wprss_item_enclosure', $enclosure_url );
|
679 |
|
6 |
* @package WPRSSAggregator
|
7 |
*/
|
8 |
|
9 |
+
// Warning: Order may be important
|
|
|
|
|
10 |
add_filter('wprss_normalize_permalink', 'wprss_google_news_url_fix', 8);
|
11 |
add_filter('wprss_normalize_permalink', 'wprss_bing_news_url_fix', 9);
|
12 |
add_filter('wprss_normalize_permalink', 'wprss_google_alerts_url_fix', 10);
|
98 |
}
|
99 |
}
|
100 |
|
101 |
+
$unique_titles_only = get_post_meta($feed_ID, 'wprss_unique_titles', true);
|
102 |
+
$unique_titles_only = ($unique_titles_only === '')
|
103 |
+
? wprss_get_general_setting('unique_titles')
|
104 |
+
: $unique_titles_only;
|
105 |
+
$unique_titles_only = filter_var($unique_titles_only, FILTER_VALIDATE_BOOLEAN);
|
106 |
// Gather the titles of the items that are imported
|
107 |
+
// The import process will check not only the titles in the DB but the titles currently in the feed
|
108 |
$existing_titles = [];
|
109 |
|
110 |
+
// Gather the permalinks of existing feed item's related to this feed source
|
111 |
+
$existing_permalinks = wprss_get_existing_permalinks( $feed_ID );
|
112 |
+
|
113 |
// Generate a list of items fetched, that are not already in the DB
|
114 |
$new_items = array();
|
115 |
foreach ( $items_to_insert as $item ) {
|
118 |
$permalink = wprss_normalize_permalink( $item->get_permalink(), $item, $feed_ID );
|
119 |
$logger->debug('Checking item "{0}"', [$item_title]);
|
120 |
|
121 |
+
// Check if blacklisted
|
122 |
+
if (wprss_is_blacklisted($permalink)) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
123 |
$logger->debug('Item "{0}" is blacklisted', [$item_title]);
|
124 |
|
125 |
continue;
|
126 |
}
|
127 |
|
128 |
+
// Check if already imported
|
129 |
+
if (array_key_exists($permalink, $existing_permalinks)) {
|
130 |
$logger->debug('Item "{0}" already exists in the database', [$item_title]);
|
131 |
|
132 |
continue;
|
133 |
}
|
134 |
|
135 |
+
// Check if title exists (if the option is enabled)
|
136 |
+
if ($unique_titles_only) {
|
137 |
+
$title_exists_db = wprss_item_title_exists($item->get_title());
|
138 |
+
$title_exists_feed = array_key_exists($item_title, $existing_titles);
|
139 |
+
$title_exists = $title_exists_db || $title_exists_feed;
|
140 |
+
// Add this item's title to the list to check against
|
141 |
+
$existing_titles[$item_title] = 1;
|
142 |
|
143 |
+
if ($title_exists) {
|
144 |
+
$logger->debug('An item with the title "{0}" already exists', [$item_title]);
|
145 |
+
|
146 |
+
continue;
|
147 |
+
}
|
148 |
}
|
149 |
|
150 |
$new_items[] = $item;
|
238 |
/* Fetch the feed from the soure URL specified */
|
239 |
$feed = wprss_fetch_feed( $feed_url, $source, $force_feed );
|
240 |
|
241 |
+
update_post_meta( $source, 'wprss_site_url', $feed->get_permalink() );
|
242 |
+
update_post_meta( $source, 'wprss_feed_image', $feed->get_image_url() );
|
243 |
+
|
244 |
// Remove previously added filters and actions
|
245 |
remove_filter( 'wp_feed_cache_transient_lifetime' , 'wprss_feed_cache_lifetime' );
|
246 |
|
557 |
// Count of items inserted
|
558 |
$items_inserted = 0;
|
559 |
|
560 |
+
foreach ( $items as $i => $item ) {
|
561 |
|
562 |
// Normalize the URL
|
563 |
$permalink = $item->get_permalink(); // Link or enclosure URL
|
600 |
$format = 'Y-m-d H:i:s';
|
601 |
$has_date = $item->get_date( 'U' ) ? TRUE : FALSE;
|
602 |
$timestamp = $has_date ? $item->get_date( 'U' ) : date( 'U' );
|
603 |
+
|
604 |
+
if (apply_filters('wpra/importer/allow_scheduled_items', false) !== true) {
|
605 |
+
$timestamp = min(time() - $i, $timestamp);
|
606 |
+
}
|
607 |
+
|
608 |
+
$date = date( $format, $timestamp );
|
609 |
+
$date_gmt = gmdate( $format, $timestamp );
|
610 |
|
611 |
// Do not let WordPress sanitize the excerpt
|
612 |
// WordPress sanitizes the excerpt because it's expected to be typed by a user and sent in a POST
|
680 |
update_post_meta( $feed_ID, 'wprss_last_update_items', $items_inserted );
|
681 |
}
|
682 |
|
683 |
+
/**
|
684 |
+
* Inserts the appropriate post meta for feed items.
|
685 |
+
*
|
686 |
+
* Called from 'wprss_items_insert_post'
|
687 |
+
*
|
688 |
+
* @since 2.3
|
689 |
+
*
|
690 |
+
* @param int $inserted_ID The inserted post ID.
|
691 |
+
* @param SimplePie_Item $item The SimplePie item object.
|
692 |
+
* @param string $permalink The item's permalink.
|
693 |
+
* @param string $enclosure_url The URL to the item's enclosure.
|
694 |
+
*/
|
695 |
function wprss_items_insert_post_meta( $inserted_ID, $item, $feed_ID, $permalink, $enclosure_url ) {
|
696 |
+
update_post_meta( $inserted_ID, 'wprss_item_date', $item->get_date(DATE_ISO8601) );
|
697 |
update_post_meta( $inserted_ID, 'wprss_item_permalink', $permalink );
|
698 |
update_post_meta( $inserted_ID, 'wprss_item_enclosure', $enclosure_url );
|
699 |
|
File without changes
|
File without changes
|
@@ -4,10 +4,106 @@ use Aventura\Wprss\Core\Model\Regex\HtmlEncoder;
|
|
4 |
|
5 |
/**
|
6 |
* Helper and misc functions.
|
7 |
-
*
|
8 |
* @todo Make this part of Core instead
|
9 |
*/
|
10 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
/**
|
12 |
* Returns a representation of an HTML expression that matches all representations of that HTML.
|
13 |
*
|
@@ -117,7 +213,7 @@ if (!function_exists('uri_is_absolute')) {
|
|
117 |
|
118 |
/**
|
119 |
* Check if the URI is absolute.
|
120 |
-
*
|
121 |
* Check is made based on whether or not there's a '//' sequence
|
122 |
* somewhere in the beginning.
|
123 |
*
|
4 |
|
5 |
/**
|
6 |
* Helper and misc functions.
|
7 |
+
*
|
8 |
* @todo Make this part of Core instead
|
9 |
*/
|
10 |
|
11 |
+
/**
|
12 |
+
* Checks if developer mode is enabled.
|
13 |
+
*
|
14 |
+
* @since 4.15.1
|
15 |
+
*
|
16 |
+
* @return bool
|
17 |
+
*/
|
18 |
+
function wpra_is_dev_mode()
|
19 |
+
{
|
20 |
+
return apply_filters('wpra_dev_mode', false) === true;
|
21 |
+
}
|
22 |
+
|
23 |
+
/**
|
24 |
+
* WP RSS Aggregator's version of {@link wp_remote_get()}.
|
25 |
+
*
|
26 |
+
* It ensures that the feed request useragent is used as the HTTP request's User Agent String.
|
27 |
+
*
|
28 |
+
* @since 4.15.1
|
29 |
+
*
|
30 |
+
* @see https://developer.wordpress.org/reference/classes/WP_Http/request/ Information on the $args array parameter.
|
31 |
+
*
|
32 |
+
* @param string $url The URL
|
33 |
+
* @param array $args The arguments.
|
34 |
+
*
|
35 |
+
* @return array|WP_Error
|
36 |
+
*/
|
37 |
+
function wpra_remote_get($url, $args)
|
38 |
+
{
|
39 |
+
$args['user-agent'] = wprss_get_general_setting('feed_request_useragent');
|
40 |
+
|
41 |
+
return wp_remote_get($url, $args);
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* WP RSS Aggregator's version of {@link wp_safe_remote_get()}.
|
46 |
+
*
|
47 |
+
* It ensures that the feed request useragent is used as the HTTP request's User Agent String.
|
48 |
+
*
|
49 |
+
* @since 4.15.1
|
50 |
+
*
|
51 |
+
* @see https://developer.wordpress.org/reference/classes/WP_Http/request/ Information on the $args array parameter.
|
52 |
+
*
|
53 |
+
* @param string $url The URL
|
54 |
+
* @param array $args The arguments.
|
55 |
+
*
|
56 |
+
* @return array|WP_Error
|
57 |
+
*/
|
58 |
+
function wpra_safe_remote_get($url, $args)
|
59 |
+
{
|
60 |
+
$args['user-agent'] = wprss_get_general_setting('feed_request_useragent');
|
61 |
+
|
62 |
+
return wp_safe_remote_get($url, $args);
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Utility function for checking a plugin's state, even if it's inactive.
|
67 |
+
*
|
68 |
+
* @since 4.15.1
|
69 |
+
*
|
70 |
+
* @param string $basename The basename of the plugin.
|
71 |
+
*
|
72 |
+
* @return int 0 if the plugin is not installed, 1 if installed but not activated, 2 if installed and activated.
|
73 |
+
*/
|
74 |
+
function wpra_get_plugin_state($basename)
|
75 |
+
{
|
76 |
+
// ACTIVE
|
77 |
+
if (is_plugin_active($basename)) {
|
78 |
+
return 2;
|
79 |
+
}
|
80 |
+
|
81 |
+
// INSTALLED & INACTIVE
|
82 |
+
if (file_exists(WP_PLUGIN_DIR . '/' . $basename) && is_plugin_inactive($basename)) {
|
83 |
+
return 1;
|
84 |
+
}
|
85 |
+
|
86 |
+
// NOT INSTALLED
|
87 |
+
return 0;
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Utillity function for generating a URL that activates a plugin.
|
92 |
+
*
|
93 |
+
* @since 4.15.1
|
94 |
+
*
|
95 |
+
* @param string $basename The basename of the plugin.
|
96 |
+
*
|
97 |
+
* @return string
|
98 |
+
*/
|
99 |
+
function wpra_get_activate_plugin_url($basename)
|
100 |
+
{
|
101 |
+
return wp_nonce_url(
|
102 |
+
sprintf('plugins.php?action=activate&plugin=%s', $basename),
|
103 |
+
sprintf('activate-plugin_%s', $basename)
|
104 |
+
);
|
105 |
+
}
|
106 |
+
|
107 |
/**
|
108 |
* Returns a representation of an HTML expression that matches all representations of that HTML.
|
109 |
*
|
213 |
|
214 |
/**
|
215 |
* Check if the URI is absolute.
|
216 |
+
*
|
217 |
* Check is made based on whether or not there's a '//' sequence
|
218 |
* somewhere in the beginning.
|
219 |
*
|
@@ -488,7 +488,7 @@ class WPRSS_Image_Cache {
|
|
488 |
* @see WPRSS_Image_Cache_Image::get_current_path()
|
489 |
* @see get_tmp_dir()
|
490 |
* @see wp_mkdir_p()
|
491 |
-
* @see
|
492 |
* @see verify_file_md5()
|
493 |
* @param WPRSS_Image_Cache_Image|string $image An instance of a cache file, or the URL to download.
|
494 |
* @param int|null $request_timeout The timeout for the download request.
|
@@ -544,7 +544,14 @@ class WPRSS_Image_Cache {
|
|
544 |
require_once( $file_lib_path );
|
545 |
|
546 |
// Retrieving the remote resource
|
547 |
-
$response =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
548 |
|
549 |
// Could not retrieve
|
550 |
if ( is_wp_error( $response ) ) {
|
488 |
* @see WPRSS_Image_Cache_Image::get_current_path()
|
489 |
* @see get_tmp_dir()
|
490 |
* @see wp_mkdir_p()
|
491 |
+
* @see wpra_safe_remote_get()
|
492 |
* @see verify_file_md5()
|
493 |
* @param WPRSS_Image_Cache_Image|string $image An instance of a cache file, or the URL to download.
|
494 |
* @param int|null $request_timeout The timeout for the download request.
|
544 |
require_once( $file_lib_path );
|
545 |
|
546 |
// Retrieving the remote resource
|
547 |
+
$response = wpra_remote_get(
|
548 |
+
$url,
|
549 |
+
array(
|
550 |
+
'timeout' => $timeout,
|
551 |
+
'stream' => true,
|
552 |
+
'filename' => $tmpfname
|
553 |
+
)
|
554 |
+
);
|
555 |
|
556 |
// Could not retrieve
|
557 |
if ( is_wp_error( $response ) ) {
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -51,11 +51,6 @@
|
|
51 |
'pause' => __( 'Pause', WPRSS_TEXT_DOMAIN )
|
52 |
));
|
53 |
|
54 |
-
wp_register_script( 'wprss-custom-bulk-actions-feed-item', WPRSS_JS . 'admin-custom-bulk-actions-feed-item.js', array( 'jquery' ), $version );
|
55 |
-
wp_localize_script( 'wprss-custom-bulk-actions-feed-item', 'wprss_admin_bulk_feed_item', array(
|
56 |
-
'trash' => __( 'Move to Trash', WPRSS_TEXT_DOMAIN )
|
57 |
-
));
|
58 |
-
|
59 |
wp_register_script( 'wprss-feed-source-table-heartbeat', WPRSS_JS .'heartbeat.js', array(), $version );
|
60 |
wp_localize_script( 'wprss-feed-source-table-heartbeat', 'wprss_admin_heartbeat', array(
|
61 |
'ago' => __( 'ago', WPRSS_TEXT_DOMAIN )
|
51 |
'pause' => __( 'Pause', WPRSS_TEXT_DOMAIN )
|
52 |
));
|
53 |
|
|
|
|
|
|
|
|
|
|
|
54 |
wp_register_script( 'wprss-feed-source-table-heartbeat', WPRSS_JS .'heartbeat.js', array(), $version );
|
55 |
wp_localize_script( 'wprss-feed-source-table-heartbeat', 'wprss_admin_heartbeat', array(
|
56 |
'ago' => __( 'ago', WPRSS_TEXT_DOMAIN )
|
@@ -13,13 +13,13 @@
|
|
13 |
|
14 |
/**
|
15 |
* Generate the system information
|
16 |
-
*
|
17 |
* @since 3.1
|
18 |
-
*/
|
19 |
-
|
20 |
-
|
21 |
|
22 |
-
|
23 |
<h3><?php _e( 'System Information', WPRSS_TEXT_DOMAIN ) ?></h3>
|
24 |
<?php
|
25 |
$form_url = admin_url( 'edit.php?post_type=wprss_feed&page=wprss-debugging' );
|
@@ -31,29 +31,29 @@
|
|
31 |
<p class="submit">
|
32 |
<input type="hidden" name="wprss-action" value="download_sysinfo" />
|
33 |
<button type="submit" class="button button-primary" id="wprss-download-sysinfo">
|
34 |
-
|
35 |
-
|
36 |
</button>
|
37 |
</p>
|
38 |
</form>
|
39 |
|
40 |
-
|
41 |
-
|
42 |
|
43 |
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
global $wpdb;
|
51 |
-
|
52 |
if ( ! class_exists( 'Browser' ) )
|
53 |
require_once WPRSS_DIR . 'includes/libraries/browser.php';
|
54 |
|
55 |
$browser = new Browser();
|
56 |
-
|
57 |
?>
|
58 |
### Begin System Info ###
|
59 |
|
@@ -70,15 +70,29 @@ WordPress Version: <?php echo get_bloginfo( 'version' ) . "\n"; ?>
|
|
70 |
<?php echo $browser ; ?>
|
71 |
|
72 |
PHP Version: <?php echo PHP_VERSION . "\n"; ?>
|
73 |
-
MySQL Version: <?php
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
|
79 |
Web Server Info: <?php echo $_SERVER['SERVER_SOFTWARE'] . "\n"; ?>
|
80 |
|
81 |
-
PHP Safe Mode: <?php
|
|
|
|
|
|
|
|
|
82 |
PHP Memory Limit: <?php echo ini_get( 'memory_limit' ) . "\n"; ?>
|
83 |
PHP Post Max Size: <?php echo ini_get( 'post_max_size' ) . "\n"; ?>
|
84 |
PHP Time Limit: <?php echo ini_get( 'max_execution_time' ) . "\n"; ?>
|
@@ -119,15 +133,15 @@ $plugins = get_plugins();
|
|
119 |
$active_plugins = get_option( 'active_plugins', array() );
|
120 |
$inactive_plugins = array();
|
121 |
foreach ( $plugins as $plugin_path => $plugin ):
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
|
128 |
echo $plugin['Name']; ?>: <?php echo $plugin['Version'] ."\n";
|
129 |
|
130 |
-
endforeach;
|
131 |
|
132 |
if ( is_multisite() ) :
|
133 |
?>
|
@@ -139,18 +153,18 @@ $plugins = wp_get_active_network_plugins();
|
|
139 |
$active_plugins = get_site_option( 'active_sitewide_plugins', array() );
|
140 |
|
141 |
foreach ( $plugins as $plugin_path ) {
|
142 |
-
|
143 |
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
|
148 |
-
|
149 |
|
150 |
-
|
151 |
}
|
152 |
|
153 |
-
endif;
|
154 |
|
155 |
if ( ! is_multisite() ) : ?>
|
156 |
|
@@ -162,7 +176,7 @@ foreach ( $inactive_plugins as $inactive_plugin ):
|
|
162 |
|
163 |
echo $inactive_plugin['Name']; ?>: <?php echo $inactive_plugin['Version'] ."\n";
|
164 |
|
165 |
-
endforeach;
|
166 |
|
167 |
endif; ?>
|
168 |
|
@@ -170,11 +184,11 @@ CURRENT THEME:
|
|
170 |
|
171 |
<?php
|
172 |
if ( get_bloginfo( 'version' ) < '3.4' ) {
|
173 |
-
|
174 |
-
|
175 |
} else {
|
176 |
-
|
177 |
-
|
178 |
}
|
179 |
?>
|
180 |
|
@@ -219,79 +233,89 @@ foreach ($extensions as $extension) {
|
|
219 |
|
220 |
### End System Info ###
|
221 |
<?php
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
|
14 |
/**
|
15 |
* Generate the system information
|
16 |
+
*
|
17 |
* @since 3.1
|
18 |
+
*/
|
19 |
+
function wprss_system_info() {
|
20 |
+
global $wpdb;
|
21 |
|
22 |
+
?>
|
23 |
<h3><?php _e( 'System Information', WPRSS_TEXT_DOMAIN ) ?></h3>
|
24 |
<?php
|
25 |
$form_url = admin_url( 'edit.php?post_type=wprss_feed&page=wprss-debugging' );
|
31 |
<p class="submit">
|
32 |
<input type="hidden" name="wprss-action" value="download_sysinfo" />
|
33 |
<button type="submit" class="button button-primary" id="wprss-download-sysinfo">
|
34 |
+
<i class="fa fa-download"></i>
|
35 |
+
<?php _e( 'Download System Info File', WPRSS_TEXT_DOMAIN ) ?>
|
36 |
</button>
|
37 |
</p>
|
38 |
</form>
|
39 |
|
40 |
+
<?php
|
41 |
+
}
|
42 |
|
43 |
|
44 |
+
/**
|
45 |
+
* Prints the system information
|
46 |
+
*
|
47 |
+
* @since 4.6.8
|
48 |
+
*/
|
49 |
+
function wprss_print_system_info() {
|
50 |
global $wpdb;
|
51 |
+
|
52 |
if ( ! class_exists( 'Browser' ) )
|
53 |
require_once WPRSS_DIR . 'includes/libraries/browser.php';
|
54 |
|
55 |
$browser = new Browser();
|
56 |
+
|
57 |
?>
|
58 |
### Begin System Info ###
|
59 |
|
70 |
<?php echo $browser ; ?>
|
71 |
|
72 |
PHP Version: <?php echo PHP_VERSION . "\n"; ?>
|
73 |
+
MySQL Version: <?php $server_info = wprss_sysinfo_get_db_server();
|
74 |
+
if ( $server_info ) {
|
75 |
+
if (isset($server_info['warning'])) {
|
76 |
+
echo $server_info['extension'] . ' - ' . $server_info['warning'];
|
77 |
+
} else {
|
78 |
+
echo sprintf(
|
79 |
+
'%1$s (%2$s)',
|
80 |
+
$server_info['server_info'],
|
81 |
+
$server_info['extension']
|
82 |
+
);
|
83 |
+
}
|
84 |
+
} else {
|
85 |
+
_e( 'Could not determine database driver version', WPRSS_TEXT_DOMAIN );
|
86 |
+
}
|
87 |
+
?>
|
88 |
|
89 |
Web Server Info: <?php echo $_SERVER['SERVER_SOFTWARE'] . "\n"; ?>
|
90 |
|
91 |
+
PHP Safe Mode: <?php if (version_compare(PHP_VERSION, '5.4', '>=')) {
|
92 |
+
echo "No\n";
|
93 |
+
} else {
|
94 |
+
echo ini_get( 'safe_mode' ) ? "Yes" : "No\n";
|
95 |
+
} ?>
|
96 |
PHP Memory Limit: <?php echo ini_get( 'memory_limit' ) . "\n"; ?>
|
97 |
PHP Post Max Size: <?php echo ini_get( 'post_max_size' ) . "\n"; ?>
|
98 |
PHP Time Limit: <?php echo ini_get( 'max_execution_time' ) . "\n"; ?>
|
133 |
$active_plugins = get_option( 'active_plugins', array() );
|
134 |
$inactive_plugins = array();
|
135 |
foreach ( $plugins as $plugin_path => $plugin ):
|
136 |
+
// If the plugin isn't active, don't show it.
|
137 |
+
if ( ! in_array( $plugin_path, $active_plugins ) ) {
|
138 |
+
$inactive_plugins[] = $plugin;
|
139 |
+
continue;
|
140 |
+
}
|
141 |
|
142 |
echo $plugin['Name']; ?>: <?php echo $plugin['Version'] ."\n";
|
143 |
|
144 |
+
endforeach;
|
145 |
|
146 |
if ( is_multisite() ) :
|
147 |
?>
|
153 |
$active_plugins = get_site_option( 'active_sitewide_plugins', array() );
|
154 |
|
155 |
foreach ( $plugins as $plugin_path ) {
|
156 |
+
$plugin_base = plugin_basename( $plugin_path );
|
157 |
|
158 |
+
// If the plugin isn't active, don't show it.
|
159 |
+
if ( ! array_key_exists( $plugin_base, $active_plugins ) )
|
160 |
+
continue;
|
161 |
|
162 |
+
$plugin = get_plugin_data( $plugin_path );
|
163 |
|
164 |
+
echo $plugin['Name'] . ': ' . $plugin['Version'] ."\n";
|
165 |
}
|
166 |
|
167 |
+
endif;
|
168 |
|
169 |
if ( ! is_multisite() ) : ?>
|
170 |
|
176 |
|
177 |
echo $inactive_plugin['Name']; ?>: <?php echo $inactive_plugin['Version'] ."\n";
|
178 |
|
179 |
+
endforeach;
|
180 |
|
181 |
endif; ?>
|
182 |
|
184 |
|
185 |
<?php
|
186 |
if ( get_bloginfo( 'version' ) < '3.4' ) {
|
187 |
+
$theme_data = get_theme_data( get_stylesheet_directory() . '/style.css' );
|
188 |
+
echo $theme_data['Name'] . ': ' . $theme_data['Version'];
|
189 |
} else {
|
190 |
+
$theme_data = wp_get_theme();
|
191 |
+
echo $theme_data->Name . ': ' . $theme_data->Version;
|
192 |
}
|
193 |
?>
|
194 |
|
233 |
|
234 |
### End System Info ###
|
235 |
<?php
|
236 |
+
}
|
237 |
+
|
238 |
+
|
239 |
+
/**
|
240 |
+
* Generates the System Info Download File
|
241 |
+
*
|
242 |
+
* @since 3.1
|
243 |
+
* @return void
|
244 |
+
*/
|
245 |
+
function wprss_generate_sysinfo_download() {
|
246 |
+
nocache_headers();
|
247 |
+
|
248 |
+
check_admin_referer('wprss-sysinfo');
|
249 |
+
|
250 |
+
header( "Content-type: text/plain" );
|
251 |
+
header( 'Content-Disposition: attachment; filename="wprss-system-info.txt"' );
|
252 |
+
|
253 |
+
echo wp_strip_all_tags( $_POST['wprss-sysinfo'] );
|
254 |
+
exit;
|
255 |
+
}
|
256 |
+
add_action( 'wprss_download_sysinfo', 'wprss_generate_sysinfo_download' );
|
257 |
+
|
258 |
+
|
259 |
+
/**
|
260 |
+
* Retrieves information about the DB server.
|
261 |
+
*
|
262 |
+
* Will use WordPress configuration by default;
|
263 |
+
* Currently, the following members are present in the result:
|
264 |
+
* - 'extension': The extension that is used to connect. Possible values: 'mysqli', 'mysql'.
|
265 |
+
* - 'server_info': The version number of the database engine, i.e. '5.6.22'.
|
266 |
+
*
|
267 |
+
* @since 4.7.2
|
268 |
+
* @param null|string $host The address of the database host, to which to connect.
|
269 |
+
* May contain the port number in standard URI format.
|
270 |
+
* Default: value of the DB_HOST constant, if defined, otherwise null.
|
271 |
+
* @param null|string $username The username to be used for connecting to the databse.
|
272 |
+
* Default: value of the DB_USER constant, if defined, otherwise null.
|
273 |
+
* @param null|string $password The password to be used for connecting to the database.
|
274 |
+
* Default: value of the DB_PASSWORD constant, if defined, otherwise null.
|
275 |
+
* @param null|int $port An integer, representing the port, at which to connect to the DB server.
|
276 |
+
* Default: auto-determined from host.
|
277 |
+
* @return array|null An array, containing the following indexes, if successful: 'extension', 'server_info'.
|
278 |
+
* Otherwise, null.
|
279 |
+
*/
|
280 |
+
function wprss_sysinfo_get_db_server( $host = null, $username = null, $password = null, $port = null ) {
|
281 |
+
$result = array();
|
282 |
+
|
283 |
+
if ( is_null( $host ) && defined( 'DB_HOST') ) $host = DB_HOST;
|
284 |
+
if ( is_null( $username ) && defined( 'DB_USER') ) $username = DB_USER;
|
285 |
+
if ( is_null( $password ) && defined( 'DB_PASSWORD') ) $password = DB_PASSWORD;
|
286 |
+
|
287 |
+
$server_address = explode( ':', $host, 2 );
|
288 |
+
$host = $server_address[0];
|
289 |
+
$port = is_null( $port )
|
290 |
+
? ( isset( $server_address[1] ) ? $server_address[1] : null )
|
291 |
+
: $port;
|
292 |
+
$port = $port ? intval( (string)$port ) : null;
|
293 |
+
|
294 |
+
if ( function_exists( 'mysqli_get_server_info' ) ){
|
295 |
+
$mysqli = new mysqli( $host, $username, $password, '', $port );
|
296 |
+
$result['extension'] = 'mysqli';
|
297 |
+
$result['server_info'] = $mysqli->server_info;
|
298 |
+
return $result;
|
299 |
+
}
|
300 |
+
|
301 |
+
if ( function_exists( 'mysql_connect' ) ) {
|
302 |
+
if (version_compare(PHP_VERSION, '7.0', '>=')) {
|
303 |
+
$result['warning'] = __(
|
304 |
+
'The mysql extension is deprecated since PHP 5.5 and removed since PHP 7.0; Use mysqli instead',
|
305 |
+
'wprss'
|
306 |
+
);
|
307 |
+
$result['extension'] = 'mysql';
|
308 |
+
$result['server_info'] = '';
|
309 |
+
return $result;
|
310 |
+
}
|
311 |
+
|
312 |
+
if ( $port ) $host = implode ( ':', array( $host, $port ) );
|
313 |
+
|
314 |
+
$mysql = mysql_connect( $host, $username, $password );
|
315 |
+
$result['extension'] = 'mysql';
|
316 |
+
$result['server_info'] = mysql_get_server_info( $mysql );
|
317 |
+
return $result;
|
318 |
+
}
|
319 |
+
|
320 |
+
return null;
|
321 |
+
}
|
@@ -285,7 +285,7 @@
|
|
285 |
'expiration_notice_period' => '2 weeks',
|
286 |
|
287 |
// From 4.8.2
|
288 |
-
'feed_request_useragent' => '
|
289 |
|
290 |
// From 4.11.2
|
291 |
'limit_feed_items_per_import' => null,
|
285 |
'expiration_notice_period' => '2 weeks',
|
286 |
|
287 |
// From 4.8.2
|
288 |
+
'feed_request_useragent' => 'Mozilla/5.0 (Linux 10.0; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36',
|
289 |
|
290 |
// From 4.11.2
|
291 |
'limit_feed_items_per_import' => null,
|
File without changes
|
@@ -1,16 +0,0 @@
|
|
1 |
-
/**
|
2 |
-
* Adds and manages custom bulk actions for the Feed Items page.
|
3 |
-
*
|
4 |
-
* @since 4.7
|
5 |
-
*/
|
6 |
-
(function($, wprss_admin_bulk_feed_item){
|
7 |
-
|
8 |
-
$(document).ready( function(){
|
9 |
-
var bulk_actions_select = $( 'select#bulk-action-selector-top, select#bulk-action-selector-bottom' );
|
10 |
-
var bulk_actions_edit = bulk_actions_select.find( "option[value='edit']" );
|
11 |
-
|
12 |
-
$( '<option>' ).attr( 'value', 'trash' ).text( wprss_admin_bulk_feed_item.trash ).insertBefore( bulk_actions_edit );
|
13 |
-
bulk_actions_edit.remove();
|
14 |
-
});
|
15 |
-
|
16 |
-
})(jQuery, wprss_admin_bulk_feed_item);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<template>
|
2 |
+
<div class="wpra-bottom-panel">
|
3 |
+
<slot></slot>
|
4 |
+
</div>
|
5 |
+
</template>
|
6 |
+
|
7 |
+
<script>
|
8 |
+
export default {}
|
9 |
+
</script>
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
export default {
|
2 |
+
props: {
|
3 |
+
loading: {
|
4 |
+
type: Boolean,
|
5 |
+
default: false,
|
6 |
+
}
|
7 |
+
},
|
8 |
+
render () {
|
9 |
+
return <button
|
10 |
+
disabled={this.loading}
|
11 |
+
class={{'button': true, 'loading-button': this.loading}}
|
12 |
+
>{ this.$slots.default }</button>
|
13 |
+
}
|
14 |
+
}
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<template>
|
2 |
+
<div class="wpra-expander" :class="{'wpra-expander--expanded':isExpanded}">
|
3 |
+
<div class="wpra-expander__title" @click="isExpanded = !isExpanded">
|
4 |
+
{{ title }}
|
5 |
+
<span class="dashicons dashicons-arrow-down-alt2"></span>
|
6 |
+
</div>
|
7 |
+
<transition-expand>
|
8 |
+
<div v-if="isExpanded">
|
9 |
+
<div class="wpra-expander__content">
|
10 |
+
<slot></slot>
|
11 |
+
</div>
|
12 |
+
</div>
|
13 |
+
</transition-expand>
|
14 |
+
</div>
|
15 |
+
</template>
|
16 |
+
|
17 |
+
<script>
|
18 |
+
import TransitionExpand from './TransitionExpand'
|
19 |
+
|
20 |
+
export default {
|
21 |
+
data () {
|
22 |
+
return {
|
23 |
+
isExpanded: this.defaultExpanded
|
24 |
+
}
|
25 |
+
},
|
26 |
+
props: {
|
27 |
+
title: {},
|
28 |
+
defaultExpanded: {
|
29 |
+
value: false
|
30 |
+
}
|
31 |
+
},
|
32 |
+
components: {
|
33 |
+
TransitionExpand
|
34 |
+
}
|
35 |
+
}
|
36 |
+
</script>
|
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import MediaInput from './MediaInput'
|
2 |
+
|
3 |
+
export default {
|
4 |
+
mixins: [
|
5 |
+
MediaInput
|
6 |
+
],
|
7 |
+
props: {
|
8 |
+
id: {
|
9 |
+
type: String,
|
10 |
+
default () {
|
11 |
+
return Math.random().toString(36).substr(0, 12)
|
12 |
+
}
|
13 |
+
},
|
14 |
+
label: {},
|
15 |
+
description: {},
|
16 |
+
after: {},
|
17 |
+
type: {},
|
18 |
+
value: {},
|
19 |
+
placeholder: {},
|
20 |
+
title: {},
|
21 |
+
inputDisabled: {},
|
22 |
+
options: {
|
23 |
+
default () {
|
24 |
+
return {}
|
25 |
+
}
|
26 |
+
},
|
27 |
+
},
|
28 |
+
methods: {
|
29 |
+
inputNode () {
|
30 |
+
if (this.type === 'media') {
|
31 |
+
return this.mediaNode()
|
32 |
+
}
|
33 |
+
|
34 |
+
if (this.type === 'checkbox') {
|
35 |
+
return <input type="checkbox"
|
36 |
+
id={this.id}
|
37 |
+
checked={!!this.value}
|
38 |
+
onChange={() => this.$emit('input', !this.value)}
|
39 |
+
placeholder={this.placeholder}
|
40 |
+
disabled={this.$attrs.disabled || this.inputDisabled}
|
41 |
+
{...{attrs: this.$attrs}}
|
42 |
+
/>
|
43 |
+
}
|
44 |
+
|
45 |
+
if (this.type !== 'select') {
|
46 |
+
return <input type={this.type}
|
47 |
+
value={this.value}
|
48 |
+
id={this.id}
|
49 |
+
onInput={(e) => this.$emit('input', e.target.value)}
|
50 |
+
placeholder={this.placeholder}
|
51 |
+
disabled={this.$attrs.disabled || this.inputDisabled}
|
52 |
+
{...{attrs: this.$attrs}}
|
53 |
+
/>
|
54 |
+
}
|
55 |
+
return this.selectNode()
|
56 |
+
},
|
57 |
+
|
58 |
+
selectNode () {
|
59 |
+
let options = Object.keys(this.options)
|
60 |
+
.map(key => <option value={key} selected={ this.value === key }>{ this.options[key] }</option>)
|
61 |
+
|
62 |
+
return <select
|
63 |
+
{...{attrs: this.$attrs}}
|
64 |
+
id={this.id}
|
65 |
+
disabled={this.$attrs.disabled || this.inputDisabled}
|
66 |
+
onChange={(e) => this.$emit('input', e.target.value)}
|
67 |
+
>{ options }</select>
|
68 |
+
},
|
69 |
+
},
|
70 |
+
render () {
|
71 |
+
let directives = []
|
72 |
+
|
73 |
+
if (this.title) {
|
74 |
+
directives.push({
|
75 |
+
name: 'tippy',
|
76 |
+
})
|
77 |
+
}
|
78 |
+
|
79 |
+
return <div class={{'form-input': true, 'form-input--disabled': this.$attrs.disabled || false}}>
|
80 |
+
{ this.label ? (
|
81 |
+
<label class="form-input__label" for={this.id}>
|
82 |
+
<div>
|
83 |
+
{this.label}
|
84 |
+
{
|
85 |
+
this.title ? (
|
86 |
+
<div class="form-input__tip" {...{directives}} title={this.title}>
|
87 |
+
<span class="dashicons dashicons-editor-help"/>
|
88 |
+
</div>
|
89 |
+
) : null
|
90 |
+
}
|
91 |
+
</div>
|
92 |
+
{this.description ? <div class="form-input__label-description" {...{domProps: {innerHTML: this.description}}}/> : ''}
|
93 |
+
</label>
|
94 |
+
) : null }
|
95 |
+
<div class="form-input__field">
|
96 |
+
{ this.inputNode() }{ this.after }
|
97 |
+
</div>
|
98 |
+
</div>
|
99 |
+
}
|
100 |
+
}
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
export default {
|
2 |
+
render () {
|
3 |
+
return (
|
4 |
+
<div id="post-body">
|
5 |
+
{
|
6 |
+
this.$slots.default
|
7 |
+
}
|
8 |
+
</div>
|
9 |
+
)
|
10 |
+
}
|
11 |
+
}
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
export default {
|
2 |
+
render () {
|
3 |
+
return (
|
4 |
+
<div id="postbox-container-2" class="postbox-container">
|
5 |
+
{
|
6 |
+
this.$slots.default
|
7 |
+
}
|
8 |
+
</div>
|
9 |
+
)
|
10 |
+
}
|
11 |
+
}
|
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
let imageFrame = null
|
2 |
+
|
3 |
+
/**
|
4 |
+
* @see https://core.trac.wordpress.org/browser/tags/5.1.1/src/js/_enqueues/wp/media?order=name
|
5 |
+
*
|
6 |
+
* @var {{media: Function}} wp
|
7 |
+
*
|
8 |
+
* @property {{}} value
|
9 |
+
*/
|
10 |
+
export default {
|
11 |
+
props: {
|
12 |
+
mediaType: {
|
13 |
+
type: String,
|
14 |
+
default: 'image'
|
15 |
+
},
|
16 |
+
mediaTitle: {
|
17 |
+
type: String,
|
18 |
+
default: 'Select Media'
|
19 |
+
},
|
20 |
+
/**
|
21 |
+
* Property to use as a value for the media. Can be `id` or `url`.
|
22 |
+
*
|
23 |
+
* @property {string} mediaValueProperty
|
24 |
+
*/
|
25 |
+
mediaValueProperty: {
|
26 |
+
type: String,
|
27 |
+
default: 'id',
|
28 |
+
},
|
29 |
+
},
|
30 |
+
methods: {
|
31 |
+
mediaNode () {
|
32 |
+
this.assertMediaLoaded()
|
33 |
+
|
34 |
+
return <div>
|
35 |
+
<input type="text" value={this.value}/>
|
36 |
+
<button class="button" onClick={this.openFrame}>Choose image</button>
|
37 |
+
</div>
|
38 |
+
},
|
39 |
+
|
40 |
+
openFrame () {
|
41 |
+
if (!imageFrame) {
|
42 |
+
imageFrame = this.createFrame()
|
43 |
+
}
|
44 |
+
imageFrame.open()
|
45 |
+
},
|
46 |
+
|
47 |
+
createFrame () {
|
48 |
+
imageFrame = wp.media({
|
49 |
+
title: this.mediaTitle,
|
50 |
+
multiple: false,
|
51 |
+
library: {
|
52 |
+
type: this.mediaType,
|
53 |
+
}
|
54 |
+
})
|
55 |
+
|
56 |
+
imageFrame.on('close', () => {
|
57 |
+
const selection = imageFrame.state().get('selection')
|
58 |
+
let selectedAttachment = null
|
59 |
+
selection.each((attachment) => {
|
60 |
+
console.info({attachment})
|
61 |
+
selectedAttachment = attachment
|
62 |
+
})
|
63 |
+
if (!selectedAttachment || !selectedAttachment.id) {
|
64 |
+
return
|
65 |
+
}
|
66 |
+
this.$emit('input', ({
|
67 |
+
id: selectedAttachment.id,
|
68 |
+
url: selectedAttachment.attributes.url
|
69 |
+
})[this.mediaValueProperty])
|
70 |
+
})
|
71 |
+
|
72 |
+
imageFrame.on('open', () => {
|
73 |
+
const selection = imageFrame.state().get('selection')
|
74 |
+
|
75 |
+
if (this.mediaValueProperty === 'id' && this.value) {
|
76 |
+
const attachment = wp.media.attachment(this.value)
|
77 |
+
attachment.fetch()
|
78 |
+
selection.add(attachment ? [attachment] : [])
|
79 |
+
}
|
80 |
+
})
|
81 |
+
|
82 |
+
return imageFrame
|
83 |
+
},
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Check whether wp.media is loaded. If not - throw an error.
|
87 |
+
*
|
88 |
+
* @throws Error When wp.media is not loaded.
|
89 |
+
*/
|
90 |
+
assertMediaLoaded () {
|
91 |
+
if (!window.wp.media) {
|
92 |
+
throw Error('[MediaInput] wp.media dependency is not loaded')
|
93 |
+
}
|
94 |
+
}
|
95 |
+
},
|
96 |
+
}
|
@@ -0,0 +1,114 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<template>
|
2 |
+
<transition name="modal-transition">
|
3 |
+
<div class="modal" v-if="active" @click.self="$emit('close')">
|
4 |
+
<div :class="['modal__body', this.modalBodyClass]">
|
5 |
+
<div class="modal__header" :class="headerClass">
|
6 |
+
<slot name="header"></slot>
|
7 |
+
</div>
|
8 |
+
<div class="modal__content">
|
9 |
+
<slot name="body"></slot>
|
10 |
+
</div>
|
11 |
+
<div class="modal__footer">
|
12 |
+
<slot name="footer"></slot>
|
13 |
+
</div>
|
14 |
+
</div>
|
15 |
+
</div>
|
16 |
+
</transition>
|
17 |
+
</template>
|
18 |
+
|
19 |
+
<script>
|
20 |
+
/**
|
21 |
+
* Abstract dialog component, solid foundation for
|
22 |
+
* any modals and dialogs that opened over the rest page content.
|
23 |
+
*
|
24 |
+
* @param Vue
|
25 |
+
*/
|
26 |
+
export default {
|
27 |
+
props: {
|
28 |
+
/**
|
29 |
+
* Determines dialog visibility. This property is passed
|
30 |
+
* from outside and cannot be changed inside dialog.
|
31 |
+
* Dialog's consumer is responsible for manipulating dialog's visibility.
|
32 |
+
*
|
33 |
+
* @property {bool}
|
34 |
+
*/
|
35 |
+
active: {
|
36 |
+
type: Boolean
|
37 |
+
},
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Modal title
|
41 |
+
*
|
42 |
+
* @property {string}
|
43 |
+
*/
|
44 |
+
title: {
|
45 |
+
type: String
|
46 |
+
},
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Additional class modifier for modal customization.
|
50 |
+
*
|
51 |
+
* @property {string}
|
52 |
+
*/
|
53 |
+
modalBodyClass: {
|
54 |
+
type: String,
|
55 |
+
default: ''
|
56 |
+
},
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Additional classes for modal header.
|
60 |
+
*
|
61 |
+
* @property {object|Array}
|
62 |
+
*/
|
63 |
+
headerClass: {
|
64 |
+
default () {
|
65 |
+
return {}
|
66 |
+
}
|
67 |
+
},
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Class that applies to the body and used
|
71 |
+
* to prevent body's scroll catch, so long dialog can be scrolled
|
72 |
+
* without interfering with body scroll.
|
73 |
+
*
|
74 |
+
* @property {string}
|
75 |
+
*/
|
76 |
+
dialogOpenedClass: {
|
77 |
+
type: String,
|
78 |
+
default: 'modal-opened'
|
79 |
+
}
|
80 |
+
},
|
81 |
+
|
82 |
+
watch: {
|
83 |
+
/**
|
84 |
+
* Watch for "active" property change and emit corresponding
|
85 |
+
* event when it changed.
|
86 |
+
*
|
87 |
+
* @param isDialogActive {bool}
|
88 |
+
*/
|
89 |
+
active (isDialogActive) {
|
90 |
+
this.$emit(isDialogActive ? 'open' : 'close')
|
91 |
+
}
|
92 |
+
},
|
93 |
+
|
94 |
+
mounted () {
|
95 |
+
/*
|
96 |
+
* Add body "frozen" class to the body when dialog is opened.
|
97 |
+
*/
|
98 |
+
this.$on('open', () => {
|
99 |
+
document.querySelector('body')
|
100 |
+
.classList
|
101 |
+
.add(this.dialogOpenedClass);
|
102 |
+
});
|
103 |
+
|
104 |
+
/*
|
105 |
+
* Remove body "frozen" class from the body when dialog is closed.
|
106 |
+
*/
|
107 |
+
this.$on('close', () => {
|
108 |
+
document.querySelector('body')
|
109 |
+
.classList
|
110 |
+
.remove(this.dialogOpenedClass);
|
111 |
+
});
|
112 |
+
},
|
113 |
+
}
|
114 |
+
</script>
|
@@ -0,0 +1,143 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import Button from './Button'
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Big notice block that is used to provide some information for users.
|
5 |
+
* Also can display "learn more" button to allow users to read more about
|
6 |
+
* the announce.
|
7 |
+
*/
|
8 |
+
export default {
|
9 |
+
data () {
|
10 |
+
return {
|
11 |
+
shouldBeVisible: true,
|
12 |
+
}
|
13 |
+
},
|
14 |
+
|
15 |
+
props: {
|
16 |
+
/**
|
17 |
+
* Unique identifier of the notice block.
|
18 |
+
*
|
19 |
+
* @property {string}
|
20 |
+
*/
|
21 |
+
id: {
|
22 |
+
type: String,
|
23 |
+
required: true,
|
24 |
+
},
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Visible title on top of the block.
|
28 |
+
*
|
29 |
+
* @property {string}
|
30 |
+
*/
|
31 |
+
title: {
|
32 |
+
type: String,
|
33 |
+
},
|
34 |
+
|
35 |
+
/**
|
36 |
+
* The notice's block body. Can be HTML with text formatting, links and so on.
|
37 |
+
*
|
38 |
+
* @property {string}
|
39 |
+
*/
|
40 |
+
body: {
|
41 |
+
type: String,
|
42 |
+
},
|
43 |
+
|
44 |
+
/**
|
45 |
+
* The link to a "learn more" article. Will be opened in a new tab.
|
46 |
+
* If value is empty, "learn more" button won't be rendered.
|
47 |
+
*
|
48 |
+
* @property {string|boolean}
|
49 |
+
*/
|
50 |
+
learnMore: {
|
51 |
+
default: false,
|
52 |
+
},
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Text on the button that will hide the message.
|
56 |
+
*
|
57 |
+
* @property {string}
|
58 |
+
*/
|
59 |
+
okayText: {
|
60 |
+
type: String,
|
61 |
+
default: 'Got it'
|
62 |
+
},
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Text on the button that will open a "learn more" article.
|
66 |
+
*
|
67 |
+
* @property {string}
|
68 |
+
*/
|
69 |
+
learnMoreText: {
|
70 |
+
type: String,
|
71 |
+
default: 'Learn more'
|
72 |
+
},
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Whether the notice block is visible in UI.
|
76 |
+
*
|
77 |
+
* @property {boolean}
|
78 |
+
*/
|
79 |
+
visible: {
|
80 |
+
type: Boolean,
|
81 |
+
default: true,
|
82 |
+
},
|
83 |
+
},
|
84 |
+
|
85 |
+
computed: {
|
86 |
+
isVisible () {
|
87 |
+
return this.visible
|
88 |
+
&& this.shouldBeVisible
|
89 |
+
&& JSON.parse(localStorage.getItem(this.getBlockKey()) || 'true')
|
90 |
+
}
|
91 |
+
},
|
92 |
+
|
93 |
+
methods: {
|
94 |
+
/**
|
95 |
+
* Hide the block.
|
96 |
+
*/
|
97 |
+
onOkayClick () {
|
98 |
+
this.shouldBeVisible = false
|
99 |
+
localStorage.setItem(this.getBlockKey(), JSON.stringify(false))
|
100 |
+
},
|
101 |
+
|
102 |
+
/**
|
103 |
+
* Open learn more link in a new tab when user clicks on the "learn more" button.
|
104 |
+
*/
|
105 |
+
onLearnMoreClick () {
|
106 |
+
window.open(this.learnMore, '_blank').focus()
|
107 |
+
},
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Notice's block key in local storage.
|
111 |
+
*
|
112 |
+
* @return {string}
|
113 |
+
*/
|
114 |
+
getBlockKey () {
|
115 |
+
return `wpra-${this.id}-visible`
|
116 |
+
}
|
117 |
+
},
|
118 |
+
|
119 |
+
render () {
|
120 |
+
/*
|
121 |
+
* Template is not rendered when it was hidden by user, or server.
|
122 |
+
*/
|
123 |
+
if (!this.isVisible) {
|
124 |
+
return null
|
125 |
+
}
|
126 |
+
|
127 |
+
let learnMoreButton = this.learnMore ?
|
128 |
+
<Button class="button-clear" nativeOnClick={this.onLearnMoreClick}>
|
129 |
+
{this.learnMoreText} <span class="dashicons dashicons-external"/>
|
130 |
+
</Button> : null
|
131 |
+
|
132 |
+
return (
|
133 |
+
<div class="wpra-notice-block">
|
134 |
+
<div class="wpra-notice-block__title">{this.title}</div>
|
135 |
+
<div class="wpra-notice-block__body" {...{domProps: {innerHTML: this.body}}}/>
|
136 |
+
<div class="wpra-notice-block__buttons">
|
137 |
+
<Button class="brand button-primary" nativeOnClick={this.onOkayClick}>{this.okayText}</Button>
|
138 |
+
{learnMoreButton}
|
139 |
+
</div>
|
140 |
+
</div>
|
141 |
+
)
|
142 |
+
}
|
143 |
+
}
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<script>
|
2 |
+
export default {
|
3 |
+
inject: ['hooks'],
|
4 |
+
data () {
|
5 |
+
return {
|
6 |
+
expanded: true,
|
7 |
+
}
|
8 |
+
},
|
9 |
+
props: {
|
10 |
+
title: {},
|
11 |
+
id: {},
|
12 |
+
submit: {
|
13 |
+
type: Boolean,
|
14 |
+
default: false,
|
15 |
+
},
|
16 |
+
context: {},
|
17 |
+
},
|
18 |
+
methods: {
|
19 |
+
toggle () {
|
20 |
+
this.expanded = !this.expanded
|
21 |
+
}
|
22 |
+
},
|
23 |
+
render (h) {
|
24 |
+
return this.hooks.apply('postbox-' + this.id, this.context || this, (
|
25 |
+
<div class="postbox wpra-postbox" id={ this.submit ? 'submitdiv' : ''}>
|
26 |
+
<button type="button" class="handlediv" aria-expanded="true" onClick={this.toggle}>
|
27 |
+
<span class="screen-reader-text">Toggle panel: { this.title }</span>
|
28 |
+
<span class="toggle-indicator" aria-hidden="true"></span>
|
29 |
+
</button>
|
30 |
+
<h2 class="hndle ui-sortable-handle"
|
31 |
+
onClick={this.toggle}
|
32 |
+
><span>{ this.title }</span></h2>
|
33 |
+
<div class="inside">
|
34 |
+
{
|
35 |
+
this.hooks.apply('postbox-content-' + this.id, this.context || this, [
|
36 |
+
this.$slots.default
|
37 |
+
], {h})
|
38 |
+
}
|
39 |
+
</div>
|
40 |
+
</div>
|
41 |
+
), {h})
|
42 |
+
}
|
43 |
+
}
|
44 |
+
</script>
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
export default {
|
2 |
+
props: {
|
3 |
+
path: {},
|
4 |
+
gate: {}
|
5 |
+
},
|
6 |
+
inject: [
|
7 |
+
'router'
|
8 |
+
],
|
9 |
+
methods: {
|
10 |
+
getPath () {
|
11 |
+
return this.router.buildRoute(this.path)
|
12 |
+
},
|
13 |
+
navigate (e) {
|
14 |
+
const allowed = !this.gate || this.gate()
|
15 |
+
|
16 |
+
e.preventDefault()
|
17 |
+
|
18 |
+
if (allowed) {
|
19 |
+
this.router.navigate(this.path)
|
20 |
+
}
|
21 |
+
}
|
22 |
+
},
|
23 |
+
render () {
|
24 |
+
const path = this.getPath()
|
25 |
+
return <a href={path} onClick={this.navigate}>{ this.$slots.default }</a>
|
26 |
+
}
|
27 |
+
}
|
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
export default function ({ store, router }) {
|
2 |
+
return {
|
3 |
+
store,
|
4 |
+
data () {
|
5 |
+
return {
|
6 |
+
afterNavigate: () => {},
|
7 |
+
params: {},
|
8 |
+
currentRoute: null,
|
9 |
+
}
|
10 |
+
},
|
11 |
+
created () {
|
12 |
+
router.setApp(this)
|
13 |
+
this.currentRoute = router.parseLocation(window.location)
|
14 |
+
this.navigated()
|
15 |
+
},
|
16 |
+
mounted () {
|
17 |
+
window.addEventListener('popstate', () => {
|
18 |
+
this.currentRoute = router.parseLocation(window.location)
|
19 |
+
this.navigated()
|
20 |
+
})
|
21 |
+
},
|
22 |
+
methods: {
|
23 |
+
ViewComponent () {
|
24 |
+
const matchingView = router.findRoute(this.currentRoute)
|
25 |
+
return matchingView.component
|
26 |
+
},
|
27 |
+
navigated () {
|
28 |
+
this.$nextTick(() => {
|
29 |
+
const main = this.$refs.main
|
30 |
+
if (!main || !main.navigated) {
|
31 |
+
return
|
32 |
+
}
|
33 |
+
main.navigated({
|
34 |
+
route: router.findRoute(this.currentRoute),
|
35 |
+
})
|
36 |
+
})
|
37 |
+
}
|
38 |
+
},
|
39 |
+
render (h) {
|
40 |
+
const content = h(this.ViewComponent(), {
|
41 |
+
ref: 'main'
|
42 |
+
})
|
43 |
+
this.afterNavigate()
|
44 |
+
return content
|
45 |
+
}
|
46 |
+
}
|
47 |
+
}
|
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<template>
|
2 |
+
<div class="form">
|
3 |
+
<div class="form-group"
|
4 |
+
v-for="datum of form"
|
5 |
+
v-if="satisfiesCondition(datum)"
|
6 |
+
>
|
7 |
+
<template v-if="datum.type === 'radio'">
|
8 |
+
<label :for="datum.name" v-html="datum.label" v-if="datum.label"></label>
|
9 |
+
<div class="form-check" v-for="(radio, $i) of datum.options">
|
10 |
+
<input type="radio"
|
11 |
+
:name="datum.name"
|
12 |
+
:id="datum.name + '_' + $i"
|
13 |
+
:value="radio.value"
|
14 |
+
v-model="model[datum.name]"
|
15 |
+
>
|
16 |
+
<label :for="datum.name + '_' + $i">
|
17 |
+
{{ radio.label || radio.value }}
|
18 |
+
</label>
|
19 |
+
</div>
|
20 |
+
</template>
|
21 |
+
|
22 |
+
<template v-if="datum.type === 'textarea'">
|
23 |
+
<label :for="datum.name" v-html="datum.label" v-if="datum.label"></label>
|
24 |
+
<textarea v-model="model[datum.name]" :id="datum.name"></textarea>
|
25 |
+
</template>
|
26 |
+
|
27 |
+
<template v-if="datum.type === 'content'">
|
28 |
+
<div :class="datum.className">
|
29 |
+
<p v-html="datum.label"></p>
|
30 |
+
</div>
|
31 |
+
</template>
|
32 |
+
</div>
|
33 |
+
</div>
|
34 |
+
</template>
|
35 |
+
|
36 |
+
<script>
|
37 |
+
export default {
|
38 |
+
props: {
|
39 |
+
/*
|
40 |
+
* Form, described by object containing information
|
41 |
+
* about each field.
|
42 |
+
*/
|
43 |
+
form: {
|
44 |
+
type: Array,
|
45 |
+
},
|
46 |
+
|
47 |
+
/*
|
48 |
+
* Form model.
|
49 |
+
*/
|
50 |
+
value: {
|
51 |
+
type: Object,
|
52 |
+
}
|
53 |
+
},
|
54 |
+
computed: {
|
55 |
+
model: {
|
56 |
+
get () {
|
57 |
+
return this.value
|
58 |
+
},
|
59 |
+
set (value) {
|
60 |
+
this.$emit('input', value)
|
61 |
+
}
|
62 |
+
}
|
63 |
+
},
|
64 |
+
methods: {
|
65 |
+
satisfiesCondition (datum) {
|
66 |
+
if (!datum.condition) {
|
67 |
+
return true
|
68 |
+
}
|
69 |
+
let compareFunction = this.getConditionFunction(datum.condition.operator);
|
70 |
+
if (!compareFunction) {
|
71 |
+
return false
|
72 |
+
}
|
73 |
+
return compareFunction(datum.condition.field, datum.condition.value)
|
74 |
+
},
|
75 |
+
|
76 |
+
getConditionFunction (operator) {
|
77 |
+
const fns = {
|
78 |
+
'=': (field, value) => {
|
79 |
+
return this.model[field] === value
|
80 |
+
}
|
81 |
+
}
|
82 |
+
if (!fns[operator]) {
|
83 |
+
return null
|
84 |
+
}
|
85 |
+
return fns[operator]
|
86 |
+
}
|
87 |
+
}
|
88 |
+
}
|
89 |
+
</script>
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
export default {
|
2 |
+
render () {
|
3 |
+
return (
|
4 |
+
<div id="postbox-container-1" class="wpra-postbox-container postbox-container">
|
5 |
+
{
|
6 |
+
this.$slots.default
|
7 |
+
}
|
8 |
+
</div>
|
9 |
+
)
|
10 |
+
}
|
11 |
+
}
|
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<script>
|
2 |
+
export default {
|
3 |
+
name: `TransitionExpand`,
|
4 |
+
functional: true,
|
5 |
+
render (createElement, context) {
|
6 |
+
const data = {
|
7 |
+
props: {
|
8 |
+
name: `expand`,
|
9 |
+
},
|
10 |
+
on: {
|
11 |
+
afterEnter (element) {
|
12 |
+
// eslint-disable-next-line no-param-reassign
|
13 |
+
element.style.height = `auto`
|
14 |
+
},
|
15 |
+
enter (element) {
|
16 |
+
const {width} = getComputedStyle(element)
|
17 |
+
|
18 |
+
/* eslint-disable no-param-reassign */
|
19 |
+
element.style.width = width
|
20 |
+
element.style.position = `absolute`
|
21 |
+
element.style.visibility = `hidden`
|
22 |
+
element.style.height = `auto`
|
23 |
+
/* eslint-enable */
|
24 |
+
|
25 |
+
const {height} = getComputedStyle(element)
|
26 |
+
|
27 |
+
/* eslint-disable no-param-reassign */
|
28 |
+
element.style.width = null
|
29 |
+
element.style.position = null
|
30 |
+
element.style.visibility = null
|
31 |
+
element.style.height = 0
|
32 |
+
/* eslint-enable */
|
33 |
+
|
34 |
+
// Force repaint to make sure the
|
35 |
+
// animation is triggered correctly.
|
36 |
+
// eslint-disable-next-line no-unused-expressions
|
37 |
+
getComputedStyle(element).height
|
38 |
+
|
39 |
+
setTimeout(() => {
|
40 |
+
// eslint-disable-next-line no-param-reassign
|
41 |
+
element.style.height = height
|
42 |
+
})
|
43 |
+
},
|
44 |
+
leave (element) {
|
45 |
+
const {height} = getComputedStyle(element)
|
46 |
+
|
47 |
+
// eslint-disable-next-line no-param-reassign
|
48 |
+
element.style.height = height
|
49 |
+
|
50 |
+
// Force repaint to make sure the
|
51 |
+
// animation is triggered correctly.
|
52 |
+
// eslint-disable-next-line no-unused-expressions
|
53 |
+
getComputedStyle(element).height
|
54 |
+
|
55 |
+
setTimeout(() => {
|
56 |
+
// eslint-disable-next-line no-param-reassign
|
57 |
+
element.style.height = 0
|
58 |
+
})
|
59 |
+
},
|
60 |
+
},
|
61 |
+
}
|
62 |
+
|
63 |
+
return createElement(`transition`, data, context.children)
|
64 |
+
},
|
65 |
+
}
|
66 |
+
</script>
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import Input from './Input'
|
2 |
+
import NoticeBlock from './NoticeBlock'
|
3 |
+
import Postbox from './Postbox'
|
4 |
+
import RouteLink from './RouteLink'
|
5 |
+
import TransitionExpand from './TransitionExpand'
|
6 |
+
import Button from './Button'
|
7 |
+
|
8 |
+
export default {
|
9 |
+
Input,
|
10 |
+
NoticeBlock,
|
11 |
+
Postbox,
|
12 |
+
RouteLink,
|
13 |
+
TransitionExpand,
|
14 |
+
Button,
|
15 |
+
}
|
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
* Library agnostic wrapper for notifications.
|
3 |
+
*
|
4 |
+
* @since 4.14
|
5 |
+
*
|
6 |
+
* @class NotificationsCenter
|
7 |
+
*/
|
8 |
+
export default class NotificationsCenter {
|
9 |
+
/**
|
10 |
+
* NotificationsCenter constructor.
|
11 |
+
*
|
12 |
+
* @since 4.14
|
13 |
+
*
|
14 |
+
* @param {Function} show Function implementation for displaying messages.
|
15 |
+
* @param {Function} error Function implementation for displaying errors.
|
16 |
+
*/
|
17 |
+
constructor (show, error) {
|
18 |
+
this.showMethod = show
|
19 |
+
this.errorMethod = error
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Display informational message.
|
24 |
+
*
|
25 |
+
* @since 4.14
|
26 |
+
*
|
27 |
+
* @param {string} msg Message for displaying
|
28 |
+
* @param {object} options Options for notification.
|
29 |
+
*/
|
30 |
+
show (msg, options = {}) {
|
31 |
+
this.showMethod(msg, options)
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Display error message.
|
36 |
+
*
|
37 |
+
* @since 4.14
|
38 |
+
*
|
39 |
+
* @param {string} msg Message for displaying
|
40 |
+
* @param {object} options Options for notification.
|
41 |
+
*/
|
42 |
+
error (msg, options = {}) {
|
43 |
+
this.errorMethod(msg, options)
|
44 |
+
}
|
45 |
+
}
|
@@ -0,0 +1,122 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
const getJsonFromUrl = (url) => {
|
2 |
+
if (!url) url = location.href
|
3 |
+
var question = url.indexOf('?')
|
4 |
+
var hash = url.indexOf('#')
|
5 |
+
if (hash == -1 && question == -1) return {}
|
6 |
+
if (hash == -1) hash = url.length
|
7 |
+
var query = question == -1 || hash == question + 1 ? url.substring(hash) :
|
8 |
+
url.substring(question + 1, hash)
|
9 |
+
var result = {}
|
10 |
+
query.split('&').forEach(function (part) {
|
11 |
+
if (!part) return
|
12 |
+
part = part.split('+').join(' ') // replace every + with space, regexp-free version
|
13 |
+
var eq = part.indexOf('=')
|
14 |
+
var key = eq > -1 ? part.substr(0, eq) : part
|
15 |
+
var val = eq > -1 ? decodeURIComponent(part.substr(eq + 1)) : ''
|
16 |
+
var from = key.indexOf('[')
|
17 |
+
if (from == -1) result[decodeURIComponent(key)] = val
|
18 |
+
else {
|
19 |
+
var to = key.indexOf(']', from)
|
20 |
+
var index = decodeURIComponent(key.substring(from + 1, to))
|
21 |
+
key = decodeURIComponent(key.substring(0, from))
|
22 |
+
if (!result[key]) result[key] = []
|
23 |
+
if (!index) result[key].push(val)
|
24 |
+
else result[key][index] = val
|
25 |
+
}
|
26 |
+
})
|
27 |
+
return result
|
28 |
+
}
|
29 |
+
|
30 |
+
export default class Router {
|
31 |
+
constructor (routes, options) {
|
32 |
+
this.routes = routes
|
33 |
+
this.options = options
|
34 |
+
this.baseParams = options.baseParams || ['post_type', 'page', 'action', 'id']
|
35 |
+
}
|
36 |
+
|
37 |
+
get params () {
|
38 |
+
return this.app ? this.app.params : {}
|
39 |
+
}
|
40 |
+
|
41 |
+
setApp (app) {
|
42 |
+
this.app = app
|
43 |
+
this.app.afterNavigate = this.options.afterNavigating || (() => {})
|
44 |
+
}
|
45 |
+
|
46 |
+
findRoute (location) {
|
47 |
+
return this.routes.find(({route}) => {
|
48 |
+
return location.indexOf(route) !== -1
|
49 |
+
})
|
50 |
+
}
|
51 |
+
|
52 |
+
updateParams (params) {
|
53 |
+
this.app.$set(this.app, 'params', params)
|
54 |
+
}
|
55 |
+
|
56 |
+
mergeParams (paramsPart) {
|
57 |
+
let currentParams = Object.keys(this.params).filter(key => {
|
58 |
+
return this.baseParams.indexOf(key) !== -1 || paramsPart.hasOwnProperty(key)
|
59 |
+
}).reduce((acc, key) => {
|
60 |
+
acc[key] = this.params[key]
|
61 |
+
return acc
|
62 |
+
}, {})
|
63 |
+
|
64 |
+
let params = Object.assign({}, currentParams, paramsPart)
|
65 |
+
|
66 |
+
this.updateParams(params)
|
67 |
+
|
68 |
+
window.history.pushState(
|
69 |
+
null,
|
70 |
+
null,
|
71 |
+
this.routeFromParams()
|
72 |
+
)
|
73 |
+
|
74 |
+
this.app.navigated()
|
75 |
+
}
|
76 |
+
|
77 |
+
routeFromParams () {
|
78 |
+
const hasParams = !!Object.keys(this.params).length
|
79 |
+
return location.pathname + (hasParams ? '?' + this.buildParams(this.params) : '')
|
80 |
+
}
|
81 |
+
|
82 |
+
buildRoute (route) {
|
83 |
+
if (route.name) {
|
84 |
+
let routeObject = this.routes.find(r => r.name === route.name)
|
85 |
+
if (!routeObject) {
|
86 |
+
return null
|
87 |
+
}
|
88 |
+
const routeStr = routeObject.route
|
89 |
+
const join = routeStr.indexOf('?') !== -1 ? '&' : '?'
|
90 |
+
|
91 |
+
return routeStr + (route.params ? join + this.buildParams(route.params ? route.params : {}) : '')
|
92 |
+
}
|
93 |
+
}
|
94 |
+
|
95 |
+
buildParams (params) {
|
96 |
+
return Object.keys(params).map(param => {
|
97 |
+
return `${param}=${params[param]}`
|
98 |
+
}).join('&')
|
99 |
+
}
|
100 |
+
|
101 |
+
parseLocation (location) {
|
102 |
+
this.updateParams(getJsonFromUrl(location.search))
|
103 |
+
console.info('ROUTE PARSE LOCATION PARAMS', getJsonFromUrl(location.search))
|
104 |
+
return location.pathname + location.search
|
105 |
+
}
|
106 |
+
|
107 |
+
navigate (route) {
|
108 |
+
if (this.app) {
|
109 |
+
this.app.currentRoute = this.buildRoute(route)
|
110 |
+
}
|
111 |
+
|
112 |
+
this.updateParams(Object.assign({}, route.params || {}, getJsonFromUrl(this.buildRoute(route))))
|
113 |
+
|
114 |
+
window.history.pushState(
|
115 |
+
null,
|
116 |
+
null,
|
117 |
+
this.buildRoute(route)
|
118 |
+
)
|
119 |
+
|
120 |
+
this.app.navigated()
|
121 |
+
}
|
122 |
+
}
|
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import jsonClone from 'app/utils/jsonClone'
|
2 |
+
import equal from 'fast-deep-equal'
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Mixing for functionality that allows to track down and revert changes made on
|
6 |
+
* the primary editing data model.
|
7 |
+
*
|
8 |
+
* `model` property on base object is required for using this mixin.
|
9 |
+
*/
|
10 |
+
export default {
|
11 |
+
data () {
|
12 |
+
return {
|
13 |
+
changes: {
|
14 |
+
model: {},
|
15 |
+
}
|
16 |
+
}
|
17 |
+
},
|
18 |
+
methods: {
|
19 |
+
/**
|
20 |
+
* Whether the model has been changed after last model "remembering".
|
21 |
+
*
|
22 |
+
* @return {boolean}
|
23 |
+
*/
|
24 |
+
isChanged () {
|
25 |
+
return !equal(this.model, this.changes.model)
|
26 |
+
},
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Remember current data model, but without any references to main model
|
30 |
+
* properties. It is important to clean any additional observers from object
|
31 |
+
* otherwise "memorized" model clone will be changed when model get changed.
|
32 |
+
*/
|
33 |
+
rememberModel () {
|
34 |
+
this.$set(this.changes, 'model', jsonClone(this.model))
|
35 |
+
},
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Cancel any changes on main model object.
|
39 |
+
*/
|
40 |
+
cancelChanges () {
|
41 |
+
if (!confirm('Are you sure you want to cancel your changes for this template? This action cannot be reverted and all changes made since your last save will be lost.')) {
|
42 |
+
return
|
43 |
+
}
|
44 |
+
this.$set(this, 'model', jsonClone(this.changes.model))
|
45 |
+
},
|
46 |
+
}
|
47 |
+
}
|
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Component } from '@wordpress/element'
|
2 |
+
import {
|
3 |
+
FormTokenField,
|
4 |
+
Placeholder,
|
5 |
+
Spinner,
|
6 |
+
BaseControl,
|
7 |
+
} from '@wordpress/components'
|
8 |
+
|
9 |
+
export default class MultipleSelectControl extends Component {
|
10 |
+
constructor (props) {
|
11 |
+
super(...arguments)
|
12 |
+
this.props = props
|
13 |
+
this.state = {
|
14 |
+
tokens: [],
|
15 |
+
loading: false,
|
16 |
+
items: []
|
17 |
+
}
|
18 |
+
}
|
19 |
+
|
20 |
+
componentDidMount () {
|
21 |
+
this.setState({loading: true})
|
22 |
+
|
23 |
+
jQuery.post(WPRA_BLOCK.ajax_url, {
|
24 |
+
action: 'wprss_fetch_items',
|
25 |
+
}, (data) => {
|
26 |
+
data = JSON.parse(data)
|
27 |
+
this.setState({
|
28 |
+
loading: false,
|
29 |
+
items: data.items
|
30 |
+
})
|
31 |
+
})
|
32 |
+
}
|
33 |
+
|
34 |
+
render () {
|
35 |
+
const setState = this.setState.bind(this)
|
36 |
+
const onChange = this.props.onChange
|
37 |
+
const items = this.state.items
|
38 |
+
|
39 |
+
if (this.state.loading) {
|
40 |
+
return <Placeholder>
|
41 |
+
<Spinner/>
|
42 |
+
</Placeholder>
|
43 |
+
}
|
44 |
+
return <BaseControl
|
45 |
+
help={this.props.help || ''}
|
46 |
+
>
|
47 |
+
<FormTokenField
|
48 |
+
label={this.props.label || ''}
|
49 |
+
placeholder={this.props.placeholder || ''}
|
50 |
+
value={this.props.value.map(function (id) {
|
51 |
+
return items.find(item => item.value === id)
|
52 |
+
}).filter(item => !!item)}
|
53 |
+
suggestions={this.state.items.map(function (item) {
|
54 |
+
item.toLocaleLowerCase = function () {
|
55 |
+
return item.title.toLocaleLowerCase()
|
56 |
+
}
|
57 |
+
item.toString = function () {
|
58 |
+
return item.title
|
59 |
+
}
|
60 |
+
return item
|
61 |
+
})}
|
62 |
+
displayTransform={function (item) {
|
63 |
+
if ('number' === typeof item) {
|
64 |
+
item = items.find(function (iteratedItem) {
|
65 |
+
return iteratedItem.value === item
|
66 |
+
})
|
67 |
+
}
|
68 |
+
if ('object' === typeof item) {
|
69 |
+
return item.title
|
70 |
+
}
|
71 |
+
return item
|
72 |
+
}}
|
73 |
+
saveTransform={function (token) {
|
74 |
+
return token
|
75 |
+
}}
|
76 |
+
onChange={function (tokens) {
|
77 |
+
setState({tokens})
|
78 |
+
onChange(tokens.map(function (item) {
|
79 |
+
return item.value
|
80 |
+
}))
|
81 |
+
}}
|
82 |
+
/>
|
83 |
+
</BaseControl>
|
84 |
+
}
|
85 |
+
}
|
@@ -0,0 +1,209 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
require('css/src/gutenberg-block/index.scss')
|
2 |
+
|
3 |
+
import { __ } from '@wordpress/i18n'
|
4 |
+
import { registerBlockType } from '@wordpress/blocks'
|
5 |
+
import { InspectorControls } from '@wordpress/editor'
|
6 |
+
import {
|
7 |
+
ToggleControl,
|
8 |
+
ServerSideRender,
|
9 |
+
TextControl,
|
10 |
+
TextareaControl,
|
11 |
+
BaseControl,
|
12 |
+
PanelBody,
|
13 |
+
PanelRow,
|
14 |
+
Spinner,
|
15 |
+
Placeholder,
|
16 |
+
FormTokenField,
|
17 |
+
SelectControl,
|
18 |
+
} from '@wordpress/components'
|
19 |
+
import { addFilter, applyFilters } from '@wordpress/hooks'
|
20 |
+
|
21 |
+
import MultipleSelectControl from './components/MultipleSelectControl'
|
22 |
+
|
23 |
+
// Default template is selected by default.
|
24 |
+
let selectedTemplate = WPRA_BLOCK.templates[0]
|
25 |
+
|
26 |
+
// Selected template field getter. Additional function can be passed.
|
27 |
+
const getTemplateDefault = (field, wrapper = val => val, def = 0) => selectedTemplate[field] ? wrapper(selectedTemplate[field]) : def
|
28 |
+
|
29 |
+
// Helps to not override attributes that selected manually by user.
|
30 |
+
let templateLock = {}
|
31 |
+
|
32 |
+
// Whether the block is loaded initial information.
|
33 |
+
let _isLoaded = false
|
34 |
+
|
35 |
+
registerBlockType('wpra-shortcode/wpra-shortcode', {
|
36 |
+
title: __('WP RSS Aggregator Feeds'),
|
37 |
+
description: __('Display feed items imported using WP RSS Aggregator.'),
|
38 |
+
icon: 'rss',
|
39 |
+
category: 'widgets',
|
40 |
+
|
41 |
+
// Remove to make block editable in HTML mode.
|
42 |
+
supportHTML: false,
|
43 |
+
|
44 |
+
attributes: applyFilters('wpra.gutenbergBlock.attributes', {
|
45 |
+
isAll: {
|
46 |
+
type: 'boolean',
|
47 |
+
default: true
|
48 |
+
},
|
49 |
+
template: {
|
50 |
+
type: 'string',
|
51 |
+
default: 'default'
|
52 |
+
},
|
53 |
+
pagination: {
|
54 |
+
type: 'boolean',
|
55 |
+
default: true
|
56 |
+
},
|
57 |
+
limit: {
|
58 |
+
type: 'number',
|
59 |
+
},
|
60 |
+
page: {
|
61 |
+
type: 'number',
|
62 |
+
},
|
63 |
+
exclude: {
|
64 |
+
type: 'string'
|
65 |
+
},
|
66 |
+
source: {
|
67 |
+
type: 'string'
|
68 |
+
}
|
69 |
+
}),
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Called when Gutenberg initially loads the block.
|
73 |
+
*/
|
74 |
+
edit: function (props) {
|
75 |
+
/*
|
76 |
+
* If block is not loaded, check whether we should block auto limit selection.
|
77 |
+
* It will be blocked if user selected entered limit value different from template's default.
|
78 |
+
*/
|
79 |
+
if (!_isLoaded && props.attributes.template) {
|
80 |
+
selectedTemplate = WPRA_BLOCK.templates.find(item => item.value === (props.attributes.template || 'default'))
|
81 |
+
|
82 |
+
if (parseInt(props.attributes.limit) !== getTemplateDefault('limit', parseInt)) {
|
83 |
+
templateLock['limit'] = true
|
84 |
+
}
|
85 |
+
|
86 |
+
if (!!props.attributes.pagination !== getTemplateDefault('pagination', v => !!v, false)) {
|
87 |
+
templateLock['pagination'] = true
|
88 |
+
}
|
89 |
+
|
90 |
+
_isLoaded = true
|
91 |
+
}
|
92 |
+
|
93 |
+
const etWarning = WPRA_BLOCK.is_et_active ? <p style={{fontStyle: 'italic'}}>
|
94 |
+
Excerpts & Thumbnails is incompatible with the WP RSS Aggregator Feeds block. <a
|
95 |
+
href="https://kb.wprssaggregator.com/article/459-using-excerpts-thumbnails-with-templates" target={'_blank'}>Learn
|
96 |
+
more</a>.
|
97 |
+
</p> : null
|
98 |
+
|
99 |
+
const panels = applyFilters('wpra.gutenbergBlock.panels', [
|
100 |
+
<PanelBody
|
101 |
+
title={__('Feed Sources')}
|
102 |
+
initialOpen={true}
|
103 |
+
>
|
104 |
+
{applyFilters('wpra.gutenbergBlock.panelItems', [
|
105 |
+
<ToggleControl
|
106 |
+
label={__('Show all Feed Sources ')}
|
107 |
+
checked={props.attributes.isAll}
|
108 |
+
onChange={(value) => {
|
109 |
+
props.setAttributes({isAll: value})
|
110 |
+
props.setAttributes({exclude: ''})
|
111 |
+
props.setAttributes({source: ''})
|
112 |
+
}}
|
113 |
+
/>,
|
114 |
+
<MultipleSelectControl
|
115 |
+
label={props.attributes.isAll ? __('Feed Sources to Exclude') : __('Feed Sources to Show')}
|
116 |
+
key={'select'}
|
117 |
+
help={__('Start typing to search feed sources by name')}
|
118 |
+
value={((props.attributes.isAll ? props.attributes.exclude : props.attributes.source) || '').split(',').map(item => parseInt(item))}
|
119 |
+
onChange={(selected) => {
|
120 |
+
selected = selected.join(',')
|
121 |
+
if (props.attributes.isAll) {
|
122 |
+
props.setAttributes({exclude: selected})
|
123 |
+
props.setAttributes({source: ''})
|
124 |
+
return
|
125 |
+
}
|
126 |
+
props.setAttributes({exclude: ''})
|
127 |
+
props.setAttributes({source: selected})
|
128 |
+
}}
|
129 |
+
/>
|
130 |
+
], 'feedSources', {props})}
|
131 |
+
</PanelBody>,
|
132 |
+
<PanelBody
|
133 |
+
title={__('Display Options')}
|
134 |
+
initialOpen={false}
|
135 |
+
>
|
136 |
+
{applyFilters('wpra.gutenbergBlock.panelItems', [
|
137 |
+
<SelectControl
|
138 |
+
label={__('Select Template')}
|
139 |
+
value={props.attributes.template}
|
140 |
+
onChange={(template) => {
|
141 |
+
selectedTemplate = WPRA_BLOCK.templates.find(item => item.value === template)
|
142 |
+
props.setAttributes({template: template || ''})
|
143 |
+
if (!templateLock['limit']) {
|
144 |
+
props.setAttributes({limit: getTemplateDefault('limit', parseInt, 15)})
|
145 |
+
}
|
146 |
+
if (!templateLock['pagination']) {
|
147 |
+
props.setAttributes({pagination: getTemplateDefault('pagination', v => !!v, false)})
|
148 |
+
}
|
149 |
+
}}
|
150 |
+
options={WPRA_BLOCK.templates}
|
151 |
+
/>,
|
152 |
+
<TextControl
|
153 |
+
label={__('Feed Limit')}
|
154 |
+
help={__('Number of feed items to display')}
|
155 |
+
placeholder={getTemplateDefault('limit', parseInt)}
|
156 |
+
type={'number'}
|
157 |
+
min={1}
|
158 |
+
value={props.attributes.limit || getTemplateDefault('limit', parseInt)}
|
159 |
+
onChange={(value) => {
|
160 |
+
templateLock['limit'] = true
|
161 |
+
props.setAttributes({limit: parseInt(value) || getTemplateDefault('limit', parseInt)})
|
162 |
+
}}
|
163 |
+
/>,
|
164 |
+
<ToggleControl
|
165 |
+
label={__('Show Pagination ')}
|
166 |
+
checked={props.attributes.pagination}
|
167 |
+
onChange={(value) => {
|
168 |
+
templateLock['pagination'] = true
|
169 |
+
props.setAttributes({pagination: value})
|
170 |
+
}}
|
171 |
+
/>,
|
172 |
+
<TextControl
|
173 |
+
label={__('Page')}
|
174 |
+
placeholder={__('1')}
|
175 |
+
type={'number'}
|
176 |
+
min={1}
|
177 |
+
value={props.attributes.page || 1}
|
178 |
+
onChange={(value) => {
|
179 |
+
props.setAttributes({page: parseInt(value) || 1})
|
180 |
+
}}
|
181 |
+
/>,
|
182 |
+
etWarning
|
183 |
+
], 'displayOptions', {props})}
|
184 |
+
</PanelBody>,
|
185 |
+
], {props})
|
186 |
+
|
187 |
+
console.warn({panels})
|
188 |
+
|
189 |
+
return <div>
|
190 |
+
<ServerSideRender
|
191 |
+
block={'wpra-shortcode/wpra-shortcode'}
|
192 |
+
attributes={props.attributes}
|
193 |
+
className={'wpra-gutenberg-block'}
|
194 |
+
/>
|
195 |
+
{applyFilters('wpra.gutenbergBlock.before', [], {props})}
|
196 |
+
<InspectorControls>
|
197 |
+
{panels}
|
198 |
+
</InspectorControls>
|
199 |
+
{applyFilters('wpra.gutenbergBlock.after', [], {props})}
|
200 |
+
</div>
|
201 |
+
},
|
202 |
+
|
203 |
+
/**
|
204 |
+
* Called when Gutenberg "saves" the block to post_content
|
205 |
+
*/
|
206 |
+
save: function (props) {
|
207 |
+
return null
|
208 |
+
}
|
209 |
+
})
|
@@ -0,0 +1,440 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<template>
|
2 |
+
<div class="wizard-holder animated fadeIn">
|
3 |
+
<div class="connect-steps">
|
4 |
+
<div class="step-items">
|
5 |
+
<div class="step-progress" :class="'step-progress--' + activeScreenIndex"></div>
|
6 |
+
<div class="step-item"
|
7 |
+
:class="{ 'step-item_active': active(screen.id), 'step-item_completed' : screen.completed() && index < activeScreenIndex }"
|
8 |
+
v-for="(screen, index) of screens"
|
9 |
+
>
|
10 |
+
<div class="step-item__status">
|
11 |
+
<span class="dashicons dashicons-yes" v-if="screen.completed() && index < activeScreenIndex"></span>
|
12 |
+
</div>
|
13 |
+
<div class="step-item__info">
|
14 |
+
<div class="step-item__title">{{ screen.title }}</div>
|
15 |
+
<div class="step-item__description" v-if="screen.description">{{ screen.description }}</div>
|
16 |
+
</div>
|
17 |
+
</div>
|
18 |
+
</div>
|
19 |
+
</div>
|
20 |
+
<div class="wizard">
|
21 |
+
<transition :name="transition" mode="out-in">
|
22 |
+
<div class="wizard_content" :key="activeScreen" v-if="active('feed')">
|
23 |
+
<div class="wizard_hello">
|
24 |
+
Enter your first RSS Feed URL
|
25 |
+
</div>
|
26 |
+
|
27 |
+
<form id="feedForm" @submit.prevent="next" class="wizard_info">
|
28 |
+
<div class="form-group">
|
29 |
+
<input type="text" placeholder="https://www.sourcedomain.com/feed/" v-model="form.feedSourceUrl"
|
30 |
+
class="wpra-feed-input"
|
31 |
+
>
|
32 |
+
<span class="dashicons dashicons-warning warning-icon" v-if="isFeedError"></span>
|
33 |
+
<a :href="validateLink" target="_blank" v-if="isFeedError">Validate feed</a>
|
34 |
+
</div>
|
35 |
+
</form>
|
36 |
+
|
37 |
+
<div class="wizard_error" v-if="isFeedError">
|
38 |
+
<p>This RSS feed URL appears to be invalid. Here are a couple of things you can try:</p>
|
39 |
+
<ol>
|
40 |
+
<li>Check whether the URL you entered is the correct one by trying one of the options when clicking on "How do I find an RSS feed URL?" below.</li>
|
41 |
+
<li>
|
42 |
+
Test out this other RSS feed URL to make sure the plugin is working correctly - https://www.wpmayor.com/feed/ - If it works, you may <a :href="supportUrl" target="_blank">contact us here</a> to help you with your source.
|
43 |
+
</li>
|
44 |
+
<li>Test the URL's validity by W3C standards, the standards we use in our plugins, using the “Validate feed” link above.</li>
|
45 |
+
</ol>
|
46 |
+
</div>
|
47 |
+
|
48 |
+
<expander title="How do I find an RSS feed URL?">
|
49 |
+
<p>WP RSS Aggregator fetches feed items through RSS feeds. Almost every website in the world provides an RSS feed. Here's how to find it:</p>
|
50 |
+
<p>Option 1: Add /feed to the website's homepage URL </p>
|
51 |
+
<p>Many sites have their RSS feed at the same URL. For instance, if the website's URL is www.thiswebsite.com, then the RSS feed could be at www.thiswebsite.com/feed.</p>
|
52 |
+
<p>Option 2: Look for the RSS share icon</p>
|
53 |
+
<p>Many websites have share icons on their pages for Facebook, Twitter and more. Many times, there will also be an orange RSS icon. Click on that to access the RSS feed URL.</p>
|
54 |
+
<p>Option 3: Browser RSS Auto-Discovery</p>
|
55 |
+
<p>Most browsers either include an RSS auto-discovery tool by default or they allow you to add extensions for it. Firefox shows an RSS icon above the website, in the address bar, which you can click on directly. Chrome offers extensions such as this one.</p>
|
56 |
+
<p>Option 4: Look at the Page Source</p>
|
57 |
+
<p>When on any page of the website you're looking to import feed items from, right click and press "View Page Source". Once the new window opens, use the “Find” feature (Ctrl-F on PC, Command-F on Mac) and search for " RSS". This should take you to a line that reads like this (or similar):</p>
|
58 |
+
<p>
|
59 |
+
<code>
|
60 |
+
<link rel="alternate" type="application/rss+xml" title="RSS Feed" href="https://www.sourcedomain.com/feed/" />
|
61 |
+
</code>
|
62 |
+
</p>
|
63 |
+
<p>The RSS feed’s URL is found between the quotes after href=. In the above case, it would be https://www.sourcedomain.com/feed/.</p>
|
64 |
+
<p><a :href="knowledgeBaseUrl" target="_blank">Browse our Knowledge Base for more information.</a></p>
|
65 |
+
</expander>
|
66 |
+
</div>
|
67 |
+
|
68 |
+
<div class="wizard_content" :key="activeScreen" v-if="active('feedItems')">
|
69 |
+
<div class="wizard_hello">
|
70 |
+
Latest feed items from your selected feed source:
|
71 |
+
</div>
|
72 |
+
|
73 |
+
<div class="wpra-feed-items">
|
74 |
+
<div class="wpra-feed-item" v-for="item of feed.items">
|
75 |
+
<div class="wpra-feed-item__link">
|
76 |
+
<a :href="item.permalink" target="_blank">{{ item.title }}</a>
|
77 |
+
</div>
|
78 |
+
<div class="wpra-feed-item__info">
|
79 |
+
<template v-if="item.date || item.author">
|
80 |
+
<template v-if="item.date">
|
81 |
+
Published on {{ item.date }}
|
82 |
+
</template>
|
83 |
+
<template v-if="item.date && item.author">|</template>
|
84 |
+
<template v-if="item.author">
|
85 |
+
By {{ item.author }}
|
86 |
+
</template>
|
87 |
+
</template>
|
88 |
+
</div>
|
89 |
+
</div>
|
90 |
+
</div>
|
91 |
+
|
92 |
+
<div class="wrpa-shortcode">
|
93 |
+
<div class="wrpa-shortcode-preview">
|
94 |
+
<div class="wrpa-shortcode-label">
|
95 |
+
Create a draft page to preview these feed items on your site:
|
96 |
+
</div>
|
97 |
+
<a :href="previewUrl" target="_blank" class="button"
|
98 |
+
@click="preparePreview"
|
99 |
+
:class="{'button-primary': isPrepared, 'loading-button': isPreparing}"
|
100 |
+
>
|
101 |
+
{{ isPrepared ? 'Preview the Page' : 'Create Draft Page' }}
|
102 |
+
</a>
|
103 |
+
</div>
|
104 |
+
<div class="wrpa-shortcode-form" @click="copyToClipboard()">
|
105 |
+
<div class="wrpa-shortcode-label">
|
106 |
+
Copy the shortcode to any page or post on your site:
|
107 |
+
</div>
|
108 |
+
<input class="wrpa-shortcode-form__shortcode"
|
109 |
+
type="text"
|
110 |
+
readonly
|
111 |
+
value="[wp-rss-aggregator]"
|
112 |
+
ref="selected"
|
113 |
+
/>
|
114 |
+
<div class="wrpa-shortcode-form__button">
|
115 |
+
{{ isCopied ? 'Copied!' : 'Click to copy' }}
|
116 |
+
</div>
|
117 |
+
</div>
|
118 |
+
</div>
|
119 |
+
</div>
|
120 |
+
|
121 |
+
<div class="wizard_content" :key="activeScreen" v-if="active('finish')">
|
122 |
+
<div class="wizard_hello">
|
123 |
+
You’ve successfully set up your first feed source 😄
|
124 |
+
</div>
|
125 |
+
|
126 |
+
<div class="wpra-cols-title">
|
127 |
+
Do more with WP RSS Aggregator - here is what we did at CryptoHeadlines.com.
|
128 |
+
</div>
|
129 |
+
|
130 |
+
<div class="wpra-cols">
|
131 |
+
<div class="col">
|
132 |
+
<p>CryptoHeadlines.com displays latest news, Youtube videos, podcasts, jobs and more from the Cryptocurrency industry.</p>
|
133 |
+
<p>It uses Feed to Post to import articles, Youtube videos, and podcast links.</p>
|
134 |
+
<p>Full Text RSS Feeds is used to fetch the full content of the job listings to present more information to the potential applicant.</p>
|
135 |
+
<p>Keyword Filtering is used to filter out content that contains profanity and keywords or phrases deemed as inappropriate.</p>
|
136 |
+
<div style="margin-bottom: .5rem">
|
137 |
+
<a :href="addOnsUrl" class="button" target="_blank">
|
138 |
+
Browse Add-ons ⭐️
|
139 |
+
</a>
|
140 |
+
</div>
|
141 |
+
<div>
|
142 |
+
<a :href="supportUrl" target="_blank" style="font-size: .9em">Contact support for more information.</a>
|
143 |
+
</div>
|
144 |
+
</div>
|
145 |
+
<div class="col">
|
146 |
+
<img :src="demoImageUrl"
|
147 |
+
class="img wpra-demo-photo">
|
148 |
+
|
149 |
+
<div class="wpra-feedback">
|
150 |
+
<!--<div class="wpra-feedback__photo">-->
|
151 |
+
<!--<img src="https://www.wprssaggregator.com/wp-content/themes/wp_rss_theme/assets/images/review2.jpg">-->
|
152 |
+
<!--</div>-->
|
153 |
+
<div class="wpra-feedback__copy">
|
154 |
+
<div class="wpra-feedback__text">
|
155 |
+
This plugin has made my life a lot easier, and the support has been great as well.
|
156 |
+
</div>
|
157 |
+
<div class="wpra-feedback__rating">
|
158 |
+
<span class="dashicons dashicons-star-filled"></span>
|
159 |
+
<span class="dashicons dashicons-star-filled"></span>
|
160 |
+
<span class="dashicons dashicons-star-filled"></span>
|
161 |
+
<span class="dashicons dashicons-star-filled"></span>
|
162 |
+
<span class="dashicons dashicons-star-filled"></span>
|
163 |
+
</div>
|
164 |
+
<div class="wpra-feedback__by">
|
165 |
+
<a :href="feedbackUrl" target="_blank">
|
166 |
+
Review by officeinnovator
|
167 |
+
</a>
|
168 |
+
</div>
|
169 |
+
</div>
|
170 |
+
</div>
|
171 |
+
</div>
|
172 |
+
</div>
|
173 |
+
</div>
|
174 |
+
</transition>
|
175 |
+
|
176 |
+
<div class="connect-actions pad">
|
177 |
+
<div class="pad-item--grow">
|
178 |
+
<button v-if="!active('finish')"
|
179 |
+
class="button-clear"
|
180 |
+
@click="finish"
|
181 |
+
>
|
182 |
+
Skip the introduction
|
183 |
+
</button>
|
184 |
+
</div>
|
185 |
+
<div class="pad-item--no-shrink">
|
186 |
+
<button class="button-clear"
|
187 |
+
@click="back"
|
188 |
+
v-if="isBackAvailable"
|
189 |
+
>
|
190 |
+
Back
|
191 |
+
</button>
|
192 |
+
<button @click="next"
|
193 |
+
class="button button-primary button-large"
|
194 |
+
:class="{'loading-button': isLoading}"
|
195 |
+
>
|
196 |
+
{{ active('finish') ? 'Continue to Plugin' : 'Next' }}
|
197 |
+
</button>
|
198 |
+
</div>
|
199 |
+
</div>
|
200 |
+
</div>
|
201 |
+
</div>
|
202 |
+
</template>
|
203 |
+
|
204 |
+
<script>
|
205 |
+
import Expander from 'app/components/Expander'
|
206 |
+
import { post } from 'app/utils/fetch'
|
207 |
+
import { copyToClipboard } from 'app/utils/copy'
|
208 |
+
|
209 |
+
const _ = (str) => str
|
210 |
+
|
211 |
+
const CONFIG = window.wprssWizardConfig
|
212 |
+
|
213 |
+
export default {
|
214 |
+
data () {
|
215 |
+
return {
|
216 |
+
prevHeight: 0,
|
217 |
+
screens: [{
|
218 |
+
id: 'feed',
|
219 |
+
title: _('Add feed source URL'),
|
220 |
+
description: false,
|
221 |
+
next: this.submitFeed,
|
222 |
+
completed: () => {
|
223 |
+
return this.feed.items.length
|
224 |
+
},
|
225 |
+
entered: () => {
|
226 |
+
this.focusOnInput('feed')
|
227 |
+
}
|
228 |
+
}, {
|
229 |
+
id: 'feedItems',
|
230 |
+
title: _('Display feed items'),
|
231 |
+
description: false,
|
232 |
+
next: this.continueItems,
|
233 |
+
completed: () => {
|
234 |
+
return this.feed.items.length && this.itemsPassed
|
235 |
+
}
|
236 |
+
}, {
|
237 |
+
id: 'finish',
|
238 |
+
title: _('Complete introduction'),
|
239 |
+
description: false,
|
240 |
+
next: this.completeIntroduction,
|
241 |
+
completed: () => {
|
242 |
+
return this.feed.items.length && this.itemsPassed
|
243 |
+
}
|
244 |
+
}],
|
245 |
+
isCopied: false,
|
246 |
+
|
247 |
+
isPreparing: false,
|
248 |
+
isPrepared: false,
|
249 |
+
|
250 |
+
transition: 'slide-up', // 'slide-down',
|
251 |
+
|
252 |
+
activeScreen: 'feed',
|
253 |
+
form: {
|
254 |
+
feedSourceUrl: null,
|
255 |
+
},
|
256 |
+
itemsPassed: false,
|
257 |
+
|
258 |
+
stepLoading: false,
|
259 |
+
isLoading: false,
|
260 |
+
|
261 |
+
isFeedError: false,
|
262 |
+
|
263 |
+
feed: {
|
264 |
+
items: [],
|
265 |
+
},
|
266 |
+
previewUrl: CONFIG.previewUrl,
|
267 |
+
addOnsUrl: CONFIG.addOnsUrl,
|
268 |
+
supportUrl: CONFIG.supportUrl,
|
269 |
+
demoImageUrl: CONFIG.demoImageUrl,
|
270 |
+
feedbackUrl: CONFIG.feedbackUrl,
|
271 |
+
knowledgeBaseUrl: CONFIG.knowledgeBaseUrl,
|
272 |
+
}
|
273 |
+
},
|
274 |
+
computed: {
|
275 |
+
validateLink () {
|
276 |
+
return 'https://validator.w3.org/feed/check.cgi?url=' + encodeURI(this.form.feedSourceUrl)
|
277 |
+
},
|
278 |
+
|
279 |
+
activeScreenIndex () {
|
280 |
+
return this.screens.findIndex(screen => screen.id === this.activeScreen)
|
281 |
+
},
|
282 |
+
currentScreen () {
|
283 |
+
return this.screens.find(screen => screen.id === this.activeScreen)
|
284 |
+
},
|
285 |
+
actionCompleted () {
|
286 |
+
return this.currentScreen.completed()
|
287 |
+
},
|
288 |
+
isBackAvailable () {
|
289 |
+
return this.activeScreenIndex > 0 && this.activeScreenIndex < this.screens.length
|
290 |
+
},
|
291 |
+
},
|
292 |
+
mounted () {
|
293 |
+
this.onScreenEnter()
|
294 |
+
},
|
295 |
+
methods: {
|
296 |
+
preparePreview (e) {
|
297 |
+
if (this.isPreparing) {
|
298 |
+
e.preventDefault()
|
299 |
+
return
|
300 |
+
}
|
301 |
+
if (!this.isPrepared) {
|
302 |
+
e.preventDefault()
|
303 |
+
this.isPreparing = true
|
304 |
+
fetch(this.previewUrl).then(() => {
|
305 |
+
this.isPreparing = false
|
306 |
+
this.isPrepared = true
|
307 |
+
})
|
308 |
+
}
|
309 |
+
},
|
310 |
+
|
311 |
+
/**
|
312 |
+
* Submits first feed step.
|
313 |
+
*
|
314 |
+
* @return {Promise<any>}
|
315 |
+
*/
|
316 |
+
submitFeed () {
|
317 |
+
const data = Object.assign(CONFIG.feedEndpoint.defaultPayload, {
|
318 |
+
wprss_intro_feed_url: this.form.feedSourceUrl
|
319 |
+
})
|
320 |
+
this.isLoading = true
|
321 |
+
this.isFeedError = false
|
322 |
+
return post(CONFIG.feedEndpoint.url, data).then((responseData) => {
|
323 |
+
this.feed.items = responseData.data.feed_items.slice(0, 3)
|
324 |
+
this.isLoading = false
|
325 |
+
return {}
|
326 |
+
}).catch((resp) => {
|
327 |
+
this.isLoading = false
|
328 |
+
this.isFeedError = true
|
329 |
+
throw resp
|
330 |
+
})
|
331 |
+
},
|
332 |
+
|
333 |
+
/**
|
334 |
+
* Continue from items step.
|
335 |
+
*
|
336 |
+
* @return {Promise<any>}
|
337 |
+
*/
|
338 |
+
continueItems () {
|
339 |
+
this.itemsPassed = true
|
340 |
+
return Promise.resolve({})
|
341 |
+
},
|
342 |
+
|
343 |
+
/**
|
344 |
+
* Complete the introduction and proceed to sources list.
|
345 |
+
*
|
346 |
+
* @return {Promise<any>}
|
347 |
+
*/
|
348 |
+
completeIntroduction () {
|
349 |
+
return Promise.resolve({})
|
350 |
+
},
|
351 |
+
|
352 |
+
/**
|
353 |
+
* Go to the next screen in this wizard.
|
354 |
+
*/
|
355 |
+
next () {
|
356 |
+
this.transition = 'slide-up'
|
357 |
+
const nextTransistor = this.currentScreen.next ? this.currentScreen.next : () => Promise.resolve(false)
|
358 |
+
this.stepLoading = true
|
359 |
+
nextTransistor().then(result => {
|
360 |
+
this.stepLoading = false
|
361 |
+
}, (err) => {
|
362 |
+
throw err
|
363 |
+
}).then(() => {
|
364 |
+
const nextStepIndex = this.activeScreenIndex + 1
|
365 |
+
if (nextStepIndex >= this.screens.length) {
|
366 |
+
this.finish()
|
367 |
+
}
|
368 |
+
else {
|
369 |
+
this.activeScreen = this.screens[nextStepIndex].id
|
370 |
+
this.onScreenEnter()
|
371 |
+
}
|
372 |
+
}).catch((err) => {
|
373 |
+
console.error(err)
|
374 |
+
})
|
375 |
+
},
|
376 |
+
|
377 |
+
/**
|
378 |
+
* Run on screen event.
|
379 |
+
*/
|
380 |
+
onScreenEnter () {
|
381 |
+
this.$nextTick(() => {
|
382 |
+
if (this.currentScreen.entered) {
|
383 |
+
this.currentScreen.entered()
|
384 |
+
}
|
385 |
+
})
|
386 |
+
},
|
387 |
+
|
388 |
+
/**
|
389 |
+
* Focus on some ref input.
|
390 |
+
*/
|
391 |
+
focusOnInput (refName) {
|
392 |
+
if (!this.$refs[refName] || !this.$refs[refName].focus) {
|
393 |
+
return false
|
394 |
+
}
|
395 |
+
this.$refs[refName].focus()
|
396 |
+
},
|
397 |
+
|
398 |
+
/**
|
399 |
+
* Go back in the wizard on one step.
|
400 |
+
*/
|
401 |
+
back () {
|
402 |
+
this.transition = 'slide-down'
|
403 |
+
this.activeScreen = this.screens[this.activeScreenIndex - 1].id
|
404 |
+
},
|
405 |
+
|
406 |
+
/**
|
407 |
+
* Finish this wizard.
|
408 |
+
*/
|
409 |
+
finish (confirmFinish = false) {
|
410 |
+
const visitList = () => window.location.href = CONFIG.feedListUrl
|
411 |
+
if (confirmFinish) {
|
412 |
+
if (confirm('Are you sure you want to skip the introduction?')) {
|
413 |
+
visitList()
|
414 |
+
}
|
415 |
+
return
|
416 |
+
}
|
417 |
+
visitList()
|
418 |
+
// redirect to the URL.
|
419 |
+
},
|
420 |
+
|
421 |
+
active (pageName) {
|
422 |
+
return this.activeScreen === pageName
|
423 |
+
},
|
424 |
+
|
425 |
+
copyToClipboard () {
|
426 |
+
if (this.isCopied) {
|
427 |
+
return
|
428 |
+
}
|
429 |
+
copyToClipboard('[wp-rss-aggregator]')
|
430 |
+
this.isCopied = true
|
431 |
+
setTimeout(() => {
|
432 |
+
this.isCopied = false
|
433 |
+
}, 1000)
|
434 |
+
}
|
435 |
+
},
|
436 |
+
components: {
|
437 |
+
Expander
|
438 |
+
}
|
439 |
+
}
|
440 |
+
</script>
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
require('css/src/intro/steps.scss')
|
2 |
+
|
3 |
+
import Vue from 'vue'
|
4 |
+
import Wizard from './Wizard'
|
5 |
+
import 'whatwg-fetch'
|
6 |
+
|
7 |
+
new Vue({
|
8 |
+
el: '#wpra-wizard-app',
|
9 |
+
template: '<Wizard/>',
|
10 |
+
components: { Wizard }
|
11 |
+
})
|
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
require('css/src/pagination/index.scss')
|
2 |
+
|
3 |
+
jQuery(document).ready(($) => {
|
4 |
+
const fetchList = function ($targetEl, params) {
|
5 |
+
$targetEl.addClass('wpra-loading')
|
6 |
+
|
7 |
+
$([document.documentElement, document.body]).animate({
|
8 |
+
scrollTop: $targetEl.offset().top - 50
|
9 |
+
}, 500);
|
10 |
+
|
11 |
+
const template = params.template
|
12 |
+
delete params.template
|
13 |
+
|
14 |
+
let tmp = template.length? template : '0'
|
15 |
+
let url = WpraPagination.baseUri.replace('%s', tmp)
|
16 |
+
|
17 |
+
$.ajax({
|
18 |
+
type: 'POST',
|
19 |
+
url,
|
20 |
+
data: JSON.stringify(params),
|
21 |
+
contentType: 'application/json',
|
22 |
+
}).done((data) => {
|
23 |
+
$newEl = $(data.html)
|
24 |
+
$newEl.find('.colorbox').colorbox({iframe:true, width:'80%', height:'80%'})
|
25 |
+
$targetEl.replaceWith($newEl)
|
26 |
+
})
|
27 |
+
}
|
28 |
+
|
29 |
+
const handleClick = function ($link) {
|
30 |
+
const $targetEl = $link.closest('[data-template-ctx]')
|
31 |
+
|
32 |
+
const template = $targetEl.data('wpra-template')
|
33 |
+
const templateOptions = $targetEl.data('template-ctx')
|
34 |
+
|
35 |
+
let options = Object.assign({}, {
|
36 |
+
template
|
37 |
+
}, JSON.parse(atob(templateOptions)))
|
38 |
+
options['page'] = $link.data('wpra-page')
|
39 |
+
|
40 |
+
fetchList($targetEl, options)
|
41 |
+
}
|
42 |
+
|
43 |
+
$('body').on('click', 'a[data-wpra-page]', function (e) {
|
44 |
+
e.preventDefault()
|
45 |
+
handleClick($(this))
|
46 |
+
});
|
47 |
+
})
|
@@ -0,0 +1,122 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<template>
|
2 |
+
<div class="wpra-plugin-disable-poll">
|
3 |
+
<modal :active="isModalVisible"
|
4 |
+
@close="closeModal"
|
5 |
+
:header-class="'invisible-header'"
|
6 |
+
>
|
7 |
+
<div slot="header">
|
8 |
+
<div class="wpra-plugin-disable-poll__logo">
|
9 |
+
<img :src="image('light-line-logo.png')" alt="">
|
10 |
+
</div>
|
11 |
+
<h3>
|
12 |
+
Do you have a moment to share why you are deactivating WP RSS Aggregator?
|
13 |
+
</h3>
|
14 |
+
<p>
|
15 |
+
Your feedback will help us to improve our plugins and service.
|
16 |
+
</p>
|
17 |
+
</div>
|
18 |
+
|
19 |
+
<div slot="body">
|
20 |
+
<SerializedForm :form="form" v-model="model"/>
|
21 |
+
</div>
|
22 |
+
|
23 |
+
<div slot="footer">
|
24 |
+
<div class="footer-confirm__buttons">
|
25 |
+
<button class="button button-clear" @click="deactivate">
|
26 |
+
Skip & Deactivate
|
27 |
+
</button>
|
28 |
+
<button class="button button-primary"
|
29 |
+
:class="{'loading-button': isDeactivating}"
|
30 |
+
@click="submit">
|
31 |
+
Submit & Deactivate
|
32 |
+
</button>
|
33 |
+
</div>
|
34 |
+
</div>
|
35 |
+
</modal>
|
36 |
+
</div>
|
37 |
+
</template>
|
38 |
+
|
39 |
+
<script>
|
40 |
+
import Modal from 'app/components/Modal'
|
41 |
+
import SerializedForm from 'app/components/SerializedForm'
|
42 |
+
import axios from 'axios'
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Selector string for plugin's deactivation link.
|
46 |
+
*
|
47 |
+
* @type {string}
|
48 |
+
*/
|
49 |
+
const deactivateSelector = '[data-slug="wp-rss-aggregator"] .deactivate a'
|
50 |
+
const deactivateLink = document.querySelector(deactivateSelector)
|
51 |
+
|
52 |
+
export default {
|
53 |
+
components: {
|
54 |
+
Modal,
|
55 |
+
SerializedForm,
|
56 |
+
},
|
57 |
+
data () {
|
58 |
+
return {
|
59 |
+
isDeactivating: false,
|
60 |
+
deactivateUrl: null,
|
61 |
+
submitUrl: WrpaDisablePoll.url,
|
62 |
+
model: WrpaDisablePoll.model,
|
63 |
+
form: WrpaDisablePoll.form,
|
64 |
+
audience: WrpaDisablePoll.audience || 100,
|
65 |
+
isModalVisible: false
|
66 |
+
}
|
67 |
+
},
|
68 |
+
watch: {
|
69 |
+
'model.reason' () {
|
70 |
+
this.model.follow_up = null
|
71 |
+
}
|
72 |
+
},
|
73 |
+
mounted () {
|
74 |
+
const isVisible = this.getRandomInt(0, 100) < this.audience
|
75 |
+
if (isVisible) {
|
76 |
+
deactivateLink.addEventListener('click', this.handleDeactivateClick)
|
77 |
+
}
|
78 |
+
},
|
79 |
+
methods: {
|
80 |
+
getRandomInt (min, max) {
|
81 |
+
min = Math.ceil(min);
|
82 |
+
max = Math.floor(max);
|
83 |
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
84 |
+
},
|
85 |
+
|
86 |
+
image (path) {
|
87 |
+
return WrpaDisablePoll.image + path
|
88 |
+
},
|
89 |
+
|
90 |
+
handleDeactivateClick (e) {
|
91 |
+
if (this.isModalVisible) {
|
92 |
+
return
|
93 |
+
}
|
94 |
+
|
95 |
+
e.preventDefault()
|
96 |
+
this.isModalVisible = true
|
97 |
+
},
|
98 |
+
|
99 |
+
closeModal () {
|
100 |
+
this.isModalVisible = false
|
101 |
+
this.deactivateUrl = null
|
102 |
+
},
|
103 |
+
|
104 |
+
submit () {
|
105 |
+
this.isDeactivating = true
|
106 |
+
axios.post(this.submitUrl, this.model, {
|
107 |
+
headers: {
|
108 |
+
'Content-Type': 'application/x-www-form-urlencoded'
|
109 |
+
}
|
110 |
+
}).then(() => {
|
111 |
+
this.deactivate()
|
112 |
+
}).finally(() => {
|
113 |
+
this.isDeactivating = false
|
114 |
+
})
|
115 |
+
},
|
116 |
+
|
117 |
+
deactivate () {
|
118 |
+
deactivateLink.click()
|
119 |
+
}
|
120 |
+
}
|
121 |
+
}
|
122 |
+
</script>
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
require('css/src/plugins/index.scss')
|
2 |
+
|
3 |
+
import Vue from 'vue'
|
4 |
+
import PluginDisablePoll from './PluginDisablePoll'
|
5 |
+
|
6 |
+
new Vue({
|
7 |
+
el: '#wpra-plugins-app',
|
8 |
+
template: '<PluginDisablePoll/>',
|
9 |
+
components: { PluginDisablePoll }
|
10 |
+
})
|
@@ -0,0 +1,491 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import Postbox from 'app/components/Postbox'
|
2 |
+
import Main from 'app/components/Main'
|
3 |
+
import Sidebar from 'app/components/Sidebar'
|
4 |
+
import Layout from 'app/components/Layout'
|
5 |
+
import RouteLink from 'app/components/RouteLink'
|
6 |
+
import Input from 'app/components/Input'
|
7 |
+
import Button from 'app/components/Button'
|
8 |
+
import NoticeBlock from 'app/components/NoticeBlock'
|
9 |
+
import deepmerge from 'app/utils/deepmerge'
|
10 |
+
import DataChangesAware from 'app/mixins/DataChangesAware'
|
11 |
+
import jsonClone from 'app/utils/jsonClone'
|
12 |
+
import base64 from 'app/utils/base64'
|
13 |
+
import { copyToClipboard } from 'app/utils/copy'
|
14 |
+
|
15 |
+
export default {
|
16 |
+
mixins: [DataChangesAware],
|
17 |
+
data () {
|
18 |
+
return {
|
19 |
+
typeOptions: Object.keys(WpraTemplates.options.type)
|
20 |
+
.filter(key => key[0] !== '_')
|
21 |
+
.reduce((acc, key) => {
|
22 |
+
acc[key] = WpraTemplates.options.type[key]
|
23 |
+
return acc
|
24 |
+
}, {}),
|
25 |
+
|
26 |
+
model: jsonClone(WpraTemplates.model_schema),
|
27 |
+
validation: jsonClone(WpraTemplates.model_schema),
|
28 |
+
tooltips: jsonClone(WpraTemplates.model_tooltips),
|
29 |
+
|
30 |
+
baseUrl: WpraTemplates.base_url,
|
31 |
+
isSaving: false,
|
32 |
+
isLoading: false,
|
33 |
+
}
|
34 |
+
},
|
35 |
+
inject: [
|
36 |
+
'hooks',
|
37 |
+
'http',
|
38 |
+
'router',
|
39 |
+
'notification',
|
40 |
+
],
|
41 |
+
mounted () {
|
42 |
+
this.resolveEditingItem()
|
43 |
+
},
|
44 |
+
computed: {
|
45 |
+
previewUrl () {
|
46 |
+
let options = base64.encode(JSON.stringify(this.model.options))
|
47 |
+
|
48 |
+
return `${WpraGlobal.admin_base_url}?wpra_preview_template=${this.router.params.id}&wpra_template_options=${options}`
|
49 |
+
}
|
50 |
+
},
|
51 |
+
methods: {
|
52 |
+
resolveEditingItem () {
|
53 |
+
let modelDefault = deepmerge(jsonClone(WpraTemplates.model_schema), this.$store.state.templates.preset)
|
54 |
+
|
55 |
+
this.isLoading = true
|
56 |
+
const loadItem = () => {
|
57 |
+
const id = this.router.params.id
|
58 |
+
if (!id) {
|
59 |
+
return Promise.resolve(null)
|
60 |
+
}
|
61 |
+
let item = this.$store.getters['templates/item'](id)
|
62 |
+
if (item) {
|
63 |
+
return Promise.resolve(item)
|
64 |
+
}
|
65 |
+
return this.http.get(`${this.baseUrl}/${id}`).then(response => {
|
66 |
+
return response.data
|
67 |
+
})
|
68 |
+
}
|
69 |
+
|
70 |
+
loadItem().then(item => {
|
71 |
+
this.isLoading = false
|
72 |
+
if (!item) {
|
73 |
+
this.$set(this, 'model', modelDefault)
|
74 |
+
this.rememberModel()
|
75 |
+
return
|
76 |
+
}
|
77 |
+
item = Object.assign({}, item)
|
78 |
+
this.model = deepmerge(this.model, item)
|
79 |
+
this.rememberModel()
|
80 |
+
})
|
81 |
+
},
|
82 |
+
save () {
|
83 |
+
const isNew = !this.model.id
|
84 |
+
this.isSaving = true
|
85 |
+
this.runRequest().then(response => {
|
86 |
+
this.model = deepmerge(this.model, response.data)
|
87 |
+
this.rememberModel()
|
88 |
+
|
89 |
+
this.notification.show('Template saved!', {
|
90 |
+
type: 'success',
|
91 |
+
icon (el) {
|
92 |
+
el.classList.add('dashicons', 'dashicons-yes')
|
93 |
+
return el
|
94 |
+
},
|
95 |
+
})
|
96 |
+
|
97 |
+
if (!isNew) {
|
98 |
+
return
|
99 |
+
}
|
100 |
+
this.router.navigate({
|
101 |
+
name: 'templates',
|
102 |
+
params: {
|
103 |
+
action: 'edit',
|
104 |
+
id: response.data.id
|
105 |
+
}
|
106 |
+
})
|
107 |
+
}, response => {
|
108 |
+
this.notification.show('Something went wrong. Template is not saved!', {
|
109 |
+
type: 'error',
|
110 |
+
icon (el) {
|
111 |
+
el.classList.add('dashicons', 'dashicons-warning')
|
112 |
+
return el
|
113 |
+
},
|
114 |
+
})
|
115 |
+
}).finally(() => {
|
116 |
+
this.isSaving = false
|
117 |
+
})
|
118 |
+
},
|
119 |
+
runRequest () {
|
120 |
+
const method = this.model.id ? 'put' : 'post'
|
121 |
+
const url = this.model.id ? `${this.baseUrl}/${this.model.id}` : this.baseUrl
|
122 |
+
return this.http[method](url, this.prepareModel())
|
123 |
+
},
|
124 |
+
prepareModel () {
|
125 |
+
const availableKeys = Object.keys(WpraTemplates.model_schema)
|
126 |
+
|
127 |
+
return Object.keys(this.model)
|
128 |
+
.filter(key => {
|
129 |
+
/*
|
130 |
+
* Only keys from model_schema can be saved.
|
131 |
+
*/
|
132 |
+
if (!availableKeys.includes(key)) {
|
133 |
+
return false
|
134 |
+
}
|
135 |
+
|
136 |
+
/*
|
137 |
+
* Name and type shouldn't be passed for default template.
|
138 |
+
*/
|
139 |
+
if (this.model.type === '__built_in' && ['name', 'type'].includes(key)) {
|
140 |
+
return false
|
141 |
+
}
|
142 |
+
|
143 |
+
/*
|
144 |
+
* Slug and ID fields are always ignored and not sent in the request body.
|
145 |
+
*/
|
146 |
+
return !['slug', 'id'].includes(key)
|
147 |
+
})
|
148 |
+
.reduce((acc, key) => {
|
149 |
+
acc[key] = this.model[key]
|
150 |
+
return acc
|
151 |
+
}, {})
|
152 |
+
},
|
153 |
+
getShortcode () {
|
154 |
+
return `[wp-rss-aggregator template="${this.model.slug}"]`
|
155 |
+
},
|
156 |
+
preventLoosingNotSavedData () {
|
157 |
+
return !this.isChanged() || confirm('You have unsaved changes. All changes will be lost if you go back to the Template list before updating. Are you sure you want to continue?')
|
158 |
+
},
|
159 |
+
copyShortcode (e) {
|
160 |
+
copyToClipboard(this.getShortcode())
|
161 |
+
|
162 |
+
const text = e.target.innerText
|
163 |
+
|
164 |
+
e.target.style.width = e.target.getBoundingClientRect().width + 'px'
|
165 |
+
e.target.disabled = true
|
166 |
+
e.target.innerText = 'Copied!'
|
167 |
+
|
168 |
+
setTimeout(() => {
|
169 |
+
e.target.style.width = null
|
170 |
+
e.target.innerText = text
|
171 |
+
e.target.disabled = false
|
172 |
+
}, 5000)
|
173 |
+
},
|
174 |
+
},
|
175 |
+
render () {
|
176 |
+
let back = {
|
177 |
+
name: 'templates'
|
178 |
+
}
|
179 |
+
|
180 |
+
let minorActions = null,
|
181 |
+
shortcode = null,
|
182 |
+
noticeBlock = <NoticeBlock
|
183 |
+
class={'postbox'}
|
184 |
+
id={'templates-usage'}
|
185 |
+
title={'Setting up your Templates'}
|
186 |
+
body={'Templates are used to display the items imported using WP RSS Aggregator. Choose the preferred options ' +
|
187 |
+
'below and use them anywhere on your site via our <a href="https://kb.wprssaggregator.com/article/54-displaying-imported-items-shortcode#tinymce" target="_blank">shortcode</a> ' +
|
188 |
+
'or our <a href="https://kb.wprssaggregator.com/article/454-displaying-imported-items-block-gutenberg" target="_blank">block</a>.'}
|
189 |
+
learnMore={'https://kb.wprssaggregator.com/article/457-templates'}
|
190 |
+
/>
|
191 |
+
|
192 |
+
if (this.router.params.id) {
|
193 |
+
minorActions = <div id="" style={{padding: '6px 0'}}>
|
194 |
+
<div class="misc-pub-section misc-pub-visibility">
|
195 |
+
<a href={this.previewUrl}
|
196 |
+
class="wpra-preview-link"
|
197 |
+
role="button"
|
198 |
+
target="wpra-preview-template"
|
199 |
+
style={{marginLeft: '4px', textDecoration: 'none'}}
|
200 |
+
>
|
201 |
+
Open preview
|
202 |
+
<span class="dashicons dashicons-external"/>
|
203 |
+
</a>
|
204 |
+
</div>
|
205 |
+
</div>
|
206 |
+
}
|
207 |
+
|
208 |
+
if (this.model.id) {
|
209 |
+
shortcode = <div class="wpra-shortcode-copy" title={'Copy chortcode'}>
|
210 |
+
<div class="wpra-shortcode-copy__content">
|
211 |
+
<strong>Shortcode: </strong>
|
212 |
+
<code>{ this.getShortcode() }</code>
|
213 |
+
</div>
|
214 |
+
<div class="wpra-shortcode-copy__icon">
|
215 |
+
<button class="button" onClick={this.copyShortcode}>Copy Shortcode</button>
|
216 |
+
</div>
|
217 |
+
</div>
|
218 |
+
}
|
219 |
+
|
220 |
+
let content = <div>
|
221 |
+
<div class="page-title">
|
222 |
+
<RouteLink class="back-button" path={back} gate={this.preventLoosingNotSavedData}>
|
223 |
+
<span class="dashicons dashicons-arrow-left-alt"></span>
|
224 |
+
Templates
|
225 |
+
</RouteLink>
|
226 |
+
<h1>
|
227 |
+
{this.router.params.id ? (this.changes.model.name || this.changes.model.slug) : 'Create a New Template'}
|
228 |
+
</h1>
|
229 |
+
{shortcode}
|
230 |
+
</div>
|
231 |
+
<div id="poststuff">
|
232 |
+
{
|
233 |
+
this.isLoading ? <div class="loading-container"/> : <Layout class="metabox-holder columns-2">
|
234 |
+
<Main>
|
235 |
+
{noticeBlock}
|
236 |
+
<Postbox id="template-details" title="Template Details" context={this}>
|
237 |
+
<Input type="text"
|
238 |
+
label={'Template name'}
|
239 |
+
value={this.model.name}
|
240 |
+
onInput={(e) => this.model.name = e}
|
241 |
+
disabled={this.model.type === '__built_in'}
|
242 |
+
/>
|
243 |
+
<Input type="select"
|
244 |
+
label={'Template type'}
|
245 |
+
value={this.model.type}
|
246 |
+
options={this.typeOptions}
|
247 |
+
onInput={(e) => this.model.type = e}
|
248 |
+
disabled={this.model.type === '__built_in'}
|
249 |
+
inputDisabled={!WpraTemplates.options.is_type_enabled}
|
250 |
+
description={
|
251 |
+
WpraTemplates.options.is_type_enabled ? null : '<div class="disable-ignored"><strong class="disable-ignored">Get more template types, including a customisable grid template.</strong> <a target="_blank" href="https://www.wprssaggregator.com/extensions/templates/" class="disable-ignored">Learn more.</a></div>'
|
252 |
+
}
|
253 |
+
/>
|
254 |
+
{
|
255 |
+
(this.model.type === '__built_in') ?
|
256 |
+
<div class="wpra-info-box">
|
257 |
+
<div class="wpra-info-box__icon">
|
258 |
+
<span class="dashicons dashicons-info"/>
|
259 |
+
</div>
|
260 |
+
<div class="wpra-info-box__text">
|
261 |
+
This is the default template for WP RSS Aggregator. It is used as the fallback template when one is not selected via the shortcode or block. To create a new one, please go back to the Templates List.
|
262 |
+
</div>
|
263 |
+
</div>
|
264 |
+
:
|
265 |
+
null
|
266 |
+
}
|
267 |
+
</Postbox>
|
268 |
+
<Postbox id="template-options" title="Template Options" context={this}>
|
269 |
+
<Input type="checkbox"
|
270 |
+
label={'Link title to original article'}
|
271 |
+
value={this.model.options.title_is_link}
|
272 |
+
onInput={(e) => this.model.options.title_is_link = e}
|
273 |
+
title={this.tooltips.options.title_is_link}
|
274 |
+
/>
|
275 |
+
<Input type="number"
|
276 |
+
label={'Title maximum length'}
|
277 |
+
value={this.model.options.title_max_length || ''}
|
278 |
+
placeholder={'No limit'}
|
279 |
+
onInput={(e) => this.model.options.title_max_length = e}
|
280 |
+
title={this.tooltips.options.title_max_length}
|
281 |
+
/>
|
282 |
+
<Input type="number"
|
283 |
+
label={'Number of items to show'}
|
284 |
+
value={this.model.options.limit || ''}
|
285 |
+
onInput={(e) => this.model.options.limit = (e === '') ? 0 : e}
|
286 |
+
title={this.tooltips.options.limit}
|
287 |
+
placeholder={"Show all items"}
|
288 |
+
min="0"
|
289 |
+
/>
|
290 |
+
|
291 |
+
<div id={'wpra-list-template-publish-date'} style={{paddingTop: '10px'}}>
|
292 |
+
<Input type="checkbox"
|
293 |
+
label={'Show publish date'}
|
294 |
+
value={this.model.options.date_enabled}
|
295 |
+
onInput={(e) => this.model.options.date_enabled = e}
|
296 |
+
style={{fontWeight: 'bold'}}
|
297 |
+
title={this.tooltips.options.date_enabled}
|
298 |
+
/>
|
299 |
+
<Input type="text"
|
300 |
+
label={'Date prefix'}
|
301 |
+
value={this.model.options.date_prefix}
|
302 |
+
onInput={(e) => this.model.options.date_prefix = e}
|
303 |
+
disabled={!this.model.options.date_enabled}
|
304 |
+
title={this.tooltips.options.date_prefix}
|
305 |
+
/>
|
306 |
+
<Input type="text"
|
307 |
+
label={'Date format'}
|
308 |
+
value={this.model.options.date_format}
|
309 |
+
onInput={(e) => this.model.options.date_format = e}
|
310 |
+
disabled={this.model.options.date_use_time_ago || !this.model.options.date_enabled}
|
311 |
+
title={this.tooltips.options.date_format}
|
312 |
+
/>
|
313 |
+
<Input type="checkbox"
|
314 |
+
label={'Use "time ago" format'}
|
315 |
+
description={'Example: 20 minutes ago'}
|
316 |
+
value={this.model.options.date_use_time_ago}
|
317 |
+
onInput={(e) => this.model.options.date_use_time_ago = e}
|
318 |
+
disabled={!this.model.options.date_enabled}
|
319 |
+
title={this.tooltips.options.date_use_time_ago}
|
320 |
+
/>
|
321 |
+
</div>
|
322 |
+
|
323 |
+
<div id={'wpra-list-template-source'} style={{paddingTop: '10px'}}>
|
324 |
+
<Input type="checkbox"
|
325 |
+
label={'Show source name'}
|
326 |
+
value={this.model.options.source_enabled}
|
327 |
+
onInput={(e) => this.model.options.source_enabled = e}
|
328 |
+
style={{fontWeight: 'bold'}}
|
329 |
+
title={this.tooltips.options.source_enabled}
|
330 |
+
/>
|
331 |
+
<Input type="text"
|
332 |
+
label={'Source prefix'}
|
333 |
+
value={this.model.options.source_prefix}
|
334 |
+
onInput={(e) => this.model.options.source_prefix = e}
|
335 |
+
disabled={!this.model.options.source_enabled}
|
336 |
+
title={this.tooltips.options.source_prefix}
|
337 |
+
/>
|
338 |
+
<Input type="checkbox"
|
339 |
+
label={'Link source name'}
|
340 |
+
value={this.model.options.source_is_link}
|
341 |
+
onInput={(e) => this.model.options.source_is_link = e}
|
342 |
+
disabled={!this.model.options.source_enabled}
|
343 |
+
title={this.tooltips.options.source_is_link}
|
344 |
+
/>
|
345 |
+
</div>
|
346 |
+
|
347 |
+
<div id={'wpra-list-template-author'} style={{paddingTop: '10px'}}>
|
348 |
+
<Input type="checkbox"
|
349 |
+
label={'Show author name'}
|
350 |
+
value={this.model.options.author_enabled}
|
351 |
+
onInput={(e) => this.model.options.author_enabled = e}
|
352 |
+
style={{fontWeight: 'bold'}}
|
353 |
+
title={this.tooltips.options.author_enabled}
|
354 |
+
/>
|
355 |
+
<Input type="text"
|
356 |
+
label={'Author prefix'}
|
357 |
+
value={this.model.options.author_prefix}
|
358 |
+
onInput={(e) => this.model.options.author_prefix = e}
|
359 |
+
disabled={!this.model.options.author_enabled}
|
360 |
+
title={this.tooltips.options.author_prefix}
|
361 |
+
/>
|
362 |
+
</div>
|
363 |
+
|
364 |
+
<div id={'wpra-list-template-pagination'} style={{paddingTop: '10px'}}>
|
365 |
+
<Input type="checkbox"
|
366 |
+
label={'Pagination'}
|
367 |
+
value={this.model.options.pagination}
|
368 |
+
onInput={(e) => this.model.options.pagination = e}
|
369 |
+
style={{fontWeight: 'bold'}}
|
370 |
+
title={this.tooltips.options.pagination}
|
371 |
+
disabled={parseInt(this.model.options.limit) < 1 || !this.model.options.limit}
|
372 |
+
/>
|
373 |
+
<Input type="select"
|
374 |
+
label={'Pagination style'}
|
375 |
+
options={WpraTemplates.options.pagination_type}
|
376 |
+
value={this.model.options.pagination_type}
|
377 |
+
onInput={(e) => this.model.options.pagination_type = e}
|
378 |
+
disabled={!this.model.options.pagination || parseInt(this.model.options.limit) < 1 || !this.model.options.limit}
|
379 |
+
title={this.tooltips.options.pagination_type}
|
380 |
+
/>
|
381 |
+
</div>
|
382 |
+
|
383 |
+
<div id={'wpra-list-template-bullets'} style={{paddingTop: '10px'}}>
|
384 |
+
<Input type="checkbox"
|
385 |
+
label={'Show bullets'}
|
386 |
+
value={this.model.options.bullets_enabled}
|
387 |
+
onInput={(e) => this.model.options.bullets_enabled = e}
|
388 |
+
style={{fontWeight: 'bold'}}
|
389 |
+
title={this.tooltips.options.bullets_enabled}
|
390 |
+
/>
|
391 |
+
<Input type="select"
|
392 |
+
label={'Bullet style'}
|
393 |
+
options={WpraTemplates.options.bullet_type}
|
394 |
+
value={this.model.options.bullet_type}
|
395 |
+
onInput={(e) => this.model.options.bullet_type = e}
|
396 |
+
disabled={!this.model.options.bullets_enabled}
|
397 |
+
title={this.tooltips.options.bullet_type}
|
398 |
+
/>
|
399 |
+
</div>
|
400 |
+
</Postbox>
|
401 |
+
</Main>
|
402 |
+
<Sidebar>
|
403 |
+
<Postbox id="template-create"
|
404 |
+
title={this.model.id ? 'Update Template' : 'Create Template'}
|
405 |
+
submit={true}
|
406 |
+
class={'wpra-postbox-last'}
|
407 |
+
context={this}
|
408 |
+
>
|
409 |
+
<div class="submitbox" id="submitpost">
|
410 |
+
{minorActions}
|
411 |
+
|
412 |
+
<div id="major-publishing-actions">
|
413 |
+
<div id="delete-action">
|
414 |
+
{
|
415 |
+
this.isChanged() ? <a href="#" class="submitdelete" onClick={(e) => {
|
416 |
+
e.preventDefault()
|
417 |
+
this.cancelChanges()
|
418 |
+
}}>
|
419 |
+
Cancel Changes
|
420 |
+
</a> : null
|
421 |
+
}
|
422 |
+
</div>
|
423 |
+
|
424 |
+
<div id="publishing-action">
|
425 |
+
<Button class="button-primary button-large"
|
426 |
+
loading={this.isSaving}
|
427 |
+
nativeOnClick={this.save}
|
428 |
+
>
|
429 |
+
{this.model.id ? 'Save' : 'Publish'}
|
430 |
+
</Button>
|
431 |
+
</div>
|
432 |
+
<div class="clear"></div>
|
433 |
+
</div>
|
434 |
+
</div>
|
435 |
+
</Postbox>
|
436 |
+
<Postbox id="template-link-preferences" title="Link Preferences" context={this}>
|
437 |
+
<p style={{opacity: .65}}>
|
438 |
+
These options apply to all links within this template.
|
439 |
+
</p>
|
440 |
+
<Input type="checkbox"
|
441 |
+
label={'Set links as nofollow'}
|
442 |
+
value={this.model.options.links_nofollow}
|
443 |
+
onInput={(e) => this.model.options.links_nofollow = e}
|
444 |
+
title={this.tooltips.options.links_nofollow}
|
445 |
+
/>
|
446 |
+
<Input type="select"
|
447 |
+
label={'Open links behaviour'}
|
448 |
+
class="form-input--vertical"
|
449 |
+
value={this.model.options.links_behavior}
|
450 |
+
options={WpraTemplates.options.links_behavior}
|
451 |
+
onInput={(e) => this.model.options.links_behavior = e}
|
452 |
+
title={this.tooltips.options.links_behavior}
|
453 |
+
/>
|
454 |
+
{
|
455 |
+
(this.model.options.links_behavior === 'lightbox' )?
|
456 |
+
<div class="notice notice-info notice-alt">
|
457 |
+
<p>Some sites may not allow their content to be shown in a lightbox.</p>
|
458 |
+
<p>Embedded content usually works. Try ticking the below checkbox.</p>
|
459 |
+
<p>
|
460 |
+
<a href="https://kb.wprssaggregator.com/article/471-q-why-wont-some-of-my-feed-items-work-with-the-lightbox-link-behaviour-for-templates"
|
461 |
+
target="_blank">
|
462 |
+
{'Learn more'}
|
463 |
+
</a>
|
464 |
+
</p>
|
465 |
+
</div>
|
466 |
+
: null
|
467 |
+
}
|
468 |
+
<Input type="checkbox"
|
469 |
+
label={'Set links to open embeds'}
|
470 |
+
value={this.model.options.link_to_embed}
|
471 |
+
onInput={(e) => this.model.options.link_to_embed = e}
|
472 |
+
title={this.tooltips.options.link_to_embed}
|
473 |
+
/>
|
474 |
+
</Postbox>
|
475 |
+
<Postbox id="template-custom-css" title="Custom Style" context={this}>
|
476 |
+
<Input type="text"
|
477 |
+
class="form-input--vertical"
|
478 |
+
label={'Custom HTML class name'}
|
479 |
+
value={this.model.options.custom_css_classname}
|
480 |
+
onInput={(e) => this.model.options.custom_css_classname = e}
|
481 |
+
title={this.tooltips.options.custom_css_classname}
|
482 |
+
/>
|
483 |
+
</Postbox>
|
484 |
+
</Sidebar>
|
485 |
+
</Layout>
|
486 |
+
}
|
487 |
+
</div>
|
488 |
+
</div>
|
489 |
+
return this.hooks.apply('wpra-templates-form', this, content)
|
490 |
+
}
|
491 |
+
}
|
@@ -0,0 +1,350 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import VueTable from '@rebelcode/vue-wp-list-table/dist/vue-wp-list-table.common'
|
2 |
+
import RouteLink from 'app/components/RouteLink'
|
3 |
+
import Input from 'app/components/Input'
|
4 |
+
import BottomPanel from 'app/components/BottomPanel'
|
5 |
+
import jsonClone from 'app/utils/jsonClone'
|
6 |
+
import collect from 'app/utils/Collection'
|
7 |
+
|
8 |
+
export default {
|
9 |
+
data () {
|
10 |
+
return {
|
11 |
+
loading: false,
|
12 |
+
|
13 |
+
columns: {
|
14 |
+
name: {
|
15 |
+
label: ('Template Name'),
|
16 |
+
class: 'column-primary'
|
17 |
+
},
|
18 |
+
style: {
|
19 |
+
label: ('Template Type'),
|
20 |
+
},
|
21 |
+
previewTemplate: {
|
22 |
+
label: ('Preview')
|
23 |
+
}
|
24 |
+
},
|
25 |
+
|
26 |
+
filters: WpraTemplates.options.type,
|
27 |
+
|
28 |
+
checked: [],
|
29 |
+
|
30 |
+
filter: {
|
31 |
+
paged: parseInt(this.router.params.paged || 1),
|
32 |
+
type: this.router.params.type || '',
|
33 |
+
s: this.router.params.s || '',
|
34 |
+
},
|
35 |
+
|
36 |
+
baseUrl: WpraTemplates.base_url,
|
37 |
+
|
38 |
+
total: 0,
|
39 |
+
}
|
40 |
+
},
|
41 |
+
inject: [
|
42 |
+
'hooks',
|
43 |
+
'http',
|
44 |
+
'router',
|
45 |
+
],
|
46 |
+
computed: {
|
47 |
+
totalPages () {
|
48 |
+
return Math.ceil(this.total / 20)
|
49 |
+
},
|
50 |
+
list: {
|
51 |
+
get () {
|
52 |
+
return this.$store.state.templates.items
|
53 |
+
},
|
54 |
+
set (value) {
|
55 |
+
this.$store.commit('templates/set', value)
|
56 |
+
},
|
57 |
+
}
|
58 |
+
},
|
59 |
+
methods: {
|
60 |
+
navigated () {
|
61 |
+
Object.keys(this.filter).forEach(key => {
|
62 |
+
this.filter[key] = this.router.params[key] || ''
|
63 |
+
})
|
64 |
+
this.filter.paged = parseInt(this.filter.paged || 1)
|
65 |
+
this.fetchList()
|
66 |
+
},
|
67 |
+
|
68 |
+
fetchList () {
|
69 |
+
this.loading = true
|
70 |
+
|
71 |
+
let params = this.getParams()
|
72 |
+
|
73 |
+
let paged = parseInt(params.paged)
|
74 |
+
delete params.paged
|
75 |
+
if (!!paged && paged !== 1) {
|
76 |
+
params['page'] = paged
|
77 |
+
}
|
78 |
+
|
79 |
+
return this.http.get(this.baseUrl, {
|
80 |
+
params
|
81 |
+
}).then((response) => {
|
82 |
+
this.list = response.data.items
|
83 |
+
this.total = response.data.count
|
84 |
+
}).finally(() => {
|
85 |
+
this.loading = false
|
86 |
+
})
|
87 |
+
},
|
88 |
+
|
89 |
+
deleteTemplate (id) {
|
90 |
+
if (!confirm('Are you sure you want to delete this template? If this template is being used in a shortcode or Gutenberg block anywhere on your site, the default template will be used instead.')) {
|
91 |
+
return
|
92 |
+
}
|
93 |
+
this.loading = true
|
94 |
+
return this.http.delete(`${this.baseUrl}/${id}`).then(() => {
|
95 |
+
return this.fetchList()
|
96 |
+
}).then(() => {
|
97 |
+
this.loading = false
|
98 |
+
})
|
99 |
+
},
|
100 |
+
|
101 |
+
bulkDelete () {
|
102 |
+
if (!confirm('Are you sure you want to delete these templates? If a template is being used in a shortcode or Gutenberg block anywhere on your site, the default template will be used instead.')) {
|
103 |
+
return
|
104 |
+
}
|
105 |
+
this.loading = true
|
106 |
+
return this.http.delete(this.baseUrl, {
|
107 |
+
params: {
|
108 |
+
ids: this.checked
|
109 |
+
}
|
110 |
+
}).then(() => {
|
111 |
+
this.checked = []
|
112 |
+
this.$refs.table.checkedItems = []
|
113 |
+
return this.fetchList()
|
114 |
+
}).then(() => {
|
115 |
+
this.loading = false
|
116 |
+
})
|
117 |
+
},
|
118 |
+
|
119 |
+
duplicateTemplate (row) {
|
120 |
+
let template = jsonClone(row)
|
121 |
+
|
122 |
+
delete template.id
|
123 |
+
|
124 |
+
if (template.type === '__built_in') {
|
125 |
+
delete template.type
|
126 |
+
}
|
127 |
+
|
128 |
+
// add copy to the title so it is mor obvious for the user that this is duplicate.
|
129 |
+
template.name = `${template.name} (Copy)`
|
130 |
+
|
131 |
+
this.$store.commit('templates/updatePreset', template)
|
132 |
+
this.router.navigate({
|
133 |
+
name: 'templates',
|
134 |
+
params: {
|
135 |
+
action: 'new',
|
136 |
+
}
|
137 |
+
})
|
138 |
+
},
|
139 |
+
|
140 |
+
getPreviewLink (row) {
|
141 |
+
return `${WpraGlobal.admin_base_url}?wpra_preview_template=${row.id}`
|
142 |
+
},
|
143 |
+
|
144 |
+
createTemplate () {
|
145 |
+
this.$store.commit('templates/updatePreset', {})
|
146 |
+
this.router.navigate({
|
147 |
+
name: 'templates',
|
148 |
+
params: {
|
149 |
+
action: 'new',
|
150 |
+
}
|
151 |
+
})
|
152 |
+
},
|
153 |
+
|
154 |
+
setChecked (values) {
|
155 |
+
this.checked = values.filter(id => {
|
156 |
+
return collect(this.list).find(id, {}).type !== '__built_in'
|
157 |
+
})
|
158 |
+
},
|
159 |
+
|
160 |
+
getParams () {
|
161 |
+
return Object.keys(this.filter).filter(key => {
|
162 |
+
return !!this.filter[key] && this.filter[key] !== 'all'
|
163 |
+
}).reduce((acc, key) => {
|
164 |
+
acc[key] = this.filter[key]
|
165 |
+
return acc
|
166 |
+
}, {})
|
167 |
+
},
|
168 |
+
|
169 |
+
setFilter (name, value) {
|
170 |
+
this.filter[name] = value
|
171 |
+
},
|
172 |
+
|
173 |
+
submitFilter () {
|
174 |
+
this.router.mergeParams(this.getParams())
|
175 |
+
},
|
176 |
+
|
177 |
+
getRowClass (row) {
|
178 |
+
return row.type === '__built_in' ? 'built-in' : ''
|
179 |
+
}
|
180 |
+
},
|
181 |
+
render () {
|
182 |
+
const editPath = (id) => {
|
183 |
+
return {
|
184 |
+
name: 'templates',
|
185 |
+
params: {
|
186 |
+
action: 'edit',
|
187 |
+
id,
|
188 |
+
}
|
189 |
+
}
|
190 |
+
}
|
191 |
+
|
192 |
+
let cells = this.hooks.apply('wpra-templates-list-cells', this, {
|
193 |
+
name: ({row}) => {
|
194 |
+
return [
|
195 |
+
<div>
|
196 |
+
<strong><RouteLink path={editPath(row.id)}>{row.name}</RouteLink></strong>
|
197 |
+
<small style={{paddingLeft: '4px', opacity: '0.6'}}>{row.slug}</small>
|
198 |
+
{
|
199 |
+
(row.type === '__built_in') ?
|
200 |
+
<span style={{opacity: '0.6', display: 'block'}}>
|
201 |
+
This is the default feed template. To create your own, either duplicate it or click "Add New" above.
|
202 |
+
</span>
|
203 |
+
:
|
204 |
+
null
|
205 |
+
}
|
206 |
+
</div>,
|
207 |
+
<div class="row-actions">
|
208 |
+
<span className="edit">
|
209 |
+
<RouteLink path={editPath(row.id)}>Edit</RouteLink> |
|
210 |
+
</span>
|
211 |
+
<span class="inline" style={{paddingLeft: '4px'}}>
|
212 |
+
<a href="#"
|
213 |
+
onClick={(e) => {
|
214 |
+
e.preventDefault()
|
215 |
+
this.duplicateTemplate(row)
|
216 |
+
}}
|
217 |
+
>Duplicate</a> {row.type !== '__built_in' ? '|' : ''}
|
218 |
+
</span>
|
219 |
+
{
|
220 |
+
(row.type !== '__built_in')
|
221 |
+
?
|
222 |
+
<span class="trash" style={{paddingLeft: '4px'}} onClick={(e) => {
|
223 |
+
e.preventDefault()
|
224 |
+
this.deleteTemplate(row.id)
|
225 |
+
}}>
|
226 |
+
<a href="#" class="submitdelete" aria-label="Delete Item">Delete</a>
|
227 |
+
</span>
|
228 |
+
:
|
229 |
+
null
|
230 |
+
}
|
231 |
+
</div>
|
232 |
+
]
|
233 |
+
},
|
234 |
+
style: ({row}) => {
|
235 |
+
if (this.filters[row.type]) {
|
236 |
+
return [
|
237 |
+
<div>{this.filters[row.type]}</div>
|
238 |
+
]
|
239 |
+
}
|
240 |
+
|
241 |
+
return [
|
242 |
+
<div>
|
243 |
+
{this.filters.list}
|
244 |
+
|
245 |
+
<span style={{opacity: 0.7, fontSize: '90%'}}>
|
246 |
+
(Missing type: <code>{row.type}</code>)
|
247 |
+
</span>
|
248 |
+
</div>
|
249 |
+
];
|
250 |
+
},
|
251 |
+
previewTemplate: ({row}) => {
|
252 |
+
return [
|
253 |
+
<div>
|
254 |
+
<a href={this.getPreviewLink(row)}
|
255 |
+
target="wpra-preview-template"
|
256 |
+
class="wpra-preview-link"
|
257 |
+
>
|
258 |
+
Open preview <span class="dashicons dashicons-external"></span>
|
259 |
+
</a>
|
260 |
+
</div>
|
261 |
+
]
|
262 |
+
},
|
263 |
+
filters: () => {
|
264 |
+
let templateTypes = Object.keys(WpraTemplates.options.type)
|
265 |
+
.filter(key => key[0] !== '_')
|
266 |
+
.reduce((carry, key) => {
|
267 |
+
carry[key] = WpraTemplates.options.type[key]
|
268 |
+
return carry
|
269 |
+
}, {
|
270 |
+
'all': 'Select Template Type',
|
271 |
+
})
|
272 |
+
return [
|
273 |
+
<Input type="select"
|
274 |
+
style={{margin: 0}}
|
275 |
+
options={templateTypes}
|
276 |
+
value={this.filter.type}
|
277 |
+
onInput={(value) => {
|
278 |
+
this.filter.type = value
|
279 |
+
this.submitFilter()
|
280 |
+
}}
|
281 |
+
/>
|
282 |
+
]
|
283 |
+
}
|
284 |
+
})
|
285 |
+
|
286 |
+
let content = <div>
|
287 |
+
<h1 class="wp-heading-inline">Templates</h1>
|
288 |
+
<a class="page-title-action"
|
289 |
+
href="#"
|
290 |
+
onClick={e => {
|
291 |
+
e.preventDefault()
|
292 |
+
this.createTemplate()
|
293 |
+
}}
|
294 |
+
>Add New</a>
|
295 |
+
|
296 |
+
<p class="search-box" style={{padding: '10px 0'}}>
|
297 |
+
<label class="screen-reader-text" for="post-search-input">Search Templates:</label>
|
298 |
+
<input type="search"
|
299 |
+
id="post-search-input"
|
300 |
+
name="s"
|
301 |
+
value={this.filter.s}
|
302 |
+
onInput={e => this.filter.s = e.target.value}
|
303 |
+
onKeyup:enter={this.submitFilter}
|
304 |
+
/>
|
305 |
+
<input type="submit" id="search-submit" class="button" value="Search Templates"
|
306 |
+
onClick={this.submitFilter}
|
307 |
+
/>
|
308 |
+
</p>
|
309 |
+
|
310 |
+
<VueTable
|
311 |
+
onChecked={this.setChecked}
|
312 |
+
onPagination={page => {
|
313 |
+
this.filter.paged = page
|
314 |
+
this.submitFilter()
|
315 |
+
}}
|
316 |
+
columns={this.columns}
|
317 |
+
rows={this.list}
|
318 |
+
loading={this.loading}
|
319 |
+
totalItems={this.total}
|
320 |
+
perPage={20}
|
321 |
+
totalPages={this.totalPages}
|
322 |
+
currentPage={this.filter.paged}
|
323 |
+
ref="table"
|
324 |
+
notFound="No templates found."
|
325 |
+
rowClass={this.getRowClass}
|
326 |
+
class={{
|
327 |
+
'wpra-no-cb': this.list.length === 0 || (this.list.length === 1 && this.list[0].type === '__built_in')
|
328 |
+
}}
|
329 |
+
scopedSlots={
|
330 |
+
cells
|
331 |
+
}
|
332 |
+
/>
|
333 |
+
|
334 |
+
{
|
335 |
+
this.checked.length ? <BottomPanel>
|
336 |
+
<div class="flex-row">
|
337 |
+
<div class="flex-col">
|
338 |
+
<div class="wpra-bottom-panel__title">Bulk Actions</div>
|
339 |
+
<a href="#" onClick={(e) => {
|
340 |
+
e.preventDefault()
|
341 |
+
this.bulkDelete()
|
342 |
+
}}>Delete</a>
|
343 |
+
</div>
|
344 |
+
</div>
|
345 |
+
</BottomPanel> : null
|
346 |
+
}
|
347 |
+
</div>
|
348 |
+
return this.hooks.apply('wpra-templates-list', this, content)
|
349 |
+
}
|
350 |
+
}
|
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import axios from 'axios'
|
2 |
+
import toasted from 'vue-toasted'
|
3 |
+
import VueTippy from 'vue-tippy'
|
4 |
+
|
5 |
+
import Vuex from 'vuex'
|
6 |
+
import List from './List'
|
7 |
+
import Edit from './Edit'
|
8 |
+
|
9 |
+
import makeRouterApp from 'app/components/RouterApp'
|
10 |
+
import Router from 'app/libs/Router'
|
11 |
+
import templates from './store'
|
12 |
+
import NotificationCenter from 'app/libs/NotificationCenter'
|
13 |
+
|
14 |
+
import components from 'app/components'
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Main application's container.
|
18 |
+
*/
|
19 |
+
export default {
|
20 |
+
register (services) {
|
21 |
+
/*
|
22 |
+
* Component for editing templates.
|
23 |
+
*/
|
24 |
+
services['TemplateEdit'] = () => Edit
|
25 |
+
|
26 |
+
/*
|
27 |
+
* Component for managing templates.
|
28 |
+
*/
|
29 |
+
services['TemplateList'] = () => List
|
30 |
+
|
31 |
+
/*
|
32 |
+
* Application router instance.
|
33 |
+
*/
|
34 |
+
services['router'] = ({ document, TemplateEdit, TemplateList }) => {
|
35 |
+
return new Router([{
|
36 |
+
route: WpraGlobal.templates_url_base + '&action',
|
37 |
+
name: 'templates-form',
|
38 |
+
component: TemplateEdit,
|
39 |
+
}, {
|
40 |
+
route: WpraGlobal.templates_url_base,
|
41 |
+
name: 'templates',
|
42 |
+
component: TemplateList,
|
43 |
+
}], {
|
44 |
+
afterNavigating: () => {
|
45 |
+
document.querySelector('html').scrollTop = 0
|
46 |
+
}
|
47 |
+
})
|
48 |
+
}
|
49 |
+
|
50 |
+
/*
|
51 |
+
* Application with client side routes.
|
52 |
+
*/
|
53 |
+
services['App'] = (container) => {
|
54 |
+
return makeRouterApp(container)
|
55 |
+
}
|
56 |
+
|
57 |
+
/*
|
58 |
+
* Setup and register central storage management.
|
59 |
+
*/
|
60 |
+
services['vuex'] = ({ vue }) => {
|
61 |
+
vue.use(Vuex)
|
62 |
+
return Vuex
|
63 |
+
}
|
64 |
+
|
65 |
+
services['notification'] = ({ vue }) => {
|
66 |
+
vue.use(toasted, {
|
67 |
+
position: 'top-center',
|
68 |
+
duration: 4000,
|
69 |
+
iconPack: 'callback'
|
70 |
+
})
|
71 |
+
return new NotificationCenter(vue.toasted.show, vue.toasted.error)
|
72 |
+
}
|
73 |
+
|
74 |
+
services['store'] = ({ vuex }) => {
|
75 |
+
return new vuex.Store({
|
76 |
+
modules: {
|
77 |
+
templates
|
78 |
+
},
|
79 |
+
state: {}
|
80 |
+
})
|
81 |
+
}
|
82 |
+
|
83 |
+
services['http'] = () => {
|
84 |
+
/*
|
85 |
+
* Create authorized client for requests when nonce
|
86 |
+
* exists in global WPRA variable.
|
87 |
+
*/
|
88 |
+
let httpClientOptions = !!WpraGlobal && !!WpraGlobal.nonce ? {
|
89 |
+
headers: {
|
90 |
+
'X-WP-Nonce': WpraGlobal.nonce,
|
91 |
+
}
|
92 |
+
} : {}
|
93 |
+
return axios.create(httpClientOptions)
|
94 |
+
}
|
95 |
+
|
96 |
+
/*
|
97 |
+
* Register components.
|
98 |
+
*/
|
99 |
+
for(const [name, definition] of Object.entries(components)) {
|
100 |
+
services[name] = () => definition
|
101 |
+
}
|
102 |
+
|
103 |
+
return services
|
104 |
+
},
|
105 |
+
run ({ container }) {
|
106 |
+
/*
|
107 |
+
* Enable tippy.js tooltips.
|
108 |
+
*/
|
109 |
+
container.vue.use(VueTippy, {
|
110 |
+
theme: 'light',
|
111 |
+
animation: 'fade',
|
112 |
+
arrow: true,
|
113 |
+
arrowTransform: 'scale(0)',
|
114 |
+
placement: 'right'
|
115 |
+
})
|
116 |
+
},
|
117 |
+
}
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
require('css/src/templates/index.scss')
|
2 |
+
|
3 |
+
import * as UiFramework from '@rebelcode/ui-framework'
|
4 |
+
import Bottle from 'bottlejs'
|
5 |
+
import TemplatesApplication from './app'
|
6 |
+
import Vue from 'vue'
|
7 |
+
|
8 |
+
const { Container, Core, Services } = UiFramework
|
9 |
+
|
10 |
+
/*
|
11 |
+
* Extend UI framework object.
|
12 |
+
*/
|
13 |
+
if (window.UiFramework) {
|
14 |
+
window.UiFramework = Object.assign({}, window.UiFramework, Core.UiFramework)
|
15 |
+
}
|
16 |
+
|
17 |
+
let services = {
|
18 |
+
uiFramework: UiFramework,
|
19 |
+
hooks: new Services.HookService,
|
20 |
+
document: document,
|
21 |
+
vue: function (container) {
|
22 |
+
Vue.use(container.uiFramework.Core.InjectedComponents, {
|
23 |
+
container
|
24 |
+
})
|
25 |
+
return Vue
|
26 |
+
}
|
27 |
+
}
|
28 |
+
const containerFactory = new Container.ContainerFactory(Bottle)
|
29 |
+
const app = new Core.UiFramework.App(containerFactory, services)
|
30 |
+
|
31 |
+
window.UiFramework.registerPlugin('templates-app', TemplatesApplication)
|
32 |
+
|
33 |
+
app.use(WpraTemplates.modules || ['templates-app'])
|
34 |
+
app.init({
|
35 |
+
'#wpra-templates-app': 'App',
|
36 |
+
})
|
@@ -0,0 +1 @@
|
|
|
1 |
+
export default {}
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import collect from 'app/utils/Collection'
|
2 |
+
|
3 |
+
export default {
|
4 |
+
item: state => id => {
|
5 |
+
return collect(state.items).find(id)
|
6 |
+
}
|
7 |
+
}
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import mutations from './mutations'
|
2 |
+
import actions from './actions'
|
3 |
+
import state from './state'
|
4 |
+
import getters from './getters'
|
5 |
+
|
6 |
+
export default {
|
7 |
+
namespaced: true,
|
8 |
+
mutations,
|
9 |
+
actions,
|
10 |
+
state,
|
11 |
+
getters,
|
12 |
+
}
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
export default {
|
2 |
+
set (state, items = []) {
|
3 |
+
state.isInitialized = true
|
4 |
+
state.items = items
|
5 |
+
},
|
6 |
+
|
7 |
+
updatePreset (state, preset = null) {
|
8 |
+
state.preset = preset
|
9 |
+
}
|
10 |
+
}
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
export default {
|
2 |
+
/*
|
3 |
+
* Whether the templates was initialized.
|
4 |
+
*
|
5 |
+
* @todo: remove it. This is trick to not handle proper route params watcher.
|
6 |
+
*/
|
7 |
+
isInitialized: false,
|
8 |
+
|
9 |
+
/*
|
10 |
+
* All loaded template items.
|
11 |
+
*/
|
12 |
+
items: [],
|
13 |
+
|
14 |
+
/*
|
15 |
+
* Predefined template value. Used for items duplication.
|
16 |
+
*/
|
17 |
+
preset: {},
|
18 |
+
}
|
@@ -0,0 +1,178 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
class Collection {
|
2 |
+
constructor (data, primaryField = 'id') {
|
3 |
+
this.data = data
|
4 |
+
this.primaryField = primaryField
|
5 |
+
return this
|
6 |
+
}
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Find element by params
|
10 |
+
*
|
11 |
+
* @param params
|
12 |
+
* @param _default
|
13 |
+
* @returns {*}
|
14 |
+
*/
|
15 |
+
find (params, _default = null) {
|
16 |
+
if (typeof params !== 'object' && params !== null) {
|
17 |
+
params = {
|
18 |
+
[this.primaryField]: params
|
19 |
+
}
|
20 |
+
}
|
21 |
+
for (let i in this.data) {
|
22 |
+
if (this._isMatching(this.data[i], params)) {
|
23 |
+
return this.data[i]
|
24 |
+
}
|
25 |
+
}
|
26 |
+
|
27 |
+
return _default
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Get and left only one column
|
32 |
+
*
|
33 |
+
* @param field
|
34 |
+
* @returns {*}
|
35 |
+
*/
|
36 |
+
pluck (field) {
|
37 |
+
return this.data.map((item) => {
|
38 |
+
return item[field]
|
39 |
+
})
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Remove all elements matching given params
|
44 |
+
*
|
45 |
+
* @param params
|
46 |
+
*/
|
47 |
+
remove (params) {
|
48 |
+
for (let i in this.data) {
|
49 |
+
if (this._isMatching(this.data[i], params)) {
|
50 |
+
this.data.splice(i, 1)
|
51 |
+
}
|
52 |
+
}
|
53 |
+
return this
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Add data from parameter array that not in
|
58 |
+
* collection;
|
59 |
+
*
|
60 |
+
* @param data
|
61 |
+
*/
|
62 |
+
appendDiff (data) {
|
63 |
+
for (let el of data) {
|
64 |
+
if (!this.contains(el)) {
|
65 |
+
this.data.push(el)
|
66 |
+
}
|
67 |
+
}
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Add data from parameter array that not in
|
72 |
+
* collection;
|
73 |
+
*
|
74 |
+
* @param data
|
75 |
+
*/
|
76 |
+
prependDiff (data) {
|
77 |
+
for (let el of data.slice().reverse()) {
|
78 |
+
if (!this.contains(el)) {
|
79 |
+
this.data.unshift(el)
|
80 |
+
}
|
81 |
+
}
|
82 |
+
}
|
83 |
+
|
84 |
+
contains (element) {
|
85 |
+
for (let el of this.data) {
|
86 |
+
if (el['id'] == element['id'])
|
87 |
+
return true
|
88 |
+
}
|
89 |
+
return false
|
90 |
+
}
|
91 |
+
|
92 |
+
filterValues (callback) {
|
93 |
+
return Object.keys(this.data).filter(key => {
|
94 |
+
return callback(this.data[key], key)
|
95 |
+
}).reduce((filteredResult, key) => {
|
96 |
+
filteredResult[key] = this.data[key]
|
97 |
+
return filteredResult
|
98 |
+
}, {})
|
99 |
+
}
|
100 |
+
|
101 |
+
filter (params) {
|
102 |
+
return this.data.filter((item) => {
|
103 |
+
return this._isMatching(item, params)
|
104 |
+
})
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Select all items where value of column in given array
|
109 |
+
*
|
110 |
+
* @param data
|
111 |
+
* @param key
|
112 |
+
* @returns {Array}
|
113 |
+
*/
|
114 |
+
whereIn (data, key = 'id') {
|
115 |
+
let newCollection = [],
|
116 |
+
param = {}
|
117 |
+
|
118 |
+
param[key] = null
|
119 |
+
|
120 |
+
for (let val of data) {
|
121 |
+
param[key] = val
|
122 |
+
|
123 |
+
let item = this.find(param)
|
124 |
+
if (item) {
|
125 |
+
newCollection.push(item)
|
126 |
+
}
|
127 |
+
}
|
128 |
+
|
129 |
+
return newCollection
|
130 |
+
}
|
131 |
+
|
132 |
+
key (field) {
|
133 |
+
const data = this.data.slice().reduce((obj, item) => {
|
134 |
+
obj[item[field]] = item
|
135 |
+
return obj
|
136 |
+
}, {})
|
137 |
+
return new Collection(data)
|
138 |
+
}
|
139 |
+
|
140 |
+
mapValues (callback) {
|
141 |
+
Object.keys(this.data).map((key) => {
|
142 |
+
this.data[key] = callback(this.data[key], key)
|
143 |
+
})
|
144 |
+
return this
|
145 |
+
}
|
146 |
+
|
147 |
+
values () {
|
148 |
+
return this.data
|
149 |
+
}
|
150 |
+
|
151 |
+
/**
|
152 |
+
* Check element is matching params.
|
153 |
+
*
|
154 |
+
* @param element
|
155 |
+
* @param params
|
156 |
+
* @return {boolean}
|
157 |
+
* @private
|
158 |
+
*/
|
159 |
+
_isMatching (element, params) {
|
160 |
+
if (!(element instanceof Object) && !(params instanceof Object)) {
|
161 |
+
return element == params
|
162 |
+
}
|
163 |
+
|
164 |
+
let match = true
|
165 |
+
for (let key of Object.keys(params)) {
|
166 |
+
let keyMatch = element.hasOwnProperty(key) && (element[key] == params[key])
|
167 |
+
match = match && (keyMatch)
|
168 |
+
}
|
169 |
+
return match
|
170 |
+
}
|
171 |
+
|
172 |
+
}
|
173 |
+
|
174 |
+
function collect (data) {
|
175 |
+
return new Collection(data)
|
176 |
+
}
|
177 |
+
|
178 |
+
export default collect
|
@@ -0,0 +1,133 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
let Base64 = {
|
2 |
+
|
3 |
+
// private property
|
4 |
+
_keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
|
5 |
+
|
6 |
+
// public method for encoding
|
7 |
+
encode: function (input) {
|
8 |
+
var output = "";
|
9 |
+
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
|
10 |
+
var i = 0;
|
11 |
+
|
12 |
+
input = Base64._utf8_encode(input);
|
13 |
+
|
14 |
+
while (i < input.length) {
|
15 |
+
|
16 |
+
chr1 = input.charCodeAt(i++);
|
17 |
+
chr2 = input.charCodeAt(i++);
|
18 |
+
chr3 = input.charCodeAt(i++);
|
19 |
+
|
20 |
+
enc1 = chr1 >> 2;
|
21 |
+
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
|
22 |
+
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
|
23 |
+
enc4 = chr3 & 63;
|
24 |
+
|
25 |
+
if (isNaN(chr2)) {
|
26 |
+
enc3 = enc4 = 64;
|
27 |
+
} else if (isNaN(chr3)) {
|
28 |
+
enc4 = 64;
|
29 |
+
}
|
30 |
+
|
31 |
+
output = output +
|
32 |
+
this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
|
33 |
+
this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
|
34 |
+
|
35 |
+
}
|
36 |
+
|
37 |
+
return output;
|
38 |
+
},
|
39 |
+
|
40 |
+
// public method for decoding
|
41 |
+
decode: function (input) {
|
42 |
+
var output = "";
|
43 |
+
var chr1, chr2, chr3;
|
44 |
+
var enc1, enc2, enc3, enc4;
|
45 |
+
var i = 0;
|
46 |
+
|
47 |
+
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
|
48 |
+
|
49 |
+
while (i < input.length) {
|
50 |
+
|
51 |
+
enc1 = this._keyStr.indexOf(input.charAt(i++));
|
52 |
+
enc2 = this._keyStr.indexOf(input.charAt(i++));
|
53 |
+
enc3 = this._keyStr.indexOf(input.charAt(i++));
|
54 |
+
enc4 = this._keyStr.indexOf(input.charAt(i++));
|
55 |
+
|
56 |
+
chr1 = (enc1 << 2) | (enc2 >> 4);
|
57 |
+
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
|
58 |
+
chr3 = ((enc3 & 3) << 6) | enc4;
|
59 |
+
|
60 |
+
output = output + String.fromCharCode(chr1);
|
61 |
+
|
62 |
+
if (enc3 != 64) {
|
63 |
+
output = output + String.fromCharCode(chr2);
|
64 |
+
}
|
65 |
+
if (enc4 != 64) {
|
66 |
+
output = output + String.fromCharCode(chr3);
|
67 |
+
}
|
68 |
+
|
69 |
+
}
|
70 |
+
|
71 |
+
output = Base64._utf8_decode(output);
|
72 |
+
|
73 |
+
return output;
|
74 |
+
|
75 |
+
},
|
76 |
+
|
77 |
+
// private method for UTF-8 encoding
|
78 |
+
_utf8_encode: function (string) {
|
79 |
+
string = string.replace(/\r\n/g, "\n");
|
80 |
+
var utftext = "";
|
81 |
+
|
82 |
+
for (var n = 0; n < string.length; n++) {
|
83 |
+
|
84 |
+
var c = string.charCodeAt(n);
|
85 |
+
|
86 |
+
if (c < 128) {
|
87 |
+
utftext += String.fromCharCode(c);
|
88 |
+
} else if ((c > 127) && (c < 2048)) {
|
89 |
+
utftext += String.fromCharCode((c >> 6) | 192);
|
90 |
+
utftext += String.fromCharCode((c & 63) | 128);
|
91 |
+
} else {
|
92 |
+
utftext += String.fromCharCode((c >> 12) | 224);
|
93 |
+
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
|
94 |
+
utftext += String.fromCharCode((c & 63) | 128);
|
95 |
+
}
|
96 |
+
|
97 |
+
}
|
98 |
+
|
99 |
+
return utftext;
|
100 |
+
},
|
101 |
+
|
102 |
+
// private method for UTF-8 decoding
|
103 |
+
_utf8_decode: function (utftext) {
|
104 |
+
var string = "";
|
105 |
+
var i = 0;
|
106 |
+
var c = 0, c1 = 0, c2 = 0;
|
107 |
+
|
108 |
+
while (i < utftext.length) {
|
109 |
+
|
110 |
+
c = utftext.charCodeAt(i);
|
111 |
+
|
112 |
+
if (c < 128) {
|
113 |
+
string += String.fromCharCode(c);
|
114 |
+
i++;
|
115 |
+
} else if ((c > 191) && (c < 224)) {
|
116 |
+
c2 = utftext.charCodeAt(i + 1);
|
117 |
+
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
|
118 |
+
i += 2;
|
119 |
+
} else {
|
120 |
+
c2 = utftext.charCodeAt(i + 1);
|
121 |
+
c3 = utftext.charCodeAt(i + 2);
|
122 |
+
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
|
123 |
+
i += 3;
|
124 |
+
}
|
125 |
+
|
126 |
+
}
|
127 |
+
|
128 |
+
return string;
|
129 |
+
}
|
130 |
+
|
131 |
+
}
|
132 |
+
|
133 |
+
export default Base64
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
* Helper functions to copy text to clipboard.
|
3 |
+
*
|
4 |
+
* @see https://stackoverflow.com/questions/400212/how-do-i-copy-to-the-clipboard-in-javascript
|
5 |
+
*
|
6 |
+
* @param text
|
7 |
+
*/
|
8 |
+
|
9 |
+
const fallbackCopyToClipboard = function (text, scrollContainer = null) {
|
10 |
+
scrollContainer = scrollContainer || document.body.parentElement
|
11 |
+
var textArea = document.createElement('textarea')
|
12 |
+
textArea.value = text
|
13 |
+
|
14 |
+
var currentScrollTop = scrollContainer.scrollTop
|
15 |
+
|
16 |
+
document.body.appendChild(textArea)
|
17 |
+
textArea.focus()
|
18 |
+
textArea.select()
|
19 |
+
|
20 |
+
try {
|
21 |
+
var successful = document.execCommand('copy')
|
22 |
+
var msg = successful ? 'successful' : 'unsuccessful'
|
23 |
+
console.log('Fallback: Copying text command was ' + msg)
|
24 |
+
} catch (err) {
|
25 |
+
console.error('Fallback: Oops, unable to copy', err)
|
26 |
+
}
|
27 |
+
|
28 |
+
document.body.removeChild(textArea)
|
29 |
+
|
30 |
+
scrollContainer.scrollTop = currentScrollTop
|
31 |
+
}
|
32 |
+
|
33 |
+
export function copyToClipboard (text, scrollContainer = null) {
|
34 |
+
if (!navigator.clipboard) {
|
35 |
+
fallbackCopyToClipboard(text, scrollContainer)
|
36 |
+
return
|
37 |
+
}
|
38 |
+
navigator.clipboard.writeText(text).then(function () {
|
39 |
+
console.log('Async: Copying to clipboard was successful!')
|
40 |
+
}, function (err) {
|
41 |
+
console.error('Async: Could not copy text: ', err)
|
42 |
+
})
|
43 |
+
}
|
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
function isMergeableObject (val) {
|
2 |
+
var nonNullObject = val && typeof val === 'object'
|
3 |
+
|
4 |
+
return nonNullObject
|
5 |
+
&& Object.prototype.toString.call(val) !== '[object RegExp]'
|
6 |
+
&& Object.prototype.toString.call(val) !== '[object Date]'
|
7 |
+
}
|
8 |
+
|
9 |
+
function emptyTarget (val) {
|
10 |
+
return Array.isArray(val) ? [] : {}
|
11 |
+
}
|
12 |
+
|
13 |
+
function cloneIfNecessary (value, optionsArgument) {
|
14 |
+
var clone = optionsArgument && optionsArgument.clone === true
|
15 |
+
return (clone && isMergeableObject(value)) ? deepmerge(emptyTarget(value), value, optionsArgument) : value
|
16 |
+
}
|
17 |
+
|
18 |
+
function defaultArrayMerge (target, source, optionsArgument) {
|
19 |
+
var destination = target.slice()
|
20 |
+
source.forEach(function (e, i) {
|
21 |
+
if (typeof destination[i] === 'undefined') {
|
22 |
+
destination[i] = cloneIfNecessary(e, optionsArgument)
|
23 |
+
} else if (isMergeableObject(e)) {
|
24 |
+
destination[i] = deepmerge(target[i], e, optionsArgument)
|
25 |
+
} else if (target.indexOf(e) === -1) {
|
26 |
+
destination.push(cloneIfNecessary(e, optionsArgument))
|
27 |
+
}
|
28 |
+
})
|
29 |
+
return destination
|
30 |
+
}
|
31 |
+
|
32 |
+
function mergeObject (target, source, optionsArgument) {
|
33 |
+
var destination = {}
|
34 |
+
if (isMergeableObject(target)) {
|
35 |
+
Object.keys(target).forEach(function (key) {
|
36 |
+
destination[key] = cloneIfNecessary(target[key], optionsArgument)
|
37 |
+
})
|
38 |
+
}
|
39 |
+
Object.keys(source).forEach(function (key) {
|
40 |
+
if (!isMergeableObject(source[key]) || !target[key]) {
|
41 |
+
destination[key] = cloneIfNecessary(source[key], optionsArgument)
|
42 |
+
} else {
|
43 |
+
destination[key] = deepmerge(target[key], source[key], optionsArgument)
|
44 |
+
}
|
45 |
+
})
|
46 |
+
return destination
|
47 |
+
}
|
48 |
+
|
49 |
+
function deepmerge (target, source, optionsArgument) {
|
50 |
+
var array = Array.isArray(source)
|
51 |
+
var options = optionsArgument || {arrayMerge: defaultArrayMerge}
|
52 |
+
var arrayMerge = options.arrayMerge || defaultArrayMerge
|
53 |
+
|
54 |
+
if (array) {
|
55 |
+
return Array.isArray(target) ? arrayMerge(target, source, optionsArgument) : cloneIfNecessary(source, optionsArgument)
|
56 |
+
} else {
|
57 |
+
return mergeObject(target, source, optionsArgument)
|
58 |
+
}
|
59 |
+
}
|
60 |
+
|
61 |
+
deepmerge.all = function deepmergeAll (array, optionsArgument) {
|
62 |
+
if (!Array.isArray(array) || array.length < 2) {
|
63 |
+
throw new Error('first argument should be an array with at least two elements')
|
64 |
+
}
|
65 |
+
|
66 |
+
// we are sure there are at least 2 values, so it is safe to have no initial value
|
67 |
+
return array.reduce(function (prev, next) {
|
68 |
+
return deepmerge(prev, next, optionsArgument)
|
69 |
+
})
|
70 |
+
}
|
71 |
+
|
72 |
+
export default deepmerge
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
* Make fetch request and parse response JSON.
|
3 |
+
*
|
4 |
+
* @param url
|
5 |
+
* @param data
|
6 |
+
* @param config
|
7 |
+
*
|
8 |
+
* @return {Promise<Response>}
|
9 |
+
*/
|
10 |
+
export function post (url, data, config = {}) {
|
11 |
+
const preparedData = new FormData()
|
12 |
+
for (let key of Object.keys(data)) {
|
13 |
+
preparedData.set(key, data[key])
|
14 |
+
}
|
15 |
+
return fetch(url, {
|
16 |
+
method: 'post',
|
17 |
+
body: preparedData
|
18 |
+
}).then(response => {
|
19 |
+
return response.json()
|
20 |
+
}).then(data => {
|
21 |
+
if (data.status !== 200) {
|
22 |
+
throw data
|
23 |
+
}
|
24 |
+
return data
|
25 |
+
})
|
26 |
+
}
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
export default function (data) {
|
2 |
+
return JSON.parse(JSON.stringify(data))
|
3 |
+
}
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -5,7 +5,7 @@ Tags: RSS import, RSS aggregator, feed import, content curation, feed to post
|
|
5 |
Requires at least: 4.0 or higher
|
6 |
Tested up to: 5.2.2
|
7 |
Requires PHP: 5.4
|
8 |
-
Stable tag: 4.15
|
9 |
License: GPLv3
|
10 |
|
11 |
WP RSS Aggregator is the original & most popular WordPress solution for importing RSS feeds, auto-blogging, content curation & aggregation.
|
@@ -259,23 +259,22 @@ Our complete Knowledge Base with FAQs can be found [here](https://kb.wprssaggreg
|
|
259 |
|
260 |
== Changelog ==
|
261 |
|
262 |
-
= 4.15 (2019-
|
263 |
|
264 |
**Added**
|
265 |
-
- New
|
266 |
-
- New option to enable feed caching for better performance.
|
267 |
-
- New option to import source name and URL for each item individually.
|
268 |
-
- The custom feed now includes source info for every item.
|
269 |
|
270 |
**Changed**
|
271 |
-
-
|
272 |
-
-
|
273 |
-
- Added the current site URL to the custom feed URL option's label.
|
274 |
|
275 |
**Fixed**
|
276 |
-
-
|
277 |
-
-
|
278 |
-
- The custom feed
|
279 |
-
-
|
280 |
-
-
|
281 |
-
-
|
|
|
|
|
|
5 |
Requires at least: 4.0 or higher
|
6 |
Tested up to: 5.2.2
|
7 |
Requires PHP: 5.4
|
8 |
+
Stable tag: 4.15.1
|
9 |
License: GPLv3
|
10 |
|
11 |
WP RSS Aggregator is the original & most popular WordPress solution for importing RSS feeds, auto-blogging, content curation & aggregation.
|
259 |
|
260 |
== Changelog ==
|
261 |
|
262 |
+
= 4.15.1 (2019-08-14) =
|
263 |
|
264 |
**Added**
|
265 |
+
- New link to the custom feed in the "Custom Feed" settings page.
|
|
|
|
|
|
|
266 |
|
267 |
**Changed**
|
268 |
+
- Updated the logging system to no longer cause VaultPress to trigger false positive warnings.
|
269 |
+
- The date format in the custom feed now uses the "RFC3339 Extended" format.
|
|
|
270 |
|
271 |
**Fixed**
|
272 |
+
- Items with the same title were not being imported even when "Unique titles only" was turned off.
|
273 |
+
- Items with future dates where marked as "scheduled" by WordPress.
|
274 |
+
- The custom feed's "Content-Type" header was set for RSS 2.0 instead of Atom.
|
275 |
+
- Imported images were not being deleted from the media library when the imported item is deleted.
|
276 |
+
- PHP notice for "undefined index enclosure" when a feed cannot be fetched.
|
277 |
+
- Deprecation notice on PHP 7.2 or later for "each" function.
|
278 |
+
- Warnings when the `wprss_log` function is used incorrectly.
|
279 |
+
- PHP notice for "property of non-object" when using YoastSEO.
|
280 |
+
- After using the Templates add-on, images would continue to be imported after the add-on was deactivated.
|
@@ -3,6 +3,7 @@
|
|
3 |
namespace RebelCode\Wpra\Core\Database;
|
4 |
|
5 |
use RebelCode\Wpra\Core\Data\Collections\CollectionInterface;
|
|
|
6 |
|
7 |
/**
|
8 |
* Interface for objects that represent a database table.
|
@@ -50,6 +51,8 @@ interface TableInterface extends CollectionInterface
|
|
50 |
* Creates the table if it does not exist in the database.
|
51 |
*
|
52 |
* @since 4.13
|
|
|
|
|
53 |
*/
|
54 |
public function create();
|
55 |
|
@@ -57,6 +60,8 @@ interface TableInterface extends CollectionInterface
|
|
57 |
* Drops the table if it exists in the database.
|
58 |
*
|
59 |
* @since 4.13
|
|
|
|
|
60 |
*/
|
61 |
public function drop();
|
62 |
}
|
3 |
namespace RebelCode\Wpra\Core\Database;
|
4 |
|
5 |
use RebelCode\Wpra\Core\Data\Collections\CollectionInterface;
|
6 |
+
use RuntimeException;
|
7 |
|
8 |
/**
|
9 |
* Interface for objects that represent a database table.
|
51 |
* Creates the table if it does not exist in the database.
|
52 |
*
|
53 |
* @since 4.13
|
54 |
+
*
|
55 |
+
* @throws RuntimeException If the table could not be created.
|
56 |
*/
|
57 |
public function create();
|
58 |
|
60 |
* Drops the table if it exists in the database.
|
61 |
*
|
62 |
* @since 4.13
|
63 |
+
*
|
64 |
+
* @throws RuntimeException If the table could not be dropped.
|
65 |
*/
|
66 |
public function drop();
|
67 |
}
|
@@ -8,7 +8,6 @@ use RebelCode\Wpra\Core\Data\ArrayDataSet;
|
|
8 |
use RebelCode\Wpra\Core\Data\DataSetInterface;
|
9 |
use RebelCode\Wpra\Core\Data\MergedDataSet;
|
10 |
use RebelCode\Wpra\Core\Data\Wp\WpCptDataSet;
|
11 |
-
use SimplePie;
|
12 |
use WP_Post;
|
13 |
|
14 |
/**
|
@@ -62,14 +61,6 @@ class WpPostFeedSource extends WpCptDataSet
|
|
62 |
$meta = parent::createMetaDataSet($postOrId);
|
63 |
$url = isset($meta['url']) ? $meta['url'] : '';
|
64 |
|
65 |
-
if (!isset($meta['site_url']) && ($feed = wprss_fetch_feed($url)) instanceof SimplePie) {
|
66 |
-
$meta['site_url'] = $feed->get_permalink();
|
67 |
-
$meta['feed_image'] = $feed->get_image_url();
|
68 |
-
} else {
|
69 |
-
$meta['site_url'] = $url;
|
70 |
-
$meta['feed_image'] = '';
|
71 |
-
}
|
72 |
-
|
73 |
$defaults = $this->getDefaultMetaData($meta);
|
74 |
$fullMeta = new MergedDataSet($meta, $defaults);
|
75 |
|
8 |
use RebelCode\Wpra\Core\Data\DataSetInterface;
|
9 |
use RebelCode\Wpra\Core\Data\MergedDataSet;
|
10 |
use RebelCode\Wpra\Core\Data\Wp\WpCptDataSet;
|
|
|
11 |
use WP_Post;
|
12 |
|
13 |
/**
|
61 |
$meta = parent::createMetaDataSet($postOrId);
|
62 |
$url = isset($meta['url']) ? $meta['url'] : '';
|
63 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
$defaults = $this->getDefaultMetaData($meta);
|
65 |
$fullMeta = new MergedDataSet($meta, $defaults);
|
66 |
|
@@ -68,7 +68,7 @@ class RenderCustomFeedHandler
|
|
68 |
$protocol = (isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0');
|
69 |
header("$protocol 200 OK");
|
70 |
// Send content header and start ATOM output
|
71 |
-
header('Content-Type: application/
|
72 |
// Disabling caching
|
73 |
header('Cache-Control: no-cache, no-store, must-revalidate'); // HTTP 1.1.
|
74 |
header('Pragma: no-cache'); // HTTP 1.0.
|
68 |
$protocol = (isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0');
|
69 |
header("$protocol 200 OK");
|
70 |
// Send content header and start ATOM output
|
71 |
+
header('Content-Type: application/atom+xml');
|
72 |
// Disabling caching
|
73 |
header('Cache-Control: no-cache, no-store, must-revalidate'); // HTTP 1.1.
|
74 |
header('Pragma: no-cache'); // HTTP 1.0.
|
@@ -65,6 +65,10 @@ class RenderTemplateContentHandler
|
|
65 |
{
|
66 |
global $post;
|
67 |
|
|
|
|
|
|
|
|
|
68 |
// Check if current post type is a WPRA template
|
69 |
if ($post->post_type !== $this->cpt) {
|
70 |
return $content;
|
65 |
{
|
66 |
global $post;
|
67 |
|
68 |
+
if (!$post) {
|
69 |
+
return $content;
|
70 |
+
}
|
71 |
+
|
72 |
// Check if current post type is a WPRA template
|
73 |
if ($post->post_type !== $this->cpt) {
|
74 |
return $content;
|
@@ -36,18 +36,21 @@ class DeleteImagesHandler
|
|
36 |
*
|
37 |
* @since 4.14
|
38 |
*/
|
39 |
-
public function __invoke($
|
40 |
{
|
41 |
try {
|
42 |
-
$item = $this->importedItems[$
|
43 |
} catch (Exception $e) {
|
44 |
-
// Item
|
45 |
-
|
|
|
|
|
|
|
46 |
}
|
47 |
|
48 |
// Get the attachments
|
49 |
$attachments = get_children([
|
50 |
-
'post_parent' => $
|
51 |
'post_type' => 'attachment',
|
52 |
'post_mime_type' => 'image',
|
53 |
]);
|
36 |
*
|
37 |
* @since 4.14
|
38 |
*/
|
39 |
+
public function __invoke($postId)
|
40 |
{
|
41 |
try {
|
42 |
+
$item = $this->importedItems[$postId];
|
43 |
} catch (Exception $e) {
|
44 |
+
// Item may not be imported by WPRA or does not exist
|
45 |
+
// Here we do a manual post meta check, just to be safe
|
46 |
+
if (get_post_meta($postId, 'wprss_feed_id', true) === '') {
|
47 |
+
return;
|
48 |
+
}
|
49 |
}
|
50 |
|
51 |
// Get the attachments
|
52 |
$attachments = get_children([
|
53 |
+
'post_parent' => $postId,
|
54 |
'post_type' => 'attachment',
|
55 |
'post_mime_type' => 'image',
|
56 |
]);
|
@@ -1,54 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace RebelCode\Wpra\Core\Logger;
|
4 |
-
|
5 |
-
use Psr\Log\AbstractLogger;
|
6 |
-
use Psr\Log\LoggerInterface;
|
7 |
-
|
8 |
-
/**
|
9 |
-
* A PSR-3 logger decorator that conditionally delegates to an inner logger.
|
10 |
-
*
|
11 |
-
* @since 4.14
|
12 |
-
*/
|
13 |
-
class ConditionalLogger extends AbstractLogger
|
14 |
-
{
|
15 |
-
/**
|
16 |
-
* @since 4.14
|
17 |
-
*
|
18 |
-
* @var LoggerInterface
|
19 |
-
*/
|
20 |
-
protected $logger;
|
21 |
-
|
22 |
-
/**
|
23 |
-
* @since 4.14
|
24 |
-
*
|
25 |
-
* @var bool
|
26 |
-
*/
|
27 |
-
protected $enabled;
|
28 |
-
|
29 |
-
/**
|
30 |
-
* Constructor.
|
31 |
-
*
|
32 |
-
* @since 4.14
|
33 |
-
*
|
34 |
-
* @param LoggerInterface $logger The inner logger instance.
|
35 |
-
* @param bool $enabled The enabled flag: true to log using the inner logger, false to not log.
|
36 |
-
*/
|
37 |
-
public function __construct(LoggerInterface $logger, $enabled)
|
38 |
-
{
|
39 |
-
$this->logger = $logger;
|
40 |
-
$this->enabled = $enabled;
|
41 |
-
}
|
42 |
-
|
43 |
-
/**
|
44 |
-
* @inheritdoc
|
45 |
-
*
|
46 |
-
* @since 4.14
|
47 |
-
*/
|
48 |
-
public function log($level, $message, array $context = [])
|
49 |
-
{
|
50 |
-
if ($this->enabled) {
|
51 |
-
$this->logger->log($level, $message, $context);
|
52 |
-
}
|
53 |
-
}
|
54 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace RebelCode\Wpra\Core\Logger;
|
4 |
+
|
5 |
+
use Psr\Log\LoggerInterface;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Interface for a logger that can log messages for specific feed sources.
|
9 |
+
*
|
10 |
+
* @since 4.15.1
|
11 |
+
*/
|
12 |
+
interface FeedLoggerInterface extends LoggerInterface
|
13 |
+
{
|
14 |
+
/**
|
15 |
+
* Returns a copy of the logger instance that logs messages related to a particular feed source.
|
16 |
+
*
|
17 |
+
* @since 4.15.1
|
18 |
+
*
|
19 |
+
* @param int $feedId The ID of the feed source.
|
20 |
+
*
|
21 |
+
* @return LoggerInterface
|
22 |
+
*/
|
23 |
+
public function forFeedSource($feedId);
|
24 |
+
}
|
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace RebelCode\Wpra\Core\Logger;
|
4 |
+
|
5 |
+
use Psr\Log\NullLogger;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* A special null logger that is used when an error occurs and the original logger cannot be used.
|
9 |
+
*
|
10 |
+
* @since 4.15
|
11 |
+
*/
|
12 |
+
class ProblemLogger extends NullLogger implements LogReaderInterface, ClearableLoggerInterface
|
13 |
+
{
|
14 |
+
/**
|
15 |
+
* The error.
|
16 |
+
*
|
17 |
+
* @since 4.15
|
18 |
+
*
|
19 |
+
* @var string
|
20 |
+
*/
|
21 |
+
public $error;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Constructor.
|
25 |
+
*
|
26 |
+
* @since [*next-version*]
|
27 |
+
*
|
28 |
+
* @param string $error The error.
|
29 |
+
*/
|
30 |
+
public function __construct($error)
|
31 |
+
{
|
32 |
+
$this->error = $error;
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* @inheritdoc
|
37 |
+
*
|
38 |
+
* @since 4.15
|
39 |
+
*/
|
40 |
+
public function clearLogs()
|
41 |
+
{
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* @inheritdoc
|
46 |
+
*
|
47 |
+
* @since 4.15
|
48 |
+
*/
|
49 |
+
public function getLogs($num = null, $page = 1)
|
50 |
+
{
|
51 |
+
return [];
|
52 |
+
}
|
53 |
+
}
|
@@ -55,12 +55,12 @@ class WpdbLogger extends AbstractLogger implements ClearableLoggerInterface, Log
|
|
55 |
/**
|
56 |
* A mapping of log properties to table column names.
|
57 |
*
|
58 |
-
* @see COL_DATE
|
59 |
-
* @see COL_LEVEL
|
60 |
-
* @see COL_MESSAGE
|
61 |
-
*
|
62 |
* @since 4.13
|
63 |
*
|
|
|
|
|
|
|
|
|
64 |
* @var string[]
|
65 |
*/
|
66 |
protected $columns;
|
@@ -83,10 +83,12 @@ class WpdbLogger extends AbstractLogger implements ClearableLoggerInterface, Log
|
|
83 |
* @param array $columns A mapping of log data keys to column names. The `COL_*` constants may be used to
|
84 |
* map standard log properties and any non-standard properties may also be included
|
85 |
* to insert fixed values with the $extra parameter.
|
86 |
-
* @param array $extra A mapping of log properties and the values to insert for them.
|
87 |
-
*
|
88 |
-
*
|
89 |
-
*
|
|
|
|
|
90 |
*/
|
91 |
public function __construct(TableInterface $table, $columns = [], $extra = [])
|
92 |
{
|
@@ -203,16 +205,22 @@ class WpdbLogger extends AbstractLogger implements ClearableLoggerInterface, Log
|
|
203 |
}
|
204 |
|
205 |
if ($prop === static::LOG_LEVEL) {
|
206 |
-
return $level;
|
207 |
}
|
208 |
|
209 |
if ($prop === static::LOG_MESSAGE) {
|
210 |
return $message;
|
211 |
}
|
212 |
|
213 |
-
|
214 |
-
|
215 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
216 |
}
|
217 |
|
218 |
/**
|
55 |
/**
|
56 |
* A mapping of log properties to table column names.
|
57 |
*
|
|
|
|
|
|
|
|
|
58 |
* @since 4.13
|
59 |
*
|
60 |
+
* @see WpdbLogger::LOG_DATE
|
61 |
+
* @see WpdbLogger::LOG_LEVEL
|
62 |
+
* @see WpdbLogger::LOG_MESSAGE
|
63 |
+
*
|
64 |
* @var string[]
|
65 |
*/
|
66 |
protected $columns;
|
83 |
* @param array $columns A mapping of log data keys to column names. The `COL_*` constants may be used to
|
84 |
* map standard log properties and any non-standard properties may also be included
|
85 |
* to insert fixed values with the $extra parameter.
|
86 |
+
* @param array $extra A mapping of log properties and the values to insert for them. The values may be
|
87 |
+
* functions, which will be invoked during insertion. The function will receive the
|
88 |
+
* level, message and this $extra argument array as arguments.
|
89 |
+
* Be aware that the standard log properties, "id", "level", "message" and "date",
|
90 |
+
* will be overridden if those keys are given in this array.All non-standard data
|
91 |
+
* is stored in the table as VARCHAR with a limit of 100 characters.
|
92 |
*/
|
93 |
public function __construct(TableInterface $table, $columns = [], $extra = [])
|
94 |
{
|
205 |
}
|
206 |
|
207 |
if ($prop === static::LOG_LEVEL) {
|
208 |
+
return (string) $level;
|
209 |
}
|
210 |
|
211 |
if ($prop === static::LOG_MESSAGE) {
|
212 |
return $message;
|
213 |
}
|
214 |
|
215 |
+
if (!isset($this->extra[$prop])) {
|
216 |
+
return null;
|
217 |
+
}
|
218 |
+
|
219 |
+
if (is_callable($this->extra[$prop])) {
|
220 |
+
return call_user_func_array($this->extra[$prop], [$level, $message, $this->extra]);
|
221 |
+
}
|
222 |
+
|
223 |
+
return $this->extra[$prop];
|
224 |
}
|
225 |
|
226 |
/**
|
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace RebelCode\Wpra\Core\Logger;
|
4 |
+
|
5 |
+
use RebelCode\Wpra\Core\Database\TableInterface;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* A logger specific to WP RSS Aggregator.
|
9 |
+
*
|
10 |
+
* This logger is an extended version of the {@link WpdbLogger}, that stores the feed ID extra property internally.
|
11 |
+
* By implementing the {@link FeedLoggerInterface}, it is able to yield new instances that log messages spefific to
|
12 |
+
* that feed source.
|
13 |
+
*
|
14 |
+
* @since [*next-version*]
|
15 |
+
*
|
16 |
+
* @see WpdbLogger
|
17 |
+
* @see FeedLoggerInterface
|
18 |
+
*/
|
19 |
+
class WpraLogger extends WpdbLogger implements FeedLoggerInterface
|
20 |
+
{
|
21 |
+
/**
|
22 |
+
* The key of the extra feed ID column in the logs table.
|
23 |
+
*
|
24 |
+
* @since [*next-version*]
|
25 |
+
*/
|
26 |
+
CONST LOG_FEED_ID = 'feed_id';
|
27 |
+
|
28 |
+
/**
|
29 |
+
* The ID of the feed for which messages are being logged.
|
30 |
+
*
|
31 |
+
* @since [*next-version*]
|
32 |
+
*
|
33 |
+
* @var string
|
34 |
+
*/
|
35 |
+
protected $feedId;
|
36 |
+
|
37 |
+
/**
|
38 |
+
* @inheritdoc
|
39 |
+
*
|
40 |
+
* @since [*next-version*]
|
41 |
+
*/
|
42 |
+
public function __construct(TableInterface $table, $columns = [], $extra = [])
|
43 |
+
{
|
44 |
+
parent::__construct($table, $columns, $extra);
|
45 |
+
|
46 |
+
// Start without a feed ID
|
47 |
+
$this->feedId = '';
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* @inheritdoc
|
52 |
+
*
|
53 |
+
* @since [*next-version*]
|
54 |
+
*/
|
55 |
+
public function forFeedSource($feedId)
|
56 |
+
{
|
57 |
+
$instance = clone $this;
|
58 |
+
$instance->setFeedId($feedId);
|
59 |
+
|
60 |
+
return $instance;
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Sets the ID of the feed source for which messages will be logged by this instance.
|
65 |
+
*
|
66 |
+
* Also updates the callback for the extra feed ID table column.
|
67 |
+
*
|
68 |
+
* @since [*next-version*]
|
69 |
+
*
|
70 |
+
* @param int $feedId The ID of the feed source.
|
71 |
+
*/
|
72 |
+
protected function setFeedId($feedId)
|
73 |
+
{
|
74 |
+
$this->feedId = $feedId;
|
75 |
+
|
76 |
+
// The feed ID extra prop will lazily evaluate to the feed ID in this instance
|
77 |
+
$this->extra[static::LOG_FEED_ID] = function () {
|
78 |
+
return $this->feedId;
|
79 |
+
};
|
80 |
+
}
|
81 |
+
}
|
@@ -14,8 +14,6 @@ use RebelCode\Wpra\Core\Handlers\RegisterMetaBoxHandler;
|
|
14 |
use RebelCode\Wpra\Core\Handlers\RenderTemplateHandler;
|
15 |
use RebelCode\Wpra\Core\Importer\Images\FbImageContainer;
|
16 |
use RebelCode\Wpra\Core\Importer\Images\ImageContainer;
|
17 |
-
use RebelCode\Wpra\Core\Logger\ConditionalLogger;
|
18 |
-
use RebelCode\Wpra\Core\Logger\FeedLoggerDataSet;
|
19 |
use WPRSS_Help;
|
20 |
|
21 |
/**
|
@@ -55,55 +53,15 @@ class ImagesModule implements ModuleInterface
|
|
55 |
* @since 4.14
|
56 |
*/
|
57 |
'wpra/images/logging/logger' => function (ContainerInterface $c) {
|
|
|
|
|
|
|
|
|
|
|
58 |
// Get the original logger from WPRA's logger module, if available
|
59 |
-
|
60 |
? $c->get('wpra/logging/logger')
|
61 |
: new NullLogger();
|
62 |
-
|
63 |
-
// Get the decorator
|
64 |
-
$decorator = $c->get('wpra/images/logging/decorator');
|
65 |
-
|
66 |
-
// Decorate the original logger and return it
|
67 |
-
return $decorator($logger);
|
68 |
-
},
|
69 |
-
/*
|
70 |
-
* The decorator for decorating other loggers for image import logging.
|
71 |
-
*
|
72 |
-
* @since 4.14
|
73 |
-
*/
|
74 |
-
'wpra/images/logging/decorator' => function (ContainerInterface $c) {
|
75 |
-
return function($logger) use ($c) {
|
76 |
-
return new ConditionalLogger($logger, $c->get('wpra/images/logging/enabled'));
|
77 |
-
};
|
78 |
-
},
|
79 |
-
/*
|
80 |
-
* The data set that contains the image import logger instances for each feed source.
|
81 |
-
*
|
82 |
-
* @since 4.14
|
83 |
-
*/
|
84 |
-
'wpra/images/logging/feed_logger_dataset' => function (ContainerInterface $c) {
|
85 |
-
return new FeedLoggerDataSet($c->get('wpra/images/logging/feed_logger_factory'));
|
86 |
-
},
|
87 |
-
/*
|
88 |
-
* The factory that creates image importing logger instances for specific feeds.
|
89 |
-
*
|
90 |
-
* @since 4.14
|
91 |
-
*/
|
92 |
-
'wpra/images/logging/feed_logger_factory' => function (ContainerInterface $c) {
|
93 |
-
$factory = $c->has('wpra/logging/feed_logger_factory')
|
94 |
-
? $c->get('wpra/logging/feed_logger_factory')
|
95 |
-
: null;
|
96 |
-
|
97 |
-
if ($factory === null) {
|
98 |
-
return $c->get('wpra/images/logging/logger');
|
99 |
-
}
|
100 |
-
|
101 |
-
// Get the decorator
|
102 |
-
$decorator = $c->get('wpra/images/logging/decorator');
|
103 |
-
|
104 |
-
return function($feedId) use ($c, $factory, $decorator) {
|
105 |
-
return $decorator($factory($feedId));
|
106 |
-
};
|
107 |
},
|
108 |
/*
|
109 |
* Whether the feature to import featured images is enabled or not.
|
@@ -402,7 +360,7 @@ class ImagesModule implements ModuleInterface
|
|
402 |
}
|
403 |
|
404 |
// Show the developer images meta box for feed items, if the developer filter is enabled
|
405 |
-
if (
|
406 |
add_action('add_meta_boxes', $c->get('wpra/images/items/dev_meta_box/handler'));
|
407 |
}
|
408 |
|
14 |
use RebelCode\Wpra\Core\Handlers\RenderTemplateHandler;
|
15 |
use RebelCode\Wpra\Core\Importer\Images\FbImageContainer;
|
16 |
use RebelCode\Wpra\Core\Importer\Images\ImageContainer;
|
|
|
|
|
17 |
use WPRSS_Help;
|
18 |
|
19 |
/**
|
53 |
* @since 4.14
|
54 |
*/
|
55 |
'wpra/images/logging/logger' => function (ContainerInterface $c) {
|
56 |
+
// If image logging is disabled, return a null logger
|
57 |
+
if (!$c->get('wpra/images/logging/enabled')) {
|
58 |
+
return new NullLogger();
|
59 |
+
}
|
60 |
+
|
61 |
// Get the original logger from WPRA's logger module, if available
|
62 |
+
return $c->has('wpra/logging/logger')
|
63 |
? $c->get('wpra/logging/logger')
|
64 |
: new NullLogger();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
},
|
66 |
/*
|
67 |
* Whether the feature to import featured images is enabled or not.
|
360 |
}
|
361 |
|
362 |
// Show the developer images meta box for feed items, if the developer filter is enabled
|
363 |
+
if (wpra_is_dev_mode()) {
|
364 |
add_action('add_meta_boxes', $c->get('wpra/images/items/dev_meta_box/handler'));
|
365 |
}
|
366 |
|
@@ -2,7 +2,9 @@
|
|
2 |
|
3 |
namespace RebelCode\Wpra\Core\Modules;
|
4 |
|
|
|
5 |
use Psr\Container\ContainerInterface;
|
|
|
6 |
use RebelCode\Wpra\Core\Database\NullTable;
|
7 |
use RebelCode\Wpra\Core\Database\WpdbTable;
|
8 |
use RebelCode\Wpra\Core\Handlers\Logger\ClearLogHandler;
|
@@ -11,9 +13,9 @@ use RebelCode\Wpra\Core\Handlers\Logger\RenderLogHandler;
|
|
11 |
use RebelCode\Wpra\Core\Handlers\Logger\SaveLogOptionsHandler;
|
12 |
use RebelCode\Wpra\Core\Handlers\Logger\TruncateLogsCronHandler;
|
13 |
use RebelCode\Wpra\Core\Handlers\ScheduleCronJobHandler;
|
14 |
-
use RebelCode\Wpra\Core\Logger\
|
15 |
-
use RebelCode\Wpra\Core\Logger\FeedLoggerDataSet;
|
16 |
use RebelCode\Wpra\Core\Logger\WpdbLogger;
|
|
|
17 |
|
18 |
/**
|
19 |
* A module that adds a logger to WP RSS Aggregator.
|
@@ -44,22 +46,25 @@ class LoggerModule implements ModuleInterface
|
|
44 |
* @since 4.13
|
45 |
*/
|
46 |
'wpra/logging/logger' => function (ContainerInterface $c) {
|
47 |
-
return
|
48 |
-
$c->get('wpra/logging/
|
49 |
-
|
50 |
-
);
|
51 |
},
|
52 |
/*
|
53 |
* The WPDB logger instance.
|
54 |
*
|
55 |
-
* @since 4.
|
56 |
*/
|
57 |
-
'wpra/logging/
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
|
|
|
|
|
|
|
|
63 |
},
|
64 |
/*
|
65 |
* The log reader instance.
|
@@ -67,7 +72,7 @@ class LoggerModule implements ModuleInterface
|
|
67 |
* @since 4.14
|
68 |
*/
|
69 |
'wpra/logging/reader' => function (ContainerInterface $c) {
|
70 |
-
return $c->get('wpra/logging/
|
71 |
},
|
72 |
/*
|
73 |
* The log clearer instance.
|
@@ -75,7 +80,7 @@ class LoggerModule implements ModuleInterface
|
|
75 |
* @since 4.14
|
76 |
*/
|
77 |
'wpra/logging/clearer' => function (ContainerInterface $c) {
|
78 |
-
return $c->get('wpra/logging/
|
79 |
},
|
80 |
/*
|
81 |
* The table where logs are stored.
|
@@ -146,34 +151,7 @@ class LoggerModule implements ModuleInterface
|
|
146 |
* @since 4.13
|
147 |
*/
|
148 |
'wpra/logging/log_table_extra' => function () {
|
149 |
-
return [
|
150 |
-
'feed_id' => '',
|
151 |
-
];
|
152 |
-
},
|
153 |
-
/*
|
154 |
-
* The data set that contains the logger instances for each feed source.
|
155 |
-
*
|
156 |
-
* @since 4.13
|
157 |
-
*/
|
158 |
-
'wpra/logging/feed_logger_dataset' => function (ContainerInterface $c) {
|
159 |
-
return new FeedLoggerDataSet($c->get('wpra/logging/feed_logger_factory'));
|
160 |
-
},
|
161 |
-
/*
|
162 |
-
* The factory that creates logger instances for specific feeds.
|
163 |
-
*
|
164 |
-
* @since 4.13
|
165 |
-
*/
|
166 |
-
'wpra/logging/feed_logger_factory' => function (ContainerInterface $c) {
|
167 |
-
return function ($feedId) use ($c) {
|
168 |
-
return new ConditionalLogger(
|
169 |
-
new WpdbLogger(
|
170 |
-
$c->get('wpra/logging/log_table'),
|
171 |
-
$c->get('wpra/logging/log_table_columns'),
|
172 |
-
['feed_id' => $feedId]
|
173 |
-
),
|
174 |
-
$c->get('wpra/logging/enabled')
|
175 |
-
);
|
176 |
-
};
|
177 |
},
|
178 |
/*
|
179 |
* The scheduler for the log truncation cron job.
|
2 |
|
3 |
namespace RebelCode\Wpra\Core\Modules;
|
4 |
|
5 |
+
use Exception;
|
6 |
use Psr\Container\ContainerInterface;
|
7 |
+
use Psr\Log\NullLogger;
|
8 |
use RebelCode\Wpra\Core\Database\NullTable;
|
9 |
use RebelCode\Wpra\Core\Database\WpdbTable;
|
10 |
use RebelCode\Wpra\Core\Handlers\Logger\ClearLogHandler;
|
13 |
use RebelCode\Wpra\Core\Handlers\Logger\SaveLogOptionsHandler;
|
14 |
use RebelCode\Wpra\Core\Handlers\Logger\TruncateLogsCronHandler;
|
15 |
use RebelCode\Wpra\Core\Handlers\ScheduleCronJobHandler;
|
16 |
+
use RebelCode\Wpra\Core\Logger\ProblemLogger;
|
|
|
17 |
use RebelCode\Wpra\Core\Logger\WpdbLogger;
|
18 |
+
use RebelCode\Wpra\Core\Logger\WpraLogger;
|
19 |
|
20 |
/**
|
21 |
* A module that adds a logger to WP RSS Aggregator.
|
46 |
* @since 4.13
|
47 |
*/
|
48 |
'wpra/logging/logger' => function (ContainerInterface $c) {
|
49 |
+
return $c->get('wpra/logging/enabled')
|
50 |
+
? $c->get('wpra/logging/main_logger')
|
51 |
+
: new NullLogger();
|
|
|
52 |
},
|
53 |
/*
|
54 |
* The WPDB logger instance.
|
55 |
*
|
56 |
+
* @since 4.15.1
|
57 |
*/
|
58 |
+
'wpra/logging/main_logger' => function (ContainerInterface $c) {
|
59 |
+
try {
|
60 |
+
return new WpraLogger(
|
61 |
+
$c->get('wpra/logging/log_table'),
|
62 |
+
$c->get('wpra/logging/log_table_columns'),
|
63 |
+
$c->get('wpra/logging/log_table_extra')
|
64 |
+
);
|
65 |
+
} catch (Exception $exception) {
|
66 |
+
return new ProblemLogger($exception->getMessage());
|
67 |
+
}
|
68 |
},
|
69 |
/*
|
70 |
* The log reader instance.
|
72 |
* @since 4.14
|
73 |
*/
|
74 |
'wpra/logging/reader' => function (ContainerInterface $c) {
|
75 |
+
return $c->get('wpra/logging/main_logger');
|
76 |
},
|
77 |
/*
|
78 |
* The log clearer instance.
|
80 |
* @since 4.14
|
81 |
*/
|
82 |
'wpra/logging/clearer' => function (ContainerInterface $c) {
|
83 |
+
return $c->get('wpra/logging/main_logger');
|
84 |
},
|
85 |
/*
|
86 |
* The table where logs are stored.
|
151 |
* @since 4.13
|
152 |
*/
|
153 |
'wpra/logging/log_table_extra' => function () {
|
154 |
+
return [];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
155 |
},
|
156 |
/*
|
157 |
* The scheduler for the log truncation cron job.
|
@@ -0,0 +1,123 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace RebelCode\Wpra\Core\Modules;
|
4 |
+
|
5 |
+
use Psr\Container\ContainerInterface;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* The module that adds Lorem's embeds in WP RSS Aggregator.
|
9 |
+
*
|
10 |
+
* @since 4.15.1
|
11 |
+
*/
|
12 |
+
class LoremModule implements ModuleInterface
|
13 |
+
{
|
14 |
+
/**
|
15 |
+
* @inheritdoc
|
16 |
+
*
|
17 |
+
* @since 4.15.1
|
18 |
+
*/
|
19 |
+
public function run(ContainerInterface $c)
|
20 |
+
{
|
21 |
+
// Registers the script on the admin-side
|
22 |
+
add_action('admin_init', $c->get('wpra/lorem/script/register_fn'));
|
23 |
+
|
24 |
+
// Enqueues the script on the admin-side
|
25 |
+
add_action('wprss_admin_exclusive_scripts_styles', $c->get('wpra/lorem/script/enqueue_fn'));
|
26 |
+
|
27 |
+
// Adds the Lorem embed on the "Help & Support" page, after the page title.
|
28 |
+
add_action('wpra/help_page/after_title', function () use ($c) {
|
29 |
+
echo $c->get('wpra/lorem/help_page/html');
|
30 |
+
});
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* @inheritdoc
|
35 |
+
*
|
36 |
+
* @since 4.15.1
|
37 |
+
*/
|
38 |
+
public function getFactories()
|
39 |
+
{
|
40 |
+
return [
|
41 |
+
/*
|
42 |
+
* The key (or "handle") for the Lorem embed script.
|
43 |
+
*
|
44 |
+
* @since 4.15.1
|
45 |
+
*/
|
46 |
+
'wpra/lorem/script/key' => function (ContainerInterface $c) {
|
47 |
+
return 'lorem-embed-script';
|
48 |
+
},
|
49 |
+
/*
|
50 |
+
* The URL of the Lorem embed script.
|
51 |
+
*
|
52 |
+
* @since 4.15.1
|
53 |
+
*/
|
54 |
+
'wpra/lorem/script/url' => function (ContainerInterface $c) {
|
55 |
+
return 'https://embed.asklorem.com/load.js';
|
56 |
+
},
|
57 |
+
/*
|
58 |
+
* The function that registers the Lorem embed script.
|
59 |
+
*
|
60 |
+
* @since 4.15.1
|
61 |
+
*/
|
62 |
+
'wpra/lorem/script/register_fn' => function (ContainerInterface $c) {
|
63 |
+
$scriptKey = $c->get('wpra/lorem/script/key');
|
64 |
+
$scriptUrl = $c->get('wpra/lorem/script/url');
|
65 |
+
|
66 |
+
return function () use ($scriptKey, $scriptUrl) {
|
67 |
+
wp_register_script($scriptKey, $scriptUrl, [], null, true);
|
68 |
+
};
|
69 |
+
},
|
70 |
+
/*
|
71 |
+
* The function that enqueues the Lorem embed script.
|
72 |
+
*
|
73 |
+
* @since 4.15.1
|
74 |
+
*/
|
75 |
+
'wpra/lorem/script/enqueue_fn' => function (ContainerInterface $c) {
|
76 |
+
$scriptKey = $c->get('wpra/lorem/script/key');
|
77 |
+
|
78 |
+
return function () use ($scriptKey) {
|
79 |
+
return wp_enqueue_script($scriptKey);
|
80 |
+
};
|
81 |
+
},
|
82 |
+
/*
|
83 |
+
* The Lorem item to show on the "More features" page.
|
84 |
+
*
|
85 |
+
* @since 4.15.1
|
86 |
+
*/
|
87 |
+
'wpra/lorem/more_features_page/item' => function (ContainerInterface $c) {
|
88 |
+
return [
|
89 |
+
'type' => 'lorem',
|
90 |
+
];
|
91 |
+
},
|
92 |
+
/**
|
93 |
+
* The HTML to add on the "Help & Support" page.
|
94 |
+
*
|
95 |
+
* @since 4.15.1
|
96 |
+
*/
|
97 |
+
'wpra/lorem/help_page/html' => function (ContainerInterface $c) {
|
98 |
+
return '<div data-lorem-embed-id="rss-help-and-support"></div>';
|
99 |
+
},
|
100 |
+
];
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* @inheritdoc
|
105 |
+
*
|
106 |
+
* @since 4.15.1
|
107 |
+
*/
|
108 |
+
public function getExtensions()
|
109 |
+
{
|
110 |
+
return [
|
111 |
+
/*
|
112 |
+
* Extends the items on the "More Features" page to add the Lorem item.
|
113 |
+
*
|
114 |
+
* @since 4.15.1
|
115 |
+
*/
|
116 |
+
'wpra/upsell/items' => function (ContainerInterface $c, $items) {
|
117 |
+
$items[] = $c->get('wpra/lorem/more_features_page/item');
|
118 |
+
|
119 |
+
return $items;
|
120 |
+
},
|
121 |
+
];
|
122 |
+
}
|
123 |
+
}
|
@@ -0,0 +1,284 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace RebelCode\Wpra\Core\Modules;
|
4 |
+
|
5 |
+
use Psr\Container\ContainerInterface;
|
6 |
+
use RebelCode\Wpra\Core\Handlers\RegisterSubMenuPageHandler;
|
7 |
+
use RebelCode\Wpra\Core\Util\NullFunction;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* The module that adds upselling of the addons and other services within WP RSS Aggregator's UI.
|
11 |
+
*
|
12 |
+
* Specifically, it adds UI elements such as the the "More Features" page, and the upselling of the addons in the
|
13 |
+
* "Share The Love" metabox in the Feed Source new/edit page.
|
14 |
+
*
|
15 |
+
* @since 4.15.1
|
16 |
+
*/
|
17 |
+
class UpsellModule implements ModuleInterface
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* @inheritdoc
|
21 |
+
*
|
22 |
+
* @since 4.15.1
|
23 |
+
*/
|
24 |
+
public function run(ContainerInterface $c)
|
25 |
+
{
|
26 |
+
// Registers the "More Features" menu and page
|
27 |
+
add_action(
|
28 |
+
'admin_menu',
|
29 |
+
$c->get('wpra/upsell/more_features_page/register'),
|
30 |
+
$c->get('wpra/upsell/more_features_page/menu_pos')
|
31 |
+
);
|
32 |
+
|
33 |
+
// Add the add-ons list to the "Share the Love" metabox
|
34 |
+
add_action('wpra_share_the_love_metabox', $c->get('wpra/upsell/share_the_love/render_addon_list_fn'));
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* @inheritdoc
|
39 |
+
*
|
40 |
+
* @since 4.15.1
|
41 |
+
*/
|
42 |
+
public function getFactories()
|
43 |
+
{
|
44 |
+
return array(
|
45 |
+
/*
|
46 |
+
* The items to upsell.
|
47 |
+
*
|
48 |
+
* @since 4.15.1
|
49 |
+
*/
|
50 |
+
'wpra/upsell/items' => function (ContainerInterface $c) {
|
51 |
+
$f2pBaseName = 'wp-rss-feed-to-post/wp-rss-feed-to-post.php';
|
52 |
+
$ftrBaseName = 'wp-rss-full-text-feeds/wp-rss-full-text.php';
|
53 |
+
$tmpBaseName = 'wp-rss-templates/wp-rss-templates.php';
|
54 |
+
$kwfBaseName = 'wp-rss-keyword-filtering/wp-rss-keyword-filtering.php';
|
55 |
+
$catBaseName = 'wp-rss-categories/wp-rss-categories.php';
|
56 |
+
$waiBaseName = 'wp-rss-wordai/wp-rss-wordai.php';
|
57 |
+
$spcBaseName = 'wp-rss-spinnerchief/wp-rss-spinnerchief.php';
|
58 |
+
|
59 |
+
return apply_filters('wprss_extra_addons', [
|
60 |
+
[
|
61 |
+
'code' => 'ftp',
|
62 |
+
'type' => 'add-on',
|
63 |
+
'title' => 'Feed to Post',
|
64 |
+
'desc' => __(
|
65 |
+
'An advanced importer that lets you import RSS feed items as WordPress posts or any other custom post type. You can use it to populate a website in minutes (auto-blog). This is the most popular and feature-filled extension.',
|
66 |
+
'wprss'
|
67 |
+
),
|
68 |
+
'url' => 'https://www.wprssaggregator.com/extension/feed-to-post/',
|
69 |
+
'state' => wpra_get_plugin_state($f2pBaseName),
|
70 |
+
'activateUrl' => wpra_get_activate_plugin_url($f2pBaseName),
|
71 |
+
],
|
72 |
+
[
|
73 |
+
'code' => 'ftr',
|
74 |
+
'type' => 'add-on',
|
75 |
+
'title' => 'Full Text RSS Feeds',
|
76 |
+
'desc' => __(
|
77 |
+
'An extension for Feed to Post that adds connectivity to our premium full text service, which allows you to import the full post content for an unlimited number of feed items per feed source, even when the feed itself doesn\'t provide it',
|
78 |
+
'wprss'
|
79 |
+
),
|
80 |
+
'url' => 'https://www.wprssaggregator.com/extension/full-text-rss-feeds/',
|
81 |
+
'state' => wpra_get_plugin_state($ftrBaseName),
|
82 |
+
'activateUrl' => wpra_get_activate_plugin_url($ftrBaseName),
|
83 |
+
],
|
84 |
+
[
|
85 |
+
'code' => 'tmp',
|
86 |
+
'type' => 'add-on',
|
87 |
+
'title' => 'Templates',
|
88 |
+
'desc' => __(
|
89 |
+
'Premium templates to display images and excerpts in various ways. It includes a fully customisable grid template and a list template that includes excerpts & thumbnails, both of which will spruce up your site!',
|
90 |
+
'wprss'
|
91 |
+
),
|
92 |
+
'url' => 'https://www.wprssaggregator.com/extension/templates/',
|
93 |
+
'state' => wpra_get_plugin_state($tmpBaseName),
|
94 |
+
'activateUrl' => wpra_get_activate_plugin_url($tmpBaseName),
|
95 |
+
],
|
96 |
+
[
|
97 |
+
'code' => 'kf',
|
98 |
+
'type' => 'add-on',
|
99 |
+
'title' => 'Keyword Filtering',
|
100 |
+
'desc' => __(
|
101 |
+
'Filters the feed items to be imported based on your own keywords, key phrases, or tags; you only get the items you\'re interested in. It is compatible with all other add-ons.',
|
102 |
+
'wprss'
|
103 |
+
),
|
104 |
+
'url' => 'https://www.wprssaggregator.com/extension/keyword-filtering/',
|
105 |
+
'state' => wpra_get_plugin_state($kwfBaseName),
|
106 |
+
'activateUrl' => wpra_get_activate_plugin_url($kwfBaseName),
|
107 |
+
],
|
108 |
+
[
|
109 |
+
'code' => 'cat',
|
110 |
+
'type' => 'add-on',
|
111 |
+
'title' => 'Source Categories',
|
112 |
+
'desc' => __(
|
113 |
+
'Categorises your feed sources and allows you to display feed items from a particular category within your site using the shortcode parameters.',
|
114 |
+
'wprss'
|
115 |
+
),
|
116 |
+
'url' => 'https://www.wprssaggregator.com/extension/categories/',
|
117 |
+
'state' => wpra_get_plugin_state($catBaseName),
|
118 |
+
'activateUrl' => wpra_get_activate_plugin_url($catBaseName),
|
119 |
+
],
|
120 |
+
[
|
121 |
+
'code' => 'wai',
|
122 |
+
'type' => 'add-on',
|
123 |
+
'title' => 'WordAi',
|
124 |
+
'desc' => __(
|
125 |
+
'An extension for Feed to Post that allows you to integrate the WordAi article spinner so that the imported content is both completely unique and completely readable.',
|
126 |
+
'wprss'
|
127 |
+
),
|
128 |
+
'url' => 'https://www.wprssaggregator.com/extension/wordai/',
|
129 |
+
'state' => wpra_get_plugin_state($waiBaseName),
|
130 |
+
'activateUrl' => wpra_get_activate_plugin_url($waiBaseName),
|
131 |
+
],
|
132 |
+
[
|
133 |
+
'code' => 'spc',
|
134 |
+
'type' => 'add-on',
|
135 |
+
'title' => 'SpinnerChief',
|
136 |
+
'desc' => __(
|
137 |
+
'An extension for Feed to Post that allows you to integrate the SpinnerChief article spinner so that the imported content is both completely unique and completely readable.',
|
138 |
+
'wprss'
|
139 |
+
),
|
140 |
+
'url' => 'https://www.wprssaggregator.com/extension/spinnerchief/',
|
141 |
+
'state' => wpra_get_plugin_state($spcBaseName),
|
142 |
+
'activateUrl' => wpra_get_activate_plugin_url($spcBaseName),
|
143 |
+
],
|
144 |
+
]
|
145 |
+
);
|
146 |
+
},
|
147 |
+
/*
|
148 |
+
* The function that registers the "More Features" page and menu.
|
149 |
+
*
|
150 |
+
* @since 4.15.1
|
151 |
+
*/
|
152 |
+
'wpra/upsell/more_features_page/register' => function (ContainerInterface $c) {
|
153 |
+
return new RegisterSubMenuPageHandler([
|
154 |
+
'parent' => $c->get('wpra/upsell/more_features_page/parent'),
|
155 |
+
'slug' => $c->get('wpra/upsell/more_features_page/slug'),
|
156 |
+
'page_title' => $c->get('wpra/upsell/more_features_page/title'),
|
157 |
+
'menu_label' => $c->get('wpra/upsell/more_features_page/menu_label'),
|
158 |
+
'capability' => $c->get('wpra/upsell/more_features_page/capability'),
|
159 |
+
'callback' => $c->get('wpra/upsell/more_features_page/render_fn'),
|
160 |
+
]);
|
161 |
+
},
|
162 |
+
/*
|
163 |
+
* The slug of the "More Features"'s parent page.
|
164 |
+
*
|
165 |
+
* @since 4.15.1
|
166 |
+
*/
|
167 |
+
'wpra/upsell/more_features_page/parent' => function () {
|
168 |
+
return 'edit.php?post_type=wprss_feed';
|
169 |
+
},
|
170 |
+
/*
|
171 |
+
* The slug of the "More Features" page.
|
172 |
+
*
|
173 |
+
* @since 4.15.1
|
174 |
+
*/
|
175 |
+
'wpra/upsell/more_features_page/slug' => function () {
|
176 |
+
return 'wprss_addons';
|
177 |
+
},
|
178 |
+
/*
|
179 |
+
* The title for the "More Features" page.
|
180 |
+
*
|
181 |
+
* @since 4.15.1
|
182 |
+
*/
|
183 |
+
'wpra/upsell/more_features_page/title' => function () {
|
184 |
+
return __('More Features', 'wprss');
|
185 |
+
},
|
186 |
+
/*
|
187 |
+
* The required admin capability for viewing the "More Features" page.
|
188 |
+
*
|
189 |
+
* @since 4.15.1
|
190 |
+
*/
|
191 |
+
'wpra/upsell/more_features_page/capability' => function () {
|
192 |
+
return apply_filters('wprss_capability', 'manage_feed_settings');
|
193 |
+
},
|
194 |
+
/*
|
195 |
+
* The label for the "More Features" menu.
|
196 |
+
*
|
197 |
+
* @since 4.15.1
|
198 |
+
*/
|
199 |
+
'wpra/upsell/more_features_page/menu_label' => function (ContainerInterface $c) {
|
200 |
+
return $c->get('wpra/upsell/more_features_page/title') . $c->get('wpra/upsell/more_features_page/menu_icon');
|
201 |
+
},
|
202 |
+
/*
|
203 |
+
* The icon for the "More Features" menu.
|
204 |
+
*
|
205 |
+
* @since 4.15.1
|
206 |
+
*/
|
207 |
+
'wpra/upsell/more_features_page/menu_icon' => function () {
|
208 |
+
return '<span class="dashicons dashicons-star-filled wprss-more-features-glyph"></span>';
|
209 |
+
},
|
210 |
+
/*
|
211 |
+
* The position of the "More Features" menu.
|
212 |
+
*
|
213 |
+
* @since 4.15.1
|
214 |
+
*/
|
215 |
+
'wpra/upsell/more_features_page/menu_pos' => function () {
|
216 |
+
return 50;
|
217 |
+
},
|
218 |
+
/*
|
219 |
+
* The function to use for rendering the "More Features" page.
|
220 |
+
*
|
221 |
+
* @since 4.15.1
|
222 |
+
*/
|
223 |
+
'wpra/upsell/more_features_page/render_fn' => function (ContainerInterface $c) {
|
224 |
+
if (!$c->has('wpra/twig/collection')) {
|
225 |
+
return new NullFunction();
|
226 |
+
}
|
227 |
+
|
228 |
+
return function () use ($c) {
|
229 |
+
$collection = $c->get('wpra/twig/collection');
|
230 |
+
$template = $collection[$c->get('wpra/upsell/more_features_page/template')];
|
231 |
+
$items = $c->get('wpra/upsell/items');
|
232 |
+
|
233 |
+
echo $template->render(['items' => $items]);
|
234 |
+
};
|
235 |
+
},
|
236 |
+
/*
|
237 |
+
* The path to the template to use when rendering the "More Features" page.
|
238 |
+
*
|
239 |
+
* @since 4.15.1
|
240 |
+
*/
|
241 |
+
'wpra/upsell/more_features_page/template' => function () {
|
242 |
+
return 'admin/upsell/more-features-page/main.twig';
|
243 |
+
},
|
244 |
+
/*
|
245 |
+
* The path to the template to use when rendering the add-on list in the "Share the Love" metabox.
|
246 |
+
*
|
247 |
+
* @since 4.15.1
|
248 |
+
*/
|
249 |
+
'wpra/upsell/share_the_love/addon_list_template' => function () {
|
250 |
+
return 'admin/upsell/add-on-list.twig';
|
251 |
+
},
|
252 |
+
/*
|
253 |
+
* The function for rendering the add-on list in the "Share the Love" metabox.
|
254 |
+
*
|
255 |
+
* @since 4.15.1
|
256 |
+
*/
|
257 |
+
'wpra/upsell/share_the_love/render_addon_list_fn' => function (ContainerInterface $c) {
|
258 |
+
if (!$c->has('wpra/twig/collection')) {
|
259 |
+
return new NullFunction();
|
260 |
+
}
|
261 |
+
|
262 |
+
return function () use ($c) {
|
263 |
+
$collection = $c->get('wpra/twig/collection');
|
264 |
+
$template = $collection[$c->get('wpra/upsell/share_the_love/addon_list_template')];
|
265 |
+
$addons = array_filter($c->get('wpra/upsell/items'), function ($item) {
|
266 |
+
return $item['type'] === 'add-on';
|
267 |
+
});
|
268 |
+
|
269 |
+
echo $template->render(['addons' => $addons]);
|
270 |
+
};
|
271 |
+
},
|
272 |
+
);
|
273 |
+
}
|
274 |
+
|
275 |
+
/**
|
276 |
+
* @inheritdoc
|
277 |
+
*
|
278 |
+
* @since 4.15.1
|
279 |
+
*/
|
280 |
+
public function getExtensions()
|
281 |
+
{
|
282 |
+
return [];
|
283 |
+
}
|
284 |
+
}
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace RebelCode\Wpra\Core\Util;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* A utility class for a null (no-op) function.
|
7 |
+
*
|
8 |
+
* @since 4.15.1
|
9 |
+
*/
|
10 |
+
class NullFunction
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* @inheritdoc
|
14 |
+
*
|
15 |
+
* @since 4.15.1
|
16 |
+
*/
|
17 |
+
public function __invoke()
|
18 |
+
{
|
19 |
+
}
|
20 |
+
}
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<p><strong>{% trans 'Add functionality with our premium extensions:' %}</strong></p>
|
2 |
+
{% if addons|length > 0 %}
|
3 |
+
<ul class="add-on-list">
|
4 |
+
{% for addon in addons %}
|
5 |
+
<li class="add-on add-on-code-{{ addon.code }}">
|
6 |
+
<a href="{{ addon.url }}" target="_blank">{{ addon.title }}</a>
|
7 |
+
</li>
|
8 |
+
{% endfor %}
|
9 |
+
</ul>
|
10 |
+
{% endif %}
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% set activeClass = item.isActive ? 'add-on-active' : '' %}
|
2 |
+
{% set codeClass = 'add-on-code-' ~ item.code %}
|
3 |
+
|
4 |
+
|
5 |
+
<div class="add-on wp-box {{ activeClass }} {{ codeClass }}">
|
6 |
+
<div class="inner">
|
7 |
+
<h3>
|
8 |
+
<a target="_blank" href="{{ item.url|e('html_attr') }}">
|
9 |
+
{{ item.title }}
|
10 |
+
</a>
|
11 |
+
</h3>
|
12 |
+
<p>{{ item.desc }}</p>
|
13 |
+
</div>
|
14 |
+
<div class="footer">
|
15 |
+
{% if item.state == 2 %}
|
16 |
+
<a class="button button-disabled">
|
17 |
+
<span class="wprss-sprite-tick"></span>
|
18 |
+
{% trans "Installed!" %}
|
19 |
+
</a>
|
20 |
+
{% elseif item.state == 1 %}
|
21 |
+
<a class="button" href="{{ item.activateUrl|raw }}">
|
22 |
+
{% trans "Activate" %}
|
23 |
+
</a>
|
24 |
+
{% else %}
|
25 |
+
<a target="_blank" href="{{ item.url }}" class="button">
|
26 |
+
{% autoescape 'html' %}
|
27 |
+
{% trans "Purchase & Install" %}
|
28 |
+
{% endautoescape %}
|
29 |
+
</a>
|
30 |
+
{% endif %}
|
31 |
+
</div>
|
32 |
+
</div>
|
@@ -0,0 +1,2 @@
|
|
|
|
|
1 |
+
<div data-lorem-embed-id="rss-add-ons" style="padding-bottom: 0px;" class="add-on wp-box lorem">
|
2 |
+
</div>
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div class="wrap">
|
2 |
+
<h2>{% trans "More Features With Our Premium Add-Ons" %}</h2>
|
3 |
+
<p>
|
4 |
+
{% trans %}
|
5 |
+
The following addons are available to increase the functionality of the WP RSS Aggregator plugin.
|
6 |
+
{% endtrans %}
|
7 |
+
<p>
|
8 |
+
<p>
|
9 |
+
{% trans %}
|
10 |
+
Check out our pricing plans for bigger savings!
|
11 |
+
{% endtrans %}
|
12 |
+
</p>
|
13 |
+
|
14 |
+
<div id="add-ons" class="clearfix">
|
15 |
+
<div class="add-on-group clearfix">
|
16 |
+
{% for item in items %}
|
17 |
+
{{ include('admin/upsell/more-features-page/' ~ item.type ~ '.twig') }}
|
18 |
+
{% endfor %}
|
19 |
+
</div>
|
20 |
+
</div>
|
21 |
+
</div>
|
@@ -2,7 +2,7 @@
|
|
2 |
<id>{{ item.permalink }}</id>
|
3 |
<title type="html">{{ item.title }}</title>
|
4 |
<link href="{{ item.permalink }}" rel="alternate" />
|
5 |
-
<updated>{{ item.timestamp|date('Y-m-d\\TH:i:
|
6 |
<summary>{{ item.excerpt }}</summary>
|
7 |
<content type="html">
|
8 |
<![CDATA[{{ item.content|raw|close_tags }}]]>
|
2 |
<id>{{ item.permalink }}</id>
|
3 |
<title type="html">{{ item.title }}</title>
|
4 |
<link href="{{ item.permalink }}" rel="alternate" />
|
5 |
+
<updated>{{ item.timestamp|date('Y-m-d\\TH:i:s.vP') }}</updated>
|
6 |
<summary>{{ item.excerpt }}</summary>
|
7 |
<content type="html">
|
8 |
<![CDATA[{{ item.content|raw|close_tags }}]]>
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -4,4 +4,4 @@
|
|
4 |
|
5 |
require_once __DIR__ . '/composer/autoload_real.php';
|
6 |
|
7 |
-
return
|
4 |
|
5 |
require_once __DIR__ . '/composer/autoload_real.php';
|
6 |
|
7 |
+
return ComposerAutoloaderInit454b25077a61c37d434b6b16c544309d::getLoader();
|
File without changes
|
File without changes
|
@@ -362,11 +362,13 @@ return array(
|
|
362 |
'RebelCode\\Wpra\\Core\\Licensing\\Addon' => $baseDir . '/src/Licensing/Addon.php',
|
363 |
'RebelCode\\Wpra\\Core\\Licensing\\LicenseStatus' => $baseDir . '/src/Licensing/LicenseStatus.php',
|
364 |
'RebelCode\\Wpra\\Core\\Logger\\ClearableLoggerInterface' => $baseDir . '/src/Logger/ClearableLoggerInterface.php',
|
365 |
-
'RebelCode\\Wpra\\Core\\Logger\\ConditionalLogger' => $baseDir . '/src/Logger/ConditionalLogger.php',
|
366 |
'RebelCode\\Wpra\\Core\\Logger\\FeedLoggerDataSet' => $baseDir . '/src/Logger/FeedLoggerDataSet.php',
|
|
|
367 |
'RebelCode\\Wpra\\Core\\Logger\\LogReaderInterface' => $baseDir . '/src/Logger/LogReaderInterface.php',
|
368 |
'RebelCode\\Wpra\\Core\\Logger\\LoggerUtilsTrait' => $baseDir . '/src/Logger/LoggerUtilsTrait.php',
|
|
|
369 |
'RebelCode\\Wpra\\Core\\Logger\\WpdbLogger' => $baseDir . '/src/Logger/WpdbLogger.php',
|
|
|
370 |
'RebelCode\\Wpra\\Core\\ModularModule' => $baseDir . '/src/ModularModule.php',
|
371 |
'RebelCode\\Wpra\\Core\\Modules\\AddonsModule' => $baseDir . '/src/Modules/AddonsModule.php',
|
372 |
'RebelCode\\Wpra\\Core\\Modules\\AssetsModule' => $baseDir . '/src/Modules/AssetsModule.php',
|
@@ -384,11 +386,13 @@ return array(
|
|
384 |
'RebelCode\\Wpra\\Core\\Modules\\ImporterModule' => $baseDir . '/src/Modules/ImporterModule.php',
|
385 |
'RebelCode\\Wpra\\Core\\Modules\\LicensingModule' => $baseDir . '/src/Modules/LicensingModule.php',
|
386 |
'RebelCode\\Wpra\\Core\\Modules\\LoggerModule' => $baseDir . '/src/Modules/LoggerModule.php',
|
|
|
387 |
'RebelCode\\Wpra\\Core\\Modules\\ModuleInterface' => $baseDir . '/src/Modules/ModuleInterface.php',
|
388 |
'RebelCode\\Wpra\\Core\\Modules\\ParsedownModule' => $baseDir . '/src/Modules/ParsedownModule.php',
|
389 |
'RebelCode\\Wpra\\Core\\Modules\\RestApiModule' => $baseDir . '/src/Modules/RestApiModule.php',
|
390 |
'RebelCode\\Wpra\\Core\\Modules\\SettingsModule' => $baseDir . '/src/Modules/SettingsModule.php',
|
391 |
'RebelCode\\Wpra\\Core\\Modules\\TwigModule' => $baseDir . '/src/Modules/TwigModule.php',
|
|
|
392 |
'RebelCode\\Wpra\\Core\\Modules\\WpModule' => $baseDir . '/src/Modules/WpModule.php',
|
393 |
'RebelCode\\Wpra\\Core\\Plugin' => $baseDir . '/src/Plugin.php',
|
394 |
'RebelCode\\Wpra\\Core\\Query\\AbstractWpQueryIterator' => $baseDir . '/src/Query/AbstractWpQueryIterator.php',
|
@@ -423,6 +427,7 @@ return array(
|
|
423 |
'RebelCode\\Wpra\\Core\\Util\\IteratorDelegateTrait' => $baseDir . '/src/Util/IteratorDelegateTrait.php',
|
424 |
'RebelCode\\Wpra\\Core\\Util\\MergedIterator' => $baseDir . '/src/Util/MergedIterator.php',
|
425 |
'RebelCode\\Wpra\\Core\\Util\\NormalizeWpPostCapableTrait' => $baseDir . '/src/Util/NormalizeWpPostCapableTrait.php',
|
|
|
426 |
'RebelCode\\Wpra\\Core\\Util\\PaginatedIterator' => $baseDir . '/src/Util/PaginatedIterator.php',
|
427 |
'RebelCode\\Wpra\\Core\\Util\\ParseArgsWithSchemaCapableTrait' => $baseDir . '/src/Util/ParseArgsWithSchemaCapableTrait.php',
|
428 |
'RebelCode\\Wpra\\Core\\Util\\SanitizeIdCommaListCapableTrait' => $baseDir . '/src/Util/SanitizeIdCommaListCapableTrait.php',
|
362 |
'RebelCode\\Wpra\\Core\\Licensing\\Addon' => $baseDir . '/src/Licensing/Addon.php',
|
363 |
'RebelCode\\Wpra\\Core\\Licensing\\LicenseStatus' => $baseDir . '/src/Licensing/LicenseStatus.php',
|
364 |
'RebelCode\\Wpra\\Core\\Logger\\ClearableLoggerInterface' => $baseDir . '/src/Logger/ClearableLoggerInterface.php',
|
|
|
365 |
'RebelCode\\Wpra\\Core\\Logger\\FeedLoggerDataSet' => $baseDir . '/src/Logger/FeedLoggerDataSet.php',
|
366 |
+
'RebelCode\\Wpra\\Core\\Logger\\FeedLoggerInterface' => $baseDir . '/src/Logger/FeedLoggerInterface.php',
|
367 |
'RebelCode\\Wpra\\Core\\Logger\\LogReaderInterface' => $baseDir . '/src/Logger/LogReaderInterface.php',
|
368 |
'RebelCode\\Wpra\\Core\\Logger\\LoggerUtilsTrait' => $baseDir . '/src/Logger/LoggerUtilsTrait.php',
|
369 |
+
'RebelCode\\Wpra\\Core\\Logger\\ProblemLogger' => $baseDir . '/src/Logger/ProblemLogger.php',
|
370 |
'RebelCode\\Wpra\\Core\\Logger\\WpdbLogger' => $baseDir . '/src/Logger/WpdbLogger.php',
|
371 |
+
'RebelCode\\Wpra\\Core\\Logger\\WpraLogger' => $baseDir . '/src/Logger/WpraLogger.php',
|
372 |
'RebelCode\\Wpra\\Core\\ModularModule' => $baseDir . '/src/ModularModule.php',
|
373 |
'RebelCode\\Wpra\\Core\\Modules\\AddonsModule' => $baseDir . '/src/Modules/AddonsModule.php',
|
374 |
'RebelCode\\Wpra\\Core\\Modules\\AssetsModule' => $baseDir . '/src/Modules/AssetsModule.php',
|
386 |
'RebelCode\\Wpra\\Core\\Modules\\ImporterModule' => $baseDir . '/src/Modules/ImporterModule.php',
|
387 |
'RebelCode\\Wpra\\Core\\Modules\\LicensingModule' => $baseDir . '/src/Modules/LicensingModule.php',
|
388 |
'RebelCode\\Wpra\\Core\\Modules\\LoggerModule' => $baseDir . '/src/Modules/LoggerModule.php',
|
389 |
+
'RebelCode\\Wpra\\Core\\Modules\\LoremModule' => $baseDir . '/src/Modules/LoremModule.php',
|
390 |
'RebelCode\\Wpra\\Core\\Modules\\ModuleInterface' => $baseDir . '/src/Modules/ModuleInterface.php',
|
391 |
'RebelCode\\Wpra\\Core\\Modules\\ParsedownModule' => $baseDir . '/src/Modules/ParsedownModule.php',
|
392 |
'RebelCode\\Wpra\\Core\\Modules\\RestApiModule' => $baseDir . '/src/Modules/RestApiModule.php',
|
393 |
'RebelCode\\Wpra\\Core\\Modules\\SettingsModule' => $baseDir . '/src/Modules/SettingsModule.php',
|
394 |
'RebelCode\\Wpra\\Core\\Modules\\TwigModule' => $baseDir . '/src/Modules/TwigModule.php',
|
395 |
+
'RebelCode\\Wpra\\Core\\Modules\\UpsellModule' => $baseDir . '/src/Modules/UpsellModule.php',
|
396 |
'RebelCode\\Wpra\\Core\\Modules\\WpModule' => $baseDir . '/src/Modules/WpModule.php',
|
397 |
'RebelCode\\Wpra\\Core\\Plugin' => $baseDir . '/src/Plugin.php',
|
398 |
'RebelCode\\Wpra\\Core\\Query\\AbstractWpQueryIterator' => $baseDir . '/src/Query/AbstractWpQueryIterator.php',
|
427 |
'RebelCode\\Wpra\\Core\\Util\\IteratorDelegateTrait' => $baseDir . '/src/Util/IteratorDelegateTrait.php',
|
428 |
'RebelCode\\Wpra\\Core\\Util\\MergedIterator' => $baseDir . '/src/Util/MergedIterator.php',
|
429 |
'RebelCode\\Wpra\\Core\\Util\\NormalizeWpPostCapableTrait' => $baseDir . '/src/Util/NormalizeWpPostCapableTrait.php',
|
430 |
+
'RebelCode\\Wpra\\Core\\Util\\NullFunction' => $baseDir . '/src/Util/NullFunction.php',
|
431 |
'RebelCode\\Wpra\\Core\\Util\\PaginatedIterator' => $baseDir . '/src/Util/PaginatedIterator.php',
|
432 |
'RebelCode\\Wpra\\Core\\Util\\ParseArgsWithSchemaCapableTrait' => $baseDir . '/src/Util/ParseArgsWithSchemaCapableTrait.php',
|
433 |
'RebelCode\\Wpra\\Core\\Util\\SanitizeIdCommaListCapableTrait' => $baseDir . '/src/Util/SanitizeIdCommaListCapableTrait.php',
|
File without changes
|
File without changes
|
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
// autoload_real.php @generated by Composer
|
4 |
|
5 |
-
class
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
@@ -19,15 +19,15 @@ class ComposerAutoloaderInit2a3a9815e4e052480cff9d68c42d23a2
|
|
19 |
return self::$loader;
|
20 |
}
|
21 |
|
22 |
-
spl_autoload_register(array('
|
23 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
24 |
-
spl_autoload_unregister(array('
|
25 |
|
26 |
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
27 |
if ($useStaticLoader) {
|
28 |
require_once __DIR__ . '/autoload_static.php';
|
29 |
|
30 |
-
call_user_func(\Composer\Autoload\
|
31 |
} else {
|
32 |
$map = require __DIR__ . '/autoload_namespaces.php';
|
33 |
foreach ($map as $namespace => $path) {
|
@@ -48,19 +48,19 @@ class ComposerAutoloaderInit2a3a9815e4e052480cff9d68c42d23a2
|
|
48 |
$loader->register(true);
|
49 |
|
50 |
if ($useStaticLoader) {
|
51 |
-
$includeFiles = Composer\Autoload\
|
52 |
} else {
|
53 |
$includeFiles = require __DIR__ . '/autoload_files.php';
|
54 |
}
|
55 |
foreach ($includeFiles as $fileIdentifier => $file) {
|
56 |
-
|
57 |
}
|
58 |
|
59 |
return $loader;
|
60 |
}
|
61 |
}
|
62 |
|
63 |
-
function
|
64 |
{
|
65 |
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
66 |
require $file;
|
2 |
|
3 |
// autoload_real.php @generated by Composer
|
4 |
|
5 |
+
class ComposerAutoloaderInit454b25077a61c37d434b6b16c544309d
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
19 |
return self::$loader;
|
20 |
}
|
21 |
|
22 |
+
spl_autoload_register(array('ComposerAutoloaderInit454b25077a61c37d434b6b16c544309d', 'loadClassLoader'), true, true);
|
23 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
24 |
+
spl_autoload_unregister(array('ComposerAutoloaderInit454b25077a61c37d434b6b16c544309d', 'loadClassLoader'));
|
25 |
|
26 |
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
27 |
if ($useStaticLoader) {
|
28 |
require_once __DIR__ . '/autoload_static.php';
|
29 |
|
30 |
+
call_user_func(\Composer\Autoload\ComposerStaticInit454b25077a61c37d434b6b16c544309d::getInitializer($loader));
|
31 |
} else {
|
32 |
$map = require __DIR__ . '/autoload_namespaces.php';
|
33 |
foreach ($map as $namespace => $path) {
|
48 |
$loader->register(true);
|
49 |
|
50 |
if ($useStaticLoader) {
|
51 |
+
$includeFiles = Composer\Autoload\ComposerStaticInit454b25077a61c37d434b6b16c544309d::$files;
|
52 |
} else {
|
53 |
$includeFiles = require __DIR__ . '/autoload_files.php';
|
54 |
}
|
55 |
foreach ($includeFiles as $fileIdentifier => $file) {
|
56 |
+
composerRequire454b25077a61c37d434b6b16c544309d($fileIdentifier, $file);
|
57 |
}
|
58 |
|
59 |
return $loader;
|
60 |
}
|
61 |
}
|
62 |
|
63 |
+
function composerRequire454b25077a61c37d434b6b16c544309d($fileIdentifier, $file)
|
64 |
{
|
65 |
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
66 |
require $file;
|
@@ -4,7 +4,7 @@
|
|
4 |
|
5 |
namespace Composer\Autoload;
|
6 |
|
7 |
-
class
|
8 |
{
|
9 |
public static $files = array (
|
10 |
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
|
@@ -545,11 +545,13 @@ class ComposerStaticInit2a3a9815e4e052480cff9d68c42d23a2
|
|
545 |
'RebelCode\\Wpra\\Core\\Licensing\\Addon' => __DIR__ . '/../..' . '/src/Licensing/Addon.php',
|
546 |
'RebelCode\\Wpra\\Core\\Licensing\\LicenseStatus' => __DIR__ . '/../..' . '/src/Licensing/LicenseStatus.php',
|
547 |
'RebelCode\\Wpra\\Core\\Logger\\ClearableLoggerInterface' => __DIR__ . '/../..' . '/src/Logger/ClearableLoggerInterface.php',
|
548 |
-
'RebelCode\\Wpra\\Core\\Logger\\ConditionalLogger' => __DIR__ . '/../..' . '/src/Logger/ConditionalLogger.php',
|
549 |
'RebelCode\\Wpra\\Core\\Logger\\FeedLoggerDataSet' => __DIR__ . '/../..' . '/src/Logger/FeedLoggerDataSet.php',
|
|
|
550 |
'RebelCode\\Wpra\\Core\\Logger\\LogReaderInterface' => __DIR__ . '/../..' . '/src/Logger/LogReaderInterface.php',
|
551 |
'RebelCode\\Wpra\\Core\\Logger\\LoggerUtilsTrait' => __DIR__ . '/../..' . '/src/Logger/LoggerUtilsTrait.php',
|
|
|
552 |
'RebelCode\\Wpra\\Core\\Logger\\WpdbLogger' => __DIR__ . '/../..' . '/src/Logger/WpdbLogger.php',
|
|
|
553 |
'RebelCode\\Wpra\\Core\\ModularModule' => __DIR__ . '/../..' . '/src/ModularModule.php',
|
554 |
'RebelCode\\Wpra\\Core\\Modules\\AddonsModule' => __DIR__ . '/../..' . '/src/Modules/AddonsModule.php',
|
555 |
'RebelCode\\Wpra\\Core\\Modules\\AssetsModule' => __DIR__ . '/../..' . '/src/Modules/AssetsModule.php',
|
@@ -567,11 +569,13 @@ class ComposerStaticInit2a3a9815e4e052480cff9d68c42d23a2
|
|
567 |
'RebelCode\\Wpra\\Core\\Modules\\ImporterModule' => __DIR__ . '/../..' . '/src/Modules/ImporterModule.php',
|
568 |
'RebelCode\\Wpra\\Core\\Modules\\LicensingModule' => __DIR__ . '/../..' . '/src/Modules/LicensingModule.php',
|
569 |
'RebelCode\\Wpra\\Core\\Modules\\LoggerModule' => __DIR__ . '/../..' . '/src/Modules/LoggerModule.php',
|
|
|
570 |
'RebelCode\\Wpra\\Core\\Modules\\ModuleInterface' => __DIR__ . '/../..' . '/src/Modules/ModuleInterface.php',
|
571 |
'RebelCode\\Wpra\\Core\\Modules\\ParsedownModule' => __DIR__ . '/../..' . '/src/Modules/ParsedownModule.php',
|
572 |
'RebelCode\\Wpra\\Core\\Modules\\RestApiModule' => __DIR__ . '/../..' . '/src/Modules/RestApiModule.php',
|
573 |
'RebelCode\\Wpra\\Core\\Modules\\SettingsModule' => __DIR__ . '/../..' . '/src/Modules/SettingsModule.php',
|
574 |
'RebelCode\\Wpra\\Core\\Modules\\TwigModule' => __DIR__ . '/../..' . '/src/Modules/TwigModule.php',
|
|
|
575 |
'RebelCode\\Wpra\\Core\\Modules\\WpModule' => __DIR__ . '/../..' . '/src/Modules/WpModule.php',
|
576 |
'RebelCode\\Wpra\\Core\\Plugin' => __DIR__ . '/../..' . '/src/Plugin.php',
|
577 |
'RebelCode\\Wpra\\Core\\Query\\AbstractWpQueryIterator' => __DIR__ . '/../..' . '/src/Query/AbstractWpQueryIterator.php',
|
@@ -606,6 +610,7 @@ class ComposerStaticInit2a3a9815e4e052480cff9d68c42d23a2
|
|
606 |
'RebelCode\\Wpra\\Core\\Util\\IteratorDelegateTrait' => __DIR__ . '/../..' . '/src/Util/IteratorDelegateTrait.php',
|
607 |
'RebelCode\\Wpra\\Core\\Util\\MergedIterator' => __DIR__ . '/../..' . '/src/Util/MergedIterator.php',
|
608 |
'RebelCode\\Wpra\\Core\\Util\\NormalizeWpPostCapableTrait' => __DIR__ . '/../..' . '/src/Util/NormalizeWpPostCapableTrait.php',
|
|
|
609 |
'RebelCode\\Wpra\\Core\\Util\\PaginatedIterator' => __DIR__ . '/../..' . '/src/Util/PaginatedIterator.php',
|
610 |
'RebelCode\\Wpra\\Core\\Util\\ParseArgsWithSchemaCapableTrait' => __DIR__ . '/../..' . '/src/Util/ParseArgsWithSchemaCapableTrait.php',
|
611 |
'RebelCode\\Wpra\\Core\\Util\\SanitizeIdCommaListCapableTrait' => __DIR__ . '/../..' . '/src/Util/SanitizeIdCommaListCapableTrait.php',
|
@@ -1027,10 +1032,10 @@ class ComposerStaticInit2a3a9815e4e052480cff9d68c42d23a2
|
|
1027 |
public static function getInitializer(ClassLoader $loader)
|
1028 |
{
|
1029 |
return \Closure::bind(function () use ($loader) {
|
1030 |
-
$loader->prefixLengthsPsr4 =
|
1031 |
-
$loader->prefixDirsPsr4 =
|
1032 |
-
$loader->prefixesPsr0 =
|
1033 |
-
$loader->classMap =
|
1034 |
|
1035 |
}, null, ClassLoader::class);
|
1036 |
}
|
4 |
|
5 |
namespace Composer\Autoload;
|
6 |
|
7 |
+
class ComposerStaticInit454b25077a61c37d434b6b16c544309d
|
8 |
{
|
9 |
public static $files = array (
|
10 |
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
|
545 |
'RebelCode\\Wpra\\Core\\Licensing\\Addon' => __DIR__ . '/../..' . '/src/Licensing/Addon.php',
|
546 |
'RebelCode\\Wpra\\Core\\Licensing\\LicenseStatus' => __DIR__ . '/../..' . '/src/Licensing/LicenseStatus.php',
|
547 |
'RebelCode\\Wpra\\Core\\Logger\\ClearableLoggerInterface' => __DIR__ . '/../..' . '/src/Logger/ClearableLoggerInterface.php',
|
|
|
548 |
'RebelCode\\Wpra\\Core\\Logger\\FeedLoggerDataSet' => __DIR__ . '/../..' . '/src/Logger/FeedLoggerDataSet.php',
|
549 |
+
'RebelCode\\Wpra\\Core\\Logger\\FeedLoggerInterface' => __DIR__ . '/../..' . '/src/Logger/FeedLoggerInterface.php',
|
550 |
'RebelCode\\Wpra\\Core\\Logger\\LogReaderInterface' => __DIR__ . '/../..' . '/src/Logger/LogReaderInterface.php',
|
551 |
'RebelCode\\Wpra\\Core\\Logger\\LoggerUtilsTrait' => __DIR__ . '/../..' . '/src/Logger/LoggerUtilsTrait.php',
|
552 |
+
'RebelCode\\Wpra\\Core\\Logger\\ProblemLogger' => __DIR__ . '/../..' . '/src/Logger/ProblemLogger.php',
|
553 |
'RebelCode\\Wpra\\Core\\Logger\\WpdbLogger' => __DIR__ . '/../..' . '/src/Logger/WpdbLogger.php',
|
554 |
+
'RebelCode\\Wpra\\Core\\Logger\\WpraLogger' => __DIR__ . '/../..' . '/src/Logger/WpraLogger.php',
|
555 |
'RebelCode\\Wpra\\Core\\ModularModule' => __DIR__ . '/../..' . '/src/ModularModule.php',
|
556 |
'RebelCode\\Wpra\\Core\\Modules\\AddonsModule' => __DIR__ . '/../..' . '/src/Modules/AddonsModule.php',
|
557 |
'RebelCode\\Wpra\\Core\\Modules\\AssetsModule' => __DIR__ . '/../..' . '/src/Modules/AssetsModule.php',
|
569 |
'RebelCode\\Wpra\\Core\\Modules\\ImporterModule' => __DIR__ . '/../..' . '/src/Modules/ImporterModule.php',
|
570 |
'RebelCode\\Wpra\\Core\\Modules\\LicensingModule' => __DIR__ . '/../..' . '/src/Modules/LicensingModule.php',
|
571 |
'RebelCode\\Wpra\\Core\\Modules\\LoggerModule' => __DIR__ . '/../..' . '/src/Modules/LoggerModule.php',
|
572 |
+
'RebelCode\\Wpra\\Core\\Modules\\LoremModule' => __DIR__ . '/../..' . '/src/Modules/LoremModule.php',
|
573 |
'RebelCode\\Wpra\\Core\\Modules\\ModuleInterface' => __DIR__ . '/../..' . '/src/Modules/ModuleInterface.php',
|
574 |
'RebelCode\\Wpra\\Core\\Modules\\ParsedownModule' => __DIR__ . '/../..' . '/src/Modules/ParsedownModule.php',
|
575 |
'RebelCode\\Wpra\\Core\\Modules\\RestApiModule' => __DIR__ . '/../..' . '/src/Modules/RestApiModule.php',
|
576 |
'RebelCode\\Wpra\\Core\\Modules\\SettingsModule' => __DIR__ . '/../..' . '/src/Modules/SettingsModule.php',
|
577 |
'RebelCode\\Wpra\\Core\\Modules\\TwigModule' => __DIR__ . '/../..' . '/src/Modules/TwigModule.php',
|
578 |
+
'RebelCode\\Wpra\\Core\\Modules\\UpsellModule' => __DIR__ . '/../..' . '/src/Modules/UpsellModule.php',
|
579 |
'RebelCode\\Wpra\\Core\\Modules\\WpModule' => __DIR__ . '/../..' . '/src/Modules/WpModule.php',
|
580 |
'RebelCode\\Wpra\\Core\\Plugin' => __DIR__ . '/../..' . '/src/Plugin.php',
|
581 |
'RebelCode\\Wpra\\Core\\Query\\AbstractWpQueryIterator' => __DIR__ . '/../..' . '/src/Query/AbstractWpQueryIterator.php',
|
610 |
'RebelCode\\Wpra\\Core\\Util\\IteratorDelegateTrait' => __DIR__ . '/../..' . '/src/Util/IteratorDelegateTrait.php',
|
611 |
'RebelCode\\Wpra\\Core\\Util\\MergedIterator' => __DIR__ . '/../..' . '/src/Util/MergedIterator.php',
|
612 |
'RebelCode\\Wpra\\Core\\Util\\NormalizeWpPostCapableTrait' => __DIR__ . '/../..' . '/src/Util/NormalizeWpPostCapableTrait.php',
|
613 |
+
'RebelCode\\Wpra\\Core\\Util\\NullFunction' => __DIR__ . '/../..' . '/src/Util/NullFunction.php',
|
614 |
'RebelCode\\Wpra\\Core\\Util\\PaginatedIterator' => __DIR__ . '/../..' . '/src/Util/PaginatedIterator.php',
|
615 |
'RebelCode\\Wpra\\Core\\Util\\ParseArgsWithSchemaCapableTrait' => __DIR__ . '/../..' . '/src/Util/ParseArgsWithSchemaCapableTrait.php',
|
616 |
'RebelCode\\Wpra\\Core\\Util\\SanitizeIdCommaListCapableTrait' => __DIR__ . '/../..' . '/src/Util/SanitizeIdCommaListCapableTrait.php',
|
1032 |
public static function getInitializer(ClassLoader $loader)
|
1033 |
{
|
1034 |
return \Closure::bind(function () use ($loader) {
|
1035 |
+
$loader->prefixLengthsPsr4 = ComposerStaticInit454b25077a61c37d434b6b16c544309d::$prefixLengthsPsr4;
|
1036 |
+
$loader->prefixDirsPsr4 = ComposerStaticInit454b25077a61c37d434b6b16c544309d::$prefixDirsPsr4;
|
1037 |
+
$loader->prefixesPsr0 = ComposerStaticInit454b25077a61c37d434b6b16c544309d::$prefixesPsr0;
|
1038 |
+
$loader->classMap = ComposerStaticInit454b25077a61c37d434b6b16c544309d::$classMap;
|
1039 |
|
1040 |
}, null, ClassLoader::class);
|
1041 |
}
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -4,7 +4,7 @@
|
|
4 |
* Plugin Name: WP RSS Aggregator
|
5 |
* Plugin URI: https://www.wprssaggregator.com/#utm_source=wpadmin&utm_medium=plugin&utm_campaign=wpraplugin
|
6 |
* Description: Imports and aggregates multiple RSS Feeds.
|
7 |
-
* Version: 4.15
|
8 |
* Author: RebelCode
|
9 |
* Author URI: https://www.wprssaggregator.com
|
10 |
* Text Domain: wprss
|
@@ -53,11 +53,13 @@ use RebelCode\Wpra\Core\Modules\ImagesModule;
|
|
53 |
use RebelCode\Wpra\Core\Modules\ImporterModule;
|
54 |
use RebelCode\Wpra\Core\Modules\LicensingModule;
|
55 |
use RebelCode\Wpra\Core\Modules\LoggerModule;
|
|
|
56 |
use RebelCode\Wpra\Core\Modules\ModuleInterface;
|
57 |
use RebelCode\Wpra\Core\Modules\ParsedownModule;
|
58 |
use RebelCode\Wpra\Core\Modules\RestApiModule;
|
59 |
use RebelCode\Wpra\Core\Modules\SettingsModule;
|
60 |
use RebelCode\Wpra\Core\Modules\TwigModule;
|
|
|
61 |
use RebelCode\Wpra\Core\Modules\WpModule;
|
62 |
use RebelCode\Wpra\Core\Plugin;
|
63 |
|
@@ -67,7 +69,7 @@ use RebelCode\Wpra\Core\Plugin;
|
|
67 |
|
68 |
// Set the version number of the plugin.
|
69 |
if( !defined( 'WPRSS_VERSION' ) )
|
70 |
-
define( 'WPRSS_VERSION', '4.15' );
|
71 |
|
72 |
if( !defined( 'WPRSS_WP_MIN_VERSION' ) )
|
73 |
define( 'WPRSS_WP_MIN_VERSION', '4.8' );
|
@@ -255,9 +257,6 @@ require_once ( WPRSS_INC . 'opml-importer.php' );
|
|
255 |
/* Load the admin debugging page file */
|
256 |
require_once ( WPRSS_INC . 'admin-debugging.php' );
|
257 |
|
258 |
-
/* Load the addons page file */
|
259 |
-
require_once ( WPRSS_INC . 'admin-addons.php' );
|
260 |
-
|
261 |
/* Load the admin display-related functions */
|
262 |
require_once ( WPRSS_INC . 'admin-display.php' );
|
263 |
|
@@ -398,6 +397,8 @@ function wpra_modules()
|
|
398 |
'rest_api' => new RestApiModule(),
|
399 |
'settings' => new SettingsModule(),
|
400 |
'licensing' => new LicensingModule(),
|
|
|
|
|
401 |
'logging' => new LoggerModule(),
|
402 |
'i18n' => new I18nModule(),
|
403 |
'twig' => new TwigModule(),
|
4 |
* Plugin Name: WP RSS Aggregator
|
5 |
* Plugin URI: https://www.wprssaggregator.com/#utm_source=wpadmin&utm_medium=plugin&utm_campaign=wpraplugin
|
6 |
* Description: Imports and aggregates multiple RSS Feeds.
|
7 |
+
* Version: 4.15.1
|
8 |
* Author: RebelCode
|
9 |
* Author URI: https://www.wprssaggregator.com
|
10 |
* Text Domain: wprss
|
53 |
use RebelCode\Wpra\Core\Modules\ImporterModule;
|
54 |
use RebelCode\Wpra\Core\Modules\LicensingModule;
|
55 |
use RebelCode\Wpra\Core\Modules\LoggerModule;
|
56 |
+
use RebelCode\Wpra\Core\Modules\LoremModule;
|
57 |
use RebelCode\Wpra\Core\Modules\ModuleInterface;
|
58 |
use RebelCode\Wpra\Core\Modules\ParsedownModule;
|
59 |
use RebelCode\Wpra\Core\Modules\RestApiModule;
|
60 |
use RebelCode\Wpra\Core\Modules\SettingsModule;
|
61 |
use RebelCode\Wpra\Core\Modules\TwigModule;
|
62 |
+
use RebelCode\Wpra\Core\Modules\UpsellModule;
|
63 |
use RebelCode\Wpra\Core\Modules\WpModule;
|
64 |
use RebelCode\Wpra\Core\Plugin;
|
65 |
|
69 |
|
70 |
// Set the version number of the plugin.
|
71 |
if( !defined( 'WPRSS_VERSION' ) )
|
72 |
+
define( 'WPRSS_VERSION', '4.15.1' );
|
73 |
|
74 |
if( !defined( 'WPRSS_WP_MIN_VERSION' ) )
|
75 |
define( 'WPRSS_WP_MIN_VERSION', '4.8' );
|
257 |
/* Load the admin debugging page file */
|
258 |
require_once ( WPRSS_INC . 'admin-debugging.php' );
|
259 |
|
|
|
|
|
|
|
260 |
/* Load the admin display-related functions */
|
261 |
require_once ( WPRSS_INC . 'admin-display.php' );
|
262 |
|
397 |
'rest_api' => new RestApiModule(),
|
398 |
'settings' => new SettingsModule(),
|
399 |
'licensing' => new LicensingModule(),
|
400 |
+
'upsell' => new UpsellModule(),
|
401 |
+
// 'lorem' => new LoremModule(),
|
402 |
'logging' => new LoggerModule(),
|
403 |
'i18n' => new I18nModule(),
|
404 |
'twig' => new TwigModule(),
|