// Sandbox helper: DDS Showcase gallery dedup + field fill-in + publish. if ( ! function_exists( 'dds_cleanup_ahash' ) ) { function dds_cleanup_ahash( $attachment_id, $size = 12 ) { $path = get_attached_file( $attachment_id ); if ( ! $path || ! file_exists( $path ) ) { return null; } $info = @getimagesize( $path ); if ( ! $info ) { return null; } $mime = $info['mime']; switch ( $mime ) { case 'image/jpeg': $src = @imagecreatefromjpeg( $path ); break; case 'image/png': $src = @imagecreatefrompng( $path ); break; case 'image/gif': $src = @imagecreatefromgif( $path ); break; case 'image/webp': $src = function_exists( 'imagecreatefromwebp' ) ? @imagecreatefromwebp( $path ) : false; break; default: $src = false; } if ( ! $src ) { return null; } $sw = imagesx( $src ); $sh = imagesy( $src ); $small = imagecreatetruecolor( $size, $size ); imagecopyresampled( $small, $src, 0, 0, 0, 0, $size, $size, $sw, $sh ); imagedestroy( $src ); $vals = array(); $sum = 0; for ( $y = 0; $y < $size; $y++ ) { for ( $x = 0; $x < $size; $x++ ) { $rgb = imagecolorat( $small, $x, $y ); $r = ( $rgb >> 16 ) & 0xFF; $g = ( $rgb >> 8 ) & 0xFF; $b = $rgb & 0xFF; $gray = (int) round( 0.299 * $r + 0.587 * $g + 0.114 * $b ); $vals[] = $gray; $sum += $gray; } } imagedestroy( $small ); $avg = $sum / count( $vals ); $bits = ''; foreach ( $vals as $v ) { $bits .= ( $v > $avg ) ? '1' : '0'; } return $bits; } function dds_cleanup_hamming( $a, $b ) { if ( $a === null || $b === null || strlen( $a ) !== strlen( $b ) ) { return PHP_INT_MAX; } $d = 0; for ( $i = 0, $len = strlen( $a ); $i < $len; $i++ ) { if ( $a[ $i ] !== $b[ $i ] ) { $d++; } } return $d; } /** * Infer default tools from free text + fallback category rules. */ function dds_cleanup_infer_tools( $text, $categories ) { $text = strtolower( remove_accents( $text ) ); $map = array( 'photoshop' => 'Adobe Photoshop', 'illustrator' => 'Adobe Illustrator', 'indesign' => 'Adobe InDesign', 'premier pro' => 'Adobe Premiere Pro', 'premiere pro' => 'Adobe Premiere Pro', 'after effect' => 'Adobe After Effects', 'aftereffect' => 'Adobe After Effects', 'lightroom' => 'Adobe Lightroom', 'adobe dimension' => 'Adobe Dimension', 'adobe animate' => 'Adobe Animate', 'adobe xd' => 'Adobe XD', 'firefly' => 'Adobe Firefly', 'figma' => 'Figma', 'canva' => 'Canva', 'coreldraw' => 'CorelDRAW', 'corel draw' => 'CorelDRAW', 'blender' => 'Blender', 'cinema 4d' => 'Cinema 4D', 'davinci' => 'DaVinci Resolve', 'filmora' => 'Filmora', 'capcut' => 'CapCut', 'audacity' => 'Audacity', 'procreate' => 'Procreate', 'midjourney' => 'Midjourney', 'leonardo' => 'Leonardo AI', 'runway' => 'Runway', 'luma' => 'Luma AI', 'higgsfield' => 'Higgsfield', 'kling' => 'Kling AI', 'sora' => 'Sora', 'veo' => 'Google Veo', 'pika' => 'Pika Labs', 'hailuo' => 'Hailuo AI', 'stable diffusion' => 'Stable Diffusion', ' flux' => 'Flux', 'dall-e' => "DALL·E", 'dall e' => "DALL·E", 'ideogram' => 'Ideogram', 'krea' => 'Krea AI', 'magnific' => 'Magnific AI', 'topaz' => 'Topaz Labs', 'elevenlabs' => 'ElevenLabs', 'suno' => 'Suno AI', 'udio' => 'Udio', 'heygen' => 'HeyGen', 'synthesia' => 'Synthesia', 'descript' => 'Descript', 'freepik' => 'Freepik AI', 'recraft' => 'Recraft', 'chatgpt' => 'ChatGPT', 'voiceover' => 'AI Voiceover', 'ai music' => 'AI Music Generation', 'ai voice' => 'AI Voiceover', ); $found = array(); foreach ( $map as $needle => $label ) { if ( false !== strpos( $text, $needle ) ) { $found[ $label ] = true; } } if ( $found ) { return array_keys( $found ); } $cats = implode( '|', $categories ); if ( false !== strpos( $cats, '3D дизајн' ) ) { return array( '3D моделирање' ); } if ( false !== strpos( $cats, 'Векторски дизајн' ) ) { return array( 'Adobe Illustrator' ); } if ( false !== strpos( $cats, 'UI/UX и web' ) ) { return array( 'Web Design' ); } if ( false !== strpos( $cats, 'Видео и motion' ) ) { return array( 'Adobe Premiere Pro', 'Adobe After Effects' ); } if ( false !== strpos( $cats, 'Лого и брендинг' ) ) { return array( 'Adobe Illustrator', 'Brand Identity' ); } return array( 'Adobe Photoshop' ); } function dds_cleanup_process_project( $post_id, $dry_run = true ) { $report = array( 'post_id' => $post_id, 'title' => get_the_title( $post_id ), 'removed_orphans' => array(), 'removed_dupes' => array(), 'kept' => array(), 'gallery_before' => 0, 'gallery_after' => 0, 'tools_before' => array(), 'tools_after' => array(), 'thumbnail_before'=> 0, 'thumbnail_after' => 0, ); $gallery = get_post_meta( $post_id, '_dds_showcase_gallery', true ); $gallery = is_array( $gallery ) ? array_map( 'intval', $gallery ) : array(); $report['gallery_before'] = count( $gallery ); $thumb_id = (int) get_post_meta( $post_id, '_thumbnail_id', true ); $report['thumbnail_before'] = $thumb_id; $valid = array(); foreach ( $gallery as $aid ) { $p = get_post( $aid ); if ( $p && 'attachment' === $p->post_type ) { $valid[] = $aid; } else { $report['removed_orphans'][] = $aid; } } $images = array(); $others = array(); foreach ( $valid as $aid ) { $mime = get_post_mime_type( $aid ); if ( 0 === strpos( (string) $mime, 'image' ) ) { $images[] = $aid; } else { $others[] = $aid; } } $hash = array(); $dims = array(); foreach ( $images as $aid ) { $hash[ $aid ] = dds_cleanup_ahash( $aid ); $meta = wp_get_attachment_metadata( $aid ); $w = isset( $meta['width'] ) ? (int) $meta['width'] : 0; $h = isset( $meta['height'] ) ? (int) $meta['height'] : 0; $dims[ $aid ] = array( $w, $h, $w * $h ); } $clusters = array(); $next_cluster = 0; $order = $images; foreach ( $order as $i => $aid_a ) { if ( isset( $clusters[ $aid_a ] ) ) { continue; } $clusters[ $aid_a ] = $next_cluster; for ( $j = $i + 1; $j < count( $order ); $j++ ) { $aid_b = $order[ $j ]; if ( isset( $clusters[ $aid_b ] ) ) { continue; } $dist = dds_cleanup_hamming( $hash[ $aid_a ], $hash[ $aid_b ] ); if ( $dist === PHP_INT_MAX ) { continue; } list( $wa, $ha ) = $dims[ $aid_a ]; list( $wb, $hb ) = $dims[ $aid_b ]; $ratio_ok = false; if ( $wa > 0 && $ha > 0 && $wb > 0 && $hb > 0 ) { $ra = $wa / $ha; $rb = $wb / $hb; $ratio_ok = ( abs( $ra - $rb ) / max( $ra, $rb ) ) < 0.08; } if ( $dist <= 8 && $ratio_ok ) { $clusters[ $aid_b ] = $clusters[ $aid_a ]; } } $next_cluster++; } $groups = array(); foreach ( $images as $aid ) { $cid = $clusters[ $aid ]; $groups[ $cid ][] = $aid; } $final_images = array(); $removed_dupes = array(); foreach ( $groups as $cid => $members ) { if ( count( $members ) === 1 ) { $final_images[] = $members[0]; continue; } usort( $members, function( $a, $b ) use ( $dims ) { $areaCmp = $dims[ $b ][2] <=> $dims[ $a ][2]; if ( 0 !== $areaCmp ) { return $areaCmp; } $fa = get_attached_file( $a ); $fb = get_attached_file( $b ); $sa = $fa && file_exists( $fa ) ? filesize( $fa ) : 0; $sb = $fb && file_exists( $fb ) ? filesize( $fb ) : 0; return $sb <=> $sa; } ); $keeper = array_shift( $members ); $final_images[] = $keeper; foreach ( $members as $dupe ) { $removed_dupes[] = $dupe; } } $order_index = array_flip( $images ); usort( $final_images, function( $a, $b ) use ( $order_index ) { return $order_index[ $a ] <=> $order_index[ $b ]; } ); $report['removed_dupes'] = $removed_dupes; $report['kept'] = $final_images; $final_gallery = array(); foreach ( $valid as $aid ) { if ( in_array( $aid, $final_images, true ) || in_array( $aid, $others, true ) ) { $final_gallery[] = $aid; } } $report['gallery_after'] = count( $final_gallery ); $new_thumb = $thumb_id; if ( in_array( $thumb_id, $removed_dupes, true ) ) { $cid = $clusters[ $thumb_id ]; foreach ( $final_images as $fi ) { if ( isset( $clusters[ $fi ] ) && $clusters[ $fi ] === $cid ) { $new_thumb = $fi; break; } } } elseif ( ! $thumb_id || ( ! get_post( $thumb_id ) ) ) { $new_thumb = ! empty( $final_images ) ? $final_images[0] : 0; } $report['thumbnail_after'] = $new_thumb; $tools = get_post_meta( $post_id, '_dds_showcase_tools', true ); $tools = is_array( $tools ) ? array_filter( $tools ) : array(); $report['tools_before'] = $tools; $new_tools = $tools; if ( empty( $tools ) ) { $desc = (string) get_post_meta( $post_id, '_dds_showcase_short_description', true ); $cats = wp_get_post_terms( $post_id, 'dds_showcase_category', array( 'fields' => 'names' ) ); $cats = is_wp_error( $cats ) ? array() : $cats; $new_tools = dds_cleanup_infer_tools( get_the_title( $post_id ) . ' ' . $desc, $cats ); } $report['tools_after'] = $new_tools; $platform = (string) get_post_meta( $post_id, '_dds_showcase_platform', true ); $src_url = (string) get_post_meta( $post_id, '_dds_showcase_source_url', true ); $new_platform = $platform; if ( '' === $platform ) { if ( false !== stripos( $src_url, 'freelancer.com' ) ) { $new_platform = 'freelancer'; } elseif ( false !== stripos( $src_url, 'fiverr.com' ) ) { $new_platform = 'fiverr'; } elseif ( false !== stripos( $src_url, 'upwork.com' ) ) { $new_platform = 'upwork'; } elseif ( '' === $src_url ) { $new_platform = 'personal'; } else { $new_platform = 'direct'; } } $report['platform_before'] = $platform; $report['platform_after'] = $new_platform; if ( ! $dry_run ) { foreach ( array_unique( $removed_dupes ) as $dead ) { if ( get_post( $dead ) ) { wp_delete_attachment( $dead, true ); } } update_post_meta( $post_id, '_dds_showcase_gallery', array_values( $final_gallery ) ); if ( $new_thumb ) { update_post_meta( $post_id, '_thumbnail_id', $new_thumb ); } else { delete_post_meta( $post_id, '_thumbnail_id' ); } if ( $new_tools !== $tools ) { update_post_meta( $post_id, '_dds_showcase_tools', array_values( array_unique( $new_tools ) ) ); } if ( $new_platform !== $platform ) { update_post_meta( $post_id, '_dds_showcase_platform', $new_platform ); } } return $report; } function dds_cleanup_process_batch( $post_ids, $dry_run = true ) { $reports = array(); foreach ( $post_ids as $pid ) { $reports[] = dds_cleanup_process_project( (int) $pid, $dry_run ); } return $reports; } } // function_exists guard https://delfidesign.top/wp-sitemap-posts-post-1.xmlhttps://delfidesign.top/wp-sitemap-posts-page-1.xmlhttps://delfidesign.top/wp-sitemap-posts-dds_showcase-1.xmlhttps://delfidesign.top/wp-sitemap-posts-solace-sitebuilder-1.xmlhttps://delfidesign.top/wp-sitemap-posts-package-1.xmlhttps://delfidesign.top/wp-sitemap-posts-service-1.xmlhttps://delfidesign.top/wp-sitemap-taxonomies-category-1.xmlhttps://delfidesign.top/wp-sitemap-taxonomies-vidovi-na-bilder-optsii-1.xmlhttps://delfidesign.top/wp-sitemap-taxonomies-service-subcategory-1.xmlhttps://delfidesign.top/wp-sitemap-taxonomies-project-category-1.xmlhttps://delfidesign.top/wp-sitemap-taxonomies-dds_showcase_category-1.xmlhttps://delfidesign.top/wp-sitemap-users-1.xml