""" Plugin Distribution System Serializers """ from rest_framework import serializers from .models import Plugin, PluginVersion, PluginInstallation, PluginDownload class PluginVersionSerializer(serializers.ModelSerializer): """Serializer for plugin versions.""" download_count = serializers.SerializerMethodField() class Meta: model = PluginVersion fields = [ 'id', 'version', 'version_code', 'status', 'file_size', 'checksum', 'changelog', 'min_api_version', 'min_platform_version', 'min_php_version', 'force_update', 'released_at', 'created_at', 'download_count', ] read_only_fields = ['id', 'version_code', 'created_at', 'download_count'] def get_download_count(self, obj): return obj.get_download_count() class PluginSerializer(serializers.ModelSerializer): """Serializer for plugins.""" latest_version = serializers.SerializerMethodField() download_count = serializers.SerializerMethodField() class Meta: model = Plugin fields = [ 'id', 'name', 'slug', 'platform', 'description', 'homepage_url', 'is_active', 'latest_version', 'download_count', 'created_at', 'updated_at', ] read_only_fields = ['id', 'created_at', 'updated_at'] def get_latest_version(self, obj): latest = obj.get_latest_version() if latest: return { 'version': latest.version, 'version_code': latest.version_code, 'released_at': latest.released_at, 'changelog': latest.changelog, } return None def get_download_count(self, obj): return obj.get_download_count() class PluginDetailSerializer(PluginSerializer): """Detailed serializer for plugins including versions.""" versions = PluginVersionSerializer(many=True, read_only=True) class Meta(PluginSerializer.Meta): fields = PluginSerializer.Meta.fields + ['versions'] class PluginInfoSerializer(serializers.Serializer): """ Serializer for WordPress plugin info endpoint. Returns data in WordPress-compatible format. """ name = serializers.CharField() slug = serializers.CharField() version = serializers.CharField() author = serializers.CharField(default='IGNY8') homepage = serializers.URLField() description = serializers.CharField() changelog = serializers.CharField() download_url = serializers.URLField() file_size = serializers.IntegerField() requires_php = serializers.CharField() tested_wp = serializers.CharField(default='6.7') class CheckUpdateSerializer(serializers.Serializer): """Serializer for update check response.""" update_available = serializers.BooleanField() current_version = serializers.CharField() latest_version = serializers.CharField(allow_null=True) latest_version_code = serializers.IntegerField(allow_null=True) download_url = serializers.URLField(allow_null=True) changelog = serializers.CharField(allow_null=True) info_url = serializers.URLField(allow_null=True) force_update = serializers.BooleanField(default=False) checksum = serializers.CharField(allow_null=True) class RegisterInstallationSerializer(serializers.Serializer): """Serializer for registering plugin installations.""" site_id = serializers.IntegerField() version = serializers.CharField() def validate_site_id(self, value): from igny8_core.auth.models import Site try: Site.objects.get(id=value) except Site.DoesNotExist: raise serializers.ValidationError("Site not found") return value class HealthCheckSerializer(serializers.Serializer): """Serializer for plugin health check.""" site_id = serializers.IntegerField() version = serializers.CharField() status = serializers.ChoiceField(choices=['active', 'inactive', 'error']) error_message = serializers.CharField(required=False, allow_blank=True) class PluginInstallationSerializer(serializers.ModelSerializer): """Serializer for plugin installations.""" plugin_name = serializers.CharField(source='plugin.name', read_only=True) plugin_slug = serializers.CharField(source='plugin.slug', read_only=True) current_version_str = serializers.CharField(source='current_version.version', read_only=True) site_name = serializers.CharField(source='site.name', read_only=True) pending_update_version = serializers.SerializerMethodField() class Meta: model = PluginInstallation fields = [ 'id', 'site', 'site_name', 'plugin', 'plugin_name', 'plugin_slug', 'current_version', 'current_version_str', 'is_active', 'last_health_check', 'health_status', 'pending_update', 'pending_update_version', 'update_notified_at', 'created_at', 'updated_at', ] read_only_fields = ['id', 'created_at', 'updated_at'] def get_pending_update_version(self, obj): if obj.pending_update: return obj.pending_update.version return None class PluginDownloadSerializer(serializers.ModelSerializer): """Serializer for plugin downloads.""" plugin_name = serializers.CharField(source='plugin.name', read_only=True) version_str = serializers.CharField(source='version.version', read_only=True) class Meta: model = PluginDownload fields = [ 'id', 'plugin', 'plugin_name', 'version', 'version_str', 'site', 'account', 'download_type', 'created_at', ] read_only_fields = ['id', 'created_at'] # Admin Serializers class AdminPluginVersionCreateSerializer(serializers.ModelSerializer): """Serializer for creating new plugin versions (admin).""" class Meta: model = PluginVersion fields = [ 'version', 'status', 'changelog', 'min_api_version', 'min_platform_version', 'min_php_version', 'force_update', ] def validate_version(self, value): """Ensure version follows semantic versioning.""" import re if not re.match(r'^\d+\.\d+\.\d+$', value): raise serializers.ValidationError( "Version must follow semantic versioning (e.g., 1.0.0)" ) return value class AdminPluginVersionUploadSerializer(serializers.Serializer): """Serializer for uploading plugin ZIP file.""" file = serializers.FileField() def validate_file(self, value): """Ensure uploaded file is a ZIP.""" if not value.name.endswith('.zip'): raise serializers.ValidationError("File must be a ZIP archive") # Check file size (max 50MB) max_size = 50 * 1024 * 1024 if value.size > max_size: raise serializers.ValidationError( f"File too large. Maximum size is {max_size / 1024 / 1024}MB" ) return value