Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
99 changes: 99 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
name: CI

on:
push:
branches:
- master
- main
pull_request:
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
phpstan:
name: PHPStan
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
tools: composer
coverage: none

- name: Install Composer dependencies
run: composer install --no-interaction --prefer-dist

- name: Run PHPStan
run: composer analyze

phpunit:
name: PHPUnit
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
tools: composer
coverage: none

- name: Install Composer dependencies
run: composer install --no-interaction --prefer-dist

- name: Run PHPUnit
run: composer test

e2e:
name: E2E (WP ${{ matrix.wp.name }})
runs-on: ubuntu-latest
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
wp:
# Previous major stable release (past release).
- name: '6.9'
core: 'https://wordpress.org/wordpress-6.9.5.zip'
# WordPress development / next release branch (GitHub mirror uses master).
- name: 'trunk'
core: 'WordPress/WordPress#master'
defaults:
run:
working-directory: plugins/sahajanand-post-to-speech
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: npm
cache-dependency-path: plugins/sahajanand-post-to-speech/package-lock.json

- name: Install npm dependencies
run: npm ci

- name: Build plugin assets
run: npm run build

- name: Install Playwright Chromium
run: npx playwright install chromium --with-deps

- name: Run e2e tests
env:
WP_ENV_CORE: ${{ matrix.wp.core }}
run: npm run test:e2e
2 changes: 1 addition & 1 deletion .wp-env.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"core": "WordPress/WordPress",
"core": null,
"phpVersion": "8.2",
"plugins": [
"./plugins/sahajanand-post-to-speech"
Expand Down
6 changes: 4 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@
"squizlabs/php_codesniffer": "^3.8",
"wp-coding-standards/wpcs": "^3.0",
"dealerdirect/phpcodesniffer-composer-installer": "^1.0",
"phpstan/phpstan": "^1.10"
"phpstan/phpstan": "^1.10",
"szepeviktor/phpstan-wordpress": "^1.3"
},
"scripts": {
"test": "phpunit",
"test:coverage": "phpunit --coverage-text",
"lint": "phpcs --standard=WordPress .",
"lint:fix": "phpcbf --standard=WordPress .",
"analyze": "phpstan analyze",
"analyze": "phpstan analyse -c phpstan.neon.dist --memory-limit=1G",
"bump": "bash scripts/bump-plugin-version.sh"
},
"config": {
Expand Down
20 changes: 20 additions & 0 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
includes:
- vendor/szepeviktor/phpstan-wordpress/extension.neon

parameters:
level: 5
paths:
- plugins/sahajanand-post-to-speech/sahajanand-post-to-speech.php
- plugins/sahajanand-post-to-speech/uninstall.php
- plugins/sahajanand-post-to-speech/includes
excludePaths:
analyseAndScan:
- plugins/sahajanand-post-to-speech/build
- plugins/sahajanand-post-to-speech/assets/vendor
- plugins/sahajanand-post-to-speech/node_modules
- plugins/sahajanand-post-to-speech/tests
bootstrapFiles:
- tests/phpstan-bootstrap.php
# Plugin minimum PHP; WordPress stubs cover Core APIs used by the plugin.
phpVersion: 70400
reportUnmatchedIgnoredErrors: true
4 changes: 4 additions & 0 deletions plugins/sahajanand-post-to-speech/.distignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ WORDPRESS-ORG.md

# Optional dev tooling configs
webpack.config.js
playwright.config.js
.wp-env.json
artifacts
artifacts/**

# Keep src/ in the WordPress.org zip — reviewers require unminified JS sources.

Expand Down
4 changes: 4 additions & 0 deletions plugins/sahajanand-post-to-speech/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
node_modules/
local-fatal.log
artifacts/
test-results/
playwright-report/
blob-report/
15 changes: 15 additions & 0 deletions plugins/sahajanand-post-to-speech/.wp-env.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"$schema": "https://schemas.wp.org/trunk/wp-env.json",
"core": null,
"phpVersion": "8.2",
"plugins": [ "." ],
"mappings": {
"wp-content/mu-plugins": "./tests/e2e/mu-plugins"
},
"config": {
"WP_DEBUG": true,
"WP_DEBUG_LOG": true,
"WP_DEBUG_DISPLAY": true,
"SCRIPT_DEBUG": true
}
}
2 changes: 1 addition & 1 deletion plugins/sahajanand-post-to-speech/build/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "sahajanand-post-to-speech/post-audio",
"version": "1.0.0",
"version": "1.0.1",
"title": "Sahajanand Post To Speech",
"category": "media",
"icon": "controls-volumeon",
Expand Down
18 changes: 9 additions & 9 deletions plugins/sahajanand-post-to-speech/includes/class-api-client.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,26 @@ class Sahajanand_Post_To_Speech_API_Client {
* @return string|WP_Error Raw WAV bytes.
*/
public function generate( $text, $voice, $speed ) {
$api_url = trailingslashit( get_option( 'sahajanand_post_to_speech_api_url', '' ) );
$api_key = get_option( 'sahajanand_post_to_speech_api_key', '' );
$api_url = (string) get_option( 'sahajanand_post_to_speech_api_url', '' );
$api_key = (string) get_option( 'sahajanand_post_to_speech_api_key', '' );

if ( empty( $api_url ) ) {
if ( '' === $api_url ) {
return new WP_Error(
'sahajanand_post_to_speech_missing_api_url',
__( 'KittenTTS API URL is not configured.', 'sahajanand-post-to-speech' ),
array( 'status' => 400 )
);
}

if ( empty( $api_key ) ) {
if ( '' === $api_key ) {
return new WP_Error(
'sahajanand_post_to_speech_missing_api_key',
__( 'KittenTTS API key is not configured.', 'sahajanand-post-to-speech' ),
array( 'status' => 400 )
);
}

$endpoint = $api_url . 'v1/generate';
$endpoint = trailingslashit( $api_url ) . 'v1/generate';
$body = wp_json_encode(
array(
'text' => $text,
Expand Down Expand Up @@ -109,18 +109,18 @@ public function generate( $text, $voice, $speed ) {
* @return array|WP_Error
*/
public function get_usage() {
$api_url = trailingslashit( get_option( 'sahajanand_post_to_speech_api_url', '' ) );
$api_key = get_option( 'sahajanand_post_to_speech_api_key', '' );
$api_url = (string) get_option( 'sahajanand_post_to_speech_api_url', '' );
$api_key = (string) get_option( 'sahajanand_post_to_speech_api_key', '' );

if ( empty( $api_url ) || empty( $api_key ) ) {
if ( '' === $api_url || '' === $api_key ) {
return new WP_Error(
'sahajanand_post_to_speech_api_not_configured',
__( 'KittenTTS API is not configured.', 'sahajanand-post-to-speech' )
);
}

$response = wp_remote_get(
$api_url . 'v1/usage',
trailingslashit( $api_url ) . 'v1/usage',
array(
'timeout' => 30,
'headers' => array(
Expand Down
2 changes: 1 addition & 1 deletion plugins/sahajanand-post-to-speech/includes/class-media.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public function upload_wav_temp_path( $tmp_path, $post_id = 0 ) {

$result = $this->sideload_file_array( $file, $post_id );

if ( is_wp_error( $result ) && file_exists( $tmp_path ) ) {
if ( is_wp_error( $result ) ) {
wp_delete_file( $tmp_path );
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,8 @@ private function decode_base64_audio_to_temp_file( $audio ) {
fclose( $handle );
// phpcs:enable WordPress.WP.AlternativeFunctions.file_system_operations_fopen, WordPress.WP.AlternativeFunctions.file_system_operations_fclose

if ( 0 === $decoded_size ) {
// Empty payloads are rejected in the decode loop; this guards unexpected zero-byte writes.
if ( $decoded_size < 1 ) { // @phpstan-ignore smaller.alwaysFalse
wp_delete_file( $tmp_file );

return new WP_Error(
Expand Down
Loading
Loading