Changeset 3363822
- Timestamp:
- 09/18/2025 08:47:07 AM (6 months ago)
- Location:
- shortpixel-image-optimiser
- Files:
-
- 70 edited
- 1 copied
-
tags/6.3.4 (copied) (copied from shortpixel-image-optimiser/trunk)
-
tags/6.3.4/class/Controller/AdminController.php (modified) (1 diff)
-
tags/6.3.4/class/Controller/AjaxController.php (modified) (14 diffs)
-
tags/6.3.4/class/Controller/Api/AiController.php (modified) (1 diff)
-
tags/6.3.4/class/Controller/Api/ApiController.php (modified) (2 diffs)
-
tags/6.3.4/class/Controller/BulkController.php (modified) (2 diffs)
-
tags/6.3.4/class/Controller/Front/CDNController.php (modified) (3 diffs)
-
tags/6.3.4/class/Controller/Optimizer/OptimizeAiController.php (modified) (29 diffs)
-
tags/6.3.4/class/Controller/Optimizer/OptimizerBase.php (modified) (2 diffs)
-
tags/6.3.4/class/Controller/Queue/MediaLibraryQueue.php (modified) (3 diffs)
-
tags/6.3.4/class/Controller/Queue/Queue.php (modified) (11 diffs)
-
tags/6.3.4/class/Controller/QueueController.php (modified) (10 diffs)
-
tags/6.3.4/class/Controller/View/EditMediaViewController.php (modified) (7 diffs)
-
tags/6.3.4/class/Controller/View/ListMediaViewController.php (modified) (4 diffs)
-
tags/6.3.4/class/Controller/View/SettingsViewController.php (modified) (3 diffs)
-
tags/6.3.4/class/Helper/UiHelper.php (modified) (2 diffs)
-
tags/6.3.4/class/Helper/UtilHelper.php (modified) (2 diffs)
-
tags/6.3.4/class/Model/AiDataModel.php (modified) (9 diffs)
-
tags/6.3.4/class/Model/Image/ImageModel.php (modified) (1 diff)
-
tags/6.3.4/class/Model/Queue/QueueItem.php (modified) (5 diffs)
-
tags/6.3.4/class/Model/SettingsModel.php (modified) (1 diff)
-
tags/6.3.4/class/external/offload/wp-offload-media.php (modified) (1 diff)
-
tags/6.3.4/class/external/wp-cli/wp-cli-bulk.php (modified) (3 diffs)
-
tags/6.3.4/class/view/bulk/part-selection.php (modified) (4 diffs)
-
tags/6.3.4/class/view/settings/part-ai.php (modified) (7 diffs)
-
tags/6.3.4/class/view/snippets/part-aitext.php (modified) (3 diffs)
-
tags/6.3.4/readme.txt (modified) (2 diffs)
-
tags/6.3.4/res/css/shortpixel-bulk.css (modified) (6 diffs)
-
tags/6.3.4/res/css/shortpixel-bulk.css.map (modified) (1 diff)
-
tags/6.3.4/res/css/shortpixel-settings.css (modified) (6 diffs)
-
tags/6.3.4/res/js/screens/screen-bulk.js (modified) (2 diffs)
-
tags/6.3.4/res/js/screens/screen-item-base.js (modified) (3 diffs)
-
tags/6.3.4/res/js/screens/screen-media.js (modified) (11 diffs)
-
tags/6.3.4/res/scss/shortpixel-bulk.scss (modified) (1 diff)
-
tags/6.3.4/shortpixel-plugin.php (modified) (4 diffs)
-
tags/6.3.4/wp-shortpixel.php (modified) (2 diffs)
-
trunk/class/Controller/AdminController.php (modified) (1 diff)
-
trunk/class/Controller/AjaxController.php (modified) (14 diffs)
-
trunk/class/Controller/Api/AiController.php (modified) (1 diff)
-
trunk/class/Controller/Api/ApiController.php (modified) (2 diffs)
-
trunk/class/Controller/BulkController.php (modified) (2 diffs)
-
trunk/class/Controller/Front/CDNController.php (modified) (3 diffs)
-
trunk/class/Controller/Optimizer/OptimizeAiController.php (modified) (29 diffs)
-
trunk/class/Controller/Optimizer/OptimizerBase.php (modified) (2 diffs)
-
trunk/class/Controller/Queue/MediaLibraryQueue.php (modified) (3 diffs)
-
trunk/class/Controller/Queue/Queue.php (modified) (11 diffs)
-
trunk/class/Controller/QueueController.php (modified) (10 diffs)
-
trunk/class/Controller/View/EditMediaViewController.php (modified) (7 diffs)
-
trunk/class/Controller/View/ListMediaViewController.php (modified) (4 diffs)
-
trunk/class/Controller/View/SettingsViewController.php (modified) (3 diffs)
-
trunk/class/Helper/UiHelper.php (modified) (2 diffs)
-
trunk/class/Helper/UtilHelper.php (modified) (2 diffs)
-
trunk/class/Model/AiDataModel.php (modified) (9 diffs)
-
trunk/class/Model/Image/ImageModel.php (modified) (1 diff)
-
trunk/class/Model/Queue/QueueItem.php (modified) (5 diffs)
-
trunk/class/Model/SettingsModel.php (modified) (1 diff)
-
trunk/class/external/offload/wp-offload-media.php (modified) (1 diff)
-
trunk/class/external/wp-cli/wp-cli-bulk.php (modified) (3 diffs)
-
trunk/class/view/bulk/part-selection.php (modified) (4 diffs)
-
trunk/class/view/settings/part-ai.php (modified) (7 diffs)
-
trunk/class/view/snippets/part-aitext.php (modified) (3 diffs)
-
trunk/readme.txt (modified) (2 diffs)
-
trunk/res/css/shortpixel-bulk.css (modified) (6 diffs)
-
trunk/res/css/shortpixel-bulk.css.map (modified) (1 diff)
-
trunk/res/css/shortpixel-settings.css (modified) (6 diffs)
-
trunk/res/js/screens/screen-bulk.js (modified) (2 diffs)
-
trunk/res/js/screens/screen-item-base.js (modified) (3 diffs)
-
trunk/res/js/screens/screen-media.js (modified) (11 diffs)
-
trunk/res/scss/shortpixel-bulk.scss (modified) (1 diff)
-
trunk/shortpixel-plugin.php (modified) (4 diffs)
-
trunk/wp-shortpixel.php (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
shortpixel-image-optimiser/tags/6.3.4/class/Controller/AdminController.php
r3346588 r3363822 127 127 $queueController = new QueueController(); 128 128 129 if ($optimizeAiController->isAutoAiEnabled())129 /* if ($optimizeAiController->isAutoAiEnabled()) 130 130 { 131 131 $args = ['action' => 'requestAlt']; 132 132 $queueController->addItemToQueue($mediaItem, $args); 133 } 133 } */ 134 134 135 135 -
shortpixel-image-optimiser/tags/6.3.4/class/Controller/AjaxController.php
r3346588 r3363822 690 690 $this->checkImageAccess($imageModel); 691 691 692 $smartcrop = false; 692 $args = ['action' => 'reoptimize', 'compressionType' => $compressionType]; 693 694 // Smartcrop is not always passed, only add here when passed otherwise to defaults. 693 695 if ($actionType == ImageModel::ACTION_SMARTCROP || $actionType == ImageModel::ACTION_SMARTCROPLESS) 694 696 { 695 $ smartcrop= $actionType;697 $args['smartcrop'] = $actionType; 696 698 } 697 699 698 700 // @todo Ideally this should go to QueueController - addItemToQueue, but issue with arguments. Leaving it for now. 699 701 $queueController = new QueueController(); 700 $result = $queueController->addItemToQueue($imageModel, ['action' => 'reoptimize', 'compressionType' => $compressionType, 701 'smartcrop' => $smartcrop]); 702 $result = $queueController->addItemToQueue($imageModel, $args); 702 703 703 704 … … 807 808 protected function createBulk($json, $data) 808 809 { 810 $filters = []; 811 $has_filters = false; 812 813 if (isset($_POST['filter_startdate'])) 814 { 815 $filters['start_date'] = intval($_POST['filter_startdate']); 816 $has_filters = true; 817 } 818 if (isset($_POST['filter_enddate'])) 819 { 820 $filters['end_date'] = intval($_POST['filter_enddate']); 821 $has_filters = true; 822 823 } 824 825 $args = []; 826 if (true === $has_filters) 827 { 828 $args['filters'] = $filters; 829 } 830 831 832 809 833 $bulkControl = BulkController::getInstance(); 810 $stats = $bulkControl->createNewBulk('media' );834 $stats = $bulkControl->createNewBulk('media', $args); 811 835 $json->media->stats = $stats; 812 836 813 $stats = $bulkControl->createNewBulk('custom' );837 $stats = $bulkControl->createNewBulk('custom', $args); 814 838 $json->custom->stats = $stats; 815 839 … … 827 851 828 852 $doAi = filter_var(sanitize_text_field($_POST['aiActive']), FILTER_VALIDATE_BOOLEAN); 853 854 $aiPreserve = isset($_POST['aiPreserve']) ? filter_var(sanitize_text_field($_POST['aiPreserve']), FILTER_VALIDATE_BOOLEAN) : null; 855 829 856 $backgroundProcess = filter_var(sanitize_text_field($_POST['backgroundProcess']), FILTER_VALIDATE_BOOLEAN); 830 857 … … 841 868 \wpSPIO()->settings()->autoAIBulk = $doAi; 842 869 870 if (false === is_null($aiPreserve)) 871 { 872 \wpSPIO()->settings()->aiPreserve = $aiPreserve; 873 } 874 843 875 $bulkControl = BulkController::getInstance(); 844 876 … … 887 919 888 920 if (in_array('media', $queues)) { 889 $stats = $bulkControl->createNewBulk('media', 'bulk-restore');921 $stats = $bulkControl->createNewBulk('media', ['customOp' => 'bulk-restore']); 890 922 $json->media->stats = $stats; 891 923 } 892 924 893 925 if (in_array('custom', $queues)) { 894 $stats = $bulkControl->createNewBulk('custom', 'bulk-restore');926 $stats = $bulkControl->createNewBulk('custom', ['customOp' => 'bulk-restore']); 895 927 $json->custom->stats = $stats; 896 928 } … … 905 937 906 938 907 $stats = $bulkControl->createNewBulk('media', 'migrate');939 $stats = $bulkControl->createNewBulk('media', ['customOp' => 'migrate']); 908 940 $json->media->stats = $stats; 909 941 … … 917 949 918 950 919 $stats = $bulkControl->createNewBulk('media', 'removeLegacy');951 $stats = $bulkControl->createNewBulk('media', ['customOp' => 'removeLegacy']); 920 952 $json->media->stats = $stats; 921 953 … … 984 1016 985 1017 $optimizer = $qItem->getApiController('requestAlt'); 986 //$optimize->useCustomSettings($settingsData);987 //$result = $optimizer->enqueueItem($qItem, array_merge(['preview_only' => true, 'action' => 'requestAlt'], $settingsData));988 1018 989 1019 $qItem->requestAltAction(array_merge(['preview_only' => true], $settingsData)); … … 1021 1051 if (property_exists($result, 'aiData')) 1022 1052 { 1053 $aiModel = AiDataModel::getModelByAttachment($qItem->item_id, 'media'); 1054 1023 1055 $aiData = $optimizer->formatResultData($result->aiData, $qItem); 1056 list($items, $aiData) = $optimizer->formatGenerated($aiData, $aiModel->getCurrentData(), $aiModel->getOriginalData()); 1024 1057 $aiData['item_id'] = $qItem->item_id; 1025 1058 $aiData['time_generated'] = time(); … … 1039 1072 } 1040 1073 } 1041 1042 1043 //$is_done = true;1044 //$this->send((object) $result_json);1045 //break;1046 1074 1047 1075 } … … 1059 1087 $i++; 1060 1088 } 1061 1062 //$this->send($result_json);1063 1064 1089 } 1065 1090 … … 1076 1101 else 1077 1102 { 1078 $item = new AiDataModel($id);1103 $item = AiDataModel::getModelByAttachment($id); 1079 1104 $attach_id = $id; 1080 1105 } 1081 1082 // $attach_id = null;1083 1106 1084 1107 $imageModel = \wpSPIO()->fileSystem()->getMediaImage($attach_id); … … 1540 1563 { 1541 1564 1565 // defaults 1566 $message = __('This user is not allowed to edit this image', 'shortpixel-image-optimiser'); 1567 1542 1568 $accessModel = AccessModel::getInstance(); 1543 1569 if (is_object($mediaItem)) { 1544 1570 $bool = $accessModel->imageIsEditable($mediaItem); 1545 1571 $id = $mediaItem->get('id'); 1572 1546 1573 } else { 1547 1574 $bool = false; 1548 1575 $id = false; 1576 if (! is_object($mediaItem)) 1577 { 1578 $message = __('Image does not exist or could not be loaded', 'shortpixel-image-optimiser'); 1579 } 1549 1580 } 1550 1581 1551 1582 if ($bool === false) { 1552 1583 $json = new \stdClass; 1553 $json->message = __('This user is not allowed to edit this image', 'shortpixel-image-optimiser');1584 $json->message = $message; 1554 1585 $json->status = false; 1555 1586 $json->id = $id; … … 1573 1604 1574 1605 wp_send_json($json); 1575 1576 1606 exit(); 1577 1607 } -
shortpixel-image-optimiser/tags/6.3.4/class/Controller/Api/AiController.php
r3347742 r3363822 235 235 protected function handleSuccess($aiData, QueueItem $qItem) 236 236 { 237 237 if (false === is_null($qItem->data()->returndatalist)) 238 { 239 $returndatalist = $qItem->data()->returndatalist; 240 if (is_object($returndatalist)) 241 { 242 $returndatalist = (array) $returndatalist; 243 } 244 245 foreach($returndatalist as $name => $data) 246 { 247 if (is_object($data)) // annoying conversion somehow by json decode from record 248 { 249 $data = (array) $data; 250 } 251 if (! isset($aiData[$name]) && isset($data['status'])) 252 { 253 $aiData[$name] = $data['status']; 254 } 255 } 256 } 257 238 258 return $this->returnSuccess(['aiData' => $aiData], RequestManager::STATUS_SUCCESS, __('Retrieved AI image SEO data', 'shortpixel-image-optimiser')); ; 239 259 } -
shortpixel-image-optimiser/tags/6.3.4/class/Controller/Api/ApiController.php
r3289850 r3363822 239 239 $imageName = $imageNames[$index]; 240 240 $fileName = $fileNames[$index]; 241 $paramlist = $qItem->data()->paramlist; 242 243 // Here add paramList items that are possible needed for success checks 244 $params = isset($paramlist[$index]) ? (array) $paramlist[$index] : []; 245 246 241 247 $data = array( 242 248 'fileName' => $fileName, 243 249 'imageName' => $imageName, 244 250 ); 251 252 $data = array_merge($params, $data); 245 253 246 254 // Filesize might not be present, but also imageName ( only if smartcrop is done, might differ per image) … … 399 407 400 408 if (false === $this->checkFileSizeMargin($originalFileSize, $checkFileSize)) { 401 $image['image']['status'] = self::STATUS_OPTIMIZED_BIGGER; 402 $checkFileSize = $originalFileSize; 409 410 // Prevent this check if smartcrop is active on this image. 411 if (isset($data['resize']) && 4 == $data['resize'] ) 412 { 413 $image['image']['status'] = self::STATUS_OPTIMIZED_BIGGER; 414 $checkFileSize = $originalFileSize; 415 } 403 416 } 404 417 -
shortpixel-image-optimiser/tags/6.3.4/class/Controller/BulkController.php
r3289850 r3363822 37 37 * 'bulk-restore', or 'migrate'. 38 38 */ 39 public function createNewBulk($type = 'media', $customOp = null) 40 { 39 public function createNewBulk($type = 'media', $args = []) 40 { 41 $defaults = [ 42 'customOp' => null, 43 'filters' => [], 44 45 ]; 46 47 48 $args = wp_parse_args($args, $defaults); 49 41 50 $queueController = new QueueController(['is_bulk' => true]); 42 51 … … 53 62 $Q = $queueController->getQueue($type); 54 63 55 $Q->createNewBulk(); 56 57 if (! is_null($customOp)) 64 if (! is_null($args['customOp'])) 58 65 { 59 $options = array(); 66 $customOp = $args['customOp']; 67 //$args['customOp'] = $customOp; 60 68 if ($customOp == 'bulk-restore') 61 69 { 62 $options['numitems'] = 5; 63 $options['retry_limit'] = 5; 64 $options['process_timeout'] = 3000; 70 $args['numitems'] = 5; 71 $args['retry_limit'] = 5; 72 $args['process_timeout'] = 3000; 73 65 74 } 66 75 if ($customOp == 'migrate' || $customOp == 'removeLegacy') 67 76 { 68 $ options['numitems'] = 200;77 $args['numitems'] = 200; 69 78 } 70 79 71 $ options = apply_filters('shortpixel/bulk/custom_options', $options, $customOp);72 $Q->setCustomBulk($customOp, $options); 80 $args = apply_filters('shortpixel/bulk/custom_options', $args); 81 73 82 } 83 84 85 $Q->createNewBulk($args); 86 74 87 75 88 return $Q->getStats(); -
shortpixel-image-optimiser/tags/6.3.4/class/Controller/Front/CDNController.php
r3346588 r3363822 299 299 $fonts = ['.ttf', '.woff', '.woff2', '.otf']; 300 300 301 if (true == $settings->cdn_js) {301 if (true === $settings->cdn_js) { 302 302 $checkExtensions[] = '.js'; 303 303 304 304 } 305 if (true == $settings->cdn_css)305 if (true === $settings->cdn_css) 306 306 { 307 307 $checkExtensions[] = '.css'; … … 353 353 $replaceBlocks = $this->filterRegexExclusions($replaceBlocks); 354 354 $replaceBlocks = $this->filterOtherDomains($replaceBlocks); 355 $replaceBlocks = $this->filterFonts($replaceBlocks); 355 356 356 357 if (count($replaceBlocks) > 0) { … … 466 467 } 467 468 469 470 } 471 472 /** The image check on inline CSS might also catch inline fonts. Check against settings if they should be processed or not. 473 * 474 * @param mixed $replaceBlocks 475 * @return mixed 476 */ 477 protected function filterFonts($replaceBlocks) 478 { 479 $settings = \wpSPIO()->settings(); 480 481 if (true === $settings->cdn_css) 482 { 483 return $replaceBlocks; 484 } 485 486 $replaceBlocks = array_filter($replaceBlocks, function ($replaceBlock) 487 { 488 $fonts = ['.ttf', '.woff', '.woff2', '.otf']; 489 foreach($fonts as $extcheck) 490 { 491 if (strpos($replaceBlock->url, $extcheck) !== false) 492 { 493 return false; 494 } 495 } 496 return true; 497 498 }); 499 500 return $replaceBlocks; 468 501 469 502 } -
shortpixel-image-optimiser/tags/6.3.4/class/Controller/Optimizer/OptimizeAiController.php
r3348311 r3363822 46 46 } 47 47 48 // $qItem->addResult(['qStatus' => Queue::RESULT_ERROR]);49 48 return; 50 49 } … … 53 52 public function sendToProcessing(QueueItem $qItem) { 54 53 55 if (false == $this->isSupported($qItem))54 /* if (false == $this->isSupported($qItem)) 56 55 { 57 56 // For now only fail here is GIF support, so message is a backstop for now that later should be updated. … … 65 64 } 66 65 else 67 { 66 { */ 68 67 $this->api->processMediaItem($qItem, $qItem->imageModel); 69 }68 //} 70 69 71 70 } … … 75 74 { 76 75 77 $aiDataModel = new AiDataModel($qItem->item_id);76 $aiDataModel = AiDataModel::getModelByAttachment($qItem->item_id); 78 77 $is_processable = $aiDataModel->isProcessable(); 79 78 80 79 if (false === $is_processable) { 80 $message = $aiDataModel->getProcessableReason(); 81 81 $qItem->addResult([ 82 'message' => __('AI generation not possible or already generated', 'shortpixel-image-optimiser'),82 'message' => $message, 83 83 'is_error' => true, 84 84 'is_done' => true, … … 107 107 break; 108 108 case 'retrieveAlt': // This might be deprecated, since retrieve will be called via next_action. 109 $qItem->retrieveAltAction($args ['remote_id']);109 $qItem->retrieveAltAction($args); 110 110 $directAction = false; 111 111 break; … … 226 226 // Always save the original filename 227 227 $aiData['original_filebase'] = $qItem->imageModel->getFileBase(); 228 $returnDataList = $qItem->data()->returndatalist; 228 229 229 230 if (! isset($aiData['filebase'])) … … 236 237 foreach($textItems as $textItem) 237 238 { 238 if (isset($aiData[$textItem]) && false !== $aiData[$textItem]) 239 240 if (isset($aiData[$textItem]) && false !== $aiData[$textItem] && false === is_numeric($aiData[$textItem])) 239 241 { 240 242 $aiData[$textItem] = $this->processTextResult($aiData[$textItem]); 241 243 } 242 } 244 // If 1 is returned as data, this means for some reason the API didn't create a text for this field, while it is allowed to do so. Defer to empty string better than '1' 245 if (true === is_numeric($aiData[$textItem]) && 1 == $aiData[$textItem]) 246 { 247 $aiData[$textItem] = ''; 248 } 249 } 250 251 // Re-add Result after formatting so it passed back 252 //$qItem->addResult(['aiData' => $aiData]); 253 243 254 244 255 return $aiData; … … 248 259 { 249 260 $aiData = $qItem->result->aiData; 250 $settings = $this->getAISettings(); 251 261 $settings = \wpSPIO()->settings(); 252 262 253 263 $checks = ['alt' => 'ai_gen_alt', … … 257 267 ]; 258 268 259 foreach($checks as $check_name => $check_setting)260 {261 if (false === $settings[$check_setting])262 {263 unset($aiData[$check_name]);264 }265 }266 267 268 269 $aiData = $this->formatResultData($aiData, $qItem); 269 270 … … 273 274 $item_id = $qItem->item_id; 274 275 275 $aiModel = new AIDataModel($item_id, 'media');276 $aiModel = AiDataModel::getModelByAttachment($item_id, 'media'); 276 277 $aiModel->handleNewData($aiData); 277 278 … … 292 293 } 293 294 */ 295 294 296 $imageModel = $qItem->imageModel; 295 $qItem->addResult(['improvements' => $imageModel->getImprovements()]); 296 297 298 $this->addPreview($qItem); 297 $qItem->addResult(['improvements' => $imageModel->getImprovements()]); // Improvements for bulk UX. 298 299 $this->addPreview($qItem); // Preview ( image ) for bulk UX 300 301 AiDataModel::flushModelCache($item_id); 302 303 // Get generated data which is the final result for the action including exclusions etc. 304 $data = $this->getAltData($qItem); 305 $qItem->addResult(['aiData' => $data['generated']]); // But the generated data in the result. 299 306 300 307 $this->finishItemProcess($qItem); … … 312 319 protected function replaceImageAttributes(QueueItem $qItem, $aiData) 313 320 { 321 if (is_int($aiData['alt']) && is_int($aiData['caption'])) 322 { 323 Log::addInfo('Alt/Caption returned integer/status, not replace'); 324 return; 325 } 326 314 327 // Replacer Part 315 328 $url = $qItem->data()->url; … … 392 405 if ($targetFileObj->exists()) 393 406 { 394 //$qItem->result()->is_error = true;395 //$qItem->result()->message = __('Replace Files: File Already exists', 'shortpixel-image-optimiser');396 407 Log::addWarn('Replace files found filename conflict and didnt run', $targetFileObj->getFullPath()); 397 408 return false; … … 414 425 } 415 426 416 417 418 419 427 $replacer = new Replacer(); 420 428 $replacer->setSource($source_url); … … 424 432 425 433 $replacer->replace(); 426 427 434 428 435 $this->replaceMetaData($item_id, $base_filename, $newFileName ); … … 511 518 } */ 512 519 513 $ sources[] = $match;514 515 if (isset($aiData['alt']) )520 $do_replace = false; 521 522 if (isset($aiData['alt']) && false === is_int($aiData['alt'])) 516 523 { 517 524 $frontImage->alt = $aiData['alt']; 525 $do_replace = true; 518 526 } 519 if (isset($aiData['caption']) )527 if (isset($aiData['caption']) && false === is_int($aiData['caption'])) 520 528 { 521 529 $frontImage->caption = $aiData['caption']; 530 $do_replace = true; 522 531 } 523 532 524 $replaces[] = $frontImage->buildImage(); 525 533 if (true === $do_replace) 534 { 535 $sources[] = $match; 536 $replaces[] = $frontImage->buildImage(); 537 } 526 538 527 539 } 528 540 529 $content = $replacer2->replaceContent($content, $sources, $replaces); 530 531 $replacer2->Updater()->updatePost($post_id, $content); 541 if (count($sources) > 0 && count($replaces) > 0) 542 { 543 Log::addInfo('Running Ai Replace : ', [$aiData, $sources, $replaces]); 544 $content = $replacer2->replaceContent($content, $sources, $replaces); 545 $replacer2->Updater()->updatePost($post_id, $content); 546 } 532 547 } 533 548 … … 544 559 } 545 560 561 /* 562 protected function fetchCaptionMatches($content, $qItem) 563 { 564 $pattern = '/' 565 } 566 */ 546 567 /** 547 568 * Check if setting AI is enabled in settings. … … 598 619 } 599 620 600 protected function getRequestJSON($url, $item_id, $params = []) 621 /* 622 protected function getRequestJSON($url, $params = []) 601 623 { 602 624 $settings = $this->getAISettings($params); 625 626 $ignore_fields = (isset($params['ignore_fields'])) ? $params['ignore_fields'] : []; 603 627 604 628 $json = [ … … 646 670 } 647 671 672 */ 673 674 /* 648 675 public function parseJSONForQItem(QueueItem $qItem, $params = []) 649 676 { 650 677 $url = $qItem->data()->url; 651 678 $item_id = $qItem->item_id; 652 $json = $this->getRequestJSON($url, $item_id, $params); 679 $settings = \wpSPIO()->settings(); 680 681 // Note this is also checked in AiDataModel for checking processable. Might need to sync upon adding fields 682 if (true === $settings->aiPreserve) 683 { 684 $returnDataList = $qItem->data()->returndatalist; 685 686 $aiModel = AiDataModel::getModelByAttachment($item_id, 'media'); 687 $current = $aiModel->getCurrentData(); 688 $filtered = array_filter($current); // filter out all empty variables 689 690 // $altdata = $this->getAltData($qItem); 691 $params['ignore_fields'] = array_keys($filtered); 692 693 foreach($filtered as $key => $filter) 694 { 695 $returnDataList[$key] = AiDataModel::F_STATUS_EXCLUDE; 696 } 697 $qItem->data()->returndatalist = $returnDataList; 698 } 699 700 $json = $this->getRequestJSON($url, $params); 701 702 653 703 $qItem->data()->paramlist = $json; 654 704 } 655 705 */ 706 707 /* 656 708 protected function parseQuestionForQItem(QueueItem $qItem) 657 709 { … … 661 713 $qItem->data()->url = $question; 662 714 } 663 715 */ 716 /* 664 717 private function getAISettings($params = []) 665 718 { … … 684 737 'ai_use_exif' => $settings->ai_use_exif, 685 738 'ai_language' => $settings->ai_language, 739 'aiPreserve' => $settings->aiPreserve, 686 740 ]; 687 741 … … 690 744 return $params; 691 745 } 692 693 public function parseQuestion($url, $item_id, $params = []) 694 { 695 $settings = \wpSPIO()->settings(); 696 697 $defaults = [ 698 'ai_general_context' => $settings->ai_general_context, 699 'ai_use_post' => $settings->ai_use_post, 700 'ai_gen_alt' => $settings->ai_gen_alt, 701 'ai_gen_caption' => $settings->ai_gen_caption, 702 'ai_gen_description' => $settings->ai_gen_description, 703 'ai_filename_prefercurrent' => $settings->ai_filename_prefercurrent, 704 'ai_limit_alt_chars' => $settings->ai_limit_alt_chars, 705 'ai_alt_context' => $settings->ai_alt_context, 706 'ai_limit_description_chars' => $settings->ai_limit_description_chars, 707 'ai_description_context' => $settings->ai_description_context, 708 'ai_limit_caption_chars' => $settings->ai_limit_caption_chars, 709 'ai_caption_context' => $settings->ai_caption_context, 710 'ai_gen_filename' => $settings->ai_gen_filename, 711 'ai_limit_filename_chars' => $settings->ai_limit_filename_chars, 712 'ai_filename_context' => $settings->ai_filename_context, 713 'ai_use_exif' => $settings->ai_use_exif, 714 'ai_language' => $settings->ai_language, 715 ]; 716 717 $params = wp_parse_args($params, $defaults); 718 719 $question = [ 720 'main' => $params['ai_general_context'], 721 'language' => $params['ai_language'], 722 'required_tags' => [], 723 ]; 724 725 $question['page'] = $this->getPageQuestion($question, $item_id, $params); 746 */ 726 747 727 $question = $this->getPartQuestion($question, 'alt', $params); 728 $question = $this->getPartQuestion($question, 'caption', $params); 729 $question = $this->getPartQuestion($question, 'description', $params); 730 $question = $this->getPartQuestion($question, 'filename', $params); 731 732 if (true == $params['ai_use_exif']) 733 { 734 $question['exif'] = ' and take into account the image EXIF data when generating all the requested texts'; 735 } 736 737 // $question['tags'] = implode($question['required_tags'], ','); 738 739 $question = apply_filters('shortpixel/ai/parsed_questions', $question); 740 741 /* $alt = isset($question['alt']) ? $question['alt'] : ''; 742 $caption = isset($question['caption']) ? $question['caption'] : ''; 743 $description =isset($question['description']) ? $question['description'] : ''; 744 $filename = isset($question['filename']) ? $question['filename'] : ''; 745 */ 746 $specs = []; 747 foreach($question['required_tags'] as $tag) 748 { 749 $specs[] = $question[$tag]; 750 } 751 $specs = implode(' ', $specs); 752 753 $required_tags = implode(',', $question['required_tags_ainame']); 754 755 if (strlen(trim($params['ai_language'])) <= 0) 756 { 757 $params['ai_language'] = get_locale(); 758 } 759 760 $final_question = sprintf("For the URL %s , with this context \" %s \" , write for %s SEO friendly texts with the following specifications: %s in %s language %s . Provide the answer in JSON format, seperating the %s output in seperate fields", 761 $url, 762 $question['main'], 763 $required_tags, 764 $specs, 765 $question['language'], 766 $question['exif'], 767 $required_tags 768 769 770 ); 771 772 return $final_question; 773 774 } 775 776 protected function getPartQuestion($question, $name, $params) 777 { 778 779 $limit = 'ai_limit_' . $name . '_chars'; 780 $context = 'ai_' . $name . '_context'; 781 $to_use = 'ai_gen_' . $name; 782 783 switch($name) 784 { 785 case 'alt': 786 $aiName = 'alt tag'; 787 break; 788 case 'caption': 789 $aiName = 'caption tag'; 790 break; 791 case 'description': 792 $aiName = 'description text'; 793 break; 794 case 'filename': 795 $aiName = 'the file name'; 796 break; 797 } 798 799 if (true === $params[$to_use]) 800 { 801 $limit = $params[$limit]; 802 $context = $params[$context]; 803 804 $string = ' For the ' . $aiName . ' limit your response to the most relevant ' . $limit . ' characters for SEO '; 805 806 if ('filename' == $name) 807 { 808 $string .= ' leaving the filename extension intact '; 809 if (true === $params['ai_filename_prefercurrent']) 810 { 811 $string .= ' and change filename only when the current filename is not relevant. Otherwise return false for this field '; 812 } 813 814 } 815 816 if (strlen(trim($context)) > 0) 817 { 818 $string .= ' and use this additional information when generating the ' . $aiName . ':' . $context . '. '; 819 } 820 821 $question[$name] = $string; 822 $question['required_tags_ainame'][] = $aiName; 823 $question['required_tags'][] = $name; 824 } 825 826 827 return $question; 828 } 829 830 protected function getPageQuestion($question, $item_id, $params) 831 { 832 if (false == $params['ai_use_post']) 833 { 834 return false; 835 } 836 837 $post = get_post($item_id); 838 if (is_null($post) || false === $post) 839 { 840 return false; 841 } 842 843 $parent = $post->post_parent; 844 845 if ($parent <= 0 || ! is_int($parent)) 846 { 847 return false; 848 } 849 850 $page_post = get_post($parent); 851 if (is_null($page_post) || false === $page_post) 852 { 853 return false; 854 } 855 856 $title = $page_post->post_title; 857 $excerpt = get_the_excerpt(($page_post)); 858 859 $string = ' for the article with the title ' . $title; 860 861 if (strlen(trim($excerpt)) > 0 ) 862 { 863 $string .= ' and excerpt ' . $excerpt; 864 } 865 866 867 return $string; 868 } 869 870 871 748 749 /* 872 750 public function isSupported(queueItem $qItem) 873 751 { … … 881 759 882 760 return true; 883 } 761 } */ 884 762 885 763 public function undoAltData(QueueItem $qItem) 886 764 { 887 765 $item_id = $qItem->item_id; 888 $aiModel = new AiDataModel($item_id, 'media');766 $aiModel = AiDataModel::getModelByAttachment($item_id, 'media'); 889 767 $original = $aiModel->getOriginalData(); 890 768 $generated = $aiModel->getGeneratedData(); 769 891 770 892 771 $aiData = [ … … 898 777 899 778 $aiModel->revert(); 779 AiDataModel::flushModelCache($item_id); 900 780 901 781 $this->replaceImageAttributes($qItem, $aiData); 902 782 783 $aiData = $aiModel->getCurrentData(); 784 903 785 return $this->getAltData($qItem); 904 786 } … … 908 790 $item_id = $qItem->item_id; 909 791 910 $aiModel = new AiDataModel($item_id, 'media');792 $aiModel = AiDataModel::getModelByAttachment($item_id, 'media'); 911 793 912 794 $status = $aiModel->getStatus(); … … 920 802 $aiModel->migrate($metacheck); 921 803 delete_post_meta($item_id, 'shortpixel_alt_requests'); 922 $aiModel = new AiDataModel($item_id, 'media');804 $aiModel = AiDataModel::getModelByAttachment($item_id, 'media'); 923 805 $status = $aiModel->getStatus(); 924 806 } … … 927 809 $generated = $aiModel->getGeneratedData(); 928 810 $original = $aiModel->getOriginalData(); 811 $current = $aiModel->getCurrentData(); 929 812 930 813 $image_url = $qItem->imageModel->getUrl(); 931 814 932 $fields = ['alt', 'caption', 'description']; 933 $dataItems = []; 934 foreach($fields as $name) 935 { 936 if (isset($generated[$name]) && false === is_null($generated[$name]) && strlen($generated[$name]) > 1) 937 { 938 $dataItems[] = ucfirst($name); 939 } 940 } 815 list($dataItems, $generated) = $this->formatGenerated($generated, $current, $original); 816 941 817 942 818 $view = new ViewController(); … … 946 822 'result_alt' => $generated['alt'], 947 823 'has_data' => ($status == AiDataModel::AI_STATUS_GENERATED) ? true : false, 824 'is_processable' => $aiModel->isProcessable(), 825 'processable_reason' => $aiModel->getProcessableReason(), 826 'processable_status' => $aiModel->getProcessableReason(true), 948 827 'image_url' => $image_url, 949 828 // 'current_alt' => $current_alt, 950 829 'status' => $status, 951 'isSupported' => $this->isSupported($qItem),952 'dataItems' => $dataItems, 830 // 'isSupported' => $this->isSupported($qItem), 831 'dataItems' => $dataItems, // This seems not used(?) 953 832 'isDifferent' => $aiModel->currentIsDifferent(), 954 833 ]); 955 834 835 836 // *****!!! Temporary don't pass these back since we don't support it yet ** // 837 838 if (isset($generated['filebase'])) 839 { 840 unset($generated['filebase']); 841 } 842 if (isset($generated['filename'])) 843 { 844 unset($generated['filename']); 845 } 846 956 847 $metadata['snippet'] = $view->returnView('snippets/part-aitext'); 957 848 958 849 $metadata['generated'] = $generated; 959 850 $metadata['original'] = $original; 851 $metadata['current'] = $current; 960 852 $metadata['action'] = $qItem->data()->action; 961 853 $metadata['item_id'] = $item_id; … … 964 856 } 965 857 858 public function formatGenerated($generated, $current, $original) 859 { 860 861 $fields = ['alt', 'caption', 'description']; 862 $dataItems = []; 863 864 // Statii from AiDataModel which means generated is not available (replace for original/current?) 865 $statii = [AiDataModel::F_STATUS_PREVENTOVERRIDE, AiDataModel::F_STATUS_EXCLUDESETTING]; 866 867 foreach($fields as $name) 868 { 869 if (false === isset($generated[$name])) 870 { 871 continue; 872 } 873 $value = $generated[$name]; 874 875 876 if (false === is_null($value) && false === is_int($value) && strlen($value) > 1) 877 { 878 $dataItems[] = ucfirst($name); 879 } 880 if (is_int($value) && in_array($value, $statii)) 881 { 882 if (isset($current[$name])) 883 { 884 $value = $current[$name]; 885 } 886 elseif(isset($original[$name])) 887 { 888 $value = $original[$name]; 889 } 890 $generated[$name] = $value; 891 } 892 } 893 894 return [$dataItems, $generated]; 895 } 896 966 897 967 898 -
shortpixel-image-optimiser/tags/6.3.4/class/Controller/Optimizer/OptimizerBase.php
r3346588 r3363822 48 48 //exit('This call is wron because in it messes with ActionController - Reoptimize ( calls ActionController again instead of OptimizeConrtoller'); 49 49 $calledClass = get_called_class(); 50 //Log::addTemp('OptimizerBase Called Class - ' . $calledClass); 50 51 51 if (! isset(static::$instances[$calledClass])) 52 52 { … … 54 54 } 55 55 56 // Log::addTemp('OptimizeBase, Instances', self::$instances);57 56 return self::$instances[$calledClass]; 58 57 } -
shortpixel-image-optimiser/tags/6.3.4/class/Controller/Queue/MediaLibraryQueue.php
r3289850 r3363822 8 8 use ShortPixel\ShortQ\ShortQ as ShortQ; 9 9 use ShortPixel\Controller\CacheController as CacheController; 10 use ShortPixel\Helper\UtilHelper; 10 11 use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log; 11 12 use ShortPixel\Model\Image\ImageModel as ImageModel; … … 32 33 'retry_limit' => 30, // amount of times it will retry without errors before giving up 33 34 'enqueue_limit' => 200, // amount of items added to the queue when preparing. 35 'filters' => [], 34 36 ); 35 37 … … 56 58 } 57 59 60 public function createNewBulk($args = []) 61 { 62 /* if (isset($args['filters'])) 63 { 64 $this->addFilters($args['filters']); 65 } */ 66 67 68 // Parent should save options as well. 69 return parent::createNewBulk($args); 70 } 71 72 73 protected function addFilters($filters) 74 { 75 76 //$start_id = $end_id = null; 77 78 79 global $wpdb; 80 81 82 $start_date = isset($filters['start_date']) ? new \DateTime($filters['start_date']) : false; 83 $end_date = isset($filters['end_date']) ? new \DateTime($filters['end_date']) : false; 84 85 if (isset($filters['start_date'])) 86 { 87 //$date = UtilHelper::timestampToDB($filters['start_time']); 88 $date = $start_date->format("Y-m-d H:i:s"); 89 $startSQL = 'select max(ID) from wp_posts where post_date <= %s group by post_date order by post_date DESC limit 1'; 90 $sql = $wpdb->prepare($startSQL, $date); 91 $start_id = $wpdb->get_var($sql); 92 } 93 if (isset($filters['end_date'])) 94 { 95 // $date = UtilHelper::timestampToDB($filters['end_time']); 96 $date = $end_date->format("Y-m-d H:i:s"); 97 $endSQL = 'select MIN(ID) from wp_posts where post_date <= %s group by post_date order by post_date DESC limit 1'; 98 $sql = $wpdb->prepare($endSQL, $date); 99 $end_id = $wpdb->get_var($sql); 100 } 101 102 103 104 //echo "Start $start_id END $end_id"; 105 //exit(); 106 // IF POST DATE NEEDS 09-20 ( or 23:59:59? ) 107 // select post_date, max(ID) from wp_posts where post_date <= '2024-09-21 00:00:00' group by post_date order by post_date DESC limit 100 108 } 109 58 110 59 111 private function queryPostMeta() -
shortpixel-image-optimiser/tags/6.3.4/class/Controller/Queue/Queue.php
r3346588 r3363822 9 9 use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log; 10 10 use ShortPixel\Controller\CacheController as CacheController; 11 use ShortPixel\Controller\Optimizer\OptimizeAiController; 11 12 use ShortPixel\Controller\ResponseController as ResponseController; 12 13 use ShortPixel\Model\Converter\Converter as Converter; … … 48 49 49 50 50 public function createNewBulk( )51 public function createNewBulk($args = []) 51 52 { 52 53 $this->resetQueue(); … … 58 59 $cache = new CacheController(); 59 60 $cache->deleteItem($this->cacheName); 61 62 $this->setCustomBulk($args); 60 63 } 61 64 … … 98 101 $args = wp_parse_args($args, $defaults); 99 102 100 101 103 $qItem = QueueItems::getImageItem($imageModel); 102 103 104 104 105 $result = new \stdClass; … … 107 108 $numitems = $this->q->withRemoveDuplicates()->enqueue(); // enqueue returns numitems 108 109 110 $this->checkQueueCache($imageModel->get('id')); 111 109 112 $result->qstatus = $this->getQStatus($numitems); 110 113 $result->numitems = $numitems; … … 117 120 { 118 121 $this->q->addItems([$qItem->returnEnqueue()], false); 122 $item_id = $qItem->item_id; 119 123 $numitems = $this->q->withRemoveDuplicates()->enqueue(); // enqueue returns numitems 120 124 … … 123 127 $result->numitems = $numitems; 124 128 125 do_action('shortpixel_start_image_optimisation', $qItem->item_id, $qItem->imageModel); 129 $this->checkQueueCache($item_id); 130 131 132 do_action('shortpixel_start_image_optimisation', $item_id, $qItem->imageModel); 126 133 return $result; 127 134 } … … 270 277 } 271 278 279 $optimizeAiController = OptimizeAiController::getInstance(); 280 272 281 // If autoAi is on the bulk, add operation to the item 273 if ('media' === $mediaItem->get('type') && true === $settings->autoAIBulk) 282 $enqueueAi = false; 283 if ('media' === $mediaItem->get('type') && true === $optimizeAiController->isAiEnabled() && true === $settings->autoAIBulk) 274 284 { 275 276 $aiDataModel = new AiDataModel($mediaItem->get('id')); 277 $enqueueAi = false; 278 if ($aiDataModel->isProcessable() && in_array($mediaItem->getExtension(), $aiDataModel->supportedExtensions())) 279 { 280 $enqueueAi = true; 281 } 285 $aiDataModel = AiDataModel::getModelByAttachment($mediaItem->get('id')); 286 $enqueueAi = $aiDataModel->isProcessable(); 282 287 } 283 else284 {285 $enqueueAi = false;286 }287 288 288 289 289 if ($mediaItem->isProcessable() && $mediaItem->isOptimizePrevented() === false && ! $operation) // Checking will be done when processing queue. … … 317 317 $baseCount += $counts->baseCount; // base images (all minus webp/avif) 318 318 319 320 $this->checkQueueCache($item_id); 319 321 do_action('shortpixel_start_image_optimisation', $mediaItem); 320 322 … … 511 513 } 512 514 513 public function setCustomBulk($ type = null, $options = array())514 { 515 if ( is_null($type))515 public function setCustomBulk($options = [] ) 516 { 517 if (0 === count($options)) 516 518 return false; 517 519 518 520 $customData = $this->getStatus('custom_data'); 519 $customData->customOperation = $type; 521 522 523 if (isset($options['customOp'])) 524 { 525 $customOp = $options['customOp']; 526 $customData->customOperation = $customOp; 527 unset($options['customOp']); 528 } 529 520 530 if (is_array($options) && count($options) > 0) 521 531 $customData->queueOptions = $options; … … 613 623 return false; 614 624 } 625 626 protected function checkQueueCache($item_id) 627 { 628 629 630 if (isset(self::$isInQueue[$item_id]) && false === self::$isInQueue[$item_id]) 631 { 632 unset(self::$isInQueue[$item_id]); 633 } 634 635 636 637 638 } 615 639 616 640 public function itemFailed(QueueItem $qItem, $fatal = false) -
shortpixel-image-optimiser/tags/6.3.4/class/Controller/QueueController.php
r3346588 r3363822 63 63 'smartcrop' => null, 64 64 'next_actions' => [], 65 'returndatalist' => [], 65 66 ); 66 67 $args = wp_parse_args($args, $defaults); … … 72 73 { 73 74 $qItem->data()->next_actions = $args['next_actions']; 75 } 76 77 if (is_object($args['returndatalist'])) 78 { 79 $args['returndatalist'] = (array) $args['returndatalist']; 80 } 81 if (is_array($args['returndatalist']) && count($args['returndatalist']) > 0) 82 { 83 $qItem->data()->returndatalist = $args['returndatalist']; 74 84 } 75 85 … … 198 208 // @todo This queueItem should maybe not to stuffed with 'addresult'm since it's a different object. 199 209 $queueItem = $q->getItem($mediaItem->get('id')); 210 200 211 if (is_object($queueItem)) 201 212 { … … 327 338 { 328 339 $result = $Q->run(); 329 $results = [];330 340 $fs = \wpSPIO()->filesystem(); 331 341 … … 337 347 $qtype = strtolower($qtype); 338 348 339 //Log::addTemp('RunTick Items - ', $items);340 349 /* Only runs if result is array, dequeued items. 341 350 Item is a MediaItem subset of QueueItem … … 346 355 $action = $qItem->data()->action; 347 356 $apiController = $qItem->getAPIController($action); 357 $send_to_processing = true; 348 358 349 359 … … 374 384 } 375 385 376 if (! is_object($imageModel)) 386 if (! is_object($imageModel)) // Error in loading imageModel, can't process this. 377 387 { 378 388 Log::addWarn('ImageObject was empty when send to processing - ' . $item_id); 379 389 $qItem->addResult([ 380 390 'apiStatus' => RequestManager::STATUS_NOT_API, 381 'message' => __("File Error. Filecould not be loaded with this ID ", 'shortpixel-image-optimiser'),391 'message' => __("File Error. Media Item could not be loaded with this ID ", 'shortpixel-image-optimiser'), 382 392 'fileStatus' => ImageModel::FILE_STATUS_ERROR, 383 393 'is_done' => true, 384 394 'is_error' => true, 385 395 ]); 396 $Q->itemFailed($qItem, true); 397 $send_to_processing = false; 386 398 } 387 399 elseif(true === $qItem->block()) … … 392 404 ]); 393 405 Log::addWarn('Encountered blocked item, processing success? ', $item_id); 406 ResponseController::addData($item_id, 'fileName', $imageModel->getFileName()); 407 $send_to_processing = false; 394 408 } 395 409 else … … 403 417 ResponseController::addData($item_id, 'fileName', $imageModel->getFileName()); 404 418 } 405 406 ResponseController::addData($item_id, 'fileName', $imageModel->getFileName());407 408 419 409 420 $this->setLastID($item_id); 410 421 411 if (! is_null($apiController) )422 if (! is_null($apiController) && true === $send_to_processing) 412 423 { 413 424 $apiController->sendToProcessing($qItem); … … 821 832 $item_id = $qItem->item_id; 822 833 $responseItem = ResponseController::getResponseItem($item_id); 823 $type = $qItem->imageModel->get('type'); 834 835 $type = (is_object($qItem->imageModel)) ? $qItem->imageModel->get('type') : false; 836 837 if (false === $type) 838 { 839 return; 840 } 824 841 825 842 $fs = \wpSPIO()->filesystem(); -
shortpixel-image-optimiser/tags/6.3.4/class/Controller/View/EditMediaViewController.php
r3348311 r3363822 15 15 16 16 use ShortPixel\Controller\Queue\QueueItems as QueueItems; 17 17 use ShortPixel\Model\AiDataModel; 18 18 use ShortPixel\Model\File\FileModel as FileModel; 19 19 … … 141 141 protected function getStatistics() 142 142 { 143 //$data = $this->data; 144 $stats = array(); 143 $stats = []; 145 144 $imageObj = $this->imageModel; 146 145 $did_keepExif = $imageObj->getMeta('did_keepExif'); … … 213 212 } 214 213 214 $optimizeAiController = OptimizeAiController::getInstance(); 215 215 216 216 217 $thumbnails = $imageObj->get('thumbnails'); … … 267 268 $debugInfo[] = array(__('To Optimize URLS'), $urls); 268 269 } 269 if (isset($optimizeData)) 270 { 271 $debugInfo[] = array(__('Optimize Data'), $optimizeData);272 273 $queueControl = new QueueController(); 274 275 // $q = $queueControl->getQueue($imageObj->get('type'));276 277 $item = QueueItems::getImageItem($imageObj); 270 271 272 $item = QueueItems::getImageItem($imageObj); 273 274 if ($imageObj->isProcessable()) 275 { 276 // $queueControl = new QueueController(); 277 278 278 279 $item->setDebug(); 279 280 $item->newOptimizeAction(); … … 281 282 $returnEnqueue = $item->returnEnqueue(); 282 283 283 // TEST @todo REMOVE 284 /*$replacer2 = new \ShortPixel\Replacer\Replacer(); 285 $setup = $replacer2->Setup(); 286 $setup->forSearch()->URL()->addData($item->imageModel->getURL()); 287 288 $base_url = $setup->forSearch()->URL()->getBaseURL(); 289 290 $text = 'AI TEST'; 291 292 $finder = $replacer2->Finder(['base_url' => $base_url, 'callback' => [OptimizeAiController::getInstance(), 'handleReplace'], 'return_data' => [ 293 'retrievedText' => $text, 294 'qItem' => $item, 295 ]]); 296 297 $posts = $finder->posts(); */ 298 299 $debugInfo[] = array(__('Image to Queue V2'), $returnEnqueue ); 300 301 } 284 $debugInfo[] = array(__('Image to Queue'), $returnEnqueue ); 285 286 } 287 288 if ( $optimizeAiController->isAIEnabled()) 289 { 290 $aiDataModel = AiDataModel::getModelByAttachment($this->post_id); 291 292 $aiProcessable = ($aiDataModel->isProcessable()) ? '<span class="green">Yes</span>' : '<span class="red">No</span> '; 293 294 $debugInfo[] = ['AI - is Processable', $aiProcessable]; 295 296 if (true === $aiDataModel->isProcessable()) 297 { 298 //$item->requestAltAction(); 299 // $optimizeAiController->parseJsonForQItem($item); 300 $debugInfo[] = ['Ai - Paramlist ', $aiDataModel->getOptimizeData() ]; 301 // $debugInfo[] = ['Ai - returnDataList' , $item->data()->returndatalist]; 302 303 } 304 else 305 { 306 $debugInfo[] = ['Ai - Reason', $aiDataModel->getProcessableReason()]; 307 } 308 if (true === $aiDataModel->isSomeThingGenerated()) 309 { 310 $debugInfo[] = ['Ai -Generated ', $aiDataModel->getGeneratedData()]; 311 } 312 313 } 314 315 302 316 303 317 $debugInfo['imagemetadata'] = array(__('ImageModel Metadata (ShortPixel)'), $imageObj); … … 366 380 367 381 $display_size = ucfirst(str_replace("_", " ", $size)); 368 //$thumbObj = $imageObj->getThumbnail($size);369 382 370 383 if ($thumbObj === false) … … 374 387 } 375 388 376 $url = $thumbObj->getURL(); //$fs->pathToURL($thumbObj); //wp_get_attachment_image_src($this->post_id, $size);389 $url = $thumbObj->getURL(); 377 390 $filename = $thumbObj->getFullPath(); 378 391 $fileDir = $thumbObj->getFileDir(); -
shortpixel-image-optimiser/tags/6.3.4/class/Controller/View/ListMediaViewController.php
r3347742 r3363822 13 13 14 14 use ShortPixel\Controller\ApiKeyController as ApiKeyController; 15 use ShortPixel\Controller\Optimizer\OptimizeAiController; 15 16 use ShortPixel\Controller\QuotaController as QuotaController; 16 17 use ShortPixel\Controller\QueueController as QueueController; … … 60 61 { 61 62 $defaults['wp-shortPixel'] = __('ShortPixel Compression', 'shortpixel-image-optimiser'); 62 /*if (true === \wpSPIO()->settings()->enable_ai) 63 { 64 $defaults['wp-spio-ai'] = __('AI By Shortpixel', 'shortpixel-image-optimiser'); 65 } */ 63 66 64 67 65 return $defaults; … … 99 97 $list_actions = array(); 100 98 101 if (true === \wpSPIO()->settings()->enable_ai) 99 $optimizeAiController = OptimizeAiController::getInstance(); 100 101 102 if (true === $optimizeAiController->isAiEnabled()) 102 103 { 103 104 $aiDataModel = $this->loadAiItem($id); … … 174 175 protected function loadAiItem($item_id) 175 176 { 176 $AiDataModel = new AiDataModel($item_id);177 $AiDataModel = AiDataModel::getModelByAttachment($item_id); 177 178 $this->view->item_id = $item_id; 178 179 -
shortpixel-image-optimiser/tags/6.3.4/class/Controller/View/SettingsViewController.php
r3348311 r3363822 430 430 } 431 431 432 433 432 434 // If the compression type setting changes, remove all queued items to prevent further optimizing with a wrong type. 433 435 if (intval($this->postData['compressionType']) !== intval($this->model->compressionType)) … … 448 450 { 449 451 $type = $this->model->getType($name); 450 if ('boolean' === $type && ! isset($this->postData[$name]))452 if ('boolean' === $type ) 451 453 { 452 $this->model->{$name} = false; 454 if( ! isset($this->postData[$name])) 455 { 456 $this->model->{$name} = false; 457 } 458 else 459 { 460 $this->model->{$name} = true; 461 } 453 462 } 454 463 } … … 864 873 } 865 874 } 875 876 if (false === isset($post['enable_ai'])) 877 { 878 if (isset($post['autoAI'])) 879 { 880 unset($post['autoAI']); 881 } 882 if (isset($post['autoAIBulk'])) 883 { 884 unset($post['autoAIBulk']); 885 } 886 } 866 887 867 888 -
shortpixel-image-optimiser/tags/6.3.4/class/Helper/UiHelper.php
r3346930 r3363822 331 331 } 332 332 333 //$aiDataModel = new AiDataModel($id);334 335 333 if ($mediaItem->isSomethingOptimized() ) 336 334 { … … 439 437 440 438 441 if (false === is_null($aiDataModel) && $aiDataModel->isProcessable() && 'media' === $mediaItem->get('type') && in_array($mediaItem->getExtension(), $aiDataModel->supportedExtensions()))439 if (false === is_null($aiDataModel) && $aiDataModel->isProcessable() && 'media' === $mediaItem->get('type') ) 442 440 { 443 441 $list_actions['shortpixel-generateai'] = self::getAction('shortpixel-generateai', $id); -
shortpixel-image-optimiser/tags/6.3.4/class/Helper/UtilHelper.php
r3346588 r3363822 30 30 } 31 31 32 static public function timestampToDB($timestamp)32 public static function timestampToDB($timestamp) 33 33 { 34 34 return date("Y-m-d H:i:s", $timestamp); 35 35 } 36 36 37 static public function DBtoTimestamp($date)37 public static function DBtoTimestamp($date) 38 38 { 39 39 return strtotime($date); … … 170 170 } 171 171 return $bool; 172 } 173 174 public static function getAiSettings($params = []) 175 { 176 $settings = \wpSPIO()->settings(); 177 178 $defaults = [ 179 'ai_general_context' => $settings->ai_general_context, 180 'ai_use_post' => $settings->ai_use_post, 181 'ai_gen_alt' => $settings->ai_gen_alt, 182 'ai_gen_caption' => $settings->ai_gen_caption, 183 'ai_gen_description' => $settings->ai_gen_description, 184 'ai_filename_prefercurrent' => $settings->ai_filename_prefercurrent, 185 'ai_limit_alt_chars' => $settings->ai_limit_alt_chars, 186 'ai_alt_context' => $settings->ai_alt_context, 187 'ai_limit_description_chars' => $settings->ai_limit_description_chars, 188 'ai_description_context' => $settings->ai_description_context, 189 'ai_limit_caption_chars' => $settings->ai_limit_caption_chars, 190 'ai_caption_context' => $settings->ai_caption_context, 191 'ai_gen_filename' => $settings->ai_gen_filename, 192 'ai_limit_filename_chars' => $settings->ai_limit_filename_chars, 193 'ai_filename_context' => $settings->ai_filename_context, 194 'ai_use_exif' => $settings->ai_use_exif, 195 'ai_language' => $settings->ai_language, 196 'aiPreserve' => $settings->aiPreserve, 197 ]; 198 199 $params = wp_parse_args($params, $defaults); 200 201 return $params; 172 202 } 173 203 -
shortpixel-image-optimiser/tags/6.3.4/class/Model/AiDataModel.php
r3346588 r3363822 14 14 class AiDataModel 15 15 { 16 17 16 protected $id; 18 17 protected $attach_id; 19 18 protected $type; 19 20 protected static $models = []; 20 21 21 22 protected $original = [ … … 45 46 private $current_is_set = false; 46 47 48 private $processable_status = 0; 47 49 48 50 const TYPE_MEDIA = 1; 49 51 const TYPE_CUSTOM = 2; 50 52 53 // Status for the whole image, in the main table. 51 54 const AI_STATUS_NOTHING = 0; 52 55 const AI_STATUS_GENERATED = 1; 56 57 // IsProcessable statii 58 const P_PROCESSABLE = 0; 59 const P_ALREADYDONE = 1; // Data already there 60 const P_EXIFAI = 2; // When Exif Flag forbids AI doing 61 const P_EXTENSION = 3; 62 const P_NOJOB = 4; 63 const P_NOFIELDS = 5; 64 65 // Descriptive status if certain field is not generated / left alone. 66 const F_STATUS_OK = 1; 67 const F_STATUS_EXCLUDESETTING = -3; 68 const F_STATUS_PREVENTOVERRIDE = -4; 69 53 70 54 71 public function __construct($attach_id, $type = 'media') … … 94 111 $this->generated = array_merge($this->generated, $generatedData); 95 112 96 97 113 } 98 114 … … 108 124 109 125 return (array) $data; 126 127 } 128 129 /** Get all data needed to send API for generating AI texts, depending on settings. This includes all settings minus URL 130 * 131 * @return array{paramlist: array<string, array{context: mixed, chars: mixed}>, returndatalist: array<string, array<string, int>>} 132 */ 133 public function getOptimizeData($params = []) 134 { 135 $settings = (object) UtilHelper::getAiSettings($params); 136 137 $ignore_fields = []; 138 if (true === $settings->aiPreserve) 139 { 140 $currentData = $this->getCurrentData(); 141 $ignore_fields = array_keys(array_filter($currentData)); 142 } 143 144 145 // $fields = ['ai_gen_alt', 'ai_gen_caption', 'ai_gen_description', 'ai_gen_filename']; 146 $fields = ['alt', 'caption', 'description', 'filename']; 147 148 $paramlist = [ 149 'languages' => $settings->ai_language, 150 'context' => $settings->ai_general_context, 151 ]; 152 $returnDataList = []; 153 $field_status = false; // check if there are any fields to process / not all excluded. 154 155 foreach($fields as $field_name) 156 { 157 $api_name = $field_name; 158 //$paramlist[$api_name] = []; 159 160 switch($api_name) 161 { 162 case 'description': 163 $api_name = 'image_description'; 164 break; 165 case 'filename': 166 $api_name = 'file'; 167 break; 168 } 169 170 171 if (false === $settings->{'ai_gen_' . $field_name}) 172 { 173 $returnDataList[$field_name]['status'] = self::F_STATUS_EXCLUDESETTING; 174 continue; 175 } 176 elseif (true === in_array($field_name, $ignore_fields)) 177 { 178 $returnDataList[$field_name]['status'] = self::F_STATUS_PREVENTOVERRIDE; 179 } 180 else 181 { 182 $paramlist[$api_name] = [ 183 'context' => $settings->{'ai_' . $field_name . '_context'}, 184 'chars' => $settings->{'ai_limit_' . $field_name . '_chars'}, 185 ]; 186 $returnDataList[$field_name]['status'] = self::F_STATUS_OK; 187 $field_status = true; 188 } 189 190 191 } 192 193 if (false === $field_status) 194 { 195 $this->processable_status = self::P_NOJOB; 196 } 197 198 return ['paramlist' => $paramlist, 'returndatalist' => $returnDataList]; 110 199 111 200 } … … 143 232 } 144 233 145 146 234 // Save to WordPress 147 /*148 if (isset($this->generated['alt']) && false !== $this->generated['alt'])149 {150 $bool = update_post_meta($this->attach_id, '_wp_attachment_image_alt', $this->generated['alt']);151 } */152 153 235 $this->updateWPPost($this->generated); 154 236 $this->updateWpMeta($this->generated); 155 237 156 /* $post = get_post($this->attach_id);157 $post_updated = false;158 159 if (isset($this->generated['caption']) && false !== $this->generated['caption'])160 {161 $post->post_excerpt = $this->generated['caption'];162 $post_updated = true;163 }164 165 if (isset($this->generated['description']) && false !== $this->generated['description'])166 {167 $post->post_content = $this->generated['description'];168 $post_updated = true;169 }170 171 if (true === $post_updated)172 {173 wp_update_post($post);174 } */175 238 } 176 239 177 240 protected function updateWPPost($data) 178 241 { 179 180 // Log::addTemp('Update WpPost', $data);181 242 $post = get_post($this->attach_id); 182 243 $post_updated = false; 183 244 184 if (isset($data['caption']) && false !== $data['caption'] )245 if (isset($data['caption']) && false !== $data['caption'] && false === is_int($data['caption'])) 185 246 { 186 247 $post->post_excerpt = $data['caption']; … … 188 249 } 189 250 190 if (isset($data['description']) && false !== $data['description'] )251 if (isset($data['description']) && false !== $data['description'] && false === is_int($data['description'])) 191 252 { 192 253 $post->post_content = $data['description']; … … 203 264 { 204 265 Log::addTemp('Update WpMeta', $data); 205 if (isset($data['alt']) && false !== $data['alt'] )266 if (isset($data['alt']) && false !== $data['alt'] && false === is_int($data['alt'])) 206 267 { 207 268 $bool = update_post_meta($this->attach_id, '_wp_attachment_image_alt', $data['alt']); … … 314 375 if (true === $this->has_record) 315 376 { 377 $this->processable_status = SELF::P_ALREADYDONE; 316 378 return false; 317 379 } 380 381 // Stash here other conditions on top with && to build a big processable function 382 $processable = ( $this->isExifProcesssable() && $this->isExtensionIncluded() && $this->hasSomethingGeneratable() ) ? true : false; 383 return $processable; 384 } 385 386 387 private function isExifProcesssable() 388 { 389 $fs = \wpSPIO()->filesystem(); 390 $imageModel = $fs->getMediaImage($this->attach_id); 391 392 if (false === $imageModel->isSomethingOptimized()) 393 { 394 return true; 395 } 396 397 $imageObj = $imageModel->getSomethingOptimized(); 398 399 400 $keepExif = $imageObj->getMeta('did_keepExif'); 401 402 // 2-3 are exif_ai combined settings with keep-exif. 0-1 are when default settings are used and unset / unused 403 if (in_array($keepExif, [0,1,2,3])) 404 { 405 return true; 406 } 407 408 $this->processable_status = self::P_EXIFAI; 409 return false; 410 411 } 412 413 public function getProcessableReason($returnStatus = false ) 414 { 415 $message = false; 416 417 if (true === $returnStatus) 418 { 419 return $this->processable_status; 420 } 421 422 switch($this->processable_status) 423 { 424 case self::P_PROCESSABLE: 425 $message = __('AI is processable', 'shortpixel-image-optimiser'); 426 break; 427 case self::P_ALREADYDONE: 428 $message = __('This image already has generated data', 'shortpixel-image-optimiser'); 429 break; 430 case self::P_EXIFAI: 431 $message = __('Image Exif settings restrict AI usage', 'shortpixel-image-optimiser'); 432 break; 433 case self::P_EXTENSION: 434 $message = __('File Extension not supported', 'shortpixel-image-optimiser'); 435 break; 436 case self::P_NOJOB: 437 $message = __('No fields to generate', 'shortpixel-image-optimiser'); 438 break; 439 default: 440 $message = sprintf(__('Status %s unknown', 'shortpixel-image-optimiser'), $this->processable_status); 441 break; 442 } 443 444 return $message; 445 } 446 447 protected function isExtensionIncluded() 448 { 449 $fs = \wpSPIO()->filesystem(); 450 $imageModel = $fs->getMediaImage($this->attach_id); 451 452 // Gif removed here, since we (temporarily don't support it) 453 $extensions = ['png', 'jpeg', 'webp', 'jpg']; 454 455 if (in_array($imageModel->getExtension(), $extensions)) 456 { 457 return true; 458 } 459 460 $this->processable_status = self::P_EXTENSION; 461 return false; 462 } 463 464 protected function hasSomethingGeneratable() 465 { 466 $optimizeData = $this->getOptimizeData(); 467 468 if (self::P_NOJOB === $this->processable_status) 469 { 470 return false; 471 472 } 318 473 return true; 319 }320 321 public function supportedExtensions()322 {323 return ['png', 'jpeg', 'gif', 'webp', 'jpg'];324 474 } 325 475 … … 429 579 430 580 431 /*public static function getAiDataByAttachment($attach_id) 432 { 433 434 } */ 581 public static function getModelByAttachment($attach_id, $type = 'media') 582 { 583 if (false === isset(self::$models[$attach_id])) 584 { 585 self::$models[$attach_id] = new AiDataModel($attach_id, $type); 586 } 587 588 return self::$models[$attach_id]; 589 590 } 591 592 public static function flushModelCache($attach_id, $type = 'media') 593 { 594 if (isset(self::$models[$attach_id])) 595 { 596 unset(self::$models[$attach_id]); 597 } 598 else 599 { 600 Log::addTemp('Ai MODEL not found in cache!', $attach_id); 601 } 602 603 } 435 604 436 605 -
shortpixel-image-optimiser/tags/6.3.4/class/Model/Image/ImageModel.php
r3346588 r3363822 478 478 if (! isset($optimizeData['params']) || ! isset($optimizeData['urls'])) 479 479 { 480 array( array(), 0);480 array([], 0); 481 481 } 482 482 483 483 $count = 0; 484 $urls = array();484 $urls = []; 485 485 $i = 0; 486 486 -
shortpixel-image-optimiser/tags/6.3.4/class/Model/Queue/QueueItem.php
r3346588 r3363822 17 17 use ShortPixel\Controller\Optimizer\OptimizeAiController as OptimizeAiController; 18 18 use ShortPixel\Controller\Optimizer\ActionController as ActionController; 19 use ShortPixel\Model\AiDataModel; 19 20 20 21 class QueueItem … … 176 177 } 177 178 178 179 179 $enqueue = ['id' => $item_id, 'value' => $value, 'item_count' => $this->item_count]; 180 180 … … 185 185 186 186 return $enqueue; 187 188 187 189 188 } … … 472 471 $this->item_count = 1; 473 472 473 $item_id = $this->imageModel->get('id'); 474 475 $paramlist = []; 474 476 475 477 $preview_only = false; 476 478 if (isset($args['preview_only']) && true == $args['preview_only']) 477 479 { 478 $ this->data->paramlist = ['preview_only' => true];480 $paramlist['preview_only'] = true; 479 481 $preview_only = true; 480 482 } 481 483 484 $aiDataModel = new AiDataModel($item_id); 485 486 $data = $aiDataModel->getOptimizeData($args); 487 488 if (isset($data['paramlist'])) 489 { 490 $this->data()->paramlist = $data['paramlist']; 491 } 492 if (isset($data['returndatalist'])) 493 { 494 $this->data()->returndatalist = $data['returndatalist']; 495 $this->data()->addKeepDataArgs('returndatalist'); 496 } 497 498 482 499 $this->data->action = 'requestAlt'; // For Queue 483 500 484 $optimizer = $this->getAPIController($this->data->action);485 $optimizer->parseJSONForQItem($this, $args);501 // $optimizer = $this->getAPIController($this->data->action); 502 // $optimizer->parseJSONForQItem($this, $args); 486 503 487 504 if ($this->data()->hasNextAction()) … … 498 515 $this->data->next_actions = $next_actions; 499 516 } 517 518 500 519 501 520 } 502 521 503 public function retrieveAltAction($ remote_id)522 public function retrieveAltAction($args) 504 523 { 505 524 $this->newAction(); 525 526 $remote_id = $args['remote_id']; 527 528 if (isset($args['returndatalist'])) 529 { 530 $this->data()->returndatalist = $args['returndatalist']; 531 } 532 533 506 534 $this->data->remote_id = $remote_id; 507 535 $this->data->tries = 0; -
shortpixel-image-optimiser/tags/6.3.4/class/Model/SettingsModel.php
r3348311 r3363822 68 68 'autoAI' => ['s' => 'boolean', 'default' => false], 69 69 'autoAIBulk' => ['s' => 'boolean', 'default' => false], 70 'aiPreserve' => ['s' => 'boolean', 'default' => false ], 70 71 'ai_general_context' => ['s' => 'string', 'default' => 'callback', 'maxlength' => 500], 71 72 'ai_use_post' => ['s' => 'boolean', 'default' => true], -
shortpixel-image-optimiser/tags/6.3.4/class/external/offload/wp-offload-media.php
r3289850 r3363822 355 355 } 356 356 } 357 } 358 } 359 357 358 } 359 360 } 360 361 361 362 return $source_id; -
shortpixel-image-optimiser/tags/6.3.4/class/external/wp-cli/wp-cli-bulk.php
r3289850 r3363822 167 167 * [--special=<migrate>] 168 168 * : Run the migration 169 * --- 170 * 169 * 170 * [--start-date=<start_date>] 171 * : Filter, start from this date 172 * 173 * [--end-date=<end_date>] 174 * : Filter, don't enqueue items old than this date. 175 * 171 176 * ## EXAMPLES 172 177 * … … 186 191 187 192 $operation = null; 193 $args = $filters = []; 188 194 if (isset($assoc['special'])) { 189 195 switch ($assoc['special']) { 190 196 case 'migrate': 191 197 $operation = 'migrate'; 198 $args['customOp'] = $operation; 192 199 $queues = array('media'); // can only have one bulk, this. 193 200 break; … … 195 202 } 196 203 204 if (isset($assoc['start-date'])) 205 { 206 $filters['start_date'] = sanitize_text_field($assoc['start-date']); 207 } 208 if (isset($assoc['end-date'])) 209 { 210 $filters['end_date'] = sanitize_text_field($assoc['end-date']); 211 } 212 213 if (count($filters) > 0) 214 { 215 $args['filters'] = $filters; 216 } 217 197 218 foreach ($queues as $qname) { 198 $stats = $bulkControl->createNewBulk($qname, $ operation);219 $stats = $bulkControl->createNewBulk($qname, $args); 199 220 $json->$qname->stats = $stats; 200 221 -
shortpixel-image-optimiser/tags/6.3.4/class/view/bulk/part-selection.php
r3346588 r3363822 1 1 <?php 2 2 namespace ShortPixel; 3 4 use ShortPixel\Controller\Optimizer\OptimizeAiController; 3 5 4 6 if ( ! defined( 'ABSPATH' ) ) { … … 45 47 46 48 47 </div>49 </div> 48 50 49 51 <div class="interface wrapper"> … … 103 105 <?php endif; ?> 104 106 105 <?php if (true === \wpSPIO()->settings()->enable_ai): ?> 107 <?php 108 $optimizeAiController = OptimizeAiController::getInstance(); 109 if (true === $optimizeAiController->isAiEnabled()): ?> 106 110 <div class='ai-images optiongroup'> 107 111 <div class='switch_button'> … … 118 122 </div> 119 123 124 <div class='switch_button'> 125 <label> 126 <input type="checkbox" class="switch" id="aipreserve_checkbox" name="aipreserve_checkbox" 127 <?php checked(\wpSPIO()->settings()->aiPreserve); ?> /> 128 <div class="the_switch"> </div> 129 </label> 130 <h4><label for="aipreserve_checkbox"> 131 <?php printf(esc_html__('Prevent overriding any of the existing data with the one generated by AI', 'shortpixel-image-optimiser'), '<a href="options-general.php?page=wp-shortpixel-settings&part=ai">', '</a>' ); ?> 132 <span class='new'><?php _e('New!', 'shortpixel-image-optimiser'); ?></span> 133 </label></h4> 134 135 </div> 136 120 137 </div> 138 121 139 <?php endif ?> 122 140 -
shortpixel-image-optimiser/tags/6.3.4/class/view/settings/part-ai.php
r3348311 r3363822 12 12 <settinglist> 13 13 14 <h2><?php esc_html_e('AI Image SEO ', 'shortpixel-image-optimiser'); ?></h2>14 <h2><?php esc_html_e('AI Image SEO & Accessibility', 'shortpixel-image-optimiser'); ?></h2> 15 15 16 16 <gridbox class="width_half"> … … 24 24 'checked' => $view->data->enable_ai, 25 25 'label' => esc_html__('Enable AI Image SEO', 'shortpixel-image-optimiser'), 26 ] 26 'data' => ['data-toggle="autoAiOptions"'], 27 28 ] 27 29 ); 28 30 ?> … … 31 33 <name> 32 34 33 <?php esc_html_e('Show AI image SEO options throughout ShortPixel Image Optimizer. ', 'shortpixel-image-optimiser'); ?>35 <?php esc_html_e('Show AI image SEO options throughout ShortPixel Image Optimizer. The generated ALT tag is also very useful for accessibility.', 'shortpixel-image-optimiser'); ?> 34 36 35 37 </name> … … 37 39 </setting> 38 40 39 <setting class='switch '>41 <setting class='switch toggleTarget autoAiOptions'> 40 42 <content> 41 43 … … 58 60 </setting> 59 61 60 <setting class='switch '>62 <setting class='switch toggleTarget autoAiOptions'> 61 63 <content> 62 64 … … 65 67 'name' => 'autoAIBulk', 66 68 'checked' => $view->data->autoAIBulk, 67 'label' => esc_html__('Generate image SEO data when running Bulk Processing', 'shortpixel-image-optimiser'),69 'label' => esc_html__('Generate image SEO data during Bulk Processing', 'shortpixel-image-optimiser'), 68 70 ] 69 71 ); … … 78 80 </content> 79 81 </setting> 82 83 84 <setting class='switch toggleTarget autoAiOptions'> 85 <content> 86 87 <?php $this->printSwitchButton( 88 [ 89 'name' => 'aiPreserve', 90 'checked' => $view->data->aiPreserve, 91 'label' => esc_html__('Preserve existing Image SEO data', 'shortpixel-image-optimiser'), 92 ] 93 ); 94 ?> 95 <i class='documentation dashicons dashicons-editor-help' data-link="https://shortpixel.com/knowledge-base/article/ai-image-seo-settings-explained/#2-toc-title?target=iframe"></i> 96 97 <name> 98 99 <?php esc_html_e('When enabled, all existing ALT tags, captions and descriptions are retained. Disabling the switch means that the SEO data for images created with AI will overwrite the existing data.', 'shortpixel-image-optimiser'); ?> 100 101 </name> 102 </content> 103 </setting> 104 80 105 81 106 </gridbox> -
shortpixel-image-optimiser/tags/6.3.4/class/view/snippets/part-aitext.php
r3346588 r3363822 3 3 use ShortPixel\Controller\ApiKeyController; 4 4 use ShortPixel\Controller\QuotaController; 5 use ShortPixel\Model\AiDataModel; 5 6 6 7 $icon_url = plugins_url( '/res/images/icon/', SHORTPIXEL_PLUGIN_FILE ); … … 10 11 $item_id = $this->data['item_id']; 11 12 $has_data = $this->data['has_data']; 12 $isSupported = $this->data['isSupported'];13 //$isSupported = $this->data['isSupported']; 13 14 $isDifferent = $this->data['isDifferent']; 14 15 $dataItems = implode(',',$this->data['dataItems']); 16 17 $is_processable = $this->data['is_processable']; 18 $processable_reason = $this->data['processable_reason']; 19 $processable_status = $this->data['processable_status']; 15 20 16 21 $quotaControl = QuotaController::getInstance(); … … 23 28 <p class='hidden' id='shortpixel-noai'></p> 24 29 <?php 30 endif; 25 31 26 elseif (false === $isSupported):32 if (false === $is_processable && $processable_status !== AiDataModel::P_ALREADYDONE): 27 33 28 ?> 29 <p><?php _e('Currently, ShortPixel AI cannot generate SEO data for GIF files.', 'shortpixel-image-optimiser'); ?></p> 30 <?php 34 if (true === in_array($processable_status, [AiDataModel::P_NOJOB])) // Silent fail if all done 35 { 36 37 } 38 else 39 { 40 printf('<p>%s</p>', $processable_reason); 41 } 42 31 43 32 44 elseif (false === $has_data): -
shortpixel-image-optimiser/tags/6.3.4/readme.txt
r3348311 r3363822 5 5 Tested up to: 6.8 6 6 Requires PHP: 7.4 7 Stable tag: 6.3. 37 Stable tag: 6.3.4 8 8 License: GPLv2 or later 9 9 License URI: http://www.gnu.org/licenses/gpl-2.0.html … … 474 474 475 475 == Changelog == 476 477 = 6.3.4 = 478 479 🤖 The Smarter AI Control Update 480 481 Release Date: September 18, 2025 482 483 ✨ New Features & Improvements 484 485 * Preserve Existing SEO Data: Added an option to keep your existing ALT, caption, and description fields untouched when using AI-generated image SEO — your manual work is safe! 486 * Better Block Editor Integration: AI-generated SEO data and image optimization now work flawlessly when uploading images directly from the block editor. 487 * AI Support Chatbot: Meet our new AI-powered support assistant — here to help you faster, 24/7. 488 489 🛠️ Fixes & Behavioral Improvements 490 491 * Full AI Deactivation: Disabling AI Image SEO now also disables auto-generation and hides all related options from WP Admin, including the Bulk Processing section. 492 * EXIF-Based AI Training Block: If AI training is blocked via EXIF data, the plugin now shows a clear message and prevents the image from being sent for processing. 493 * Re-Optimize Logic Fixed: The "Re-optimize with/without SmartCrop" buttons now respect the selected option instead of always using the saved setting. 494 * Inline Font Handling: Inline fonts will no longer be replaced with CDN links if the CSS option is disabled. 495 * AI SEO for Excluded Items: Bulk AI SEO generation now skips excluded items as expected. 496 497 Update now for smarter AI behavior, more control over your data, and an improved support experience! 🚀 476 498 477 499 = 6.3.3 = -
shortpixel-image-optimiser/tags/6.3.4/res/css/shortpixel-bulk.css
r3348311 r3363822 63 63 } 64 64 .wrap.is-shortpixel-bulk-page header .top-buttons a:hover, .wrap.is-shortpixel-bulk-page header .top-buttons button:hover { 65 background: rgb(50.3421052632, 215.4868421053, 228.6578947368);65 background: #32d7e5; 66 66 } 67 67 .wrap.is-shortpixel-bulk-page header .top-buttons a i.switch, .wrap.is-shortpixel-bulk-page header .top-buttons button i.switch { … … 265 265 } 266 266 .wrap.is-shortpixel-bulk-page section.panel.dashboard .bulk-wrapper button:hover { 267 background: rgb(50.3421052632, 215.4868421053, 228.6578947368);267 background: #32d7e5; 268 268 } 269 269 .wrap.is-shortpixel-bulk-page section.panel.dashboard .bulk-wrapper button:disabled { … … 398 398 } 399 399 .wrap.is-shortpixel-bulk-page .button-primary:hover { 400 background: rgb(50.3421052632, 215.4868421053, 228.6578947368);400 background: #32d7e5; 401 401 } 402 402 .wrap.is-shortpixel-bulk-page nav { … … 605 605 } 606 606 .wrap.is-shortpixel-bulk-page .processor-paused:hover { 607 background: rgb(27.5926724138, 169.1163793103, 178.9073275862);607 background: #1ca9b3; 608 608 } 609 609 .wrap.is-shortpixel-bulk-page .processor-paused .dashicons { … … 719 719 opacity: 1; 720 720 height: auto; 721 z-index: 10; 722 position: relative; 721 723 } 722 724 .wrap.is-shortpixel-bulk-page section.panel.selection .load.wrapper .loading { … … 1245 1247 } 1246 1248 .wrap.is-shortpixel-bulk-page section.panel.finished nav button.finish:hover { 1247 background: rgb(36.2392241379, 209.2887931034, 221.2607758621);1249 background: #24d1dd; 1248 1250 } 1249 1251 .wrap.is-shortpixel-bulk-page .part-debug { -
shortpixel-image-optimiser/tags/6.3.4/res/css/shortpixel-bulk.css.map
r3348311 r3363822 1 {"version":3,"sourceRoot":"","sources":["../scss/elements/_fonts.scss","../scss/shortpixel-bulk.scss","../scss/bulk/_dashboard.scss","../scss/elements/_header.scss","../scss/elements/_mixins.scss","../scss/elements/_colors.scss","../scss/elements/_icons.scss","../scss/elements/_breakpoints.scss","../scss/elements/_animation.scss"],"names":[],"mappings":"AAEA;EAEI;EACA;EACA;EACA;;AAGJ;EAGI;EACA;EACA;EACA;;ACXJ;ACLA;ADgBE;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmcE;AA iIF;;AEplBF;EAEI;EACA;EACA;EACA;EACA;EAEA;EAEA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAEF;EACE;EACA;EACA;EACA;;AAEF;EACH;;AAEM;EC5BL;EACA,YCKa;EDJb;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACC;;AAKD;EACE;EACA;;AAEF;EAEE;EACA;EACA;;ADOM;EACE,QEXG;EFYH;EACA;EACP;EACA;;AG5BL;EAEE;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;;AACA;EACG;;AAOH;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AAIJ;EAGE;EACA;EACA;EACA;EACA;;AAEA;EAEI;EACA;EACA;;AAGJ;EACE;EACA;EACA;;AJtDA;EAEG;EACA;EACA;;AAEA;EAAa;;AAIb;EAGK;EACA;EACA;EACA;EACA;EACA;;AACA;EAEE;EACA;EACA;EAAS;;AAGX;EAEG;EACA,kBGtBA;EHwBA;EACA;EACA;EACP;EAEA;EACA;EACM;;AAEA;EACE;;AAID;EACE;EACA;;AAEF;EAEN;;AAML;EAGC,kBG1DS;EH2DT;;AACK;EACE;EACA;EACA;EACA;EACA;;AAKR;EACE;EACD;;AK7DD;EL2DA;IAIE;;;AAED;EACC;;AAIC;EAEG;EACA;EACA;;AACA;EAAK;EAAwB;;AAC7B;EACE;;AACA;EAAS;EAAqB;;AAI9B;EACE;EACA;;AAKF;EACE;EACA;EAGA;EACA;;AAHA;EAAgB;;AAChB;EAAgB;;AAGhB;EACG;EACA;EACA;;ADzFb;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EAEI;EACA;;AAGN;EACE;;AAIF;EAEG;EACA;;AAGL;EACC;EACA;EACA;EACA;EAEA;EACA;EACA,YItDiB;EJuDjB,OI1DU;EJ2DV;EACA;EACA;EACS;EACA;EACA;EACT;;AAEA;EACC,YIpES;EJqET;;AAGD;EAEC,YI1ES;;AJ4EV;EAEE;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAID;EAEE,YIvFS;EJwFT;EACA;EACA;EACA;;AACA;EAEE;;AAMN;EACE;EAED;EACA;;AACA;EAEE;;AAIH;EACG;;AAGD;EACE;;AAGJ;EACG;EACA;;AAGJ;EACG;IACG;;EAEH;IACG;;;AAIN;EAEE;EACA;;AAID;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACC;EAEE;EACA;EACA;EACA;EACA;EACA;;AAEH;EAEE;EACD;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAED;EAEC;EACA;EACA;;AACA;EACC;;AACA;EAAW;;AACR;EAAS;EAA+B;;AAE3C;EAAQ;;AACR;EACE;EACD;;AACA;EACE;;AAIJ;EAAI;EAAuB;;AAK5B;EAGI;EACA;EACA;EACP;;AAGO;EAGG;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGA;EAEE;EACA;EACA;EACN;EACA;;AAGG;EACI;EACA;EACA;EACA;EACA;EACA;;AACA;EAAU;;AACV;EAEN;EACA;;AAMH;EAEG;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACP;EACA;EACA;EACA;;AAEO;EAEI;EACA;EACA;EACA;EACA;EACA;;AAGJ;EAEG;EAED;EACA;;AAKE;EAAK;;AACL;EACE;EACA;;AACA;EAAS;;AAGf;EACE;EACA;EAEA;EACL;EACK;EACA;EACA;EACA;EACA;EACL;EACA;EAEK;EACL;EACA;EACA;;AACA;EAAS;;AAMT;EAGE;EAGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;;AAEF;EAEE;;AACA;EAEG;EACA;EACA;;AAGH;EAAiB;;AAIvB;EAEE;EACA;EAGA;EACA;EACA;EACA;EACA;EACA;;AACA;EACA;EACA;EACA;;AAEA;EAEC;EACA;EACC;;AAQH;EAEI;;AACA;EAEE;EACA;EACA;EACA;EACE;;AAEF;EAEG;EACA;EACA;EACA;EACA;;AAGH;EAEE;;AAEF;EAEE;EACA;;AAGF;EACE;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;;AAGF;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACN;;AAEI;EAEE;EACA;EACA;EACA;EACN;;AAoBG;EATH;;AAUG;EAAe;;AACf;EAAQ;;AAEX;EAEG;EACJ;EACI;;AAKA;EACE;EACL;EACA;;AAKE;EAEG;EACL;;AAKG;EAEG;EACA;EACA;EACA;EACA;EACA;;AACN;EACC;;AACA;EAAI;;AAEC;EACE;;AAEF;EOpgBV;EACI;EACA;EACA;EACA;;AAEL;EACC;IAAM;IAA2B;;;AAGlC;EACC;IAAM;IAA8B;;;AAGrC;EACC;IAAM;IAA+B;;;AAGtC;EACC;IAAM;IAAmC;;;AAG1C;EACC;IAAM;IAAgC;;;APifnC;EAEE;EACD;;AAGD;EAEE;EACD;EACA;EACA;;AAIH;EAEE;EACA;;AACA;EACE;EACD;;AAED;EAAI;;AAWA;EACG;;AAEH;EACG;EACA;EACA;EACA;;AAEH;EACE;EAEA;;AACA;EACI;EACA;;AAEJ;EACI;;AAET;EACC;EACA;EACA;;AAGH;EACE;EACA;EACA;;AAIH;EAEE;;AAYI;EAAQ;;AACR;EAAe;;AACf;EAAQ;;AAIR;EAhJH;;AAiJG;EAAe;;AACf;EAAQ;;AAEX;EAEI;EACA;EACA;;AACA;EACE;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;EACA;EACA;;AAKD;EACI;EACA;EACA;;AACA;EAEG;EACA;;AAIN;EAEG;EAEA;EACA;;AAEA;EACE;EACA;EACA;;AACA;EAEG;EACA;EACA;;AACA;EAEG;;AAIR;EAEG;EACA;EACA;EAEA;;AAOd;EAEE;EACA;EACA;EACA;;AAEA;EAAU;;AAGZ;EACI;EAEA;EAEL;;AACK;EAAM;;AACN;EACG;EACA;EACA;EACN;;AACM;EAAgB;EAAkB;;AACxC;EAAkB;;AAClB;EAAkB;;AAClB;EAAU;EAAc;;AAGrB;EACE;EACA;;AAIN;EAEG;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;;AAEF;EACE;EACA;EACA;;AACA;EAAO;;AAET;EACE,YIttBS;EJutBT;EACA;EACA;EACA;EACA;;AAGL;EAEI;EACA;EACA;;AASD;EAAQ;;AACR;EAAe;;AACf;EAAQ;;AAIR;EArSH;;AAsSG;EAAe;;AACf;EAAQ;;AAGX;EAEE;EACA;EACA;EACA;EACA;EACJ;EACA;;AAEI;EACE;EACA;EACL;EAGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGG;EACI;EACA;EACA;;AAEA;EACE;;AAEF;EACE,QI5xBD;EJ6xBC;EACA;;AAEF;EAEE;EACA;EACA;EACA;EACA;;AAKR;EAEE;EACA;EACA;;AACA;EAAQ;;AACR;EACI;EACA;EACN;;AAEE;EACG;EACA;;AACL;EAEE;;AAIA;EAEE;EACA;EACA;EACA;EACA;EACL;;AAGK;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAGP;EAEE;EACA;;AAKD;EAEE;;AAMJ;EACC;;AAIC;EACG;EACA;EACA;EACA;EACJ;;AAEA;EACG;EACD;EACA;EACA;EACA;EACA;EACA;EACA;;AAIC;EAEG;EACA;EACA;EACA;;AAIN;EAEC;EACA;EACA;;AAGK;EACI;EACA;EACA;EACP;EACA;;AAEO;EACE;;AAEF;EACE;EACA;EACA;;AAEF;EAEE;EACA;EACA;EACA;EACA;;AAKR;EAIH;EACA;EAGK;;AAEL;EAIC;EACA;EACA;;AAID;EAEC;EACC;EACD;EACA;EACA;EACA;EACA;;AAED;EAEE;;AAIF;EAGC;;AASI;EAEG;EACA;EACA;EACA;;AAEA;EACE;EACR;EACA;EASA;EACA;;AATA;EAEC;;AAED;EAEC;;AAKF;EACE;EACA;EACA;EACA;EACA;EACA;;AAGK;EACE;EACA;EACA;EACA;EACA;EACA;;AAGL;EAEG;;AAEH;EAEE;;AACN;EACE;EACD;;AAMG;EACG;;AAKR;EACI;EACA;;AAYD;EAAQ;;AACR;EAAe;;AACf;EAAQ;;AAIR;EApmBH;;AAqmBG;EAAe;;AACf;EAAQ;;AAGX;EACI;;AAEF;EAEI;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;;AAOV;EAEG;EACA;EACA;EACA;EACA;;AAKL;EAEE;EAEA;;AACA;EAAK;EACH;EACA;;AAEA;EAEE;EACA;EACA;;AAIJ;EAAW;;AAEX;EAEC;EACA;;AAEK;EACG;;AAEH;EACG;EACA;EACA;EACA;EACN;;AAEG;EACE;EAEA;;AACA;EACI;EACA;;AAEJ;EACI;;AAGX;EAEE;EACA","file":"shortpixel-bulk.css"}1 {"version":3,"sourceRoot":"","sources":["../scss/elements/_fonts.scss","../scss/shortpixel-bulk.scss","../scss/bulk/_dashboard.scss","../scss/elements/_header.scss","../scss/elements/_mixins.scss","../scss/elements/_colors.scss","../scss/elements/_icons.scss","../scss/elements/_breakpoints.scss","../scss/elements/_animation.scss"],"names":[],"mappings":"AAEA;EAEI;EACA;EACA;EACA;;AAGJ;EAGI;EACA;EACA;EACA;;ACXJ;ACLA;ADgBE;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmcE;AAmIF;;AEtlBF;EAEI;EACA;EACA;EACA;EACA;EAEA;EAEA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAEF;EACE;EACA;EACA;EACA;;AAEF;EACH;;AAEM;EC5BL;EACA,YCKa;EDJb;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACC;;AAKD;EACE;EACA;;AAEF;EAEE;EACA;EACA;;ADOM;EACE,QEXG;EFYH;EACA;EACP;EACA;;AG5BL;EAEE;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;;AACA;EACG;;AAOH;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AAIJ;EAGE;EACA;EACA;EACA;EACA;;AAEA;EAEI;EACA;EACA;;AAGJ;EACE;EACA;EACA;;AJtDA;EAEG;EACA;EACA;;AAEA;EAAa;;AAIb;EAGK;EACA;EACA;EACA;EACA;EACA;;AACA;EAEE;EACA;EACA;EAAS;;AAGX;EAEG;EACA,kBGtBA;EHwBA;EACA;EACA;EACP;EAEA;EACA;EACM;;AAEA;EACE;;AAID;EACE;EACA;;AAEF;EAEN;;AAML;EAGC,kBG1DS;EH2DT;;AACK;EACE;EACA;EACA;EACA;EACA;;AAKR;EACE;EACD;;AK7DD;EL2DA;IAIE;;;AAED;EACC;;AAIC;EAEG;EACA;EACA;;AACA;EAAK;EAAwB;;AAC7B;EACE;;AACA;EAAS;EAAqB;;AAI9B;EACE;EACA;;AAKF;EACE;EACA;EAGA;EACA;;AAHA;EAAgB;;AAChB;EAAgB;;AAGhB;EACG;EACA;EACA;;ADzFb;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EAEI;EACA;;AAGN;EACE;;AAIF;EAEG;EACA;;AAGL;EACC;EACA;EACA;EACA;EAEA;EACA;EACA,YItDiB;EJuDjB,OI1DU;EJ2DV;EACA;EACA;EACS;EACA;EACA;EACT;;AAEA;EACC,YIpES;EJqET;;AAGD;EAEC,YI1ES;;AJ4EV;EAEE;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAID;EAEE,YIvFS;EJwFT;EACA;EACA;EACA;;AACA;EAEE;;AAMN;EACE;EAED;EACA;;AACA;EAEE;;AAIH;EACG;;AAGD;EACE;;AAGJ;EACG;EACA;;AAGJ;EACG;IACG;;EAEH;IACG;;;AAIN;EAEE;EACA;;AAID;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACC;EAEE;EACA;EACA;EACA;EACA;EACA;;AAEH;EAEE;EACD;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAED;EAEC;EACA;EACA;;AACA;EACC;;AACA;EAAW;;AACR;EAAS;EAA+B;;AAE3C;EAAQ;;AACR;EACE;EACD;;AACA;EACE;;AAIJ;EAAI;EAAuB;;AAK5B;EAGI;EACA;EACA;EACP;;AAGO;EAGG;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGA;EAEE;EACA;EACA;EACN;EACA;;AAGG;EACI;EACA;EACA;EACA;EACA;EACA;;AACA;EAAU;;AACV;EAEN;EACA;;AAMH;EAEG;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACP;EACA;EACA;EACA;;AAEO;EAEI;EACA;EACA;EACA;EACA;EACA;;AAGJ;EAEG;EAED;EACA;;AAKE;EAAK;;AACL;EACE;EACA;;AACA;EAAS;;AAGf;EACE;EACA;EAEA;EACL;EACK;EACA;EACA;EACA;EACA;EACL;EACA;EAEK;EACL;EACA;EACA;;AACA;EAAS;;AAMT;EAGE;EAGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;;AAEF;EAEE;;AACA;EAEG;EACA;EACA;;AAGH;EAAiB;;AAIvB;EAEE;EACA;EAGA;EACA;EACA;EACA;EACA;EACA;;AACA;EACA;EACA;EACA;;AAEA;EAEC;EACA;EACC;;AAQH;EAEI;;AACA;EAEE;EACA;EACA;EACA;EACE;;AAEF;EAEG;EACA;EACA;EACA;EACA;;AAGH;EAEE;;AAEF;EAEE;EACA;;AAGF;EACE;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;;AAGF;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACN;;AAEI;EAEE;EACA;EACA;EACA;EACN;;AAoBG;EATH;;AAUG;EAAe;;AACf;EAAQ;;AAEX;EAEG;EACJ;EACI;;AAKA;EACE;EACL;EACA;;AAKE;EAEG;EACL;EACK;EACA;;AAKF;EAEG;EACA;EACA;EACA;EACA;EACA;;AACN;EACC;;AACA;EAAI;;AAEC;EACE;;AAEF;EOtgBV;EACI;EACA;EACA;EACA;;AAEL;EACC;IAAM;IAA2B;;;AAGlC;EACC;IAAM;IAA8B;;;AAGrC;EACC;IAAM;IAA+B;;;AAGtC;EACC;IAAM;IAAmC;;;AAG1C;EACC;IAAM;IAAgC;;;APmfnC;EAEE;EACD;;AAGD;EAEE;EACD;EACA;EACA;;AAIH;EAEE;EACA;;AACA;EACE;EACD;;AAED;EAAI;;AAWA;EACG;;AAEH;EACG;EACA;EACA;EACA;;AAEH;EACE;EAEA;;AACA;EACI;EACA;;AAEJ;EACI;;AAET;EACC;EACA;EACA;;AAGH;EACE;EACA;EACA;;AAIH;EAEE;;AAYI;EAAQ;;AACR;EAAe;;AACf;EAAQ;;AAIR;EAlJH;;AAmJG;EAAe;;AACf;EAAQ;;AAEX;EAEI;EACA;EACA;;AACA;EACE;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;EACA;EACA;;AAKD;EACI;EACA;EACA;;AACA;EAEG;EACA;;AAIN;EAEG;EAEA;EACA;;AAEA;EACE;EACA;EACA;;AACA;EAEG;EACA;EACA;;AACA;EAEG;;AAIR;EAEG;EACA;EACA;EAEA;;AAOd;EAEE;EACA;EACA;EACA;;AAEA;EAAU;;AAGZ;EACI;EAEA;EAEL;;AACK;EAAM;;AACN;EACG;EACA;EACA;EACN;;AACM;EAAgB;EAAkB;;AACxC;EAAkB;;AAClB;EAAkB;;AAClB;EAAU;EAAc;;AAGrB;EACE;EACA;;AAIN;EAEG;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;;AAEF;EACE;EACA;EACA;;AACA;EAAO;;AAET;EACE,YIxtBS;EJytBT;EACA;EACA;EACA;EACA;;AAGL;EAEI;EACA;EACA;;AASD;EAAQ;;AACR;EAAe;;AACf;EAAQ;;AAIR;EAvSH;;AAwSG;EAAe;;AACf;EAAQ;;AAGX;EAEE;EACA;EACA;EACA;EACA;EACJ;EACA;;AAEI;EACE;EACA;EACL;EAGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGG;EACI;EACA;EACA;;AAEA;EACE;;AAEF;EACE,QI9xBD;EJ+xBC;EACA;;AAEF;EAEE;EACA;EACA;EACA;EACA;;AAKR;EAEE;EACA;EACA;;AACA;EAAQ;;AACR;EACI;EACA;EACN;;AAEE;EACG;EACA;;AACL;EAEE;;AAIA;EAEE;EACA;EACA;EACA;EACA;EACL;;AAGK;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAGP;EAEE;EACA;;AAKD;EAEE;;AAMJ;EACC;;AAIC;EACG;EACA;EACA;EACA;EACJ;;AAEA;EACG;EACD;EACA;EACA;EACA;EACA;EACA;EACA;;AAIC;EAEG;EACA;EACA;EACA;;AAIN;EAEC;EACA;EACA;;AAGK;EACI;EACA;EACA;EACP;EACA;;AAEO;EACE;;AAEF;EACE;EACA;EACA;;AAEF;EAEE;EACA;EACA;EACA;EACA;;AAKR;EAIH;EACA;EAGK;;AAEL;EAIC;EACA;EACA;;AAID;EAEC;EACC;EACD;EACA;EACA;EACA;EACA;;AAED;EAEE;;AAIF;EAGC;;AASI;EAEG;EACA;EACA;EACA;;AAEA;EACE;EACR;EACA;EASA;EACA;;AATA;EAEC;;AAED;EAEC;;AAKF;EACE;EACA;EACA;EACA;EACA;EACA;;AAGK;EACE;EACA;EACA;EACA;EACA;EACA;;AAGL;EAEG;;AAEH;EAEE;;AACN;EACE;EACD;;AAMG;EACG;;AAKR;EACI;EACA;;AAYD;EAAQ;;AACR;EAAe;;AACf;EAAQ;;AAIR;EAtmBH;;AAumBG;EAAe;;AACf;EAAQ;;AAGX;EACI;;AAEF;EAEI;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;;AAOV;EAEG;EACA;EACA;EACA;EACA;;AAKL;EAEE;EAEA;;AACA;EAAK;EACH;EACA;;AAEA;EAEE;EACA;EACA;;AAIJ;EAAW;;AAEX;EAEC;EACA;;AAEK;EACG;;AAEH;EACG;EACA;EACA;EACA;EACN;;AAEG;EACE;EAEA;;AACA;EACI;EACA;;AAEJ;EACI;;AAGX;EAEE;EACA","file":"shortpixel-bulk.css"} -
shortpixel-image-optimiser/tags/6.3.4/res/css/shortpixel-settings.css
r3347742 r3363822 134 134 } 135 135 .wrap.is-shortpixel-settings-page .shortpixel-settings button:hover, .wrap.is-shortpixel-settings-page .shortpixel-settings .button-setting:hover { 136 background: rgb(50.3421052632, 215.4868421053, 228.6578947368);136 background: #32d7e5; 137 137 } 138 138 .wrap.is-shortpixel-settings-page .shortpixel-settings button i.switch, .wrap.is-shortpixel-settings-page .shortpixel-settings .button-setting i.switch { … … 240 240 } 241 241 .wrap.is-shortpixel-settings-page .shortpixel-settings section.wrapper .setting-tab .save-buttons.saving button.save { 242 background-color: rgb(14.3684210526, 104.4473684211, 111.6315789474);242 background-color: #0e6870; 243 243 } 244 244 .wrap.is-shortpixel-settings-page .shortpixel-settings section.wrapper .setting-tab .save-buttons.saving button.save i { … … 461 461 } 462 462 .wrap.is-shortpixel-settings-page header .top-buttons a:hover, .wrap.is-shortpixel-settings-page header .top-buttons button:hover { 463 background: rgb(50.3421052632, 215.4868421053, 228.6578947368);463 background: #32d7e5; 464 464 } 465 465 .wrap.is-shortpixel-settings-page header .top-buttons a i.switch, .wrap.is-shortpixel-settings-page header .top-buttons button i.switch { … … 1192 1192 } 1193 1193 .wrap.is-shortpixel-settings-page #tab-overview .wrapper .dashboard-button:hover { 1194 background: rgb(50.3421052632, 215.4868421053, 228.6578947368);1194 background: #32d7e5; 1195 1195 } 1196 1196 .wrap.is-shortpixel-settings-page #tab-overview .wrapper .dashboard-button i.switch { … … 2143 2143 min-height: 44px; 2144 2144 color: #1ABDCA; 2145 background-color: rgb(232.25, 232.25, 232.25);2145 background-color: #e8e8e8; 2146 2146 border-radius: 6px; 2147 2147 font-weight: 700; … … 2151 2151 } 2152 2152 .wrap.is-shortpixel-settings-page #tab-tools .button:hover { 2153 background: rgb(50.3421052632, 215.4868421053, 228.6578947368);2153 background: #32d7e5; 2154 2154 color: #fff; 2155 2155 } -
shortpixel-image-optimiser/tags/6.3.4/res/js/screens/screen-bulk.js
r3346588 r3363822 261 261 data.webpActive = (document.getElementById('webp_checkbox').checked) ? true : false; 262 262 data.avifActive = (document.getElementById('avif_checkbox').checked) ? true : false; 263 263 264 if (null !== document.getElementById('autoai_checkbox')) 264 265 { 265 266 data.aiActive = (document.getElementById('autoai_checkbox').checked) ? true : false; 267 data.aiPreserve = (document.getElementById('aipreserve_checkbox').checked) ? true : false; 266 268 } 267 269 else 268 270 { 269 271 data.aiActive = false; 272 // data.aiPreserve = false; 270 273 } 271 274 data.backgroundProcess = (document.getElementById('background_checkbox').checked) ? true : false; … … 510 513 }); // circles; 511 514 } 512 DoSelection() // action to update response. 513 { 514 // @todo Check the future of this function, since checking this is now createBulk. 515 var data = {screen_action: 'applyBulkSelection'}; // 516 data.callback = 'shortpixel.applySelectionDone'; 517 518 data.mediaActive = (document.getElementById('media_checkbox').checked) ? true : false; 519 data.customActive = (document.getElementById('custom_checkbox').checked) ? true : false; 520 data.webpActive = (document.getElementById('webp_checkbox').checked) ? true : false; 521 data.avifActive = (document.getElementById('avif_checkbox').checked) ? true : false; 522 data.aiActive = (document.getElementById('autoai_checkbox').checked) ? true : false; 523 data.backgroundProcess = (document.getElementById('background_checkbox').checked) ? true : false; 524 525 window.addEventListener('shortpixel.applySelectionDone', function (e) { this.SwitchPanel('summary'); }.bind(this) , {'once': true} ); 526 this.processor.AjaxRequest(data); 527 528 } 515 529 516 530 517 UpdateStats(stats, type) -
shortpixel-image-optimiser/tags/6.3.4/res/js/screens/screen-item-base.js
r3346588 r3363822 27 27 } 28 28 29 30 29 // This is final, not more messing with this. In results (multiple) defined one level higher than result object, if single, it's in result. 31 30 var item_id = resultItem.item_id; 32 31 var message = resultItem.message; 33 34 32 35 33 // This is the reporting element ( all the data, via getItemView? ) … … 66 64 if ('ai' === apiName && typeof resultItem.aiData !== 'undefined') 67 65 { 68 69 66 if (null !== element) 70 67 { … … 336 333 window.addEventListener('shortpixel.HandleUndoAlt', function (event) { 337 334 var data = event.detail.media; 338 var original = data. original;335 var original = data.current; 339 336 340 337 if ('redo' == action_type) -
shortpixel-image-optimiser/tags/6.3.4/res/js/screens/screen-media.js
r3347742 r3363822 76 76 } 77 77 78 if (typeof newAltText !== 'undefined' )78 if (typeof newAltText !== 'undefined' || newAltText < 0) 79 79 { 80 80 var inputs = this.altInputNames; … … 107 107 let captionFields = ['attachment_caption', 'attachment-details-caption']; 108 108 let descriptionFields = ['attachment_content', 'attachment-details-description']; 109 110 111 109 112 if (typeof newCaption !== 'undefined' )110 if (typeof newCaption !== 'undefined' || newCaption < 0) 113 111 { 114 112 for (var i = 0; i < captionFields.length; i++) … … 120 118 } 121 119 } 122 123 124 120 } 125 121 126 if (typeof newDescription !== 'undefined' )122 if (typeof newDescription !== 'undefined' || newDescription < 0) 127 123 { 128 124 for (var i = 0; i < descriptionFields.length; i++) … … 134 130 } 135 131 } 136 137 138 132 } 139 140 133 141 134 if (null !== attachmentAlt) … … 157 150 window.addEventListener('shortpixel.AttachAiInterface', this.AttachAiInterface.bind(this), {once: true}); 158 151 } 159 /* if (typeof aiData !== 'undefined')160 {161 this.processor.LoadItemView({ id: item_id, type: 'media' });162 } */163 164 165 152 } 166 153 … … 291 278 var res = super.HandleImage(resultItem, type); 292 279 var fileStatus = this.processor.fStatus[resultItem.fileStatus]; 280 var apiName = (typeof resultItem.apiName !== 'undefined') ? resultItem.apiName : 'optimize'; 281 293 282 294 283 // If image editor is active and file is being restored because of this reason ( or otherwise ), remove the warning if this one exists. … … 299 288 } 300 289 } 290 291 if (fileStatus == 'FILE_DONE' && apiName == 'ai') 292 { 293 this.UpdateGutenBerg(resultItem); 294 } 301 295 } 302 296 … … 323 317 ListenGallery() { 324 318 var self = this; 319 var next_item_run_process = false; 325 320 326 321 if (this.settings.hide_spio_in_popups) … … 349 344 350 345 if (typeof this.fetchSPIOData === 'function') { 351 this.fetchSPIOData(this.model.get('id')); 352 this.spioBusy = true; // Note if this system turns out not to work, the perhaps render empties all if first was painted, second cancelled? 353 346 let attach_id = this.model.get('id'); 347 348 if (typeof attach_id !== 'undefined') 349 { 350 if (true === next_item_run_process ) 351 { 352 window.ShortPixelProcessor.SetInterval(-1); 353 window.ShortPixelProcessor.RunProcess(); 354 next_item_run_process = false; 355 } 356 else 357 { 358 this.fetchSPIOData(attach_id); 359 this.spioBusy = true; // Note if this system turns out not to work, the perhaps render empties all if first was painted, second cancelled? 360 } 361 } 362 else if (true == this.model.get('uploading')) 363 { 364 next_item_run_process = true; 365 console.log('Upload Start Detected'); 366 } 367 else 368 { 369 console.log('Id not found on render'); 370 } 354 371 } 355 372 … … 447 464 wrapper.classList.add('shortpixel-ai-interface',element.getAttribute('id')); 448 465 449 wrapper.innerHTML = data.snippet; 466 wrapper.innerHTML = data.snippet; 467 468 450 469 element.after(wrapper); 451 470 … … 579 598 } 580 599 600 UpdateGutenBerg(resultItem) 601 { 602 603 var attach_id = resultItem.item_id; 604 var aiData = resultItem.aiData; 605 606 if (! wp.data || ! wp.data.select('core')) 607 { 608 return false; 609 } 610 611 console.log(wp.data.select( 'core/block-editor' )); 612 613 let blocks = wp.data.select( 'core/block-editor' ).getBlocks(); 614 console.log(blocks); 615 for (let i = 0; i < blocks.length; i++) 616 { 617 let block = blocks[i]; 618 619 if (block.attributes.id == attach_id) 620 { 621 //block.attributes.alt = "I CAME TO ALT"; 622 //block.attributes.caption = "CAPTION THIS"; 623 let clientId = block.clientId; 624 625 console.log('DATA DISPATCH ', clientId, aiData); 626 wp.data.dispatch( 'core/block-editor' ).updateBlockAttributes( clientId, 627 aiData ); 628 629 } 630 } 631 } 632 581 633 } // class 582 634 -
shortpixel-image-optimiser/tags/6.3.4/res/scss/shortpixel-bulk.scss
r3348311 r3363822 498 498 opacity: 1; 499 499 height: auto; 500 z-index: 10; 501 position: relative; 500 502 } 501 503 } -
shortpixel-image-optimiser/tags/6.3.4/shortpixel-plugin.php
r3346588 r3363822 365 365 wp_register_script('shortpixel-media', plugins_url('res/js/shortpixel-media.js', SHORTPIXEL_PLUGIN_FILE), array('jquery'), SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true); 366 366 367 wp_register_script('shortpixel-inline-help', plugins_url('res/js/shortpixel-inline-help.js', SHORTPIXEL_PLUGIN_FILE), array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true); 367 wp_register_script('shortpixel-inline-help', plugins_url('res/js/shortpixel-inline-help.js', SHORTPIXEL_PLUGIN_FILE), [], SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true); 368 wp_register_script('shortpixel-chatbot', 369 apply_filters('shortpixel/plugin/nohelp', 'https://spcdn.shortpixel.ai/assets/js/ext/ai-chat-agent.js'), [], SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true); 368 370 369 371 // This filter is from ListMediaViewController for the media library grid display, executive script in shortpixel-media.js. … … 589 591 $this->load_script( 'shortpixel-screen-nolist' ); // screen 590 592 $this->load_script( 'shortpixel-settings' ); 593 $this->load_script('shortpixel-chatbot'); 591 594 592 595 // @todo Load onboarding only when no api key / onboarding required … … 599 602 } elseif ( $plugin_page == 'wp-short-pixel-bulk' ) { 600 603 $this->load_script( 'shortpixel-screen-bulk' ); 604 $this->load_script('shortpixel-chatbot'); 601 605 602 606 $this->load_style( 'shortpixel-admin' ); … … 619 623 620 624 $this->load_script( 'shortpixel-folderbrowser' ); 625 $this->load_script('shortpixel-chatbot'); 621 626 622 627 $this->load_style( 'shortpixel-admin' ); -
shortpixel-image-optimiser/tags/6.3.4/wp-shortpixel.php
r3348311 r3363822 4 4 * Plugin URI: https://shortpixel.com/ 5 5 * Description: ShortPixel optimizes images automatically, while guarding the quality of your images. Check your <a href="https://plugins.trac.wordpress.org/wp-admin/options-general.php?page=wp-shortpixel-settings" target="_blank">Settings > ShortPixel</a> page on how to start optimizing your image library and make your website load faster. 6 * Version: 6.3. 36 * Version: 6.3.4 7 7 * Author: ShortPixel - Convert WebP/AVIF & Optimize Images 8 8 * Author URI: https://shortpixel.com … … 37 37 define('SHORTPIXEL_PLUGIN_DIR', __DIR__); 38 38 39 define('SHORTPIXEL_IMAGE_OPTIMISER_VERSION', "6.3. 3");39 define('SHORTPIXEL_IMAGE_OPTIMISER_VERSION', "6.3.4"); 40 40 41 41 define('SHORTPIXEL_BACKUP', 'ShortpixelBackups'); -
shortpixel-image-optimiser/trunk/class/Controller/AdminController.php
r3346588 r3363822 127 127 $queueController = new QueueController(); 128 128 129 if ($optimizeAiController->isAutoAiEnabled())129 /* if ($optimizeAiController->isAutoAiEnabled()) 130 130 { 131 131 $args = ['action' => 'requestAlt']; 132 132 $queueController->addItemToQueue($mediaItem, $args); 133 } 133 } */ 134 134 135 135 -
shortpixel-image-optimiser/trunk/class/Controller/AjaxController.php
r3346588 r3363822 690 690 $this->checkImageAccess($imageModel); 691 691 692 $smartcrop = false; 692 $args = ['action' => 'reoptimize', 'compressionType' => $compressionType]; 693 694 // Smartcrop is not always passed, only add here when passed otherwise to defaults. 693 695 if ($actionType == ImageModel::ACTION_SMARTCROP || $actionType == ImageModel::ACTION_SMARTCROPLESS) 694 696 { 695 $ smartcrop= $actionType;697 $args['smartcrop'] = $actionType; 696 698 } 697 699 698 700 // @todo Ideally this should go to QueueController - addItemToQueue, but issue with arguments. Leaving it for now. 699 701 $queueController = new QueueController(); 700 $result = $queueController->addItemToQueue($imageModel, ['action' => 'reoptimize', 'compressionType' => $compressionType, 701 'smartcrop' => $smartcrop]); 702 $result = $queueController->addItemToQueue($imageModel, $args); 702 703 703 704 … … 807 808 protected function createBulk($json, $data) 808 809 { 810 $filters = []; 811 $has_filters = false; 812 813 if (isset($_POST['filter_startdate'])) 814 { 815 $filters['start_date'] = intval($_POST['filter_startdate']); 816 $has_filters = true; 817 } 818 if (isset($_POST['filter_enddate'])) 819 { 820 $filters['end_date'] = intval($_POST['filter_enddate']); 821 $has_filters = true; 822 823 } 824 825 $args = []; 826 if (true === $has_filters) 827 { 828 $args['filters'] = $filters; 829 } 830 831 832 809 833 $bulkControl = BulkController::getInstance(); 810 $stats = $bulkControl->createNewBulk('media' );834 $stats = $bulkControl->createNewBulk('media', $args); 811 835 $json->media->stats = $stats; 812 836 813 $stats = $bulkControl->createNewBulk('custom' );837 $stats = $bulkControl->createNewBulk('custom', $args); 814 838 $json->custom->stats = $stats; 815 839 … … 827 851 828 852 $doAi = filter_var(sanitize_text_field($_POST['aiActive']), FILTER_VALIDATE_BOOLEAN); 853 854 $aiPreserve = isset($_POST['aiPreserve']) ? filter_var(sanitize_text_field($_POST['aiPreserve']), FILTER_VALIDATE_BOOLEAN) : null; 855 829 856 $backgroundProcess = filter_var(sanitize_text_field($_POST['backgroundProcess']), FILTER_VALIDATE_BOOLEAN); 830 857 … … 841 868 \wpSPIO()->settings()->autoAIBulk = $doAi; 842 869 870 if (false === is_null($aiPreserve)) 871 { 872 \wpSPIO()->settings()->aiPreserve = $aiPreserve; 873 } 874 843 875 $bulkControl = BulkController::getInstance(); 844 876 … … 887 919 888 920 if (in_array('media', $queues)) { 889 $stats = $bulkControl->createNewBulk('media', 'bulk-restore');921 $stats = $bulkControl->createNewBulk('media', ['customOp' => 'bulk-restore']); 890 922 $json->media->stats = $stats; 891 923 } 892 924 893 925 if (in_array('custom', $queues)) { 894 $stats = $bulkControl->createNewBulk('custom', 'bulk-restore');926 $stats = $bulkControl->createNewBulk('custom', ['customOp' => 'bulk-restore']); 895 927 $json->custom->stats = $stats; 896 928 } … … 905 937 906 938 907 $stats = $bulkControl->createNewBulk('media', 'migrate');939 $stats = $bulkControl->createNewBulk('media', ['customOp' => 'migrate']); 908 940 $json->media->stats = $stats; 909 941 … … 917 949 918 950 919 $stats = $bulkControl->createNewBulk('media', 'removeLegacy');951 $stats = $bulkControl->createNewBulk('media', ['customOp' => 'removeLegacy']); 920 952 $json->media->stats = $stats; 921 953 … … 984 1016 985 1017 $optimizer = $qItem->getApiController('requestAlt'); 986 //$optimize->useCustomSettings($settingsData);987 //$result = $optimizer->enqueueItem($qItem, array_merge(['preview_only' => true, 'action' => 'requestAlt'], $settingsData));988 1018 989 1019 $qItem->requestAltAction(array_merge(['preview_only' => true], $settingsData)); … … 1021 1051 if (property_exists($result, 'aiData')) 1022 1052 { 1053 $aiModel = AiDataModel::getModelByAttachment($qItem->item_id, 'media'); 1054 1023 1055 $aiData = $optimizer->formatResultData($result->aiData, $qItem); 1056 list($items, $aiData) = $optimizer->formatGenerated($aiData, $aiModel->getCurrentData(), $aiModel->getOriginalData()); 1024 1057 $aiData['item_id'] = $qItem->item_id; 1025 1058 $aiData['time_generated'] = time(); … … 1039 1072 } 1040 1073 } 1041 1042 1043 //$is_done = true;1044 //$this->send((object) $result_json);1045 //break;1046 1074 1047 1075 } … … 1059 1087 $i++; 1060 1088 } 1061 1062 //$this->send($result_json);1063 1064 1089 } 1065 1090 … … 1076 1101 else 1077 1102 { 1078 $item = new AiDataModel($id);1103 $item = AiDataModel::getModelByAttachment($id); 1079 1104 $attach_id = $id; 1080 1105 } 1081 1082 // $attach_id = null;1083 1106 1084 1107 $imageModel = \wpSPIO()->fileSystem()->getMediaImage($attach_id); … … 1540 1563 { 1541 1564 1565 // defaults 1566 $message = __('This user is not allowed to edit this image', 'shortpixel-image-optimiser'); 1567 1542 1568 $accessModel = AccessModel::getInstance(); 1543 1569 if (is_object($mediaItem)) { 1544 1570 $bool = $accessModel->imageIsEditable($mediaItem); 1545 1571 $id = $mediaItem->get('id'); 1572 1546 1573 } else { 1547 1574 $bool = false; 1548 1575 $id = false; 1576 if (! is_object($mediaItem)) 1577 { 1578 $message = __('Image does not exist or could not be loaded', 'shortpixel-image-optimiser'); 1579 } 1549 1580 } 1550 1581 1551 1582 if ($bool === false) { 1552 1583 $json = new \stdClass; 1553 $json->message = __('This user is not allowed to edit this image', 'shortpixel-image-optimiser');1584 $json->message = $message; 1554 1585 $json->status = false; 1555 1586 $json->id = $id; … … 1573 1604 1574 1605 wp_send_json($json); 1575 1576 1606 exit(); 1577 1607 } -
shortpixel-image-optimiser/trunk/class/Controller/Api/AiController.php
r3347742 r3363822 235 235 protected function handleSuccess($aiData, QueueItem $qItem) 236 236 { 237 237 if (false === is_null($qItem->data()->returndatalist)) 238 { 239 $returndatalist = $qItem->data()->returndatalist; 240 if (is_object($returndatalist)) 241 { 242 $returndatalist = (array) $returndatalist; 243 } 244 245 foreach($returndatalist as $name => $data) 246 { 247 if (is_object($data)) // annoying conversion somehow by json decode from record 248 { 249 $data = (array) $data; 250 } 251 if (! isset($aiData[$name]) && isset($data['status'])) 252 { 253 $aiData[$name] = $data['status']; 254 } 255 } 256 } 257 238 258 return $this->returnSuccess(['aiData' => $aiData], RequestManager::STATUS_SUCCESS, __('Retrieved AI image SEO data', 'shortpixel-image-optimiser')); ; 239 259 } -
shortpixel-image-optimiser/trunk/class/Controller/Api/ApiController.php
r3289850 r3363822 239 239 $imageName = $imageNames[$index]; 240 240 $fileName = $fileNames[$index]; 241 $paramlist = $qItem->data()->paramlist; 242 243 // Here add paramList items that are possible needed for success checks 244 $params = isset($paramlist[$index]) ? (array) $paramlist[$index] : []; 245 246 241 247 $data = array( 242 248 'fileName' => $fileName, 243 249 'imageName' => $imageName, 244 250 ); 251 252 $data = array_merge($params, $data); 245 253 246 254 // Filesize might not be present, but also imageName ( only if smartcrop is done, might differ per image) … … 399 407 400 408 if (false === $this->checkFileSizeMargin($originalFileSize, $checkFileSize)) { 401 $image['image']['status'] = self::STATUS_OPTIMIZED_BIGGER; 402 $checkFileSize = $originalFileSize; 409 410 // Prevent this check if smartcrop is active on this image. 411 if (isset($data['resize']) && 4 == $data['resize'] ) 412 { 413 $image['image']['status'] = self::STATUS_OPTIMIZED_BIGGER; 414 $checkFileSize = $originalFileSize; 415 } 403 416 } 404 417 -
shortpixel-image-optimiser/trunk/class/Controller/BulkController.php
r3289850 r3363822 37 37 * 'bulk-restore', or 'migrate'. 38 38 */ 39 public function createNewBulk($type = 'media', $customOp = null) 40 { 39 public function createNewBulk($type = 'media', $args = []) 40 { 41 $defaults = [ 42 'customOp' => null, 43 'filters' => [], 44 45 ]; 46 47 48 $args = wp_parse_args($args, $defaults); 49 41 50 $queueController = new QueueController(['is_bulk' => true]); 42 51 … … 53 62 $Q = $queueController->getQueue($type); 54 63 55 $Q->createNewBulk(); 56 57 if (! is_null($customOp)) 64 if (! is_null($args['customOp'])) 58 65 { 59 $options = array(); 66 $customOp = $args['customOp']; 67 //$args['customOp'] = $customOp; 60 68 if ($customOp == 'bulk-restore') 61 69 { 62 $options['numitems'] = 5; 63 $options['retry_limit'] = 5; 64 $options['process_timeout'] = 3000; 70 $args['numitems'] = 5; 71 $args['retry_limit'] = 5; 72 $args['process_timeout'] = 3000; 73 65 74 } 66 75 if ($customOp == 'migrate' || $customOp == 'removeLegacy') 67 76 { 68 $ options['numitems'] = 200;77 $args['numitems'] = 200; 69 78 } 70 79 71 $ options = apply_filters('shortpixel/bulk/custom_options', $options, $customOp);72 $Q->setCustomBulk($customOp, $options); 80 $args = apply_filters('shortpixel/bulk/custom_options', $args); 81 73 82 } 83 84 85 $Q->createNewBulk($args); 86 74 87 75 88 return $Q->getStats(); -
shortpixel-image-optimiser/trunk/class/Controller/Front/CDNController.php
r3346588 r3363822 299 299 $fonts = ['.ttf', '.woff', '.woff2', '.otf']; 300 300 301 if (true == $settings->cdn_js) {301 if (true === $settings->cdn_js) { 302 302 $checkExtensions[] = '.js'; 303 303 304 304 } 305 if (true == $settings->cdn_css)305 if (true === $settings->cdn_css) 306 306 { 307 307 $checkExtensions[] = '.css'; … … 353 353 $replaceBlocks = $this->filterRegexExclusions($replaceBlocks); 354 354 $replaceBlocks = $this->filterOtherDomains($replaceBlocks); 355 $replaceBlocks = $this->filterFonts($replaceBlocks); 355 356 356 357 if (count($replaceBlocks) > 0) { … … 466 467 } 467 468 469 470 } 471 472 /** The image check on inline CSS might also catch inline fonts. Check against settings if they should be processed or not. 473 * 474 * @param mixed $replaceBlocks 475 * @return mixed 476 */ 477 protected function filterFonts($replaceBlocks) 478 { 479 $settings = \wpSPIO()->settings(); 480 481 if (true === $settings->cdn_css) 482 { 483 return $replaceBlocks; 484 } 485 486 $replaceBlocks = array_filter($replaceBlocks, function ($replaceBlock) 487 { 488 $fonts = ['.ttf', '.woff', '.woff2', '.otf']; 489 foreach($fonts as $extcheck) 490 { 491 if (strpos($replaceBlock->url, $extcheck) !== false) 492 { 493 return false; 494 } 495 } 496 return true; 497 498 }); 499 500 return $replaceBlocks; 468 501 469 502 } -
shortpixel-image-optimiser/trunk/class/Controller/Optimizer/OptimizeAiController.php
r3348311 r3363822 46 46 } 47 47 48 // $qItem->addResult(['qStatus' => Queue::RESULT_ERROR]);49 48 return; 50 49 } … … 53 52 public function sendToProcessing(QueueItem $qItem) { 54 53 55 if (false == $this->isSupported($qItem))54 /* if (false == $this->isSupported($qItem)) 56 55 { 57 56 // For now only fail here is GIF support, so message is a backstop for now that later should be updated. … … 65 64 } 66 65 else 67 { 66 { */ 68 67 $this->api->processMediaItem($qItem, $qItem->imageModel); 69 }68 //} 70 69 71 70 } … … 75 74 { 76 75 77 $aiDataModel = new AiDataModel($qItem->item_id);76 $aiDataModel = AiDataModel::getModelByAttachment($qItem->item_id); 78 77 $is_processable = $aiDataModel->isProcessable(); 79 78 80 79 if (false === $is_processable) { 80 $message = $aiDataModel->getProcessableReason(); 81 81 $qItem->addResult([ 82 'message' => __('AI generation not possible or already generated', 'shortpixel-image-optimiser'),82 'message' => $message, 83 83 'is_error' => true, 84 84 'is_done' => true, … … 107 107 break; 108 108 case 'retrieveAlt': // This might be deprecated, since retrieve will be called via next_action. 109 $qItem->retrieveAltAction($args ['remote_id']);109 $qItem->retrieveAltAction($args); 110 110 $directAction = false; 111 111 break; … … 226 226 // Always save the original filename 227 227 $aiData['original_filebase'] = $qItem->imageModel->getFileBase(); 228 $returnDataList = $qItem->data()->returndatalist; 228 229 229 230 if (! isset($aiData['filebase'])) … … 236 237 foreach($textItems as $textItem) 237 238 { 238 if (isset($aiData[$textItem]) && false !== $aiData[$textItem]) 239 240 if (isset($aiData[$textItem]) && false !== $aiData[$textItem] && false === is_numeric($aiData[$textItem])) 239 241 { 240 242 $aiData[$textItem] = $this->processTextResult($aiData[$textItem]); 241 243 } 242 } 244 // If 1 is returned as data, this means for some reason the API didn't create a text for this field, while it is allowed to do so. Defer to empty string better than '1' 245 if (true === is_numeric($aiData[$textItem]) && 1 == $aiData[$textItem]) 246 { 247 $aiData[$textItem] = ''; 248 } 249 } 250 251 // Re-add Result after formatting so it passed back 252 //$qItem->addResult(['aiData' => $aiData]); 253 243 254 244 255 return $aiData; … … 248 259 { 249 260 $aiData = $qItem->result->aiData; 250 $settings = $this->getAISettings(); 251 261 $settings = \wpSPIO()->settings(); 252 262 253 263 $checks = ['alt' => 'ai_gen_alt', … … 257 267 ]; 258 268 259 foreach($checks as $check_name => $check_setting)260 {261 if (false === $settings[$check_setting])262 {263 unset($aiData[$check_name]);264 }265 }266 267 268 269 $aiData = $this->formatResultData($aiData, $qItem); 269 270 … … 273 274 $item_id = $qItem->item_id; 274 275 275 $aiModel = new AIDataModel($item_id, 'media');276 $aiModel = AiDataModel::getModelByAttachment($item_id, 'media'); 276 277 $aiModel->handleNewData($aiData); 277 278 … … 292 293 } 293 294 */ 295 294 296 $imageModel = $qItem->imageModel; 295 $qItem->addResult(['improvements' => $imageModel->getImprovements()]); 296 297 298 $this->addPreview($qItem); 297 $qItem->addResult(['improvements' => $imageModel->getImprovements()]); // Improvements for bulk UX. 298 299 $this->addPreview($qItem); // Preview ( image ) for bulk UX 300 301 AiDataModel::flushModelCache($item_id); 302 303 // Get generated data which is the final result for the action including exclusions etc. 304 $data = $this->getAltData($qItem); 305 $qItem->addResult(['aiData' => $data['generated']]); // But the generated data in the result. 299 306 300 307 $this->finishItemProcess($qItem); … … 312 319 protected function replaceImageAttributes(QueueItem $qItem, $aiData) 313 320 { 321 if (is_int($aiData['alt']) && is_int($aiData['caption'])) 322 { 323 Log::addInfo('Alt/Caption returned integer/status, not replace'); 324 return; 325 } 326 314 327 // Replacer Part 315 328 $url = $qItem->data()->url; … … 392 405 if ($targetFileObj->exists()) 393 406 { 394 //$qItem->result()->is_error = true;395 //$qItem->result()->message = __('Replace Files: File Already exists', 'shortpixel-image-optimiser');396 407 Log::addWarn('Replace files found filename conflict and didnt run', $targetFileObj->getFullPath()); 397 408 return false; … … 414 425 } 415 426 416 417 418 419 427 $replacer = new Replacer(); 420 428 $replacer->setSource($source_url); … … 424 432 425 433 $replacer->replace(); 426 427 434 428 435 $this->replaceMetaData($item_id, $base_filename, $newFileName ); … … 511 518 } */ 512 519 513 $ sources[] = $match;514 515 if (isset($aiData['alt']) )520 $do_replace = false; 521 522 if (isset($aiData['alt']) && false === is_int($aiData['alt'])) 516 523 { 517 524 $frontImage->alt = $aiData['alt']; 525 $do_replace = true; 518 526 } 519 if (isset($aiData['caption']) )527 if (isset($aiData['caption']) && false === is_int($aiData['caption'])) 520 528 { 521 529 $frontImage->caption = $aiData['caption']; 530 $do_replace = true; 522 531 } 523 532 524 $replaces[] = $frontImage->buildImage(); 525 533 if (true === $do_replace) 534 { 535 $sources[] = $match; 536 $replaces[] = $frontImage->buildImage(); 537 } 526 538 527 539 } 528 540 529 $content = $replacer2->replaceContent($content, $sources, $replaces); 530 531 $replacer2->Updater()->updatePost($post_id, $content); 541 if (count($sources) > 0 && count($replaces) > 0) 542 { 543 Log::addInfo('Running Ai Replace : ', [$aiData, $sources, $replaces]); 544 $content = $replacer2->replaceContent($content, $sources, $replaces); 545 $replacer2->Updater()->updatePost($post_id, $content); 546 } 532 547 } 533 548 … … 544 559 } 545 560 561 /* 562 protected function fetchCaptionMatches($content, $qItem) 563 { 564 $pattern = '/' 565 } 566 */ 546 567 /** 547 568 * Check if setting AI is enabled in settings. … … 598 619 } 599 620 600 protected function getRequestJSON($url, $item_id, $params = []) 621 /* 622 protected function getRequestJSON($url, $params = []) 601 623 { 602 624 $settings = $this->getAISettings($params); 625 626 $ignore_fields = (isset($params['ignore_fields'])) ? $params['ignore_fields'] : []; 603 627 604 628 $json = [ … … 646 670 } 647 671 672 */ 673 674 /* 648 675 public function parseJSONForQItem(QueueItem $qItem, $params = []) 649 676 { 650 677 $url = $qItem->data()->url; 651 678 $item_id = $qItem->item_id; 652 $json = $this->getRequestJSON($url, $item_id, $params); 679 $settings = \wpSPIO()->settings(); 680 681 // Note this is also checked in AiDataModel for checking processable. Might need to sync upon adding fields 682 if (true === $settings->aiPreserve) 683 { 684 $returnDataList = $qItem->data()->returndatalist; 685 686 $aiModel = AiDataModel::getModelByAttachment($item_id, 'media'); 687 $current = $aiModel->getCurrentData(); 688 $filtered = array_filter($current); // filter out all empty variables 689 690 // $altdata = $this->getAltData($qItem); 691 $params['ignore_fields'] = array_keys($filtered); 692 693 foreach($filtered as $key => $filter) 694 { 695 $returnDataList[$key] = AiDataModel::F_STATUS_EXCLUDE; 696 } 697 $qItem->data()->returndatalist = $returnDataList; 698 } 699 700 $json = $this->getRequestJSON($url, $params); 701 702 653 703 $qItem->data()->paramlist = $json; 654 704 } 655 705 */ 706 707 /* 656 708 protected function parseQuestionForQItem(QueueItem $qItem) 657 709 { … … 661 713 $qItem->data()->url = $question; 662 714 } 663 715 */ 716 /* 664 717 private function getAISettings($params = []) 665 718 { … … 684 737 'ai_use_exif' => $settings->ai_use_exif, 685 738 'ai_language' => $settings->ai_language, 739 'aiPreserve' => $settings->aiPreserve, 686 740 ]; 687 741 … … 690 744 return $params; 691 745 } 692 693 public function parseQuestion($url, $item_id, $params = []) 694 { 695 $settings = \wpSPIO()->settings(); 696 697 $defaults = [ 698 'ai_general_context' => $settings->ai_general_context, 699 'ai_use_post' => $settings->ai_use_post, 700 'ai_gen_alt' => $settings->ai_gen_alt, 701 'ai_gen_caption' => $settings->ai_gen_caption, 702 'ai_gen_description' => $settings->ai_gen_description, 703 'ai_filename_prefercurrent' => $settings->ai_filename_prefercurrent, 704 'ai_limit_alt_chars' => $settings->ai_limit_alt_chars, 705 'ai_alt_context' => $settings->ai_alt_context, 706 'ai_limit_description_chars' => $settings->ai_limit_description_chars, 707 'ai_description_context' => $settings->ai_description_context, 708 'ai_limit_caption_chars' => $settings->ai_limit_caption_chars, 709 'ai_caption_context' => $settings->ai_caption_context, 710 'ai_gen_filename' => $settings->ai_gen_filename, 711 'ai_limit_filename_chars' => $settings->ai_limit_filename_chars, 712 'ai_filename_context' => $settings->ai_filename_context, 713 'ai_use_exif' => $settings->ai_use_exif, 714 'ai_language' => $settings->ai_language, 715 ]; 716 717 $params = wp_parse_args($params, $defaults); 718 719 $question = [ 720 'main' => $params['ai_general_context'], 721 'language' => $params['ai_language'], 722 'required_tags' => [], 723 ]; 724 725 $question['page'] = $this->getPageQuestion($question, $item_id, $params); 746 */ 726 747 727 $question = $this->getPartQuestion($question, 'alt', $params); 728 $question = $this->getPartQuestion($question, 'caption', $params); 729 $question = $this->getPartQuestion($question, 'description', $params); 730 $question = $this->getPartQuestion($question, 'filename', $params); 731 732 if (true == $params['ai_use_exif']) 733 { 734 $question['exif'] = ' and take into account the image EXIF data when generating all the requested texts'; 735 } 736 737 // $question['tags'] = implode($question['required_tags'], ','); 738 739 $question = apply_filters('shortpixel/ai/parsed_questions', $question); 740 741 /* $alt = isset($question['alt']) ? $question['alt'] : ''; 742 $caption = isset($question['caption']) ? $question['caption'] : ''; 743 $description =isset($question['description']) ? $question['description'] : ''; 744 $filename = isset($question['filename']) ? $question['filename'] : ''; 745 */ 746 $specs = []; 747 foreach($question['required_tags'] as $tag) 748 { 749 $specs[] = $question[$tag]; 750 } 751 $specs = implode(' ', $specs); 752 753 $required_tags = implode(',', $question['required_tags_ainame']); 754 755 if (strlen(trim($params['ai_language'])) <= 0) 756 { 757 $params['ai_language'] = get_locale(); 758 } 759 760 $final_question = sprintf("For the URL %s , with this context \" %s \" , write for %s SEO friendly texts with the following specifications: %s in %s language %s . Provide the answer in JSON format, seperating the %s output in seperate fields", 761 $url, 762 $question['main'], 763 $required_tags, 764 $specs, 765 $question['language'], 766 $question['exif'], 767 $required_tags 768 769 770 ); 771 772 return $final_question; 773 774 } 775 776 protected function getPartQuestion($question, $name, $params) 777 { 778 779 $limit = 'ai_limit_' . $name . '_chars'; 780 $context = 'ai_' . $name . '_context'; 781 $to_use = 'ai_gen_' . $name; 782 783 switch($name) 784 { 785 case 'alt': 786 $aiName = 'alt tag'; 787 break; 788 case 'caption': 789 $aiName = 'caption tag'; 790 break; 791 case 'description': 792 $aiName = 'description text'; 793 break; 794 case 'filename': 795 $aiName = 'the file name'; 796 break; 797 } 798 799 if (true === $params[$to_use]) 800 { 801 $limit = $params[$limit]; 802 $context = $params[$context]; 803 804 $string = ' For the ' . $aiName . ' limit your response to the most relevant ' . $limit . ' characters for SEO '; 805 806 if ('filename' == $name) 807 { 808 $string .= ' leaving the filename extension intact '; 809 if (true === $params['ai_filename_prefercurrent']) 810 { 811 $string .= ' and change filename only when the current filename is not relevant. Otherwise return false for this field '; 812 } 813 814 } 815 816 if (strlen(trim($context)) > 0) 817 { 818 $string .= ' and use this additional information when generating the ' . $aiName . ':' . $context . '. '; 819 } 820 821 $question[$name] = $string; 822 $question['required_tags_ainame'][] = $aiName; 823 $question['required_tags'][] = $name; 824 } 825 826 827 return $question; 828 } 829 830 protected function getPageQuestion($question, $item_id, $params) 831 { 832 if (false == $params['ai_use_post']) 833 { 834 return false; 835 } 836 837 $post = get_post($item_id); 838 if (is_null($post) || false === $post) 839 { 840 return false; 841 } 842 843 $parent = $post->post_parent; 844 845 if ($parent <= 0 || ! is_int($parent)) 846 { 847 return false; 848 } 849 850 $page_post = get_post($parent); 851 if (is_null($page_post) || false === $page_post) 852 { 853 return false; 854 } 855 856 $title = $page_post->post_title; 857 $excerpt = get_the_excerpt(($page_post)); 858 859 $string = ' for the article with the title ' . $title; 860 861 if (strlen(trim($excerpt)) > 0 ) 862 { 863 $string .= ' and excerpt ' . $excerpt; 864 } 865 866 867 return $string; 868 } 869 870 871 748 749 /* 872 750 public function isSupported(queueItem $qItem) 873 751 { … … 881 759 882 760 return true; 883 } 761 } */ 884 762 885 763 public function undoAltData(QueueItem $qItem) 886 764 { 887 765 $item_id = $qItem->item_id; 888 $aiModel = new AiDataModel($item_id, 'media');766 $aiModel = AiDataModel::getModelByAttachment($item_id, 'media'); 889 767 $original = $aiModel->getOriginalData(); 890 768 $generated = $aiModel->getGeneratedData(); 769 891 770 892 771 $aiData = [ … … 898 777 899 778 $aiModel->revert(); 779 AiDataModel::flushModelCache($item_id); 900 780 901 781 $this->replaceImageAttributes($qItem, $aiData); 902 782 783 $aiData = $aiModel->getCurrentData(); 784 903 785 return $this->getAltData($qItem); 904 786 } … … 908 790 $item_id = $qItem->item_id; 909 791 910 $aiModel = new AiDataModel($item_id, 'media');792 $aiModel = AiDataModel::getModelByAttachment($item_id, 'media'); 911 793 912 794 $status = $aiModel->getStatus(); … … 920 802 $aiModel->migrate($metacheck); 921 803 delete_post_meta($item_id, 'shortpixel_alt_requests'); 922 $aiModel = new AiDataModel($item_id, 'media');804 $aiModel = AiDataModel::getModelByAttachment($item_id, 'media'); 923 805 $status = $aiModel->getStatus(); 924 806 } … … 927 809 $generated = $aiModel->getGeneratedData(); 928 810 $original = $aiModel->getOriginalData(); 811 $current = $aiModel->getCurrentData(); 929 812 930 813 $image_url = $qItem->imageModel->getUrl(); 931 814 932 $fields = ['alt', 'caption', 'description']; 933 $dataItems = []; 934 foreach($fields as $name) 935 { 936 if (isset($generated[$name]) && false === is_null($generated[$name]) && strlen($generated[$name]) > 1) 937 { 938 $dataItems[] = ucfirst($name); 939 } 940 } 815 list($dataItems, $generated) = $this->formatGenerated($generated, $current, $original); 816 941 817 942 818 $view = new ViewController(); … … 946 822 'result_alt' => $generated['alt'], 947 823 'has_data' => ($status == AiDataModel::AI_STATUS_GENERATED) ? true : false, 824 'is_processable' => $aiModel->isProcessable(), 825 'processable_reason' => $aiModel->getProcessableReason(), 826 'processable_status' => $aiModel->getProcessableReason(true), 948 827 'image_url' => $image_url, 949 828 // 'current_alt' => $current_alt, 950 829 'status' => $status, 951 'isSupported' => $this->isSupported($qItem),952 'dataItems' => $dataItems, 830 // 'isSupported' => $this->isSupported($qItem), 831 'dataItems' => $dataItems, // This seems not used(?) 953 832 'isDifferent' => $aiModel->currentIsDifferent(), 954 833 ]); 955 834 835 836 // *****!!! Temporary don't pass these back since we don't support it yet ** // 837 838 if (isset($generated['filebase'])) 839 { 840 unset($generated['filebase']); 841 } 842 if (isset($generated['filename'])) 843 { 844 unset($generated['filename']); 845 } 846 956 847 $metadata['snippet'] = $view->returnView('snippets/part-aitext'); 957 848 958 849 $metadata['generated'] = $generated; 959 850 $metadata['original'] = $original; 851 $metadata['current'] = $current; 960 852 $metadata['action'] = $qItem->data()->action; 961 853 $metadata['item_id'] = $item_id; … … 964 856 } 965 857 858 public function formatGenerated($generated, $current, $original) 859 { 860 861 $fields = ['alt', 'caption', 'description']; 862 $dataItems = []; 863 864 // Statii from AiDataModel which means generated is not available (replace for original/current?) 865 $statii = [AiDataModel::F_STATUS_PREVENTOVERRIDE, AiDataModel::F_STATUS_EXCLUDESETTING]; 866 867 foreach($fields as $name) 868 { 869 if (false === isset($generated[$name])) 870 { 871 continue; 872 } 873 $value = $generated[$name]; 874 875 876 if (false === is_null($value) && false === is_int($value) && strlen($value) > 1) 877 { 878 $dataItems[] = ucfirst($name); 879 } 880 if (is_int($value) && in_array($value, $statii)) 881 { 882 if (isset($current[$name])) 883 { 884 $value = $current[$name]; 885 } 886 elseif(isset($original[$name])) 887 { 888 $value = $original[$name]; 889 } 890 $generated[$name] = $value; 891 } 892 } 893 894 return [$dataItems, $generated]; 895 } 896 966 897 967 898 -
shortpixel-image-optimiser/trunk/class/Controller/Optimizer/OptimizerBase.php
r3346588 r3363822 48 48 //exit('This call is wron because in it messes with ActionController - Reoptimize ( calls ActionController again instead of OptimizeConrtoller'); 49 49 $calledClass = get_called_class(); 50 //Log::addTemp('OptimizerBase Called Class - ' . $calledClass); 50 51 51 if (! isset(static::$instances[$calledClass])) 52 52 { … … 54 54 } 55 55 56 // Log::addTemp('OptimizeBase, Instances', self::$instances);57 56 return self::$instances[$calledClass]; 58 57 } -
shortpixel-image-optimiser/trunk/class/Controller/Queue/MediaLibraryQueue.php
r3289850 r3363822 8 8 use ShortPixel\ShortQ\ShortQ as ShortQ; 9 9 use ShortPixel\Controller\CacheController as CacheController; 10 use ShortPixel\Helper\UtilHelper; 10 11 use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log; 11 12 use ShortPixel\Model\Image\ImageModel as ImageModel; … … 32 33 'retry_limit' => 30, // amount of times it will retry without errors before giving up 33 34 'enqueue_limit' => 200, // amount of items added to the queue when preparing. 35 'filters' => [], 34 36 ); 35 37 … … 56 58 } 57 59 60 public function createNewBulk($args = []) 61 { 62 /* if (isset($args['filters'])) 63 { 64 $this->addFilters($args['filters']); 65 } */ 66 67 68 // Parent should save options as well. 69 return parent::createNewBulk($args); 70 } 71 72 73 protected function addFilters($filters) 74 { 75 76 //$start_id = $end_id = null; 77 78 79 global $wpdb; 80 81 82 $start_date = isset($filters['start_date']) ? new \DateTime($filters['start_date']) : false; 83 $end_date = isset($filters['end_date']) ? new \DateTime($filters['end_date']) : false; 84 85 if (isset($filters['start_date'])) 86 { 87 //$date = UtilHelper::timestampToDB($filters['start_time']); 88 $date = $start_date->format("Y-m-d H:i:s"); 89 $startSQL = 'select max(ID) from wp_posts where post_date <= %s group by post_date order by post_date DESC limit 1'; 90 $sql = $wpdb->prepare($startSQL, $date); 91 $start_id = $wpdb->get_var($sql); 92 } 93 if (isset($filters['end_date'])) 94 { 95 // $date = UtilHelper::timestampToDB($filters['end_time']); 96 $date = $end_date->format("Y-m-d H:i:s"); 97 $endSQL = 'select MIN(ID) from wp_posts where post_date <= %s group by post_date order by post_date DESC limit 1'; 98 $sql = $wpdb->prepare($endSQL, $date); 99 $end_id = $wpdb->get_var($sql); 100 } 101 102 103 104 //echo "Start $start_id END $end_id"; 105 //exit(); 106 // IF POST DATE NEEDS 09-20 ( or 23:59:59? ) 107 // select post_date, max(ID) from wp_posts where post_date <= '2024-09-21 00:00:00' group by post_date order by post_date DESC limit 100 108 } 109 58 110 59 111 private function queryPostMeta() -
shortpixel-image-optimiser/trunk/class/Controller/Queue/Queue.php
r3346588 r3363822 9 9 use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log; 10 10 use ShortPixel\Controller\CacheController as CacheController; 11 use ShortPixel\Controller\Optimizer\OptimizeAiController; 11 12 use ShortPixel\Controller\ResponseController as ResponseController; 12 13 use ShortPixel\Model\Converter\Converter as Converter; … … 48 49 49 50 50 public function createNewBulk( )51 public function createNewBulk($args = []) 51 52 { 52 53 $this->resetQueue(); … … 58 59 $cache = new CacheController(); 59 60 $cache->deleteItem($this->cacheName); 61 62 $this->setCustomBulk($args); 60 63 } 61 64 … … 98 101 $args = wp_parse_args($args, $defaults); 99 102 100 101 103 $qItem = QueueItems::getImageItem($imageModel); 102 103 104 104 105 $result = new \stdClass; … … 107 108 $numitems = $this->q->withRemoveDuplicates()->enqueue(); // enqueue returns numitems 108 109 110 $this->checkQueueCache($imageModel->get('id')); 111 109 112 $result->qstatus = $this->getQStatus($numitems); 110 113 $result->numitems = $numitems; … … 117 120 { 118 121 $this->q->addItems([$qItem->returnEnqueue()], false); 122 $item_id = $qItem->item_id; 119 123 $numitems = $this->q->withRemoveDuplicates()->enqueue(); // enqueue returns numitems 120 124 … … 123 127 $result->numitems = $numitems; 124 128 125 do_action('shortpixel_start_image_optimisation', $qItem->item_id, $qItem->imageModel); 129 $this->checkQueueCache($item_id); 130 131 132 do_action('shortpixel_start_image_optimisation', $item_id, $qItem->imageModel); 126 133 return $result; 127 134 } … … 270 277 } 271 278 279 $optimizeAiController = OptimizeAiController::getInstance(); 280 272 281 // If autoAi is on the bulk, add operation to the item 273 if ('media' === $mediaItem->get('type') && true === $settings->autoAIBulk) 282 $enqueueAi = false; 283 if ('media' === $mediaItem->get('type') && true === $optimizeAiController->isAiEnabled() && true === $settings->autoAIBulk) 274 284 { 275 276 $aiDataModel = new AiDataModel($mediaItem->get('id')); 277 $enqueueAi = false; 278 if ($aiDataModel->isProcessable() && in_array($mediaItem->getExtension(), $aiDataModel->supportedExtensions())) 279 { 280 $enqueueAi = true; 281 } 285 $aiDataModel = AiDataModel::getModelByAttachment($mediaItem->get('id')); 286 $enqueueAi = $aiDataModel->isProcessable(); 282 287 } 283 else284 {285 $enqueueAi = false;286 }287 288 288 289 289 if ($mediaItem->isProcessable() && $mediaItem->isOptimizePrevented() === false && ! $operation) // Checking will be done when processing queue. … … 317 317 $baseCount += $counts->baseCount; // base images (all minus webp/avif) 318 318 319 320 $this->checkQueueCache($item_id); 319 321 do_action('shortpixel_start_image_optimisation', $mediaItem); 320 322 … … 511 513 } 512 514 513 public function setCustomBulk($ type = null, $options = array())514 { 515 if ( is_null($type))515 public function setCustomBulk($options = [] ) 516 { 517 if (0 === count($options)) 516 518 return false; 517 519 518 520 $customData = $this->getStatus('custom_data'); 519 $customData->customOperation = $type; 521 522 523 if (isset($options['customOp'])) 524 { 525 $customOp = $options['customOp']; 526 $customData->customOperation = $customOp; 527 unset($options['customOp']); 528 } 529 520 530 if (is_array($options) && count($options) > 0) 521 531 $customData->queueOptions = $options; … … 613 623 return false; 614 624 } 625 626 protected function checkQueueCache($item_id) 627 { 628 629 630 if (isset(self::$isInQueue[$item_id]) && false === self::$isInQueue[$item_id]) 631 { 632 unset(self::$isInQueue[$item_id]); 633 } 634 635 636 637 638 } 615 639 616 640 public function itemFailed(QueueItem $qItem, $fatal = false) -
shortpixel-image-optimiser/trunk/class/Controller/QueueController.php
r3346588 r3363822 63 63 'smartcrop' => null, 64 64 'next_actions' => [], 65 'returndatalist' => [], 65 66 ); 66 67 $args = wp_parse_args($args, $defaults); … … 72 73 { 73 74 $qItem->data()->next_actions = $args['next_actions']; 75 } 76 77 if (is_object($args['returndatalist'])) 78 { 79 $args['returndatalist'] = (array) $args['returndatalist']; 80 } 81 if (is_array($args['returndatalist']) && count($args['returndatalist']) > 0) 82 { 83 $qItem->data()->returndatalist = $args['returndatalist']; 74 84 } 75 85 … … 198 208 // @todo This queueItem should maybe not to stuffed with 'addresult'm since it's a different object. 199 209 $queueItem = $q->getItem($mediaItem->get('id')); 210 200 211 if (is_object($queueItem)) 201 212 { … … 327 338 { 328 339 $result = $Q->run(); 329 $results = [];330 340 $fs = \wpSPIO()->filesystem(); 331 341 … … 337 347 $qtype = strtolower($qtype); 338 348 339 //Log::addTemp('RunTick Items - ', $items);340 349 /* Only runs if result is array, dequeued items. 341 350 Item is a MediaItem subset of QueueItem … … 346 355 $action = $qItem->data()->action; 347 356 $apiController = $qItem->getAPIController($action); 357 $send_to_processing = true; 348 358 349 359 … … 374 384 } 375 385 376 if (! is_object($imageModel)) 386 if (! is_object($imageModel)) // Error in loading imageModel, can't process this. 377 387 { 378 388 Log::addWarn('ImageObject was empty when send to processing - ' . $item_id); 379 389 $qItem->addResult([ 380 390 'apiStatus' => RequestManager::STATUS_NOT_API, 381 'message' => __("File Error. Filecould not be loaded with this ID ", 'shortpixel-image-optimiser'),391 'message' => __("File Error. Media Item could not be loaded with this ID ", 'shortpixel-image-optimiser'), 382 392 'fileStatus' => ImageModel::FILE_STATUS_ERROR, 383 393 'is_done' => true, 384 394 'is_error' => true, 385 395 ]); 396 $Q->itemFailed($qItem, true); 397 $send_to_processing = false; 386 398 } 387 399 elseif(true === $qItem->block()) … … 392 404 ]); 393 405 Log::addWarn('Encountered blocked item, processing success? ', $item_id); 406 ResponseController::addData($item_id, 'fileName', $imageModel->getFileName()); 407 $send_to_processing = false; 394 408 } 395 409 else … … 403 417 ResponseController::addData($item_id, 'fileName', $imageModel->getFileName()); 404 418 } 405 406 ResponseController::addData($item_id, 'fileName', $imageModel->getFileName());407 408 419 409 420 $this->setLastID($item_id); 410 421 411 if (! is_null($apiController) )422 if (! is_null($apiController) && true === $send_to_processing) 412 423 { 413 424 $apiController->sendToProcessing($qItem); … … 821 832 $item_id = $qItem->item_id; 822 833 $responseItem = ResponseController::getResponseItem($item_id); 823 $type = $qItem->imageModel->get('type'); 834 835 $type = (is_object($qItem->imageModel)) ? $qItem->imageModel->get('type') : false; 836 837 if (false === $type) 838 { 839 return; 840 } 824 841 825 842 $fs = \wpSPIO()->filesystem(); -
shortpixel-image-optimiser/trunk/class/Controller/View/EditMediaViewController.php
r3348311 r3363822 15 15 16 16 use ShortPixel\Controller\Queue\QueueItems as QueueItems; 17 17 use ShortPixel\Model\AiDataModel; 18 18 use ShortPixel\Model\File\FileModel as FileModel; 19 19 … … 141 141 protected function getStatistics() 142 142 { 143 //$data = $this->data; 144 $stats = array(); 143 $stats = []; 145 144 $imageObj = $this->imageModel; 146 145 $did_keepExif = $imageObj->getMeta('did_keepExif'); … … 213 212 } 214 213 214 $optimizeAiController = OptimizeAiController::getInstance(); 215 215 216 216 217 $thumbnails = $imageObj->get('thumbnails'); … … 267 268 $debugInfo[] = array(__('To Optimize URLS'), $urls); 268 269 } 269 if (isset($optimizeData)) 270 { 271 $debugInfo[] = array(__('Optimize Data'), $optimizeData);272 273 $queueControl = new QueueController(); 274 275 // $q = $queueControl->getQueue($imageObj->get('type'));276 277 $item = QueueItems::getImageItem($imageObj); 270 271 272 $item = QueueItems::getImageItem($imageObj); 273 274 if ($imageObj->isProcessable()) 275 { 276 // $queueControl = new QueueController(); 277 278 278 279 $item->setDebug(); 279 280 $item->newOptimizeAction(); … … 281 282 $returnEnqueue = $item->returnEnqueue(); 282 283 283 // TEST @todo REMOVE 284 /*$replacer2 = new \ShortPixel\Replacer\Replacer(); 285 $setup = $replacer2->Setup(); 286 $setup->forSearch()->URL()->addData($item->imageModel->getURL()); 287 288 $base_url = $setup->forSearch()->URL()->getBaseURL(); 289 290 $text = 'AI TEST'; 291 292 $finder = $replacer2->Finder(['base_url' => $base_url, 'callback' => [OptimizeAiController::getInstance(), 'handleReplace'], 'return_data' => [ 293 'retrievedText' => $text, 294 'qItem' => $item, 295 ]]); 296 297 $posts = $finder->posts(); */ 298 299 $debugInfo[] = array(__('Image to Queue V2'), $returnEnqueue ); 300 301 } 284 $debugInfo[] = array(__('Image to Queue'), $returnEnqueue ); 285 286 } 287 288 if ( $optimizeAiController->isAIEnabled()) 289 { 290 $aiDataModel = AiDataModel::getModelByAttachment($this->post_id); 291 292 $aiProcessable = ($aiDataModel->isProcessable()) ? '<span class="green">Yes</span>' : '<span class="red">No</span> '; 293 294 $debugInfo[] = ['AI - is Processable', $aiProcessable]; 295 296 if (true === $aiDataModel->isProcessable()) 297 { 298 //$item->requestAltAction(); 299 // $optimizeAiController->parseJsonForQItem($item); 300 $debugInfo[] = ['Ai - Paramlist ', $aiDataModel->getOptimizeData() ]; 301 // $debugInfo[] = ['Ai - returnDataList' , $item->data()->returndatalist]; 302 303 } 304 else 305 { 306 $debugInfo[] = ['Ai - Reason', $aiDataModel->getProcessableReason()]; 307 } 308 if (true === $aiDataModel->isSomeThingGenerated()) 309 { 310 $debugInfo[] = ['Ai -Generated ', $aiDataModel->getGeneratedData()]; 311 } 312 313 } 314 315 302 316 303 317 $debugInfo['imagemetadata'] = array(__('ImageModel Metadata (ShortPixel)'), $imageObj); … … 366 380 367 381 $display_size = ucfirst(str_replace("_", " ", $size)); 368 //$thumbObj = $imageObj->getThumbnail($size);369 382 370 383 if ($thumbObj === false) … … 374 387 } 375 388 376 $url = $thumbObj->getURL(); //$fs->pathToURL($thumbObj); //wp_get_attachment_image_src($this->post_id, $size);389 $url = $thumbObj->getURL(); 377 390 $filename = $thumbObj->getFullPath(); 378 391 $fileDir = $thumbObj->getFileDir(); -
shortpixel-image-optimiser/trunk/class/Controller/View/ListMediaViewController.php
r3347742 r3363822 13 13 14 14 use ShortPixel\Controller\ApiKeyController as ApiKeyController; 15 use ShortPixel\Controller\Optimizer\OptimizeAiController; 15 16 use ShortPixel\Controller\QuotaController as QuotaController; 16 17 use ShortPixel\Controller\QueueController as QueueController; … … 60 61 { 61 62 $defaults['wp-shortPixel'] = __('ShortPixel Compression', 'shortpixel-image-optimiser'); 62 /*if (true === \wpSPIO()->settings()->enable_ai) 63 { 64 $defaults['wp-spio-ai'] = __('AI By Shortpixel', 'shortpixel-image-optimiser'); 65 } */ 63 66 64 67 65 return $defaults; … … 99 97 $list_actions = array(); 100 98 101 if (true === \wpSPIO()->settings()->enable_ai) 99 $optimizeAiController = OptimizeAiController::getInstance(); 100 101 102 if (true === $optimizeAiController->isAiEnabled()) 102 103 { 103 104 $aiDataModel = $this->loadAiItem($id); … … 174 175 protected function loadAiItem($item_id) 175 176 { 176 $AiDataModel = new AiDataModel($item_id);177 $AiDataModel = AiDataModel::getModelByAttachment($item_id); 177 178 $this->view->item_id = $item_id; 178 179 -
shortpixel-image-optimiser/trunk/class/Controller/View/SettingsViewController.php
r3348311 r3363822 430 430 } 431 431 432 433 432 434 // If the compression type setting changes, remove all queued items to prevent further optimizing with a wrong type. 433 435 if (intval($this->postData['compressionType']) !== intval($this->model->compressionType)) … … 448 450 { 449 451 $type = $this->model->getType($name); 450 if ('boolean' === $type && ! isset($this->postData[$name]))452 if ('boolean' === $type ) 451 453 { 452 $this->model->{$name} = false; 454 if( ! isset($this->postData[$name])) 455 { 456 $this->model->{$name} = false; 457 } 458 else 459 { 460 $this->model->{$name} = true; 461 } 453 462 } 454 463 } … … 864 873 } 865 874 } 875 876 if (false === isset($post['enable_ai'])) 877 { 878 if (isset($post['autoAI'])) 879 { 880 unset($post['autoAI']); 881 } 882 if (isset($post['autoAIBulk'])) 883 { 884 unset($post['autoAIBulk']); 885 } 886 } 866 887 867 888 -
shortpixel-image-optimiser/trunk/class/Helper/UiHelper.php
r3346930 r3363822 331 331 } 332 332 333 //$aiDataModel = new AiDataModel($id);334 335 333 if ($mediaItem->isSomethingOptimized() ) 336 334 { … … 439 437 440 438 441 if (false === is_null($aiDataModel) && $aiDataModel->isProcessable() && 'media' === $mediaItem->get('type') && in_array($mediaItem->getExtension(), $aiDataModel->supportedExtensions()))439 if (false === is_null($aiDataModel) && $aiDataModel->isProcessable() && 'media' === $mediaItem->get('type') ) 442 440 { 443 441 $list_actions['shortpixel-generateai'] = self::getAction('shortpixel-generateai', $id); -
shortpixel-image-optimiser/trunk/class/Helper/UtilHelper.php
r3346588 r3363822 30 30 } 31 31 32 static public function timestampToDB($timestamp)32 public static function timestampToDB($timestamp) 33 33 { 34 34 return date("Y-m-d H:i:s", $timestamp); 35 35 } 36 36 37 static public function DBtoTimestamp($date)37 public static function DBtoTimestamp($date) 38 38 { 39 39 return strtotime($date); … … 170 170 } 171 171 return $bool; 172 } 173 174 public static function getAiSettings($params = []) 175 { 176 $settings = \wpSPIO()->settings(); 177 178 $defaults = [ 179 'ai_general_context' => $settings->ai_general_context, 180 'ai_use_post' => $settings->ai_use_post, 181 'ai_gen_alt' => $settings->ai_gen_alt, 182 'ai_gen_caption' => $settings->ai_gen_caption, 183 'ai_gen_description' => $settings->ai_gen_description, 184 'ai_filename_prefercurrent' => $settings->ai_filename_prefercurrent, 185 'ai_limit_alt_chars' => $settings->ai_limit_alt_chars, 186 'ai_alt_context' => $settings->ai_alt_context, 187 'ai_limit_description_chars' => $settings->ai_limit_description_chars, 188 'ai_description_context' => $settings->ai_description_context, 189 'ai_limit_caption_chars' => $settings->ai_limit_caption_chars, 190 'ai_caption_context' => $settings->ai_caption_context, 191 'ai_gen_filename' => $settings->ai_gen_filename, 192 'ai_limit_filename_chars' => $settings->ai_limit_filename_chars, 193 'ai_filename_context' => $settings->ai_filename_context, 194 'ai_use_exif' => $settings->ai_use_exif, 195 'ai_language' => $settings->ai_language, 196 'aiPreserve' => $settings->aiPreserve, 197 ]; 198 199 $params = wp_parse_args($params, $defaults); 200 201 return $params; 172 202 } 173 203 -
shortpixel-image-optimiser/trunk/class/Model/AiDataModel.php
r3346588 r3363822 14 14 class AiDataModel 15 15 { 16 17 16 protected $id; 18 17 protected $attach_id; 19 18 protected $type; 19 20 protected static $models = []; 20 21 21 22 protected $original = [ … … 45 46 private $current_is_set = false; 46 47 48 private $processable_status = 0; 47 49 48 50 const TYPE_MEDIA = 1; 49 51 const TYPE_CUSTOM = 2; 50 52 53 // Status for the whole image, in the main table. 51 54 const AI_STATUS_NOTHING = 0; 52 55 const AI_STATUS_GENERATED = 1; 56 57 // IsProcessable statii 58 const P_PROCESSABLE = 0; 59 const P_ALREADYDONE = 1; // Data already there 60 const P_EXIFAI = 2; // When Exif Flag forbids AI doing 61 const P_EXTENSION = 3; 62 const P_NOJOB = 4; 63 const P_NOFIELDS = 5; 64 65 // Descriptive status if certain field is not generated / left alone. 66 const F_STATUS_OK = 1; 67 const F_STATUS_EXCLUDESETTING = -3; 68 const F_STATUS_PREVENTOVERRIDE = -4; 69 53 70 54 71 public function __construct($attach_id, $type = 'media') … … 94 111 $this->generated = array_merge($this->generated, $generatedData); 95 112 96 97 113 } 98 114 … … 108 124 109 125 return (array) $data; 126 127 } 128 129 /** Get all data needed to send API for generating AI texts, depending on settings. This includes all settings minus URL 130 * 131 * @return array{paramlist: array<string, array{context: mixed, chars: mixed}>, returndatalist: array<string, array<string, int>>} 132 */ 133 public function getOptimizeData($params = []) 134 { 135 $settings = (object) UtilHelper::getAiSettings($params); 136 137 $ignore_fields = []; 138 if (true === $settings->aiPreserve) 139 { 140 $currentData = $this->getCurrentData(); 141 $ignore_fields = array_keys(array_filter($currentData)); 142 } 143 144 145 // $fields = ['ai_gen_alt', 'ai_gen_caption', 'ai_gen_description', 'ai_gen_filename']; 146 $fields = ['alt', 'caption', 'description', 'filename']; 147 148 $paramlist = [ 149 'languages' => $settings->ai_language, 150 'context' => $settings->ai_general_context, 151 ]; 152 $returnDataList = []; 153 $field_status = false; // check if there are any fields to process / not all excluded. 154 155 foreach($fields as $field_name) 156 { 157 $api_name = $field_name; 158 //$paramlist[$api_name] = []; 159 160 switch($api_name) 161 { 162 case 'description': 163 $api_name = 'image_description'; 164 break; 165 case 'filename': 166 $api_name = 'file'; 167 break; 168 } 169 170 171 if (false === $settings->{'ai_gen_' . $field_name}) 172 { 173 $returnDataList[$field_name]['status'] = self::F_STATUS_EXCLUDESETTING; 174 continue; 175 } 176 elseif (true === in_array($field_name, $ignore_fields)) 177 { 178 $returnDataList[$field_name]['status'] = self::F_STATUS_PREVENTOVERRIDE; 179 } 180 else 181 { 182 $paramlist[$api_name] = [ 183 'context' => $settings->{'ai_' . $field_name . '_context'}, 184 'chars' => $settings->{'ai_limit_' . $field_name . '_chars'}, 185 ]; 186 $returnDataList[$field_name]['status'] = self::F_STATUS_OK; 187 $field_status = true; 188 } 189 190 191 } 192 193 if (false === $field_status) 194 { 195 $this->processable_status = self::P_NOJOB; 196 } 197 198 return ['paramlist' => $paramlist, 'returndatalist' => $returnDataList]; 110 199 111 200 } … … 143 232 } 144 233 145 146 234 // Save to WordPress 147 /*148 if (isset($this->generated['alt']) && false !== $this->generated['alt'])149 {150 $bool = update_post_meta($this->attach_id, '_wp_attachment_image_alt', $this->generated['alt']);151 } */152 153 235 $this->updateWPPost($this->generated); 154 236 $this->updateWpMeta($this->generated); 155 237 156 /* $post = get_post($this->attach_id);157 $post_updated = false;158 159 if (isset($this->generated['caption']) && false !== $this->generated['caption'])160 {161 $post->post_excerpt = $this->generated['caption'];162 $post_updated = true;163 }164 165 if (isset($this->generated['description']) && false !== $this->generated['description'])166 {167 $post->post_content = $this->generated['description'];168 $post_updated = true;169 }170 171 if (true === $post_updated)172 {173 wp_update_post($post);174 } */175 238 } 176 239 177 240 protected function updateWPPost($data) 178 241 { 179 180 // Log::addTemp('Update WpPost', $data);181 242 $post = get_post($this->attach_id); 182 243 $post_updated = false; 183 244 184 if (isset($data['caption']) && false !== $data['caption'] )245 if (isset($data['caption']) && false !== $data['caption'] && false === is_int($data['caption'])) 185 246 { 186 247 $post->post_excerpt = $data['caption']; … … 188 249 } 189 250 190 if (isset($data['description']) && false !== $data['description'] )251 if (isset($data['description']) && false !== $data['description'] && false === is_int($data['description'])) 191 252 { 192 253 $post->post_content = $data['description']; … … 203 264 { 204 265 Log::addTemp('Update WpMeta', $data); 205 if (isset($data['alt']) && false !== $data['alt'] )266 if (isset($data['alt']) && false !== $data['alt'] && false === is_int($data['alt'])) 206 267 { 207 268 $bool = update_post_meta($this->attach_id, '_wp_attachment_image_alt', $data['alt']); … … 314 375 if (true === $this->has_record) 315 376 { 377 $this->processable_status = SELF::P_ALREADYDONE; 316 378 return false; 317 379 } 380 381 // Stash here other conditions on top with && to build a big processable function 382 $processable = ( $this->isExifProcesssable() && $this->isExtensionIncluded() && $this->hasSomethingGeneratable() ) ? true : false; 383 return $processable; 384 } 385 386 387 private function isExifProcesssable() 388 { 389 $fs = \wpSPIO()->filesystem(); 390 $imageModel = $fs->getMediaImage($this->attach_id); 391 392 if (false === $imageModel->isSomethingOptimized()) 393 { 394 return true; 395 } 396 397 $imageObj = $imageModel->getSomethingOptimized(); 398 399 400 $keepExif = $imageObj->getMeta('did_keepExif'); 401 402 // 2-3 are exif_ai combined settings with keep-exif. 0-1 are when default settings are used and unset / unused 403 if (in_array($keepExif, [0,1,2,3])) 404 { 405 return true; 406 } 407 408 $this->processable_status = self::P_EXIFAI; 409 return false; 410 411 } 412 413 public function getProcessableReason($returnStatus = false ) 414 { 415 $message = false; 416 417 if (true === $returnStatus) 418 { 419 return $this->processable_status; 420 } 421 422 switch($this->processable_status) 423 { 424 case self::P_PROCESSABLE: 425 $message = __('AI is processable', 'shortpixel-image-optimiser'); 426 break; 427 case self::P_ALREADYDONE: 428 $message = __('This image already has generated data', 'shortpixel-image-optimiser'); 429 break; 430 case self::P_EXIFAI: 431 $message = __('Image Exif settings restrict AI usage', 'shortpixel-image-optimiser'); 432 break; 433 case self::P_EXTENSION: 434 $message = __('File Extension not supported', 'shortpixel-image-optimiser'); 435 break; 436 case self::P_NOJOB: 437 $message = __('No fields to generate', 'shortpixel-image-optimiser'); 438 break; 439 default: 440 $message = sprintf(__('Status %s unknown', 'shortpixel-image-optimiser'), $this->processable_status); 441 break; 442 } 443 444 return $message; 445 } 446 447 protected function isExtensionIncluded() 448 { 449 $fs = \wpSPIO()->filesystem(); 450 $imageModel = $fs->getMediaImage($this->attach_id); 451 452 // Gif removed here, since we (temporarily don't support it) 453 $extensions = ['png', 'jpeg', 'webp', 'jpg']; 454 455 if (in_array($imageModel->getExtension(), $extensions)) 456 { 457 return true; 458 } 459 460 $this->processable_status = self::P_EXTENSION; 461 return false; 462 } 463 464 protected function hasSomethingGeneratable() 465 { 466 $optimizeData = $this->getOptimizeData(); 467 468 if (self::P_NOJOB === $this->processable_status) 469 { 470 return false; 471 472 } 318 473 return true; 319 }320 321 public function supportedExtensions()322 {323 return ['png', 'jpeg', 'gif', 'webp', 'jpg'];324 474 } 325 475 … … 429 579 430 580 431 /*public static function getAiDataByAttachment($attach_id) 432 { 433 434 } */ 581 public static function getModelByAttachment($attach_id, $type = 'media') 582 { 583 if (false === isset(self::$models[$attach_id])) 584 { 585 self::$models[$attach_id] = new AiDataModel($attach_id, $type); 586 } 587 588 return self::$models[$attach_id]; 589 590 } 591 592 public static function flushModelCache($attach_id, $type = 'media') 593 { 594 if (isset(self::$models[$attach_id])) 595 { 596 unset(self::$models[$attach_id]); 597 } 598 else 599 { 600 Log::addTemp('Ai MODEL not found in cache!', $attach_id); 601 } 602 603 } 435 604 436 605 -
shortpixel-image-optimiser/trunk/class/Model/Image/ImageModel.php
r3346588 r3363822 478 478 if (! isset($optimizeData['params']) || ! isset($optimizeData['urls'])) 479 479 { 480 array( array(), 0);480 array([], 0); 481 481 } 482 482 483 483 $count = 0; 484 $urls = array();484 $urls = []; 485 485 $i = 0; 486 486 -
shortpixel-image-optimiser/trunk/class/Model/Queue/QueueItem.php
r3346588 r3363822 17 17 use ShortPixel\Controller\Optimizer\OptimizeAiController as OptimizeAiController; 18 18 use ShortPixel\Controller\Optimizer\ActionController as ActionController; 19 use ShortPixel\Model\AiDataModel; 19 20 20 21 class QueueItem … … 176 177 } 177 178 178 179 179 $enqueue = ['id' => $item_id, 'value' => $value, 'item_count' => $this->item_count]; 180 180 … … 185 185 186 186 return $enqueue; 187 188 187 189 188 } … … 472 471 $this->item_count = 1; 473 472 473 $item_id = $this->imageModel->get('id'); 474 475 $paramlist = []; 474 476 475 477 $preview_only = false; 476 478 if (isset($args['preview_only']) && true == $args['preview_only']) 477 479 { 478 $ this->data->paramlist = ['preview_only' => true];480 $paramlist['preview_only'] = true; 479 481 $preview_only = true; 480 482 } 481 483 484 $aiDataModel = new AiDataModel($item_id); 485 486 $data = $aiDataModel->getOptimizeData($args); 487 488 if (isset($data['paramlist'])) 489 { 490 $this->data()->paramlist = $data['paramlist']; 491 } 492 if (isset($data['returndatalist'])) 493 { 494 $this->data()->returndatalist = $data['returndatalist']; 495 $this->data()->addKeepDataArgs('returndatalist'); 496 } 497 498 482 499 $this->data->action = 'requestAlt'; // For Queue 483 500 484 $optimizer = $this->getAPIController($this->data->action);485 $optimizer->parseJSONForQItem($this, $args);501 // $optimizer = $this->getAPIController($this->data->action); 502 // $optimizer->parseJSONForQItem($this, $args); 486 503 487 504 if ($this->data()->hasNextAction()) … … 498 515 $this->data->next_actions = $next_actions; 499 516 } 517 518 500 519 501 520 } 502 521 503 public function retrieveAltAction($ remote_id)522 public function retrieveAltAction($args) 504 523 { 505 524 $this->newAction(); 525 526 $remote_id = $args['remote_id']; 527 528 if (isset($args['returndatalist'])) 529 { 530 $this->data()->returndatalist = $args['returndatalist']; 531 } 532 533 506 534 $this->data->remote_id = $remote_id; 507 535 $this->data->tries = 0; -
shortpixel-image-optimiser/trunk/class/Model/SettingsModel.php
r3348311 r3363822 68 68 'autoAI' => ['s' => 'boolean', 'default' => false], 69 69 'autoAIBulk' => ['s' => 'boolean', 'default' => false], 70 'aiPreserve' => ['s' => 'boolean', 'default' => false ], 70 71 'ai_general_context' => ['s' => 'string', 'default' => 'callback', 'maxlength' => 500], 71 72 'ai_use_post' => ['s' => 'boolean', 'default' => true], -
shortpixel-image-optimiser/trunk/class/external/offload/wp-offload-media.php
r3289850 r3363822 355 355 } 356 356 } 357 } 358 } 359 357 358 } 359 360 } 360 361 361 362 return $source_id; -
shortpixel-image-optimiser/trunk/class/external/wp-cli/wp-cli-bulk.php
r3289850 r3363822 167 167 * [--special=<migrate>] 168 168 * : Run the migration 169 * --- 170 * 169 * 170 * [--start-date=<start_date>] 171 * : Filter, start from this date 172 * 173 * [--end-date=<end_date>] 174 * : Filter, don't enqueue items old than this date. 175 * 171 176 * ## EXAMPLES 172 177 * … … 186 191 187 192 $operation = null; 193 $args = $filters = []; 188 194 if (isset($assoc['special'])) { 189 195 switch ($assoc['special']) { 190 196 case 'migrate': 191 197 $operation = 'migrate'; 198 $args['customOp'] = $operation; 192 199 $queues = array('media'); // can only have one bulk, this. 193 200 break; … … 195 202 } 196 203 204 if (isset($assoc['start-date'])) 205 { 206 $filters['start_date'] = sanitize_text_field($assoc['start-date']); 207 } 208 if (isset($assoc['end-date'])) 209 { 210 $filters['end_date'] = sanitize_text_field($assoc['end-date']); 211 } 212 213 if (count($filters) > 0) 214 { 215 $args['filters'] = $filters; 216 } 217 197 218 foreach ($queues as $qname) { 198 $stats = $bulkControl->createNewBulk($qname, $ operation);219 $stats = $bulkControl->createNewBulk($qname, $args); 199 220 $json->$qname->stats = $stats; 200 221 -
shortpixel-image-optimiser/trunk/class/view/bulk/part-selection.php
r3346588 r3363822 1 1 <?php 2 2 namespace ShortPixel; 3 4 use ShortPixel\Controller\Optimizer\OptimizeAiController; 3 5 4 6 if ( ! defined( 'ABSPATH' ) ) { … … 45 47 46 48 47 </div>49 </div> 48 50 49 51 <div class="interface wrapper"> … … 103 105 <?php endif; ?> 104 106 105 <?php if (true === \wpSPIO()->settings()->enable_ai): ?> 107 <?php 108 $optimizeAiController = OptimizeAiController::getInstance(); 109 if (true === $optimizeAiController->isAiEnabled()): ?> 106 110 <div class='ai-images optiongroup'> 107 111 <div class='switch_button'> … … 118 122 </div> 119 123 124 <div class='switch_button'> 125 <label> 126 <input type="checkbox" class="switch" id="aipreserve_checkbox" name="aipreserve_checkbox" 127 <?php checked(\wpSPIO()->settings()->aiPreserve); ?> /> 128 <div class="the_switch"> </div> 129 </label> 130 <h4><label for="aipreserve_checkbox"> 131 <?php printf(esc_html__('Prevent overriding any of the existing data with the one generated by AI', 'shortpixel-image-optimiser'), '<a href="options-general.php?page=wp-shortpixel-settings&part=ai">', '</a>' ); ?> 132 <span class='new'><?php _e('New!', 'shortpixel-image-optimiser'); ?></span> 133 </label></h4> 134 135 </div> 136 120 137 </div> 138 121 139 <?php endif ?> 122 140 -
shortpixel-image-optimiser/trunk/class/view/settings/part-ai.php
r3348311 r3363822 12 12 <settinglist> 13 13 14 <h2><?php esc_html_e('AI Image SEO ', 'shortpixel-image-optimiser'); ?></h2>14 <h2><?php esc_html_e('AI Image SEO & Accessibility', 'shortpixel-image-optimiser'); ?></h2> 15 15 16 16 <gridbox class="width_half"> … … 24 24 'checked' => $view->data->enable_ai, 25 25 'label' => esc_html__('Enable AI Image SEO', 'shortpixel-image-optimiser'), 26 ] 26 'data' => ['data-toggle="autoAiOptions"'], 27 28 ] 27 29 ); 28 30 ?> … … 31 33 <name> 32 34 33 <?php esc_html_e('Show AI image SEO options throughout ShortPixel Image Optimizer. ', 'shortpixel-image-optimiser'); ?>35 <?php esc_html_e('Show AI image SEO options throughout ShortPixel Image Optimizer. The generated ALT tag is also very useful for accessibility.', 'shortpixel-image-optimiser'); ?> 34 36 35 37 </name> … … 37 39 </setting> 38 40 39 <setting class='switch '>41 <setting class='switch toggleTarget autoAiOptions'> 40 42 <content> 41 43 … … 58 60 </setting> 59 61 60 <setting class='switch '>62 <setting class='switch toggleTarget autoAiOptions'> 61 63 <content> 62 64 … … 65 67 'name' => 'autoAIBulk', 66 68 'checked' => $view->data->autoAIBulk, 67 'label' => esc_html__('Generate image SEO data when running Bulk Processing', 'shortpixel-image-optimiser'),69 'label' => esc_html__('Generate image SEO data during Bulk Processing', 'shortpixel-image-optimiser'), 68 70 ] 69 71 ); … … 78 80 </content> 79 81 </setting> 82 83 84 <setting class='switch toggleTarget autoAiOptions'> 85 <content> 86 87 <?php $this->printSwitchButton( 88 [ 89 'name' => 'aiPreserve', 90 'checked' => $view->data->aiPreserve, 91 'label' => esc_html__('Preserve existing Image SEO data', 'shortpixel-image-optimiser'), 92 ] 93 ); 94 ?> 95 <i class='documentation dashicons dashicons-editor-help' data-link="https://shortpixel.com/knowledge-base/article/ai-image-seo-settings-explained/#2-toc-title?target=iframe"></i> 96 97 <name> 98 99 <?php esc_html_e('When enabled, all existing ALT tags, captions and descriptions are retained. Disabling the switch means that the SEO data for images created with AI will overwrite the existing data.', 'shortpixel-image-optimiser'); ?> 100 101 </name> 102 </content> 103 </setting> 104 80 105 81 106 </gridbox> -
shortpixel-image-optimiser/trunk/class/view/snippets/part-aitext.php
r3346588 r3363822 3 3 use ShortPixel\Controller\ApiKeyController; 4 4 use ShortPixel\Controller\QuotaController; 5 use ShortPixel\Model\AiDataModel; 5 6 6 7 $icon_url = plugins_url( '/res/images/icon/', SHORTPIXEL_PLUGIN_FILE ); … … 10 11 $item_id = $this->data['item_id']; 11 12 $has_data = $this->data['has_data']; 12 $isSupported = $this->data['isSupported'];13 //$isSupported = $this->data['isSupported']; 13 14 $isDifferent = $this->data['isDifferent']; 14 15 $dataItems = implode(',',$this->data['dataItems']); 16 17 $is_processable = $this->data['is_processable']; 18 $processable_reason = $this->data['processable_reason']; 19 $processable_status = $this->data['processable_status']; 15 20 16 21 $quotaControl = QuotaController::getInstance(); … … 23 28 <p class='hidden' id='shortpixel-noai'></p> 24 29 <?php 30 endif; 25 31 26 elseif (false === $isSupported):32 if (false === $is_processable && $processable_status !== AiDataModel::P_ALREADYDONE): 27 33 28 ?> 29 <p><?php _e('Currently, ShortPixel AI cannot generate SEO data for GIF files.', 'shortpixel-image-optimiser'); ?></p> 30 <?php 34 if (true === in_array($processable_status, [AiDataModel::P_NOJOB])) // Silent fail if all done 35 { 36 37 } 38 else 39 { 40 printf('<p>%s</p>', $processable_reason); 41 } 42 31 43 32 44 elseif (false === $has_data): -
shortpixel-image-optimiser/trunk/readme.txt
r3348311 r3363822 5 5 Tested up to: 6.8 6 6 Requires PHP: 7.4 7 Stable tag: 6.3. 37 Stable tag: 6.3.4 8 8 License: GPLv2 or later 9 9 License URI: http://www.gnu.org/licenses/gpl-2.0.html … … 474 474 475 475 == Changelog == 476 477 = 6.3.4 = 478 479 🤖 The Smarter AI Control Update 480 481 Release Date: September 18, 2025 482 483 ✨ New Features & Improvements 484 485 * Preserve Existing SEO Data: Added an option to keep your existing ALT, caption, and description fields untouched when using AI-generated image SEO — your manual work is safe! 486 * Better Block Editor Integration: AI-generated SEO data and image optimization now work flawlessly when uploading images directly from the block editor. 487 * AI Support Chatbot: Meet our new AI-powered support assistant — here to help you faster, 24/7. 488 489 🛠️ Fixes & Behavioral Improvements 490 491 * Full AI Deactivation: Disabling AI Image SEO now also disables auto-generation and hides all related options from WP Admin, including the Bulk Processing section. 492 * EXIF-Based AI Training Block: If AI training is blocked via EXIF data, the plugin now shows a clear message and prevents the image from being sent for processing. 493 * Re-Optimize Logic Fixed: The "Re-optimize with/without SmartCrop" buttons now respect the selected option instead of always using the saved setting. 494 * Inline Font Handling: Inline fonts will no longer be replaced with CDN links if the CSS option is disabled. 495 * AI SEO for Excluded Items: Bulk AI SEO generation now skips excluded items as expected. 496 497 Update now for smarter AI behavior, more control over your data, and an improved support experience! 🚀 476 498 477 499 = 6.3.3 = -
shortpixel-image-optimiser/trunk/res/css/shortpixel-bulk.css
r3348311 r3363822 63 63 } 64 64 .wrap.is-shortpixel-bulk-page header .top-buttons a:hover, .wrap.is-shortpixel-bulk-page header .top-buttons button:hover { 65 background: rgb(50.3421052632, 215.4868421053, 228.6578947368);65 background: #32d7e5; 66 66 } 67 67 .wrap.is-shortpixel-bulk-page header .top-buttons a i.switch, .wrap.is-shortpixel-bulk-page header .top-buttons button i.switch { … … 265 265 } 266 266 .wrap.is-shortpixel-bulk-page section.panel.dashboard .bulk-wrapper button:hover { 267 background: rgb(50.3421052632, 215.4868421053, 228.6578947368);267 background: #32d7e5; 268 268 } 269 269 .wrap.is-shortpixel-bulk-page section.panel.dashboard .bulk-wrapper button:disabled { … … 398 398 } 399 399 .wrap.is-shortpixel-bulk-page .button-primary:hover { 400 background: rgb(50.3421052632, 215.4868421053, 228.6578947368);400 background: #32d7e5; 401 401 } 402 402 .wrap.is-shortpixel-bulk-page nav { … … 605 605 } 606 606 .wrap.is-shortpixel-bulk-page .processor-paused:hover { 607 background: rgb(27.5926724138, 169.1163793103, 178.9073275862);607 background: #1ca9b3; 608 608 } 609 609 .wrap.is-shortpixel-bulk-page .processor-paused .dashicons { … … 719 719 opacity: 1; 720 720 height: auto; 721 z-index: 10; 722 position: relative; 721 723 } 722 724 .wrap.is-shortpixel-bulk-page section.panel.selection .load.wrapper .loading { … … 1245 1247 } 1246 1248 .wrap.is-shortpixel-bulk-page section.panel.finished nav button.finish:hover { 1247 background: rgb(36.2392241379, 209.2887931034, 221.2607758621);1249 background: #24d1dd; 1248 1250 } 1249 1251 .wrap.is-shortpixel-bulk-page .part-debug { -
shortpixel-image-optimiser/trunk/res/css/shortpixel-bulk.css.map
r3348311 r3363822 1 {"version":3,"sourceRoot":"","sources":["../scss/elements/_fonts.scss","../scss/shortpixel-bulk.scss","../scss/bulk/_dashboard.scss","../scss/elements/_header.scss","../scss/elements/_mixins.scss","../scss/elements/_colors.scss","../scss/elements/_icons.scss","../scss/elements/_breakpoints.scss","../scss/elements/_animation.scss"],"names":[],"mappings":"AAEA;EAEI;EACA;EACA;EACA;;AAGJ;EAGI;EACA;EACA;EACA;;ACXJ;ACLA;ADgBE;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmcE;AA iIF;;AEplBF;EAEI;EACA;EACA;EACA;EACA;EAEA;EAEA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAEF;EACE;EACA;EACA;EACA;;AAEF;EACH;;AAEM;EC5BL;EACA,YCKa;EDJb;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACC;;AAKD;EACE;EACA;;AAEF;EAEE;EACA;EACA;;ADOM;EACE,QEXG;EFYH;EACA;EACP;EACA;;AG5BL;EAEE;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;;AACA;EACG;;AAOH;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AAIJ;EAGE;EACA;EACA;EACA;EACA;;AAEA;EAEI;EACA;EACA;;AAGJ;EACE;EACA;EACA;;AJtDA;EAEG;EACA;EACA;;AAEA;EAAa;;AAIb;EAGK;EACA;EACA;EACA;EACA;EACA;;AACA;EAEE;EACA;EACA;EAAS;;AAGX;EAEG;EACA,kBGtBA;EHwBA;EACA;EACA;EACP;EAEA;EACA;EACM;;AAEA;EACE;;AAID;EACE;EACA;;AAEF;EAEN;;AAML;EAGC,kBG1DS;EH2DT;;AACK;EACE;EACA;EACA;EACA;EACA;;AAKR;EACE;EACD;;AK7DD;EL2DA;IAIE;;;AAED;EACC;;AAIC;EAEG;EACA;EACA;;AACA;EAAK;EAAwB;;AAC7B;EACE;;AACA;EAAS;EAAqB;;AAI9B;EACE;EACA;;AAKF;EACE;EACA;EAGA;EACA;;AAHA;EAAgB;;AAChB;EAAgB;;AAGhB;EACG;EACA;EACA;;ADzFb;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EAEI;EACA;;AAGN;EACE;;AAIF;EAEG;EACA;;AAGL;EACC;EACA;EACA;EACA;EAEA;EACA;EACA,YItDiB;EJuDjB,OI1DU;EJ2DV;EACA;EACA;EACS;EACA;EACA;EACT;;AAEA;EACC,YIpES;EJqET;;AAGD;EAEC,YI1ES;;AJ4EV;EAEE;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAID;EAEE,YIvFS;EJwFT;EACA;EACA;EACA;;AACA;EAEE;;AAMN;EACE;EAED;EACA;;AACA;EAEE;;AAIH;EACG;;AAGD;EACE;;AAGJ;EACG;EACA;;AAGJ;EACG;IACG;;EAEH;IACG;;;AAIN;EAEE;EACA;;AAID;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACC;EAEE;EACA;EACA;EACA;EACA;EACA;;AAEH;EAEE;EACD;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAED;EAEC;EACA;EACA;;AACA;EACC;;AACA;EAAW;;AACR;EAAS;EAA+B;;AAE3C;EAAQ;;AACR;EACE;EACD;;AACA;EACE;;AAIJ;EAAI;EAAuB;;AAK5B;EAGI;EACA;EACA;EACP;;AAGO;EAGG;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGA;EAEE;EACA;EACA;EACN;EACA;;AAGG;EACI;EACA;EACA;EACA;EACA;EACA;;AACA;EAAU;;AACV;EAEN;EACA;;AAMH;EAEG;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACP;EACA;EACA;EACA;;AAEO;EAEI;EACA;EACA;EACA;EACA;EACA;;AAGJ;EAEG;EAED;EACA;;AAKE;EAAK;;AACL;EACE;EACA;;AACA;EAAS;;AAGf;EACE;EACA;EAEA;EACL;EACK;EACA;EACA;EACA;EACA;EACL;EACA;EAEK;EACL;EACA;EACA;;AACA;EAAS;;AAMT;EAGE;EAGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;;AAEF;EAEE;;AACA;EAEG;EACA;EACA;;AAGH;EAAiB;;AAIvB;EAEE;EACA;EAGA;EACA;EACA;EACA;EACA;EACA;;AACA;EACA;EACA;EACA;;AAEA;EAEC;EACA;EACC;;AAQH;EAEI;;AACA;EAEE;EACA;EACA;EACA;EACE;;AAEF;EAEG;EACA;EACA;EACA;EACA;;AAGH;EAEE;;AAEF;EAEE;EACA;;AAGF;EACE;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;;AAGF;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACN;;AAEI;EAEE;EACA;EACA;EACA;EACN;;AAoBG;EATH;;AAUG;EAAe;;AACf;EAAQ;;AAEX;EAEG;EACJ;EACI;;AAKA;EACE;EACL;EACA;;AAKE;EAEG;EACL;;AAKG;EAEG;EACA;EACA;EACA;EACA;EACA;;AACN;EACC;;AACA;EAAI;;AAEC;EACE;;AAEF;EOpgBV;EACI;EACA;EACA;EACA;;AAEL;EACC;IAAM;IAA2B;;;AAGlC;EACC;IAAM;IAA8B;;;AAGrC;EACC;IAAM;IAA+B;;;AAGtC;EACC;IAAM;IAAmC;;;AAG1C;EACC;IAAM;IAAgC;;;APifnC;EAEE;EACD;;AAGD;EAEE;EACD;EACA;EACA;;AAIH;EAEE;EACA;;AACA;EACE;EACD;;AAED;EAAI;;AAWA;EACG;;AAEH;EACG;EACA;EACA;EACA;;AAEH;EACE;EAEA;;AACA;EACI;EACA;;AAEJ;EACI;;AAET;EACC;EACA;EACA;;AAGH;EACE;EACA;EACA;;AAIH;EAEE;;AAYI;EAAQ;;AACR;EAAe;;AACf;EAAQ;;AAIR;EAhJH;;AAiJG;EAAe;;AACf;EAAQ;;AAEX;EAEI;EACA;EACA;;AACA;EACE;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;EACA;EACA;;AAKD;EACI;EACA;EACA;;AACA;EAEG;EACA;;AAIN;EAEG;EAEA;EACA;;AAEA;EACE;EACA;EACA;;AACA;EAEG;EACA;EACA;;AACA;EAEG;;AAIR;EAEG;EACA;EACA;EAEA;;AAOd;EAEE;EACA;EACA;EACA;;AAEA;EAAU;;AAGZ;EACI;EAEA;EAEL;;AACK;EAAM;;AACN;EACG;EACA;EACA;EACN;;AACM;EAAgB;EAAkB;;AACxC;EAAkB;;AAClB;EAAkB;;AAClB;EAAU;EAAc;;AAGrB;EACE;EACA;;AAIN;EAEG;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;;AAEF;EACE;EACA;EACA;;AACA;EAAO;;AAET;EACE,YIttBS;EJutBT;EACA;EACA;EACA;EACA;;AAGL;EAEI;EACA;EACA;;AASD;EAAQ;;AACR;EAAe;;AACf;EAAQ;;AAIR;EArSH;;AAsSG;EAAe;;AACf;EAAQ;;AAGX;EAEE;EACA;EACA;EACA;EACA;EACJ;EACA;;AAEI;EACE;EACA;EACL;EAGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGG;EACI;EACA;EACA;;AAEA;EACE;;AAEF;EACE,QI5xBD;EJ6xBC;EACA;;AAEF;EAEE;EACA;EACA;EACA;EACA;;AAKR;EAEE;EACA;EACA;;AACA;EAAQ;;AACR;EACI;EACA;EACN;;AAEE;EACG;EACA;;AACL;EAEE;;AAIA;EAEE;EACA;EACA;EACA;EACA;EACL;;AAGK;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAGP;EAEE;EACA;;AAKD;EAEE;;AAMJ;EACC;;AAIC;EACG;EACA;EACA;EACA;EACJ;;AAEA;EACG;EACD;EACA;EACA;EACA;EACA;EACA;EACA;;AAIC;EAEG;EACA;EACA;EACA;;AAIN;EAEC;EACA;EACA;;AAGK;EACI;EACA;EACA;EACP;EACA;;AAEO;EACE;;AAEF;EACE;EACA;EACA;;AAEF;EAEE;EACA;EACA;EACA;EACA;;AAKR;EAIH;EACA;EAGK;;AAEL;EAIC;EACA;EACA;;AAID;EAEC;EACC;EACD;EACA;EACA;EACA;EACA;;AAED;EAEE;;AAIF;EAGC;;AASI;EAEG;EACA;EACA;EACA;;AAEA;EACE;EACR;EACA;EASA;EACA;;AATA;EAEC;;AAED;EAEC;;AAKF;EACE;EACA;EACA;EACA;EACA;EACA;;AAGK;EACE;EACA;EACA;EACA;EACA;EACA;;AAGL;EAEG;;AAEH;EAEE;;AACN;EACE;EACD;;AAMG;EACG;;AAKR;EACI;EACA;;AAYD;EAAQ;;AACR;EAAe;;AACf;EAAQ;;AAIR;EApmBH;;AAqmBG;EAAe;;AACf;EAAQ;;AAGX;EACI;;AAEF;EAEI;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;;AAOV;EAEG;EACA;EACA;EACA;EACA;;AAKL;EAEE;EAEA;;AACA;EAAK;EACH;EACA;;AAEA;EAEE;EACA;EACA;;AAIJ;EAAW;;AAEX;EAEC;EACA;;AAEK;EACG;;AAEH;EACG;EACA;EACA;EACA;EACN;;AAEG;EACE;EAEA;;AACA;EACI;EACA;;AAEJ;EACI;;AAGX;EAEE;EACA","file":"shortpixel-bulk.css"}1 {"version":3,"sourceRoot":"","sources":["../scss/elements/_fonts.scss","../scss/shortpixel-bulk.scss","../scss/bulk/_dashboard.scss","../scss/elements/_header.scss","../scss/elements/_mixins.scss","../scss/elements/_colors.scss","../scss/elements/_icons.scss","../scss/elements/_breakpoints.scss","../scss/elements/_animation.scss"],"names":[],"mappings":"AAEA;EAEI;EACA;EACA;EACA;;AAGJ;EAGI;EACA;EACA;EACA;;ACXJ;ACLA;ADgBE;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmcE;AAmIF;;AEtlBF;EAEI;EACA;EACA;EACA;EACA;EAEA;EAEA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAEF;EACE;EACA;EACA;EACA;;AAEF;EACH;;AAEM;EC5BL;EACA,YCKa;EDJb;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACC;;AAKD;EACE;EACA;;AAEF;EAEE;EACA;EACA;;ADOM;EACE,QEXG;EFYH;EACA;EACP;EACA;;AG5BL;EAEE;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;;AACA;EACG;;AAOH;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AADF;EACE;;AAIJ;EAGE;EACA;EACA;EACA;EACA;;AAEA;EAEI;EACA;EACA;;AAGJ;EACE;EACA;EACA;;AJtDA;EAEG;EACA;EACA;;AAEA;EAAa;;AAIb;EAGK;EACA;EACA;EACA;EACA;EACA;;AACA;EAEE;EACA;EACA;EAAS;;AAGX;EAEG;EACA,kBGtBA;EHwBA;EACA;EACA;EACP;EAEA;EACA;EACM;;AAEA;EACE;;AAID;EACE;EACA;;AAEF;EAEN;;AAML;EAGC,kBG1DS;EH2DT;;AACK;EACE;EACA;EACA;EACA;EACA;;AAKR;EACE;EACD;;AK7DD;EL2DA;IAIE;;;AAED;EACC;;AAIC;EAEG;EACA;EACA;;AACA;EAAK;EAAwB;;AAC7B;EACE;;AACA;EAAS;EAAqB;;AAI9B;EACE;EACA;;AAKF;EACE;EACA;EAGA;EACA;;AAHA;EAAgB;;AAChB;EAAgB;;AAGhB;EACG;EACA;EACA;;ADzFb;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EAEI;EACA;;AAGN;EACE;;AAIF;EAEG;EACA;;AAGL;EACC;EACA;EACA;EACA;EAEA;EACA;EACA,YItDiB;EJuDjB,OI1DU;EJ2DV;EACA;EACA;EACS;EACA;EACA;EACT;;AAEA;EACC,YIpES;EJqET;;AAGD;EAEC,YI1ES;;AJ4EV;EAEE;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAID;EAEE,YIvFS;EJwFT;EACA;EACA;EACA;;AACA;EAEE;;AAMN;EACE;EAED;EACA;;AACA;EAEE;;AAIH;EACG;;AAGD;EACE;;AAGJ;EACG;EACA;;AAGJ;EACG;IACG;;EAEH;IACG;;;AAIN;EAEE;EACA;;AAID;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACC;EAEE;EACA;EACA;EACA;EACA;EACA;;AAEH;EAEE;EACD;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAED;EAEC;EACA;EACA;;AACA;EACC;;AACA;EAAW;;AACR;EAAS;EAA+B;;AAE3C;EAAQ;;AACR;EACE;EACD;;AACA;EACE;;AAIJ;EAAI;EAAuB;;AAK5B;EAGI;EACA;EACA;EACP;;AAGO;EAGG;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGA;EAEE;EACA;EACA;EACN;EACA;;AAGG;EACI;EACA;EACA;EACA;EACA;EACA;;AACA;EAAU;;AACV;EAEN;EACA;;AAMH;EAEG;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACP;EACA;EACA;EACA;;AAEO;EAEI;EACA;EACA;EACA;EACA;EACA;;AAGJ;EAEG;EAED;EACA;;AAKE;EAAK;;AACL;EACE;EACA;;AACA;EAAS;;AAGf;EACE;EACA;EAEA;EACL;EACK;EACA;EACA;EACA;EACA;EACL;EACA;EAEK;EACL;EACA;EACA;;AACA;EAAS;;AAMT;EAGE;EAGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;;AAEF;EAEE;;AACA;EAEG;EACA;EACA;;AAGH;EAAiB;;AAIvB;EAEE;EACA;EAGA;EACA;EACA;EACA;EACA;EACA;;AACA;EACA;EACA;EACA;;AAEA;EAEC;EACA;EACC;;AAQH;EAEI;;AACA;EAEE;EACA;EACA;EACA;EACE;;AAEF;EAEG;EACA;EACA;EACA;EACA;;AAGH;EAEE;;AAEF;EAEE;EACA;;AAGF;EACE;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;;AAGF;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACN;;AAEI;EAEE;EACA;EACA;EACA;EACN;;AAoBG;EATH;;AAUG;EAAe;;AACf;EAAQ;;AAEX;EAEG;EACJ;EACI;;AAKA;EACE;EACL;EACA;;AAKE;EAEG;EACL;EACK;EACA;;AAKF;EAEG;EACA;EACA;EACA;EACA;EACA;;AACN;EACC;;AACA;EAAI;;AAEC;EACE;;AAEF;EOtgBV;EACI;EACA;EACA;EACA;;AAEL;EACC;IAAM;IAA2B;;;AAGlC;EACC;IAAM;IAA8B;;;AAGrC;EACC;IAAM;IAA+B;;;AAGtC;EACC;IAAM;IAAmC;;;AAG1C;EACC;IAAM;IAAgC;;;APmfnC;EAEE;EACD;;AAGD;EAEE;EACD;EACA;EACA;;AAIH;EAEE;EACA;;AACA;EACE;EACD;;AAED;EAAI;;AAWA;EACG;;AAEH;EACG;EACA;EACA;EACA;;AAEH;EACE;EAEA;;AACA;EACI;EACA;;AAEJ;EACI;;AAET;EACC;EACA;EACA;;AAGH;EACE;EACA;EACA;;AAIH;EAEE;;AAYI;EAAQ;;AACR;EAAe;;AACf;EAAQ;;AAIR;EAlJH;;AAmJG;EAAe;;AACf;EAAQ;;AAEX;EAEI;EACA;EACA;;AACA;EACE;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;EACA;EACA;;AAKD;EACI;EACA;EACA;;AACA;EAEG;EACA;;AAIN;EAEG;EAEA;EACA;;AAEA;EACE;EACA;EACA;;AACA;EAEG;EACA;EACA;;AACA;EAEG;;AAIR;EAEG;EACA;EACA;EAEA;;AAOd;EAEE;EACA;EACA;EACA;;AAEA;EAAU;;AAGZ;EACI;EAEA;EAEL;;AACK;EAAM;;AACN;EACG;EACA;EACA;EACN;;AACM;EAAgB;EAAkB;;AACxC;EAAkB;;AAClB;EAAkB;;AAClB;EAAU;EAAc;;AAGrB;EACE;EACA;;AAIN;EAEG;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;;AAEF;EACE;EACA;EACA;;AACA;EAAO;;AAET;EACE,YIxtBS;EJytBT;EACA;EACA;EACA;EACA;;AAGL;EAEI;EACA;EACA;;AASD;EAAQ;;AACR;EAAe;;AACf;EAAQ;;AAIR;EAvSH;;AAwSG;EAAe;;AACf;EAAQ;;AAGX;EAEE;EACA;EACA;EACA;EACA;EACJ;EACA;;AAEI;EACE;EACA;EACL;EAGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGG;EACI;EACA;EACA;;AAEA;EACE;;AAEF;EACE,QI9xBD;EJ+xBC;EACA;;AAEF;EAEE;EACA;EACA;EACA;EACA;;AAKR;EAEE;EACA;EACA;;AACA;EAAQ;;AACR;EACI;EACA;EACN;;AAEE;EACG;EACA;;AACL;EAEE;;AAIA;EAEE;EACA;EACA;EACA;EACA;EACL;;AAGK;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAGP;EAEE;EACA;;AAKD;EAEE;;AAMJ;EACC;;AAIC;EACG;EACA;EACA;EACA;EACJ;;AAEA;EACG;EACD;EACA;EACA;EACA;EACA;EACA;EACA;;AAIC;EAEG;EACA;EACA;EACA;;AAIN;EAEC;EACA;EACA;;AAGK;EACI;EACA;EACA;EACP;EACA;;AAEO;EACE;;AAEF;EACE;EACA;EACA;;AAEF;EAEE;EACA;EACA;EACA;EACA;;AAKR;EAIH;EACA;EAGK;;AAEL;EAIC;EACA;EACA;;AAID;EAEC;EACC;EACD;EACA;EACA;EACA;EACA;;AAED;EAEE;;AAIF;EAGC;;AASI;EAEG;EACA;EACA;EACA;;AAEA;EACE;EACR;EACA;EASA;EACA;;AATA;EAEC;;AAED;EAEC;;AAKF;EACE;EACA;EACA;EACA;EACA;EACA;;AAGK;EACE;EACA;EACA;EACA;EACA;EACA;;AAGL;EAEG;;AAEH;EAEE;;AACN;EACE;EACD;;AAMG;EACG;;AAKR;EACI;EACA;;AAYD;EAAQ;;AACR;EAAe;;AACf;EAAQ;;AAIR;EAtmBH;;AAumBG;EAAe;;AACf;EAAQ;;AAGX;EACI;;AAEF;EAEI;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;;AAOV;EAEG;EACA;EACA;EACA;EACA;;AAKL;EAEE;EAEA;;AACA;EAAK;EACH;EACA;;AAEA;EAEE;EACA;EACA;;AAIJ;EAAW;;AAEX;EAEC;EACA;;AAEK;EACG;;AAEH;EACG;EACA;EACA;EACA;EACN;;AAEG;EACE;EAEA;;AACA;EACI;EACA;;AAEJ;EACI;;AAGX;EAEE;EACA","file":"shortpixel-bulk.css"} -
shortpixel-image-optimiser/trunk/res/css/shortpixel-settings.css
r3347742 r3363822 134 134 } 135 135 .wrap.is-shortpixel-settings-page .shortpixel-settings button:hover, .wrap.is-shortpixel-settings-page .shortpixel-settings .button-setting:hover { 136 background: rgb(50.3421052632, 215.4868421053, 228.6578947368);136 background: #32d7e5; 137 137 } 138 138 .wrap.is-shortpixel-settings-page .shortpixel-settings button i.switch, .wrap.is-shortpixel-settings-page .shortpixel-settings .button-setting i.switch { … … 240 240 } 241 241 .wrap.is-shortpixel-settings-page .shortpixel-settings section.wrapper .setting-tab .save-buttons.saving button.save { 242 background-color: rgb(14.3684210526, 104.4473684211, 111.6315789474);242 background-color: #0e6870; 243 243 } 244 244 .wrap.is-shortpixel-settings-page .shortpixel-settings section.wrapper .setting-tab .save-buttons.saving button.save i { … … 461 461 } 462 462 .wrap.is-shortpixel-settings-page header .top-buttons a:hover, .wrap.is-shortpixel-settings-page header .top-buttons button:hover { 463 background: rgb(50.3421052632, 215.4868421053, 228.6578947368);463 background: #32d7e5; 464 464 } 465 465 .wrap.is-shortpixel-settings-page header .top-buttons a i.switch, .wrap.is-shortpixel-settings-page header .top-buttons button i.switch { … … 1192 1192 } 1193 1193 .wrap.is-shortpixel-settings-page #tab-overview .wrapper .dashboard-button:hover { 1194 background: rgb(50.3421052632, 215.4868421053, 228.6578947368);1194 background: #32d7e5; 1195 1195 } 1196 1196 .wrap.is-shortpixel-settings-page #tab-overview .wrapper .dashboard-button i.switch { … … 2143 2143 min-height: 44px; 2144 2144 color: #1ABDCA; 2145 background-color: rgb(232.25, 232.25, 232.25);2145 background-color: #e8e8e8; 2146 2146 border-radius: 6px; 2147 2147 font-weight: 700; … … 2151 2151 } 2152 2152 .wrap.is-shortpixel-settings-page #tab-tools .button:hover { 2153 background: rgb(50.3421052632, 215.4868421053, 228.6578947368);2153 background: #32d7e5; 2154 2154 color: #fff; 2155 2155 } -
shortpixel-image-optimiser/trunk/res/js/screens/screen-bulk.js
r3346588 r3363822 261 261 data.webpActive = (document.getElementById('webp_checkbox').checked) ? true : false; 262 262 data.avifActive = (document.getElementById('avif_checkbox').checked) ? true : false; 263 263 264 if (null !== document.getElementById('autoai_checkbox')) 264 265 { 265 266 data.aiActive = (document.getElementById('autoai_checkbox').checked) ? true : false; 267 data.aiPreserve = (document.getElementById('aipreserve_checkbox').checked) ? true : false; 266 268 } 267 269 else 268 270 { 269 271 data.aiActive = false; 272 // data.aiPreserve = false; 270 273 } 271 274 data.backgroundProcess = (document.getElementById('background_checkbox').checked) ? true : false; … … 510 513 }); // circles; 511 514 } 512 DoSelection() // action to update response. 513 { 514 // @todo Check the future of this function, since checking this is now createBulk. 515 var data = {screen_action: 'applyBulkSelection'}; // 516 data.callback = 'shortpixel.applySelectionDone'; 517 518 data.mediaActive = (document.getElementById('media_checkbox').checked) ? true : false; 519 data.customActive = (document.getElementById('custom_checkbox').checked) ? true : false; 520 data.webpActive = (document.getElementById('webp_checkbox').checked) ? true : false; 521 data.avifActive = (document.getElementById('avif_checkbox').checked) ? true : false; 522 data.aiActive = (document.getElementById('autoai_checkbox').checked) ? true : false; 523 data.backgroundProcess = (document.getElementById('background_checkbox').checked) ? true : false; 524 525 window.addEventListener('shortpixel.applySelectionDone', function (e) { this.SwitchPanel('summary'); }.bind(this) , {'once': true} ); 526 this.processor.AjaxRequest(data); 527 528 } 515 529 516 530 517 UpdateStats(stats, type) -
shortpixel-image-optimiser/trunk/res/js/screens/screen-item-base.js
r3346588 r3363822 27 27 } 28 28 29 30 29 // This is final, not more messing with this. In results (multiple) defined one level higher than result object, if single, it's in result. 31 30 var item_id = resultItem.item_id; 32 31 var message = resultItem.message; 33 34 32 35 33 // This is the reporting element ( all the data, via getItemView? ) … … 66 64 if ('ai' === apiName && typeof resultItem.aiData !== 'undefined') 67 65 { 68 69 66 if (null !== element) 70 67 { … … 336 333 window.addEventListener('shortpixel.HandleUndoAlt', function (event) { 337 334 var data = event.detail.media; 338 var original = data. original;335 var original = data.current; 339 336 340 337 if ('redo' == action_type) -
shortpixel-image-optimiser/trunk/res/js/screens/screen-media.js
r3347742 r3363822 76 76 } 77 77 78 if (typeof newAltText !== 'undefined' )78 if (typeof newAltText !== 'undefined' || newAltText < 0) 79 79 { 80 80 var inputs = this.altInputNames; … … 107 107 let captionFields = ['attachment_caption', 'attachment-details-caption']; 108 108 let descriptionFields = ['attachment_content', 'attachment-details-description']; 109 110 111 109 112 if (typeof newCaption !== 'undefined' )110 if (typeof newCaption !== 'undefined' || newCaption < 0) 113 111 { 114 112 for (var i = 0; i < captionFields.length; i++) … … 120 118 } 121 119 } 122 123 124 120 } 125 121 126 if (typeof newDescription !== 'undefined' )122 if (typeof newDescription !== 'undefined' || newDescription < 0) 127 123 { 128 124 for (var i = 0; i < descriptionFields.length; i++) … … 134 130 } 135 131 } 136 137 138 132 } 139 140 133 141 134 if (null !== attachmentAlt) … … 157 150 window.addEventListener('shortpixel.AttachAiInterface', this.AttachAiInterface.bind(this), {once: true}); 158 151 } 159 /* if (typeof aiData !== 'undefined')160 {161 this.processor.LoadItemView({ id: item_id, type: 'media' });162 } */163 164 165 152 } 166 153 … … 291 278 var res = super.HandleImage(resultItem, type); 292 279 var fileStatus = this.processor.fStatus[resultItem.fileStatus]; 280 var apiName = (typeof resultItem.apiName !== 'undefined') ? resultItem.apiName : 'optimize'; 281 293 282 294 283 // If image editor is active and file is being restored because of this reason ( or otherwise ), remove the warning if this one exists. … … 299 288 } 300 289 } 290 291 if (fileStatus == 'FILE_DONE' && apiName == 'ai') 292 { 293 this.UpdateGutenBerg(resultItem); 294 } 301 295 } 302 296 … … 323 317 ListenGallery() { 324 318 var self = this; 319 var next_item_run_process = false; 325 320 326 321 if (this.settings.hide_spio_in_popups) … … 349 344 350 345 if (typeof this.fetchSPIOData === 'function') { 351 this.fetchSPIOData(this.model.get('id')); 352 this.spioBusy = true; // Note if this system turns out not to work, the perhaps render empties all if first was painted, second cancelled? 353 346 let attach_id = this.model.get('id'); 347 348 if (typeof attach_id !== 'undefined') 349 { 350 if (true === next_item_run_process ) 351 { 352 window.ShortPixelProcessor.SetInterval(-1); 353 window.ShortPixelProcessor.RunProcess(); 354 next_item_run_process = false; 355 } 356 else 357 { 358 this.fetchSPIOData(attach_id); 359 this.spioBusy = true; // Note if this system turns out not to work, the perhaps render empties all if first was painted, second cancelled? 360 } 361 } 362 else if (true == this.model.get('uploading')) 363 { 364 next_item_run_process = true; 365 console.log('Upload Start Detected'); 366 } 367 else 368 { 369 console.log('Id not found on render'); 370 } 354 371 } 355 372 … … 447 464 wrapper.classList.add('shortpixel-ai-interface',element.getAttribute('id')); 448 465 449 wrapper.innerHTML = data.snippet; 466 wrapper.innerHTML = data.snippet; 467 468 450 469 element.after(wrapper); 451 470 … … 579 598 } 580 599 600 UpdateGutenBerg(resultItem) 601 { 602 603 var attach_id = resultItem.item_id; 604 var aiData = resultItem.aiData; 605 606 if (! wp.data || ! wp.data.select('core')) 607 { 608 return false; 609 } 610 611 console.log(wp.data.select( 'core/block-editor' )); 612 613 let blocks = wp.data.select( 'core/block-editor' ).getBlocks(); 614 console.log(blocks); 615 for (let i = 0; i < blocks.length; i++) 616 { 617 let block = blocks[i]; 618 619 if (block.attributes.id == attach_id) 620 { 621 //block.attributes.alt = "I CAME TO ALT"; 622 //block.attributes.caption = "CAPTION THIS"; 623 let clientId = block.clientId; 624 625 console.log('DATA DISPATCH ', clientId, aiData); 626 wp.data.dispatch( 'core/block-editor' ).updateBlockAttributes( clientId, 627 aiData ); 628 629 } 630 } 631 } 632 581 633 } // class 582 634 -
shortpixel-image-optimiser/trunk/res/scss/shortpixel-bulk.scss
r3348311 r3363822 498 498 opacity: 1; 499 499 height: auto; 500 z-index: 10; 501 position: relative; 500 502 } 501 503 } -
shortpixel-image-optimiser/trunk/shortpixel-plugin.php
r3346588 r3363822 365 365 wp_register_script('shortpixel-media', plugins_url('res/js/shortpixel-media.js', SHORTPIXEL_PLUGIN_FILE), array('jquery'), SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true); 366 366 367 wp_register_script('shortpixel-inline-help', plugins_url('res/js/shortpixel-inline-help.js', SHORTPIXEL_PLUGIN_FILE), array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true); 367 wp_register_script('shortpixel-inline-help', plugins_url('res/js/shortpixel-inline-help.js', SHORTPIXEL_PLUGIN_FILE), [], SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true); 368 wp_register_script('shortpixel-chatbot', 369 apply_filters('shortpixel/plugin/nohelp', 'https://spcdn.shortpixel.ai/assets/js/ext/ai-chat-agent.js'), [], SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true); 368 370 369 371 // This filter is from ListMediaViewController for the media library grid display, executive script in shortpixel-media.js. … … 589 591 $this->load_script( 'shortpixel-screen-nolist' ); // screen 590 592 $this->load_script( 'shortpixel-settings' ); 593 $this->load_script('shortpixel-chatbot'); 591 594 592 595 // @todo Load onboarding only when no api key / onboarding required … … 599 602 } elseif ( $plugin_page == 'wp-short-pixel-bulk' ) { 600 603 $this->load_script( 'shortpixel-screen-bulk' ); 604 $this->load_script('shortpixel-chatbot'); 601 605 602 606 $this->load_style( 'shortpixel-admin' ); … … 619 623 620 624 $this->load_script( 'shortpixel-folderbrowser' ); 625 $this->load_script('shortpixel-chatbot'); 621 626 622 627 $this->load_style( 'shortpixel-admin' ); -
shortpixel-image-optimiser/trunk/wp-shortpixel.php
r3348311 r3363822 4 4 * Plugin URI: https://shortpixel.com/ 5 5 * Description: ShortPixel optimizes images automatically, while guarding the quality of your images. Check your <a href="https://plugins.trac.wordpress.org/wp-admin/options-general.php?page=wp-shortpixel-settings" target="_blank">Settings > ShortPixel</a> page on how to start optimizing your image library and make your website load faster. 6 * Version: 6.3. 36 * Version: 6.3.4 7 7 * Author: ShortPixel - Convert WebP/AVIF & Optimize Images 8 8 * Author URI: https://shortpixel.com … … 37 37 define('SHORTPIXEL_PLUGIN_DIR', __DIR__); 38 38 39 define('SHORTPIXEL_IMAGE_OPTIMISER_VERSION', "6.3. 3");39 define('SHORTPIXEL_IMAGE_OPTIMISER_VERSION', "6.3.4"); 40 40 41 41 define('SHORTPIXEL_BACKUP', 'ShortpixelBackups');
Note: See TracChangeset
for help on using the changeset viewer.