Changeset 3497127
- Timestamp:
- 04/02/2026 01:32:07 AM (4 days ago)
- Location:
- 1platform-content-ai
- Files:
-
- 12 added
- 10 deleted
- 40 edited
- 1 copied
-
tags/2.19.0 (copied) (copied from 1platform-content-ai/trunk)
-
tags/2.19.0/.git/FETCH_HEAD (modified) (1 diff)
-
tags/2.19.0/.git/ORIG_HEAD (modified) (1 diff)
-
tags/2.19.0/.git/config (modified) (1 diff)
-
tags/2.19.0/.git/index (modified) (previous)
-
tags/2.19.0/.git/logs/HEAD (modified) (1 diff)
-
tags/2.19.0/.git/logs/refs/heads/main (modified) (1 diff)
-
tags/2.19.0/.git/logs/refs/remotes/origin/chore/sonarcloud-integration (modified) (1 diff)
-
tags/2.19.0/.git/logs/refs/remotes/origin/feature/adsense-integration (modified) (1 diff)
-
tags/2.19.0/.git/logs/refs/remotes/origin/feature/seo-basics-site-wizard-49 (deleted)
-
tags/2.19.0/.git/logs/refs/remotes/origin/hotfix/fix-job-queue-cron-self-healing-issue-39 (modified) (1 diff)
-
tags/2.19.0/.git/logs/refs/remotes/origin/main (modified) (1 diff)
-
tags/2.19.0/.git/objects/pack/pack-1a9b4a213d2f59620b06591b048b09ae0b7b3b85.idx (added)
-
tags/2.19.0/.git/objects/pack/pack-1a9b4a213d2f59620b06591b048b09ae0b7b3b85.pack (added)
-
tags/2.19.0/.git/objects/pack/pack-1a9b4a213d2f59620b06591b048b09ae0b7b3b85.rev (added)
-
tags/2.19.0/.git/objects/pack/pack-5dfdb5522136a69d1095109eed5c1587ddf4ff8f.idx (deleted)
-
tags/2.19.0/.git/objects/pack/pack-5dfdb5522136a69d1095109eed5c1587ddf4ff8f.pack (deleted)
-
tags/2.19.0/.git/objects/pack/pack-5dfdb5522136a69d1095109eed5c1587ddf4ff8f.rev (deleted)
-
tags/2.19.0/.git/refs/heads/main (modified) (1 diff)
-
tags/2.19.0/.git/refs/remotes/origin/feature/seo-basics-site-wizard-49 (deleted)
-
tags/2.19.0/.git/refs/remotes/origin/main (modified) (1 diff)
-
tags/2.19.0/.git/refs/tags/qa-v2.18.0-rc66 (modified) (1 diff)
-
tags/2.19.0/.git/refs/tags/v2.19.0 (added)
-
tags/2.19.0/1platform-content-ai.php (modified) (2 diffs)
-
tags/2.19.0/includes/services/content/ContentGeneratorService.php (modified) (7 diffs)
-
tags/2.19.0/includes/services/post/ContentImageProcessor.php (modified) (3 diffs)
-
tags/2.19.0/includes/services/post/ImageUploader.php (modified) (2 diffs)
-
tags/2.19.0/includes/services/post/PostGenerationOrchestrator.php (modified) (6 diffs)
-
tags/2.19.0/includes/services/post/WordPressPostCreator.php (modified) (2 diffs)
-
tags/2.19.0/includes/services/seo (added)
-
tags/2.19.0/includes/services/seo/SeoHeadService.php (added)
-
tags/2.19.0/readme.txt (modified) (2 diffs)
-
trunk/.git/FETCH_HEAD (modified) (1 diff)
-
trunk/.git/ORIG_HEAD (modified) (1 diff)
-
trunk/.git/config (modified) (1 diff)
-
trunk/.git/index (modified) (previous)
-
trunk/.git/logs/HEAD (modified) (1 diff)
-
trunk/.git/logs/refs/heads/main (modified) (1 diff)
-
trunk/.git/logs/refs/remotes/origin/chore/sonarcloud-integration (modified) (1 diff)
-
trunk/.git/logs/refs/remotes/origin/feature/adsense-integration (modified) (1 diff)
-
trunk/.git/logs/refs/remotes/origin/feature/seo-basics-site-wizard-49 (deleted)
-
trunk/.git/logs/refs/remotes/origin/hotfix/fix-job-queue-cron-self-healing-issue-39 (modified) (1 diff)
-
trunk/.git/logs/refs/remotes/origin/main (modified) (1 diff)
-
trunk/.git/objects/pack/pack-1a9b4a213d2f59620b06591b048b09ae0b7b3b85.idx (added)
-
trunk/.git/objects/pack/pack-1a9b4a213d2f59620b06591b048b09ae0b7b3b85.pack (added)
-
trunk/.git/objects/pack/pack-1a9b4a213d2f59620b06591b048b09ae0b7b3b85.rev (added)
-
trunk/.git/objects/pack/pack-5dfdb5522136a69d1095109eed5c1587ddf4ff8f.idx (deleted)
-
trunk/.git/objects/pack/pack-5dfdb5522136a69d1095109eed5c1587ddf4ff8f.pack (deleted)
-
trunk/.git/objects/pack/pack-5dfdb5522136a69d1095109eed5c1587ddf4ff8f.rev (deleted)
-
trunk/.git/refs/heads/main (modified) (1 diff)
-
trunk/.git/refs/remotes/origin/feature/seo-basics-site-wizard-49 (deleted)
-
trunk/.git/refs/remotes/origin/main (modified) (1 diff)
-
trunk/.git/refs/tags/qa-v2.18.0-rc66 (modified) (1 diff)
-
trunk/.git/refs/tags/v2.19.0 (added)
-
trunk/1platform-content-ai.php (modified) (2 diffs)
-
trunk/includes/services/content/ContentGeneratorService.php (modified) (7 diffs)
-
trunk/includes/services/post/ContentImageProcessor.php (modified) (3 diffs)
-
trunk/includes/services/post/ImageUploader.php (modified) (2 diffs)
-
trunk/includes/services/post/PostGenerationOrchestrator.php (modified) (6 diffs)
-
trunk/includes/services/post/WordPressPostCreator.php (modified) (2 diffs)
-
trunk/includes/services/seo (added)
-
trunk/includes/services/seo/SeoHeadService.php (added)
-
trunk/readme.txt (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
1platform-content-ai/tags/2.19.0/.git/FETCH_HEAD
r3497124 r3497127 1 446726a18086b3134b15ccc1642ba4ba1ae9d91bbranch 'main' of https://github.com/1platformlabs/1platform-content-ai1 709aa959b84a1cccdfcb95ca325a7dbd8019c290 branch 'main' of https://github.com/1platformlabs/1platform-content-ai -
1platform-content-ai/tags/2.19.0/.git/ORIG_HEAD
r3497124 r3497127 1 446726a18086b3134b15ccc1642ba4ba1ae9d91b 1 709aa959b84a1cccdfcb95ca325a7dbd8019c290 -
1platform-content-ai/tags/2.19.0/.git/config
r3497124 r3497127 10 10 auto = 0 11 11 [http "https://github.com/"] 12 extraheader = AUTHORIZATION: basic eC1hY2Nlc3MtdG9rZW46Z2hzX 3lNYzExNkR0OXlDZzRXblQ0SU5URzJuM3BSMmhnVDNVeFdaRw==12 extraheader = AUTHORIZATION: basic eC1hY2Nlc3MtdG9rZW46Z2hzXzA2OVU1NnFWc3l3djM3d1hOcW1nOWlLUm9YNFJqOTRIQkxUNA== 13 13 [branch "main"] 14 14 remote = origin -
1platform-content-ai/tags/2.19.0/.git/logs/HEAD
r3497124 r3497127 1 0000000000000000000000000000000000000000 446726a18086b3134b15ccc1642ba4ba1ae9d91b runner <runner@runnervm727z3.umhcbtvdydrevbqwdfzdqmnpzb.cx.internal.cloudapp.net> 1775093211+0000 checkout: moving from master to main1 0000000000000000000000000000000000000000 709aa959b84a1cccdfcb95ca325a7dbd8019c290 runner <runner@runnervmrg6be.zfkur4ax2nlu5onhaw0pux0jqe.ex.internal.cloudapp.net> 1775093477 +0000 checkout: moving from master to main -
1platform-content-ai/tags/2.19.0/.git/logs/refs/heads/main
r3497124 r3497127 1 0000000000000000000000000000000000000000 446726a18086b3134b15ccc1642ba4ba1ae9d91b runner <runner@runnervm727z3.umhcbtvdydrevbqwdfzdqmnpzb.cx.internal.cloudapp.net> 1775093211+0000 branch: Created from refs/remotes/origin/main1 0000000000000000000000000000000000000000 709aa959b84a1cccdfcb95ca325a7dbd8019c290 runner <runner@runnervmrg6be.zfkur4ax2nlu5onhaw0pux0jqe.ex.internal.cloudapp.net> 1775093477 +0000 branch: Created from refs/remotes/origin/main -
1platform-content-ai/tags/2.19.0/.git/logs/refs/remotes/origin/chore/sonarcloud-integration
r3497124 r3497127 1 0000000000000000000000000000000000000000 47874cdf78da218e5246afd6c314e0321d2dfd24 runner <runner@runnervm 727z3.umhcbtvdydrevbqwdfzdqmnpzb.cx.internal.cloudapp.net> 1775093211+0000 fetch --prune --no-recurse-submodules origin +refs/heads/*:refs/remotes/origin/* +refs/tags/*:refs/tags/*: storing head1 0000000000000000000000000000000000000000 47874cdf78da218e5246afd6c314e0321d2dfd24 runner <runner@runnervmrg6be.zfkur4ax2nlu5onhaw0pux0jqe.ex.internal.cloudapp.net> 1775093477 +0000 fetch --prune --no-recurse-submodules origin +refs/heads/*:refs/remotes/origin/* +refs/tags/*:refs/tags/*: storing head -
1platform-content-ai/tags/2.19.0/.git/logs/refs/remotes/origin/feature/adsense-integration
r3497124 r3497127 1 0000000000000000000000000000000000000000 a7a64298a2a6e9760b7176bf1c07193d78033a04 runner <runner@runnervm 727z3.umhcbtvdydrevbqwdfzdqmnpzb.cx.internal.cloudapp.net> 1775093211+0000 fetch --prune --no-recurse-submodules origin +refs/heads/*:refs/remotes/origin/* +refs/tags/*:refs/tags/*: storing head1 0000000000000000000000000000000000000000 a7a64298a2a6e9760b7176bf1c07193d78033a04 runner <runner@runnervmrg6be.zfkur4ax2nlu5onhaw0pux0jqe.ex.internal.cloudapp.net> 1775093477 +0000 fetch --prune --no-recurse-submodules origin +refs/heads/*:refs/remotes/origin/* +refs/tags/*:refs/tags/*: storing head -
1platform-content-ai/tags/2.19.0/.git/logs/refs/remotes/origin/hotfix/fix-job-queue-cron-self-healing-issue-39
r3497124 r3497127 1 0000000000000000000000000000000000000000 6a700de81959c5223e1038b4d493b8fa54344cff runner <runner@runnervm 727z3.umhcbtvdydrevbqwdfzdqmnpzb.cx.internal.cloudapp.net> 1775093211+0000 fetch --prune --no-recurse-submodules origin +refs/heads/*:refs/remotes/origin/* +refs/tags/*:refs/tags/*: storing head1 0000000000000000000000000000000000000000 6a700de81959c5223e1038b4d493b8fa54344cff runner <runner@runnervmrg6be.zfkur4ax2nlu5onhaw0pux0jqe.ex.internal.cloudapp.net> 1775093477 +0000 fetch --prune --no-recurse-submodules origin +refs/heads/*:refs/remotes/origin/* +refs/tags/*:refs/tags/*: storing head -
1platform-content-ai/tags/2.19.0/.git/logs/refs/remotes/origin/main
r3497124 r3497127 1 0000000000000000000000000000000000000000 446726a18086b3134b15ccc1642ba4ba1ae9d91b runner <runner@runnervm727z3.umhcbtvdydrevbqwdfzdqmnpzb.cx.internal.cloudapp.net> 1775093211+0000 fetch --prune --no-recurse-submodules origin +refs/heads/*:refs/remotes/origin/* +refs/tags/*:refs/tags/*: storing head1 0000000000000000000000000000000000000000 709aa959b84a1cccdfcb95ca325a7dbd8019c290 runner <runner@runnervmrg6be.zfkur4ax2nlu5onhaw0pux0jqe.ex.internal.cloudapp.net> 1775093477 +0000 fetch --prune --no-recurse-submodules origin +refs/heads/*:refs/remotes/origin/* +refs/tags/*:refs/tags/*: storing head -
1platform-content-ai/tags/2.19.0/.git/refs/heads/main
r3497124 r3497127 1 446726a18086b3134b15ccc1642ba4ba1ae9d91b 1 709aa959b84a1cccdfcb95ca325a7dbd8019c290 -
1platform-content-ai/tags/2.19.0/.git/refs/remotes/origin/main
r3497124 r3497127 1 446726a18086b3134b15ccc1642ba4ba1ae9d91b 1 709aa959b84a1cccdfcb95ca325a7dbd8019c290 -
1platform-content-ai/tags/2.19.0/.git/refs/tags/qa-v2.18.0-rc66
r3497124 r3497127 1 ab8a80691a01228df2d37bcfae7cb944c0d20edf 1 446726a18086b3134b15ccc1642ba4ba1ae9d91b -
1platform-content-ai/tags/2.19.0/1platform-content-ai.php
r3497124 r3497127 5 5 * Plugin URI: https://1platform.pro/ 6 6 * Description: SaaS client for AI-powered content generation, SEO optimization, and site management. All AI processing happens on 1Platform external servers. Includes free local tools: Table of Contents and Internal Links. 7 * Version: 2.1 7.47 * Version: 2.19.0 8 8 * Author: 1Platform 9 9 * License: GPLv2 or later … … 61 61 require_once plugin_dir_path( __FILE__ ) . 'includes/admin/agents/ContaiAgentsAdminPage.php'; 62 62 require_once plugin_dir_path( __FILE__ ) . 'includes/cron/agent-actions-cron.php'; 63 64 // SEO domain 65 require_once plugin_dir_path(__FILE__) . 'includes/services/seo/SeoHeadService.php'; 66 $contai_seo_head = new ContaiSeoHeadService(); 67 $contai_seo_head->register(); 63 68 64 69 // Analytics domain -
1platform-content-ai/tags/2.19.0/includes/services/content/ContentGeneratorService.php
r3483422 r3497127 167 167 $data['url'] ?? null, 168 168 $seo_metadata['metatitle'] ?? null, 169 $seo_metadata['meta_description'] ?? null, 169 170 $seo_metadata['post_date'] ?? null 170 171 ); … … 189 190 private ?string $slug; 190 191 private ?string $metatitle; 192 private ?string $meta_description; 191 193 private ?string $post_date; 192 194 … … 199 201 ?string $slug = null, 200 202 ?string $metatitle = null, 203 ?string $meta_description = null, 201 204 ?string $post_date = null, 202 205 ?string $error_message = null, … … 210 213 $this->slug = $slug; 211 214 $this->metatitle = $metatitle; 215 $this->meta_description = $meta_description; 212 216 $this->post_date = $post_date; 213 217 $this->error_message = $error_message; … … 222 226 ?string $slug = null, 223 227 ?string $metatitle = null, 228 ?string $meta_description = null, 224 229 ?string $post_date = null 225 230 ): self { 226 return new self(true, $title, $content, $images, $category, $slug, $metatitle, $ post_date, null, 200);231 return new self(true, $title, $content, $images, $category, $slug, $metatitle, $meta_description, $post_date, null, 200); 227 232 } 228 233 229 234 public static function failure(string $error_message, ?int $status_code = null): self { 230 return new self(false, '', '', [], null, null, null, null, $error_message, $status_code);235 return new self(false, '', '', [], null, null, null, null, null, $error_message, $status_code); 231 236 } 232 237 … … 261 266 public function getMetatitle(): ?string { 262 267 return $this->metatitle; 268 } 269 270 public function getMetaDescription(): ?string { 271 return $this->meta_description; 263 272 } 264 273 … … 280 289 'slug' => $this->slug, 281 290 'metatitle' => $this->metatitle, 291 'meta_description' => $this->meta_description, 282 292 'post_date' => $this->post_date, 283 293 'error_message' => $this->error_message, -
1platform-content-ai/tags/2.19.0/includes/services/post/ContentImageProcessor.php
r3483422 r3497127 13 13 } 14 14 15 public function process(string $content, array $images): string { 16 if (empty($images)) { 17 return $content; 15 public function process(string $content, array $images, string $alt_text = ''): string { 16 if (!empty($images)) { 17 $url_map = $this->buildUrlMap($content, $images, $alt_text); 18 $content = $this->replaceUrls($content, $url_map); 18 19 } 19 20 20 $url_map = $this->buildUrlMap($content, $images); 21 if ($alt_text !== '') { 22 $content = $this->ensureImgAltAttributes($content, $alt_text); 23 } 21 24 22 return $ this->replaceUrls($content, $url_map);25 return $content; 23 26 } 24 27 25 private function buildUrlMap(string $content, array $images ): array {28 private function buildUrlMap(string $content, array $images, string $alt_text): array { 26 29 $url_map = []; 27 30 … … 33 36 } 34 37 35 $attachment_id = $this->uploader->uploadFromUrl($external_url); 38 $image_alt = !empty($image['alt_text']) ? $image['alt_text'] : $alt_text; 39 $attachment_id = $this->uploader->uploadFromUrl($external_url, $image_alt); 36 40 37 41 if ($attachment_id === null) { … … 60 64 return $content; 61 65 } 66 67 private function ensureImgAltAttributes(string $content, string $alt_text): string { 68 $escaped_alt = esc_attr($alt_text); 69 70 // Replace empty alt attributes with the keyword-based alt text 71 $content = preg_replace( 72 '/<img([^>]*)\salt=["\']["\']/', 73 '<img$1 alt="' . $escaped_alt . '"', 74 $content 75 ); 76 77 // Add alt attribute to <img> tags missing it entirely 78 $content = preg_replace( 79 '/<img((?![^>]*\salt=)[^>]*)\s*\/?>/', 80 '<img$1 alt="' . $escaped_alt . '">', 81 $content 82 ); 83 84 return $content; 85 } 62 86 } -
1platform-content-ai/tags/2.19.0/includes/services/post/ImageUploader.php
r3483422 r3497127 9 9 } 10 10 11 public function uploadFromUrl(string $image_url ): ?int {11 public function uploadFromUrl(string $image_url, string $alt_text = ''): ?int { 12 12 $temp_file = download_url($image_url); 13 13 … … 20 20 21 21 $this->cleanupTempFile($temp_file); 22 23 if ($attachment_id !== null && $alt_text !== '') { 24 update_post_meta($attachment_id, '_wp_attachment_image_alt', sanitize_text_field($alt_text)); 25 } 22 26 23 27 return $attachment_id; -
1platform-content-ai/tags/2.19.0/includes/services/post/PostGenerationOrchestrator.php
r3497124 r3497127 117 117 $api_result['url'] ?? null, 118 118 $seo_metadata['metatitle'] ?? null, 119 $seo_metadata['meta_description'] ?? null, 119 120 $seo_metadata['post_date'] ?? null 120 121 ); … … 128 129 129 130 private function buildPost(ContaiKeyword $keyword, array $params, ContaiContentGenerationResult $content_result): ContaiPostGenerationResult { 131 $alt_text = $keyword->getTitle() ?: $keyword->getKeyword(); 132 130 133 $processed_content = $this->image_processor->process( 131 134 $content_result->getContent(), 132 $content_result->getImages() 135 $content_result->getImages(), 136 $alt_text 133 137 ); 134 138 … … 139 143 $content_result->getSlug(), 140 144 $content_result->getPostDate(), 141 $content_result->getMetatitle() 145 $content_result->getMetatitle(), 146 $content_result->getMetaDescription() 142 147 ); 143 148 … … 146 151 $this->saveMetadata($post_id, $keyword, $params); 147 152 148 $this->setFeaturedImageIfExists($post_id, $content_result->getImages() );153 $this->setFeaturedImageIfExists($post_id, $content_result->getImages(), $alt_text); 149 154 150 155 return new ContaiPostGenerationResult( … … 186 191 } 187 192 188 private function setFeaturedImageIfExists(int $post_id, array $images ): void {193 private function setFeaturedImageIfExists(int $post_id, array $images, string $alt_text = ''): void { 189 194 if (empty($images)) { 190 195 return; … … 202 207 update_post_meta($post_id, self::META_FEATURED_IMAGE_SOURCE, $selected_url); 203 208 204 $attachment_id = $this->image_uploader->uploadFromUrl($selected_url );209 $attachment_id = $this->image_uploader->uploadFromUrl($selected_url, $alt_text); 205 210 206 211 if ($attachment_id !== null) { -
1platform-content-ai/tags/2.19.0/includes/services/post/WordPressPostCreator.php
r3483422 r3497127 6 6 7 7 private const CUSTOM_FIELD_METATITLE = '_contai_metatitle'; 8 private const META_DESCRIPTION_LENGTH = 155; 8 9 9 public function create(string $title, string $content, ?string $slug = null, ?string $post_date = null, ?string $metatitle = null): int { 10 public function create(string $title, string $content, ?string $slug = null, ?string $post_date = null, ?string $metatitle = null, ?string $meta_description = null): int { 11 $excerpt = !empty($meta_description) ? $meta_description : $this->generateExcerpt($content); 12 10 13 $post_data = [ 11 14 'post_title' => sanitize_text_field($title), 12 15 'post_content' => $content, 13 16 'post_status' => 'publish', 14 'post_type' => 'post' 17 'post_type' => 'post', 18 'post_excerpt' => sanitize_text_field($excerpt), 15 19 ]; 16 20 … … 52 56 } 53 57 58 private function generateExcerpt(string $content): string { 59 $text = wp_strip_all_tags($content); 60 $text = preg_replace('/\s+/', ' ', trim($text)); 61 62 if (mb_strlen($text) <= self::META_DESCRIPTION_LENGTH) { 63 return $text; 64 } 65 66 $truncated = mb_substr($text, 0, self::META_DESCRIPTION_LENGTH); 67 $last_space = mb_strrpos($truncated, ' '); 68 69 if ($last_space !== false) { 70 $truncated = mb_substr($truncated, 0, $last_space); 71 } 72 73 return $truncated . '...'; 74 } 75 54 76 public function assignCategory(int $post_id, int $category_id): void { 55 77 wp_set_object_terms($post_id, [$category_id], 'category', false); -
1platform-content-ai/tags/2.19.0/readme.txt
r3497124 r3497127 5 5 Tested up to: 6.9 6 6 Requires PHP: 7.4 7 Stable tag: 2.1 7.47 Stable tag: 2.19.0 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 161 161 == Changelog == 162 162 163 = 2.18.0 = 164 * Added: SEO alt text on all images uploaded by the content pipeline (#49) 165 * Added: Meta description output via wp_head for generated posts (#49) 166 * Added: SEO title tag override using AI-generated metatitle (#49) 167 * Added: Auto-generated post excerpts for meta description support 168 163 169 = 2.17.3 = 164 170 * Fix: Featured image dedup no longer falls back to first image when all candidates are used — skips featured image to avoid duplication (#47) -
1platform-content-ai/trunk/.git/FETCH_HEAD
r3497124 r3497127 1 446726a18086b3134b15ccc1642ba4ba1ae9d91bbranch 'main' of https://github.com/1platformlabs/1platform-content-ai1 709aa959b84a1cccdfcb95ca325a7dbd8019c290 branch 'main' of https://github.com/1platformlabs/1platform-content-ai -
1platform-content-ai/trunk/.git/ORIG_HEAD
r3497124 r3497127 1 446726a18086b3134b15ccc1642ba4ba1ae9d91b 1 709aa959b84a1cccdfcb95ca325a7dbd8019c290 -
1platform-content-ai/trunk/.git/config
r3497124 r3497127 10 10 auto = 0 11 11 [http "https://github.com/"] 12 extraheader = AUTHORIZATION: basic eC1hY2Nlc3MtdG9rZW46Z2hzX 3lNYzExNkR0OXlDZzRXblQ0SU5URzJuM3BSMmhnVDNVeFdaRw==12 extraheader = AUTHORIZATION: basic eC1hY2Nlc3MtdG9rZW46Z2hzXzA2OVU1NnFWc3l3djM3d1hOcW1nOWlLUm9YNFJqOTRIQkxUNA== 13 13 [branch "main"] 14 14 remote = origin -
1platform-content-ai/trunk/.git/logs/HEAD
r3497124 r3497127 1 0000000000000000000000000000000000000000 446726a18086b3134b15ccc1642ba4ba1ae9d91b runner <runner@runnervm727z3.umhcbtvdydrevbqwdfzdqmnpzb.cx.internal.cloudapp.net> 1775093211+0000 checkout: moving from master to main1 0000000000000000000000000000000000000000 709aa959b84a1cccdfcb95ca325a7dbd8019c290 runner <runner@runnervmrg6be.zfkur4ax2nlu5onhaw0pux0jqe.ex.internal.cloudapp.net> 1775093477 +0000 checkout: moving from master to main -
1platform-content-ai/trunk/.git/logs/refs/heads/main
r3497124 r3497127 1 0000000000000000000000000000000000000000 446726a18086b3134b15ccc1642ba4ba1ae9d91b runner <runner@runnervm727z3.umhcbtvdydrevbqwdfzdqmnpzb.cx.internal.cloudapp.net> 1775093211+0000 branch: Created from refs/remotes/origin/main1 0000000000000000000000000000000000000000 709aa959b84a1cccdfcb95ca325a7dbd8019c290 runner <runner@runnervmrg6be.zfkur4ax2nlu5onhaw0pux0jqe.ex.internal.cloudapp.net> 1775093477 +0000 branch: Created from refs/remotes/origin/main -
1platform-content-ai/trunk/.git/logs/refs/remotes/origin/chore/sonarcloud-integration
r3497124 r3497127 1 0000000000000000000000000000000000000000 47874cdf78da218e5246afd6c314e0321d2dfd24 runner <runner@runnervm 727z3.umhcbtvdydrevbqwdfzdqmnpzb.cx.internal.cloudapp.net> 1775093211+0000 fetch --prune --no-recurse-submodules origin +refs/heads/*:refs/remotes/origin/* +refs/tags/*:refs/tags/*: storing head1 0000000000000000000000000000000000000000 47874cdf78da218e5246afd6c314e0321d2dfd24 runner <runner@runnervmrg6be.zfkur4ax2nlu5onhaw0pux0jqe.ex.internal.cloudapp.net> 1775093477 +0000 fetch --prune --no-recurse-submodules origin +refs/heads/*:refs/remotes/origin/* +refs/tags/*:refs/tags/*: storing head -
1platform-content-ai/trunk/.git/logs/refs/remotes/origin/feature/adsense-integration
r3497124 r3497127 1 0000000000000000000000000000000000000000 a7a64298a2a6e9760b7176bf1c07193d78033a04 runner <runner@runnervm 727z3.umhcbtvdydrevbqwdfzdqmnpzb.cx.internal.cloudapp.net> 1775093211+0000 fetch --prune --no-recurse-submodules origin +refs/heads/*:refs/remotes/origin/* +refs/tags/*:refs/tags/*: storing head1 0000000000000000000000000000000000000000 a7a64298a2a6e9760b7176bf1c07193d78033a04 runner <runner@runnervmrg6be.zfkur4ax2nlu5onhaw0pux0jqe.ex.internal.cloudapp.net> 1775093477 +0000 fetch --prune --no-recurse-submodules origin +refs/heads/*:refs/remotes/origin/* +refs/tags/*:refs/tags/*: storing head -
1platform-content-ai/trunk/.git/logs/refs/remotes/origin/hotfix/fix-job-queue-cron-self-healing-issue-39
r3497124 r3497127 1 0000000000000000000000000000000000000000 6a700de81959c5223e1038b4d493b8fa54344cff runner <runner@runnervm 727z3.umhcbtvdydrevbqwdfzdqmnpzb.cx.internal.cloudapp.net> 1775093211+0000 fetch --prune --no-recurse-submodules origin +refs/heads/*:refs/remotes/origin/* +refs/tags/*:refs/tags/*: storing head1 0000000000000000000000000000000000000000 6a700de81959c5223e1038b4d493b8fa54344cff runner <runner@runnervmrg6be.zfkur4ax2nlu5onhaw0pux0jqe.ex.internal.cloudapp.net> 1775093477 +0000 fetch --prune --no-recurse-submodules origin +refs/heads/*:refs/remotes/origin/* +refs/tags/*:refs/tags/*: storing head -
1platform-content-ai/trunk/.git/logs/refs/remotes/origin/main
r3497124 r3497127 1 0000000000000000000000000000000000000000 446726a18086b3134b15ccc1642ba4ba1ae9d91b runner <runner@runnervm727z3.umhcbtvdydrevbqwdfzdqmnpzb.cx.internal.cloudapp.net> 1775093211+0000 fetch --prune --no-recurse-submodules origin +refs/heads/*:refs/remotes/origin/* +refs/tags/*:refs/tags/*: storing head1 0000000000000000000000000000000000000000 709aa959b84a1cccdfcb95ca325a7dbd8019c290 runner <runner@runnervmrg6be.zfkur4ax2nlu5onhaw0pux0jqe.ex.internal.cloudapp.net> 1775093477 +0000 fetch --prune --no-recurse-submodules origin +refs/heads/*:refs/remotes/origin/* +refs/tags/*:refs/tags/*: storing head -
1platform-content-ai/trunk/.git/refs/heads/main
r3497124 r3497127 1 446726a18086b3134b15ccc1642ba4ba1ae9d91b 1 709aa959b84a1cccdfcb95ca325a7dbd8019c290 -
1platform-content-ai/trunk/.git/refs/remotes/origin/main
r3497124 r3497127 1 446726a18086b3134b15ccc1642ba4ba1ae9d91b 1 709aa959b84a1cccdfcb95ca325a7dbd8019c290 -
1platform-content-ai/trunk/.git/refs/tags/qa-v2.18.0-rc66
r3497124 r3497127 1 ab8a80691a01228df2d37bcfae7cb944c0d20edf 1 446726a18086b3134b15ccc1642ba4ba1ae9d91b -
1platform-content-ai/trunk/1platform-content-ai.php
r3497124 r3497127 5 5 * Plugin URI: https://1platform.pro/ 6 6 * Description: SaaS client for AI-powered content generation, SEO optimization, and site management. All AI processing happens on 1Platform external servers. Includes free local tools: Table of Contents and Internal Links. 7 * Version: 2.1 7.47 * Version: 2.19.0 8 8 * Author: 1Platform 9 9 * License: GPLv2 or later … … 61 61 require_once plugin_dir_path( __FILE__ ) . 'includes/admin/agents/ContaiAgentsAdminPage.php'; 62 62 require_once plugin_dir_path( __FILE__ ) . 'includes/cron/agent-actions-cron.php'; 63 64 // SEO domain 65 require_once plugin_dir_path(__FILE__) . 'includes/services/seo/SeoHeadService.php'; 66 $contai_seo_head = new ContaiSeoHeadService(); 67 $contai_seo_head->register(); 63 68 64 69 // Analytics domain -
1platform-content-ai/trunk/includes/services/content/ContentGeneratorService.php
r3483422 r3497127 167 167 $data['url'] ?? null, 168 168 $seo_metadata['metatitle'] ?? null, 169 $seo_metadata['meta_description'] ?? null, 169 170 $seo_metadata['post_date'] ?? null 170 171 ); … … 189 190 private ?string $slug; 190 191 private ?string $metatitle; 192 private ?string $meta_description; 191 193 private ?string $post_date; 192 194 … … 199 201 ?string $slug = null, 200 202 ?string $metatitle = null, 203 ?string $meta_description = null, 201 204 ?string $post_date = null, 202 205 ?string $error_message = null, … … 210 213 $this->slug = $slug; 211 214 $this->metatitle = $metatitle; 215 $this->meta_description = $meta_description; 212 216 $this->post_date = $post_date; 213 217 $this->error_message = $error_message; … … 222 226 ?string $slug = null, 223 227 ?string $metatitle = null, 228 ?string $meta_description = null, 224 229 ?string $post_date = null 225 230 ): self { 226 return new self(true, $title, $content, $images, $category, $slug, $metatitle, $ post_date, null, 200);231 return new self(true, $title, $content, $images, $category, $slug, $metatitle, $meta_description, $post_date, null, 200); 227 232 } 228 233 229 234 public static function failure(string $error_message, ?int $status_code = null): self { 230 return new self(false, '', '', [], null, null, null, null, $error_message, $status_code);235 return new self(false, '', '', [], null, null, null, null, null, $error_message, $status_code); 231 236 } 232 237 … … 261 266 public function getMetatitle(): ?string { 262 267 return $this->metatitle; 268 } 269 270 public function getMetaDescription(): ?string { 271 return $this->meta_description; 263 272 } 264 273 … … 280 289 'slug' => $this->slug, 281 290 'metatitle' => $this->metatitle, 291 'meta_description' => $this->meta_description, 282 292 'post_date' => $this->post_date, 283 293 'error_message' => $this->error_message, -
1platform-content-ai/trunk/includes/services/post/ContentImageProcessor.php
r3483422 r3497127 13 13 } 14 14 15 public function process(string $content, array $images): string { 16 if (empty($images)) { 17 return $content; 15 public function process(string $content, array $images, string $alt_text = ''): string { 16 if (!empty($images)) { 17 $url_map = $this->buildUrlMap($content, $images, $alt_text); 18 $content = $this->replaceUrls($content, $url_map); 18 19 } 19 20 20 $url_map = $this->buildUrlMap($content, $images); 21 if ($alt_text !== '') { 22 $content = $this->ensureImgAltAttributes($content, $alt_text); 23 } 21 24 22 return $ this->replaceUrls($content, $url_map);25 return $content; 23 26 } 24 27 25 private function buildUrlMap(string $content, array $images ): array {28 private function buildUrlMap(string $content, array $images, string $alt_text): array { 26 29 $url_map = []; 27 30 … … 33 36 } 34 37 35 $attachment_id = $this->uploader->uploadFromUrl($external_url); 38 $image_alt = !empty($image['alt_text']) ? $image['alt_text'] : $alt_text; 39 $attachment_id = $this->uploader->uploadFromUrl($external_url, $image_alt); 36 40 37 41 if ($attachment_id === null) { … … 60 64 return $content; 61 65 } 66 67 private function ensureImgAltAttributes(string $content, string $alt_text): string { 68 $escaped_alt = esc_attr($alt_text); 69 70 // Replace empty alt attributes with the keyword-based alt text 71 $content = preg_replace( 72 '/<img([^>]*)\salt=["\']["\']/', 73 '<img$1 alt="' . $escaped_alt . '"', 74 $content 75 ); 76 77 // Add alt attribute to <img> tags missing it entirely 78 $content = preg_replace( 79 '/<img((?![^>]*\salt=)[^>]*)\s*\/?>/', 80 '<img$1 alt="' . $escaped_alt . '">', 81 $content 82 ); 83 84 return $content; 85 } 62 86 } -
1platform-content-ai/trunk/includes/services/post/ImageUploader.php
r3483422 r3497127 9 9 } 10 10 11 public function uploadFromUrl(string $image_url ): ?int {11 public function uploadFromUrl(string $image_url, string $alt_text = ''): ?int { 12 12 $temp_file = download_url($image_url); 13 13 … … 20 20 21 21 $this->cleanupTempFile($temp_file); 22 23 if ($attachment_id !== null && $alt_text !== '') { 24 update_post_meta($attachment_id, '_wp_attachment_image_alt', sanitize_text_field($alt_text)); 25 } 22 26 23 27 return $attachment_id; -
1platform-content-ai/trunk/includes/services/post/PostGenerationOrchestrator.php
r3497124 r3497127 117 117 $api_result['url'] ?? null, 118 118 $seo_metadata['metatitle'] ?? null, 119 $seo_metadata['meta_description'] ?? null, 119 120 $seo_metadata['post_date'] ?? null 120 121 ); … … 128 129 129 130 private function buildPost(ContaiKeyword $keyword, array $params, ContaiContentGenerationResult $content_result): ContaiPostGenerationResult { 131 $alt_text = $keyword->getTitle() ?: $keyword->getKeyword(); 132 130 133 $processed_content = $this->image_processor->process( 131 134 $content_result->getContent(), 132 $content_result->getImages() 135 $content_result->getImages(), 136 $alt_text 133 137 ); 134 138 … … 139 143 $content_result->getSlug(), 140 144 $content_result->getPostDate(), 141 $content_result->getMetatitle() 145 $content_result->getMetatitle(), 146 $content_result->getMetaDescription() 142 147 ); 143 148 … … 146 151 $this->saveMetadata($post_id, $keyword, $params); 147 152 148 $this->setFeaturedImageIfExists($post_id, $content_result->getImages() );153 $this->setFeaturedImageIfExists($post_id, $content_result->getImages(), $alt_text); 149 154 150 155 return new ContaiPostGenerationResult( … … 186 191 } 187 192 188 private function setFeaturedImageIfExists(int $post_id, array $images ): void {193 private function setFeaturedImageIfExists(int $post_id, array $images, string $alt_text = ''): void { 189 194 if (empty($images)) { 190 195 return; … … 202 207 update_post_meta($post_id, self::META_FEATURED_IMAGE_SOURCE, $selected_url); 203 208 204 $attachment_id = $this->image_uploader->uploadFromUrl($selected_url );209 $attachment_id = $this->image_uploader->uploadFromUrl($selected_url, $alt_text); 205 210 206 211 if ($attachment_id !== null) { -
1platform-content-ai/trunk/includes/services/post/WordPressPostCreator.php
r3483422 r3497127 6 6 7 7 private const CUSTOM_FIELD_METATITLE = '_contai_metatitle'; 8 private const META_DESCRIPTION_LENGTH = 155; 8 9 9 public function create(string $title, string $content, ?string $slug = null, ?string $post_date = null, ?string $metatitle = null): int { 10 public function create(string $title, string $content, ?string $slug = null, ?string $post_date = null, ?string $metatitle = null, ?string $meta_description = null): int { 11 $excerpt = !empty($meta_description) ? $meta_description : $this->generateExcerpt($content); 12 10 13 $post_data = [ 11 14 'post_title' => sanitize_text_field($title), 12 15 'post_content' => $content, 13 16 'post_status' => 'publish', 14 'post_type' => 'post' 17 'post_type' => 'post', 18 'post_excerpt' => sanitize_text_field($excerpt), 15 19 ]; 16 20 … … 52 56 } 53 57 58 private function generateExcerpt(string $content): string { 59 $text = wp_strip_all_tags($content); 60 $text = preg_replace('/\s+/', ' ', trim($text)); 61 62 if (mb_strlen($text) <= self::META_DESCRIPTION_LENGTH) { 63 return $text; 64 } 65 66 $truncated = mb_substr($text, 0, self::META_DESCRIPTION_LENGTH); 67 $last_space = mb_strrpos($truncated, ' '); 68 69 if ($last_space !== false) { 70 $truncated = mb_substr($truncated, 0, $last_space); 71 } 72 73 return $truncated . '...'; 74 } 75 54 76 public function assignCategory(int $post_id, int $category_id): void { 55 77 wp_set_object_terms($post_id, [$category_id], 'category', false); -
1platform-content-ai/trunk/readme.txt
r3497124 r3497127 5 5 Tested up to: 6.9 6 6 Requires PHP: 7.4 7 Stable tag: 2.1 7.47 Stable tag: 2.19.0 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 161 161 == Changelog == 162 162 163 = 2.18.0 = 164 * Added: SEO alt text on all images uploaded by the content pipeline (#49) 165 * Added: Meta description output via wp_head for generated posts (#49) 166 * Added: SEO title tag override using AI-generated metatitle (#49) 167 * Added: Auto-generated post excerpts for meta description support 168 163 169 = 2.17.3 = 164 170 * Fix: Featured image dedup no longer falls back to first image when all candidates are used — skips featured image to avoid duplication (#47)
Note: See TracChangeset
for help on using the changeset viewer.