{
  "$schema": "https://playground.wordpress.net/blueprint-schema.json",
  "meta": {
    "title": "7S Video & Music Gallery Demo",
    "description": "A populated interactive preview of 7S Video & Music Gallery.",
    "author": "durdagi",
    "categories": [
      "gallery",
      "media",
      "music",
      "video"
    ]
  },
  "landingPage": "/galeri/",
  "preferredVersions": {
    "php": "8.3",
    "wp": "latest"
  },
  "features": {
    "networking": true
  },
  "steps": [
    {
      "step": "installPlugin",
      "pluginData": {
        "resource": "wordpress.org/plugins",
        "slug": "7sgaleri"
      },
      "options": {
        "activate": true
      }
    },
    {
      "step": "login",
      "username": "admin",
      "password": "password"
    },
    {
      "step": "runPHP",
      "code": "<?php\nrequire_once 'wordpress/wp-load.php';\n\nif ( ! class_exists( 'SG7G_Settings' ) || ! class_exists( 'SG7G_Post_Type' ) ) {\n    return;\n}\n\nSG7G_Post_Type::register();\nSG7G_Statistics::install();\nSG7G_Likes::install();\n\n$existing_demo = get_posts(\n    array(\n        'post_type'      => 'sg7g_media',\n        'post_status'    => 'any',\n        'posts_per_page' => 1,\n        'fields'         => 'ids',\n        'meta_key'       => '_sg7g_playground_demo',\n        'meta_value'     => '1',\n    )\n);\n\nif ( ! empty( $existing_demo ) ) {\n    flush_rewrite_rules( false );\n    return;\n}\n\nwp_delete_post( 1, true );\nwp_delete_post( 2, true );\n\n$settings = wp_parse_args(\n    array(\n        'posts_per_page'     => 12,\n        'pagination_mode'    => 'numbers',\n        'card_title_limit'   => 44,\n        'featured_title'     => '',\n        'popular_title'      => 'Most Liked',\n        'popular_period'     => 'all',\n        'popular_count'      => 6,\n        'popular_columns'    => 3,\n        'popular_like_color' => '#a13b43',\n        'featured_order'     => array(),\n        'width_mode'         => 'custom',\n        'custom_width'       => 1440,\n        'typography_mode'    => 'custom',\n        'text_color'         => '#161616',\n        'muted_color'        => '#6c6964',\n        'line_color'         => '#e2ded7',\n        'surface_color'      => '#f5f2ec',\n    ),\n    SG7G_Settings::defaults()\n);\nupdate_option( 'sg7g_settings', $settings, false );\n\nupdate_option( 'blogname', '7S Video & Music Gallery' );\nupdate_option( 'blogdescription', 'Interactive Demo' );\nupdate_option( 'permalink_structure', '/%postname%/' );\n\n$mu_plugins_directory = WPMU_PLUGIN_DIR;\nwp_mkdir_p( $mu_plugins_directory );\n$demo_shell = <<<'PHP'\n<?php\nadd_action(\n    'wp_enqueue_scripts',\n    static function (): void {\n        wp_register_style( 'sg7g-playground-shell', false, array(), null );\n        wp_enqueue_style( 'sg7g-playground-shell' );\n        wp_add_inline_style(\n            'sg7g-playground-shell',\n            'html,body{background:#faf8f4;color:#161616}body{margin:0}#page>#header{box-sizing:border-box;max-width:1440px;margin:0 auto;padding:30px 24px 12px}#headerimg{display:flex;align-items:center;justify-content:space-between;gap:24px;border-bottom:1px solid #e2ded7;padding:0 0 20px}#headerimg h1{margin:0;font:600 clamp(25px,2.4vw,36px)/1.1 Georgia,\"Times New Roman\",serif;letter-spacing:-.025em}#headerimg h1 a{color:#161616;text-decoration:none}#headerimg .description{color:#6c6964;font:600 11px/1.2 Arial,sans-serif;letter-spacing:.12em;text-transform:uppercase}#page>hr{display:none}#page>main.sg7g-archive{padding-top:18px}@media(max-width:700px){#page>#header{padding:22px 16px 8px}#headerimg{align-items:flex-start;flex-direction:column;gap:7px;padding-bottom:15px}#headerimg h1{font-size:25px}#page>main.sg7g-archive{padding-top:12px}}'\n        );\n    },\n    99\n);\nPHP;\nfile_put_contents( trailingslashit( $mu_plugins_directory ) . '7sgaleri-playground-shell.php', $demo_shell );\n\n$categories = array( 'Video', 'Music', 'Performance', 'Soundtrack' );\nforeach ( $categories as $category ) {\n    if ( ! term_exists( $category, 'sg7g_category' ) ) {\n        wp_insert_term( $category, 'sg7g_category' );\n    }\n}\n\n$uploads = wp_upload_dir();\nif ( ! empty( $uploads['error'] ) ) {\n    return;\n}\n\n$demo_directory = trailingslashit( $uploads['basedir'] ) . '7sgaleri-playground';\nwp_mkdir_p( $demo_directory );\n\n$audio_file = trailingslashit( $demo_directory ) . 'ambient-demo.wav';\nif ( ! file_exists( $audio_file ) ) {\n    $sample_rate = 22050;\n    $duration    = 8;\n    $sample_count = $sample_rate * $duration;\n    $pcm = '';\n\n    for ( $sample = 0; $sample < $sample_count; $sample++ ) {\n        $time = $sample / $sample_rate;\n        $fade_in  = min( 1, $time / 1.2 );\n        $fade_out = min( 1, ( $duration - $time ) / 1.5 );\n        $envelope = max( 0, min( $fade_in, $fade_out ) );\n        $tone = sin( 2 * M_PI * 220 * $time ) * 0.42;\n        $tone += sin( 2 * M_PI * 277.18 * $time ) * 0.24;\n        $tone += sin( 2 * M_PI * 329.63 * $time ) * 0.18;\n        $value = (int) max( -32767, min( 32767, $tone * $envelope * 16000 ) );\n        $pcm .= pack( 'v', $value < 0 ? $value + 65536 : $value );\n    }\n\n    $data_size = strlen( $pcm );\n    $header  = 'RIFF' . pack( 'V', 36 + $data_size ) . 'WAVE';\n    $header .= 'fmt ' . pack( 'VvvVVvv', 16, 1, 1, $sample_rate, $sample_rate * 2, 2, 16 );\n    $header .= 'data' . pack( 'V', $data_size );\n    file_put_contents( $audio_file, $header . $pcm );\n}\n\n$audio_attachment = 0;\nif ( file_exists( $audio_file ) ) {\n    $audio_attachment = wp_insert_attachment(\n        array(\n            'post_mime_type' => 'audio/wav',\n            'post_title'     => '7S Gallery Ambient Demo',\n            'post_status'    => 'inherit',\n        ),\n        $audio_file,\n        0,\n        true\n    );\n    $audio_attachment = is_wp_error( $audio_attachment ) ? 0 : (int) $audio_attachment;\n}\n\n$items = array(\n    array( 'title' => 'The Last Broadcast',   'type' => 'video', 'category' => 'Video',       'views' => 986, 'likes' => 58, 'palette' => array( '#16131c', '#8a3147', '#f2a65a' ) ),\n    array( 'title' => 'Midnight Transit',     'type' => 'audio', 'category' => 'Music',       'views' => 914, 'likes' => 46, 'palette' => array( '#081c24', '#176b73', '#73d2a6' ) ),\n    array( 'title' => 'Frames of Memory',     'type' => 'video', 'category' => 'Video',       'views' => 842, 'likes' => 39, 'palette' => array( '#1b1728', '#584a89', '#dbb4ff' ) ),\n    array( 'title' => 'Neon Soundscape',      'type' => 'audio', 'category' => 'Soundtrack',  'views' => 781, 'likes' => 35, 'palette' => array( '#10131d', '#144d72', '#f25f5c' ) ),\n    array( 'title' => 'Beyond the Horizon',   'type' => 'video', 'category' => 'Performance', 'views' => 734, 'likes' => 31, 'palette' => array( '#122026', '#4b7f72', '#e7b267' ) ),\n    array( 'title' => 'Studio Session No. 7', 'type' => 'audio', 'category' => 'Music',       'views' => 668, 'likes' => 27, 'palette' => array( '#1c1416', '#873e23', '#f0c36b' ) ),\n    array( 'title' => 'City in Motion',       'type' => 'video', 'category' => 'Video',       'views' => 603, 'likes' => 24, 'palette' => array( '#101820', '#2f5d8a', '#d0e3ff' ) ),\n    array( 'title' => 'Echoes After Dark',    'type' => 'audio', 'category' => 'Soundtrack',  'views' => 547, 'likes' => 21, 'palette' => array( '#150f20', '#55286f', '#d8a7ca' ) ),\n    array( 'title' => 'Opening Night',        'type' => 'video', 'category' => 'Performance', 'views' => 492, 'likes' => 18, 'palette' => array( '#201517', '#7e2e33', '#ffd166' ) ),\n    array( 'title' => 'Analog Dreams',        'type' => 'audio', 'category' => 'Music',       'views' => 438, 'likes' => 16, 'palette' => array( '#151b18', '#35605a', '#a8d5ba' ) ),\n    array( 'title' => 'The Long Take',        'type' => 'video', 'category' => 'Video',       'views' => 386, 'likes' => 13, 'palette' => array( '#151515', '#545454', '#d9d9d9' ) ),\n    array( 'title' => 'Signal & Silence',     'type' => 'audio', 'category' => 'Soundtrack',  'views' => 331, 'likes' => 11, 'palette' => array( '#0e1726', '#274c77', '#a3cef1' ) ),\n);\n\n$hex_to_rgb = static function ( string $hex ): array {\n    $hex = ltrim( $hex, '#' );\n    return array(\n        hexdec( substr( $hex, 0, 2 ) ),\n        hexdec( substr( $hex, 2, 2 ) ),\n        hexdec( substr( $hex, 4, 2 ) ),\n    );\n};\n\n$create_cover = static function ( int $post_id, array $item, int $index ) use ( $demo_directory, $hex_to_rgb ): int {\n    if ( ! function_exists( 'imagecreatetruecolor' ) || ! function_exists( 'imagepng' ) ) {\n        return 0;\n    }\n\n    $width  = 960;\n    $height = 540;\n    $image  = imagecreatetruecolor( $width, $height );\n    if ( ! $image ) {\n        return 0;\n    }\n\n    $start  = $hex_to_rgb( $item['palette'][0] );\n    $middle = $hex_to_rgb( $item['palette'][1] );\n    $accent_rgb = $hex_to_rgb( $item['palette'][2] );\n\n    for ( $y = 0; $y < $height; $y++ ) {\n        $ratio = $y / max( 1, $height - 1 );\n        $red   = (int) round( $start[0] + ( $middle[0] - $start[0] ) * $ratio );\n        $green = (int) round( $start[1] + ( $middle[1] - $start[1] ) * $ratio );\n        $blue  = (int) round( $start[2] + ( $middle[2] - $start[2] ) * $ratio );\n        $line  = imagecolorallocate( $image, $red, $green, $blue );\n        imageline( $image, 0, $y, $width, $y, $line );\n    }\n\n    imagealphablending( $image, true );\n    $accent      = imagecolorallocate( $image, $accent_rgb[0], $accent_rgb[1], $accent_rgb[2] );\n    $accent_soft = imagecolorallocatealpha( $image, $accent_rgb[0], $accent_rgb[1], $accent_rgb[2], 82 );\n    $white_soft  = imagecolorallocatealpha( $image, 255, 255, 255, 94 );\n    $dark_soft   = imagecolorallocatealpha( $image, 0, 0, 0, 92 );\n\n    imagefilledellipse( $image, 780 - ( $index % 3 ) * 95, 120 + ( $index % 4 ) * 55, 520, 520, $accent_soft );\n    imagefilledellipse( $image, 140 + ( $index % 4 ) * 70, 500, 420, 420, $accent_soft );\n    imagefilledrectangle( $image, 0, 455, $width, $height, $dark_soft );\n\n    for ( $line_index = 0; $line_index < 8; $line_index++ ) {\n        $offset = 74 + ( $line_index * 118 );\n        imageline( $image, $offset, 0, $offset - 180, $height, $white_soft );\n    }\n\n    imagefilledrectangle( $image, 54, 50, 142, 57, $accent );\n    imagefilledrectangle( $image, 54, 70, 102, 75, $white_soft );\n\n    if ( 'audio' === $item['type'] ) {\n        $bars = array( 56, 104, 168, 230, 148, 274, 194, 128, 176, 92, 62 );\n        $start_x = 540;\n        foreach ( $bars as $bar_index => $bar_height ) {\n            $x = $start_x + ( $bar_index * 28 );\n            $bar_color = 5 === $bar_index ? $accent : $white_soft;\n            imagefilledrectangle( $image, $x, 270 - (int) ( $bar_height / 2 ), $x + 11, 270 + (int) ( $bar_height / 2 ), $bar_color );\n        }\n    } else {\n        imagefilledellipse( $image, 700, 265, 190, 190, $accent_soft );\n        imagefilledpolygon( $image, array( 675, 210, 675, 320, 770, 265 ), $accent );\n    }\n\n    $filename = 'cover-' . ( $index + 1 ) . '.png';\n    $filepath = trailingslashit( $demo_directory ) . $filename;\n    $saved    = imagepng( $image, $filepath, 8 );\n    imagedestroy( $image );\n\n    if ( ! $saved ) {\n        return 0;\n    }\n\n    $attachment_id = wp_insert_attachment(\n        array(\n            'post_mime_type' => 'image/png',\n            'post_title'     => $item['title'] . ' — Cover',\n            'post_status'    => 'inherit',\n        ),\n        $filepath,\n        $post_id,\n        true\n    );\n\n    if ( is_wp_error( $attachment_id ) ) {\n        return 0;\n    }\n\n    require_once ABSPATH . 'wp-admin/includes/image.php';\n    $metadata = wp_generate_attachment_metadata( (int) $attachment_id, $filepath );\n    if ( is_array( $metadata ) ) {\n        wp_update_attachment_metadata( (int) $attachment_id, $metadata );\n    }\n    update_post_meta( (int) $attachment_id, '_wp_attachment_image_alt', $item['title'] );\n    set_post_thumbnail( $post_id, (int) $attachment_id );\n\n    return (int) $attachment_id;\n};\n\n$post_ids = array();\n$video_url = 'https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4';\n$base_timestamp = current_time( 'timestamp' );\n\nforeach ( $items as $index => $item ) {\n    $post_id = wp_insert_post(\n        array(\n            'post_type'    => 'sg7g_media',\n            'post_status'  => 'publish',\n            'post_title'   => $item['title'],\n            'post_excerpt' => 'A sample ' . strtolower( $item['type'] ) . ' entry created for the interactive 7S Gallery preview.',\n            'post_content' => '<p>This sample entry demonstrates the individual media page, responsive player, reversible likes, sharing controls, navigation, and related content.</p><p>Return to the gallery to explore the featured showcase, Most Liked list, category browsing, search, and the complete media stream.</p>',\n            'post_date'    => wp_date( 'Y-m-d H:i:s', $base_timestamp - ( $index * DAY_IN_SECONDS ) ),\n        ),\n        true\n    );\n\n    if ( is_wp_error( $post_id ) ) {\n        continue;\n    }\n\n    $post_id = (int) $post_id;\n    $post_ids[] = $post_id;\n    update_post_meta( $post_id, '_sg7g_playground_demo', 1 );\n    update_post_meta( $post_id, '_sg7g_media_type', $item['type'] );\n    update_post_meta( $post_id, '_sg7g_source', 'audio' === $item['type'] ? 'local_audio' : 'external_video' );\n    update_post_meta( $post_id, '_sg7g_source_url', 'audio' === $item['type'] ? '' : $video_url );\n    update_post_meta( $post_id, '_sg7g_file_id', 'audio' === $item['type'] ? $audio_attachment : 0 );\n    update_post_meta( $post_id, '_sg7g_source_valid', 1 );\n    update_post_meta( $post_id, '_sg7g_validation_schema', '4' );\n    update_post_meta( $post_id, '_sg7g_views', $item['views'] );\n    update_post_meta( $post_id, '_sg7g_likes', $item['likes'] );\n\n    if ( $index < 5 ) {\n        update_post_meta( $post_id, '_sg7g_featured', 1 );\n    }\n\n    wp_set_object_terms( $post_id, $item['category'], 'sg7g_category' );\n    $create_cover( $post_id, $item, $index );\n}\n\n$settings['featured_order'] = array_slice( $post_ids, 0, 5 );\nupdate_option( 'sg7g_settings', $settings, false );\n\nglobal $wpdb;\n$likes_table = SG7G_Likes::table_name();\n$views_table = SG7G_Statistics::table_name();\n\nforeach ( $post_ids as $index => $post_id ) {\n    $like_count = (int) $items[ $index ]['likes'];\n    for ( $like_index = 0; $like_index < $like_count; $like_index++ ) {\n        $wpdb->insert(\n            $likes_table,\n            array(\n                'post_id'    => $post_id,\n                'voter_hash' => hash( 'sha256', '7sgaleri-demo|' . $post_id . '|' . $like_index ),\n                'created_at' => gmdate( 'Y-m-d H:i:s', time() - ( ( $like_index % 28 ) * DAY_IN_SECONDS ) - ( $like_index * 97 ) ),\n            ),\n            array( '%d', '%s', '%s' )\n        );\n    }\n\n    $daily_base = max( 1, (int) floor( $items[ $index ]['views'] / 45 ) );\n    for ( $day = 0; $day < 30; $day++ ) {\n        $daily_views = max( 1, $daily_base + ( ( $index * 3 + $day * 5 ) % 13 ) - 6 );\n        $wpdb->replace(\n            $views_table,\n            array(\n                'view_date' => gmdate( 'Y-m-d', time() - ( $day * DAY_IN_SECONDS ) ),\n                'post_id'   => $post_id,\n                'views'     => $daily_views,\n            ),\n            array( '%s', '%d', '%d' )\n        );\n    }\n}\n\nflush_rewrite_rules( false );\n"
    }
  ]
}

