Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
52632e6
chore(deps): bump codeinwp/themeisle-sdk from 3.3.49 to 3.3.50
dependabot[bot] Dec 1, 2025
295d519
remove crons on uninstallation
girishpanchal30 Dec 1, 2025
0151be8
trigger compare
selul Dec 3, 2025
3ba01ed
Sync branch [skip ci]
pirate-bot Dec 9, 2025
58390da
Sync branch [skip ci]
pirate-bot Dec 10, 2025
12ae254
Sync branch [skip ci]
pirate-bot Dec 12, 2025
458d958
Sync branch [skip ci]
pirate-bot Dec 12, 2025
00211a9
fix: deprecated notice
girishpanchal30 Dec 15, 2025
71e55e7
fix: deprecated notice
girishpanchal30 Dec 15, 2025
978c0b4
enable legacy support
girishpanchal30 Dec 15, 2025
69347e0
fix: e2e
girishpanchal30 Dec 16, 2025
42dc51e
fix: e2e
girishpanchal30 Dec 16, 2025
29da353
fix: php warning
girishpanchal30 Dec 22, 2025
0f08494
fix: preserve HTML tags in content area
girishpanchal30 Jan 8, 2026
68170b6
fix: phpunit
girishpanchal30 Jan 8, 2026
22dd681
refactor: remove banner
girishpanchal30 Feb 10, 2026
6a9c45a
fix: handle feed limit for non-pro users
girishpanchal30 Feb 13, 2026
0577928
fix: phpunit
girishpanchal30 Feb 13, 2026
4fca68e
add feedzy youtube videos to dashboard
girishpanchal30 Feb 16, 2026
238932b
refactor: update CTA text
girishpanchal30 Feb 24, 2026
1d7673d
dev: add AGENTS.md (#1185)
Soare-Robert-Daniel Feb 25, 2026
0712c7e
Sync branch [skip ci]
pirate-bot Mar 16, 2026
7ea4af4
fix: make header user agent filter compatible with WP
girishpanchal30 Mar 17, 2026
d153ac7
fix: phpstan
girishpanchal30 Mar 17, 2026
08d1aaa
refactor: translatable strings
girishpanchal30 Dec 1, 2025
2fa4ed6
fix: phpstan
girishpanchal30 Dec 1, 2025
e06ef13
refactor: post status label
girishpanchal30 Dec 3, 2025
23dc72a
remove unnecessary localize strings
girishpanchal30 Dec 3, 2025
c328bee
fix: add fallback for media thumbnail retrieval
girishpanchal30 Apr 9, 2026
cc1b8d5
fix: improve media thumbnail retrieval logic
girishpanchal30 Apr 9, 2026
cf900e8
Merge pull request #1166 from Codeinwp/dependabot/composer/developmen…
vytisbulkevicius Apr 14, 2026
5b04e2d
Merge pull request #1169 from Codeinwp/bugfix/1153
vytisbulkevicius Apr 14, 2026
ee4d096
chore(deps): bump codeinwp/themeisle-sdk from 3.3.50 to 3.3.51
dependabot[bot] Apr 14, 2026
2bc993e
Merge pull request #1182 from Codeinwp/bugfix/1181
vytisbulkevicius Apr 14, 2026
8a41507
Merge pull request #1175 from Codeinwp/bugfix/1174
vytisbulkevicius Apr 14, 2026
2bfcf75
Merge pull request #1208 from Codeinwp/dependabot/composer/developmen…
vytisbulkevicius Apr 14, 2026
1627574
Merge pull request #1190 from Codeinwp/bugfix/1186
vytisbulkevicius Apr 14, 2026
1522fec
Merge pull request #1176 from Codeinwp/bugfix/pro/937
vytisbulkevicius Apr 14, 2026
b149058
Merge pull request #1177 from Codeinwp/bugfix/pro/942
vytisbulkevicius Apr 14, 2026
5fdcf70
Merge pull request #1183 from Codeinwp/bugfix/pro/951
vytisbulkevicius Apr 14, 2026
a90865d
Merge pull request #1184 from Codeinwp/bugfix/941
vytisbulkevicius Apr 14, 2026
3af0192
refactor: black friday messages (#1189)
Soare-Robert-Daniel Apr 14, 2026
54b7828
Merge pull request #1168 from Codeinwp/bugfix/1165
vytisbulkevicius Apr 14, 2026
9f3b26c
Merge pull request #1207 from Codeinwp/bugfix/pro/957
vytisbulkevicius Apr 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .distignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,5 @@ docker-compose.ci.yml
artifacts
phpstan.neon
phpstan-baseline.neon
languages
languages
AGENTS.md
107 changes: 107 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# Agent workflow

## Project Overview

Feedzy RSS Feeds is a WordPress plugin (lite/free version) for RSS aggregation, content curation, and autoblogging. It supports importing RSS feeds as WordPress posts, displaying feeds via shortcodes/blocks/widgets, and integrates with Elementor. A separate Pro plugin extends its functionality.

- **Text domain:** `feedzy-rss-feeds`
- **Min PHP:** 7.2 | **Min WP:** 6.0
- **Main bootstrap:** `feedzy-rss-feed.php` (defines constants, registers autoloader, runs plugin)

## Commands

### Build & Dev (JS/Blocks)
```bash
npm install # Install JS dependencies
npm run build # Production build all blocks/JS bundles
npm run dev # Watch mode for all blocks (parallel)
npm run build:block # Build just the Gutenberg block
npm run build:loop # Build just the Loop block
```

### PHP Linting & Static Analysis
```bash
composer install # Install PHP dependencies
composer run lint # Run PHPCS (WordPress Coding Standards)
composer run format # Auto-fix PHPCS issues
composer run phpstan # Run PHPStan (level 6, includes/ only)
```

### PHPUnit Tests
```bash
# Requires WordPress test suite (MySQL service needed)
bash bin/install-wp-tests.sh wordpress_test root root 127.0.0.1:3306
phpunit # Run all unit tests
phpunit tests/test-plugin.php # Run a single test file
```

### E2E Tests (Playwright + wp-env)
```bash
npm run wp-env start # Start Docker-based WordPress environment
npm run test:e2e # Run Playwright E2E tests
npm run test:e2e:debug # Run E2E with Playwright UI mode
```

### Other
```bash
npm run grunt # Run Grunt tasks (readme.txt → readme.md conversion, version bumping)
npm run dist # Build dist package (bin/dist.sh)
npm run lint:js # Lint JS files via wp-scripts
```

## Architecture

### Autoloading Convention
The plugin uses a custom `spl_autoload_register` in the bootstrap file. Classes prefixed with `Feedzy_Rss_Feeds` are resolved by converting underscores to hyphens and lowering the case, then searching these directories in order:
1. `includes/`
2. `includes/abstract/`
3. `includes/admin/`
4. `includes/gutenberg/`
5. `includes/util/`
6. `includes/elementor/`

Example: `Feedzy_Rss_Feeds_Admin` → `includes/admin/feedzy-rss-feeds-admin.php`

### Core Class Hierarchy
- **`Feedzy_Rss_Feeds`** (`includes/feedzy-rss-feeds.php`) — Singleton core class. Loads dependencies and registers all hooks via the Loader pattern.
- **`Feedzy_Rss_Feeds_Loader`** (`includes/feedzy-rss-feeds-loader.php`) — Central hook registration (actions/filters stored in arrays, executed via `run()`).
- **`Feedzy_Rss_Feeds_Admin_Abstract`** (`includes/abstract/`) — Base class for admin functionality including feed fetching, shortcode rendering, and image handling.
- **`Feedzy_Rss_Feeds_Admin`** (`includes/admin/feedzy-rss-feeds-admin.php`) — Extends abstract. Handles admin UI, post types (`feedzy_categories`, `feedzy_imports`), REST routes, settings, shortcode `[feedzy-rss]`.
- **`Feedzy_Rss_Feeds_Import`** (`includes/admin/feedzy-rss-feeds-import.php`) — Feed-to-post import engine. Manages cron jobs, import post type metaboxes, magic tags.

### Custom Post Types
- `feedzy_categories` — Groups of feed URLs for reuse.
- `feedzy_imports` — Import job configurations (feed source → WordPress posts).

### JavaScript / Block Architecture
Blocks are built with `@wordpress/scripts`. Each has its own entry point under `js/`:
- `js/FeedzyBlock/` → `build/block/` — Main Gutenberg block for displaying feeds
- `js/FeedzyLoop/` → `build/loop/` — Loop block variant
- `js/Onboarding/` → `build/onboarding/` — Setup wizard
- `js/ActionPopup/` → `build/action-popup/` — Action chain popup
- `js/Conditions/` → `build/conditions/` — Import filter conditions UI
- `js/FeedBack/` → `build/feedback/` — Feedback prompt
- `js/Review/` → `build/review/` — Review prompt

Legacy JS files (non-bundled) in `js/` root: TinyMCE integration, Elementor widget, lazy loading, settings, categories.

### Pro Plugin Integration
The lite plugin checks for Pro via `feedzy_is_pro()` and `FEEDZY_PRO_BASEFILE` / `FEEDZY_PRO_ABSPATH` constants. Many hooks have `feedzy_` prefixed filters that Pro extends. The import feature conditionally loads based on `feedzy_is_pro(false)` or `has_filter('feedzy_free_has_import')`.

### Key WordPress Hooks
- Shortcode: `[feedzy-rss]` registered in `define_admin_hooks()`
- REST API: routes registered via `rest_route` on `rest_api_init`
- Cron: `feedzy_cron` action drives scheduled imports
- Logging: `feedzy_log` action → `Feedzy_Rss_Feeds_Log` class

### Tests
- **PHPUnit tests:** `tests/test-*.php` files (prefixed with `test-`), bootstrapped by `tests/bootstrap.php`. Require WP test suite installation.
- **E2E tests:** `tests/e2e/specs/*.spec.js` using Playwright with `@wordpress/e2e-test-utils-playwright`. Run against `wp-env` Docker environment.
- **PHPStan stubs:** `tests/php/static-analysis-stubs/` provides type stubs for static analysis.

## Coding Standards

- Follows WordPress Coding Standards enforced via PHPCS (`phpcs.xml`)
- WordPress-VIP-Go rules included
- PHPStan level 6 for `includes/` directory
- JS linting via `@wordpress/eslint-plugin`
16 changes: 8 additions & 8 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions css/settings.css
Original file line number Diff line number Diff line change
Expand Up @@ -835,7 +835,6 @@ input.fz-switch-toggle[type=checkbox]:checked:before{
outline: 0;
cursor: pointer;
text-decoration: none;
text-transform: capitalize;
-webkit-transition: all 0.3s ease-in-out;
-moz-transition: all 0.3s ease-in-out;
-o-transition: all 0.3s ease-in-out;
Expand Down Expand Up @@ -1564,7 +1563,6 @@ input.fz-switch-toggle[type=checkbox]:checked:before{
background: transparent;
border-color: #4268CF;
color: #4268CF;
text-transform: capitalize;
-webkit-transition: all 0.3s ease-in-out;
-moz-transition: all 0.3s ease-in-out;
-o-transition: all 0.3s ease-in-out;
Expand Down Expand Up @@ -2250,7 +2248,6 @@ li.draggable-item .components-panel__body-toggle.components-button{
}
.fz-content-action div .tagify__tag-text {
padding-right: 10px;
text-transform: capitalize;
}
.popover-action-list ul li.fz-action-disabled {
cursor: not-allowed !important;
Expand Down Expand Up @@ -2971,3 +2968,7 @@ button.feedzy-action-button {
font-size: 12px;
padding: 4px 12px;
}
.tagify__tag .feedzy-custom-tag {
cursor: auto;
line-height: 1.5;
}
22 changes: 22 additions & 0 deletions feedzy-rss-feed.php
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,28 @@ function ( $labels ) {
);
}

if ( isset( $labels['about_us'] ) ) {
$labels['about_us'] = array_merge(
$labels['about_us'],
array(
'title' => __( 'About Us', 'feedzy-rss-feeds' ),
'heroHeader' => __( 'Our Story', 'feedzy-rss-feeds' ),
'heroTextFirst' => __( 'Themeisle was founded in 2012 by a group of passionate developers who wanted to create beautiful and functional WordPress themes and plugins. Since then, we have grown into a team of over 20 dedicated professionals who are committed to delivering the best possible products to our customers.', 'feedzy-rss-feeds' ),
'heroTextSecond' => __( 'At Themeisle, we offer a wide range of WordPress themes and plugins that are designed to meet the needs of both beginners and advanced users. Our products are feature-rich, easy to use, and are designed to help you create beautiful and functional websites.', 'feedzy-rss-feeds' ),
'teamImageCaption' => __( 'Our team in WCEU2022 in Portugal', 'feedzy-rss-feeds' ),
'newsHeading' => __( 'Stay connected for news & updates!', 'feedzy-rss-feeds' ),
'emailPlaceholder' => __( 'Your email address', 'feedzy-rss-feeds' ),
'signMeUp' => __( 'Sign me up', 'feedzy-rss-feeds' ),
'installNow' => __( 'Install Now', 'feedzy-rss-feeds' ),
'activate' => __( 'Activate', 'feedzy-rss-feeds' ),
'learnMore' => __( 'Learn More', 'feedzy-rss-feeds' ),
'installed' => __( 'Installed', 'feedzy-rss-feeds' ),
'notInstalled' => __( 'Not Installed', 'feedzy-rss-feeds' ),
'active' => __( 'Active', 'feedzy-rss-feeds' ),
)
);
}

return $labels;
}
);
Binary file added img/import-full-rss-posts.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/jobs-from-rss.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/rss-to-wordpress.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/youtube-to-wordpress.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 16 additions & 7 deletions includes/abstract/feedzy-rss-feeds-admin-abstract.php
Original file line number Diff line number Diff line change
Expand Up @@ -822,10 +822,10 @@ function ( $url ) {
* @since 3.1.7
* @access private
*
* @param string $feed_url The feed URL.
* @param string $cache The cache string (eg. 1_hour, 30_min etc.).
* @param array $sc The shortcode attributes.
* @param bool $allow_https Defaults to constant FEEDZY_ALLOW_HTTPS.
* @param string|array<string> $feed_url The feed URL.
* @param string $cache The cache string (eg. 1_hour, 30_min etc.).
* @param array $sc The shortcode attributes.
* @param bool $allow_https Defaults to constant FEEDZY_ALLOW_HTTPS.
*
* @return SimplePie
*/
Expand Down Expand Up @@ -858,9 +858,9 @@ private function init_feed( $feed_url, $cache, $sc, $allow_https = FEEDZY_ALLOW_
require_once ABSPATH . WPINC . '/class-wp-feed-cache-transient.php';
require_once ABSPATH . WPINC . '/class-wp-simplepie-file.php';

$feed->set_file_class( 'WP_SimplePie_File' );
$feed->get_registry()->register( SimplePie\File::class, 'WP_SimplePie_File', true );
$default_agent = $this->get_default_user_agent( $feed_url );
$feed->set_useragent( apply_filters( 'http_headers_useragent', $default_agent ) );
$feed->set_useragent( apply_filters( 'http_headers_useragent', $default_agent, is_array( $feed_url ) ? reset( $feed_url ) : $feed_url ) );
if ( false === apply_filters( 'feedzy_disable_db_cache', false, $feed_url ) ) {
SimplePie_Cache::register( 'wp_transient', 'WP_Feed_Cache_Transient' );
$feed->set_cache_location( 'wp_transient' );
Expand Down Expand Up @@ -917,7 +917,7 @@ function ( $time ) use ( $cache_time ) {
if ( isset( $_SERVER['HTTP_USER_AGENT'] ) ) {
// phpcs:ignore WordPressVIPMinimum.Variables.RestrictedVariables.cache_constraints___SERVER__HTTP_USER_AGENT__
$set_server_agent = sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) . SIMPLEPIE_USERAGENT );
$feed->set_useragent( apply_filters( 'http_headers_useragent', $set_server_agent ) );
$feed->set_useragent( apply_filters( 'http_headers_useragent', $set_server_agent, is_array( $feed_url ) ? reset( $feed_url ) : $feed_url ) );
}

$feed->init();
Expand Down Expand Up @@ -1767,6 +1767,15 @@ public function feedzy_retrieve_image( $item, $sc = null ) {
$the_thumbnail = $data['0']['attribs']['']['href'];
}
}
// xmlns:media thumbnail.
if ( empty( $the_thumbnail ) ) {
$data = $item->get_item_tags( 'http://search.yahoo.com/mrss/', 'thumbnail' );
if ( isset( $data['0']['attribs']['']['url'] ) && ! empty( $data['0']['attribs']['']['url'] ) ) {
$the_thumbnail = $data['0']['attribs']['']['url'];
} elseif ( isset( $data['0']['data'] ) && ! empty( $data['0']['data'] ) ) {
$the_thumbnail = $data['0']['data'];
}
}
// Content image.
if ( empty( $the_thumbnail ) ) {
$feed_description = $item->get_content();
Expand Down
11 changes: 11 additions & 0 deletions includes/admin/feedzy-rss-feeds-actions.php
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,8 @@ public function action_process() {
return $this->generate_image();
case 'modify_links':
return $this->modify_links();
case 'custom_html':
return $this->custom_html();
default:
return $this->default_content();
}
Expand Down Expand Up @@ -619,5 +621,14 @@ private function custom_field() {
}
return $this->default_value;
}

/**
* Get Custom HTML tag.
*
* @return string
*/
private function custom_html() {
return $this->current_job->tag;
}
}
}
Loading
Loading