def _get_derived_website_content_data(request_data: dict, site_config: SiteConfig, website_pk: str) -> dict: """Derives values that should be added to the request data if a WebsiteContent object is being created""" added_data = {} if "text_id" not in request_data: added_data["text_id"] = uuid_string() content_type = request_data.get("type") config_item = (site_config.find_item_by_name( name=content_type) if content_type is not None else None) is_page_content = False if site_config and config_item is not None: is_page_content = site_config.is_page_content(config_item) added_data["is_page_content"] = is_page_content dirpath = request_data.get("dirpath") if dirpath is None and config_item is not None and is_page_content: dirpath = config_item.file_target added_data["dirpath"] = dirpath slug_key = config_item.item.get( "slug") if config_item is not None else None if not slug_key: slug_key = "title" slug = (added_data.get(slug_key) or request_data.get(slug_key) or request_data.get("metadata", {}).get(slug_key)) if slug is not None: added_data["filename"] = get_valid_new_filename( website_pk=website_pk, dirpath=dirpath, filename_base=slugify(get_valid_base_filename(slug, content_type)), ) return added_data
def for_content( site_config: SiteConfig, website_content: WebsiteContent) -> BaseContentFileSerializer: """ Given a WebsiteContent object and site config, returns a serializer object of the correct type for serializing the WebsiteContent object into file contents. """ if website_content.is_page_content: return HugoMarkdownFileSerializer(site_config=site_config) config_item = site_config.find_item_by_name(website_content.type) destination_filepath = config_item.file_target if not destination_filepath: raise ValueError( f"WebsiteContent object is not page content, but has no 'file' destination in config ({website_content.text_id})." ) file_ext = get_file_extension(destination_filepath) if file_ext == "json": cls = JsonFileSerializer elif file_ext in {"yml", "yaml"}: # HACK: Hugo-specific logic for properly transforming data if the "menu" widget is used if _has_menu_fields(config_item): cls = HugoMenuYamlFileSerializer else: cls = YamlFileSerializer else: raise ValueError( f"Website content cannot be serialized to a file ({website_content.text_id})." ) return cls(site_config=site_config)
def _transform_hugo_menu_data(website_content: WebsiteContent, site_config: SiteConfig) -> dict: """ Adds 'url' property to internal links in menu data. Returns the dict of all values that will be serialized to the target file, including the transformed "menu" fields. """ config_item = site_config.find_item_by_name(website_content.type) menu_fields = { field["name"] for field in config_item.fields if field.get("widget") == CONTENT_MENU_FIELD } transformed_menu_fields = {} for field_name, field_data in website_content.metadata.items(): if field_name not in menu_fields: continue uuid_content_map = _get_uuid_content_map(field_data) result_menu_items = [] for menu_item in field_data: updated_menu_item = menu_item # Add/update the 'url' value if this is an internal link if menu_item["identifier"] in uuid_content_map: menu_item_content = uuid_content_map[menu_item["identifier"]] updated_menu_item["url"] = get_destination_url( menu_item_content, site_config) result_menu_items.append(updated_menu_item) transformed_menu_fields[field_name] = result_menu_items return {**website_content.metadata, **transformed_menu_fields}
def test_find_config_item_name_singleton(basic_site_config): """SiteConfig.find_item_by_name should return a singleton config item if one is found with the given name""" site_config = SiteConfig(basic_site_config) config_item = next(item for item in site_config.iter_items() if item.is_file_item()) assert config_item is not None assert site_config.find_item_by_name(config_item.name) == config_item assert site_config.find_item_by_name("other-name-123") is None
def create_gdrive_resource_content(drive_file: DriveFile): """Create a WebsiteContent resource from a Google Drive file""" try: resource_type = get_resource_type(drive_file.s3_key) resource = drive_file.resource if not resource: site_config = SiteConfig(drive_file.website.starter.config) config_item = site_config.find_item_by_name( name=CONTENT_TYPE_RESOURCE) dirpath = config_item.file_target if config_item else None basename, _ = os.path.splitext(drive_file.name) filename = get_valid_new_filename( website_pk=drive_file.website.pk, dirpath=dirpath, filename_base=slugify( get_valid_base_filename(basename, CONTENT_TYPE_RESOURCE)), ) resource_type_fields = { field: resource_type for field in settings.RESOURCE_TYPE_FIELDS } resource = WebsiteContent.objects.create( website=drive_file.website, title=drive_file.name, file=drive_file.s3_key, type=CONTENT_TYPE_RESOURCE, is_page_content=True, dirpath=dirpath, filename=filename, metadata={ **SiteConfig(drive_file.website.starter.config).generate_item_metadata( CONTENT_TYPE_RESOURCE, cls=WebsiteContent, file_type=drive_file.mime_type, **resource_type_fields, ) }, ) else: resource.file = drive_file.s3_key resource.save() drive_file.resource = resource drive_file.update_status(DriveFileStatus.COMPLETE) except: # pylint:disable=bare-except log.exception("Error creating resource for drive file %s", drive_file.file_id) drive_file.sync_error = ( f"Could not create a resource from google drive file {drive_file.name}" ) drive_file.update_status(DriveFileStatus.FAILED)
def get_destination_filepath(content: WebsiteContent, site_config: SiteConfig) -> Optional[str]: """ Returns the full filepath where the equivalent file for the WebsiteContent record should be placed """ if content.is_page_content: return os.path.join(content.dirpath, f"{content.filename}.{WEBSITE_CONTENT_FILETYPE}") config_item = site_config.find_item_by_name(name=content.type) if config_item is None: log.error( "Config item not found (content: %s, name value missing from config: %s)", (content.id, content.text_id), content.type, ) return None if config_item.is_file_item(): return config_item.file_target log.error( "Invalid config item: is_page_content flag is False, and config item is not 'file'-type (content: %s)", (content.id, content.text_id), ) return None
def get_config_file_field(self) -> Dict: """Get the site config file field for the object, if any""" site_config = SiteConfig(self.website.starter.config) content_config = site_config.find_item_by_name(self.type) if content_config: return site_config.find_file_field(content_config)