<?php if ( ! defined( 'ABSPATH' ) ) { die( 'You are not allowed to call this page directly.' ); } /** * @since 5.3 */ class FrmApplicationTemplate { /** * @var array<string>|null */ private static $keys; /** * @var array<string>|null */ private static $keys_with_images; /** * @var array<string>|null */ private static $categories; /** * @var array */ private $api_data; /** * @return void */ public static function init() { /** * @since 5.3 * * @param array $keys */ self::$keys = apply_filters( 'frm_application_data_keys', array( 'key', 'name', 'description', 'link', 'categories', 'views', 'forms', 'used_addons' ) ); self::$keys_with_images = array_merge( self::get_template_keys_with_local_png_images(), self::get_template_keys_with_local_webp_images() ); self::$categories = array(); } /** * Newer templates now use .webp files instead of .png. * * @since 6.16 * * @return array<string> */ private static function get_template_keys_with_local_webp_images() { return array( 'member-directory', 'link-in-bio-instagram', 'letter-of-recommendation', 'invoice-pdf', 'freelance-invoice-generator', 'contract-agreement', 'charity-tracker', 'certificate', 'testimonials', ); } /** * Return the template keys that have embedded images. Otherwise, we want to avoid trying to load the URL and use the placeholder instead. * * @return array<string> */ private static function get_template_keys_with_local_png_images() { return array( 'business-hours', 'faq-template-wordpress', 'restaurant-menu', 'team-directory', 'product-review', 'real-estate-listings', 'business-directory', 'artist-gallery', 'classifieds', 'community-event-calendar', 'company-timeline', 'crowdfunding', 'job-board', 'logo-cloud', 'multi-property-booking-system', 'wedding-venue-booking', 'permission-slip', 'property-directory', 'radio-station', 'recipe', 'rsvp-invite', 'searchable-directory', 'shopping-cart', 'sports-league-calendar', 'staff-directory', 'tiered-pricing', 'trip-itinerary', 'twitterx', ); } /** * @param array $api_data * * @return void */ public function __construct( $api_data ) { $this->api_data = $api_data; if ( ! empty( $api_data['categories'] ) ) { self::populate_category_information( $api_data['categories'] ); } } /** * @param array<string> $categories * * @return void */ private static function populate_category_information( $categories ) { foreach ( $categories as $category ) { if ( self::category_matches_a_license_type( $category ) ) { continue; } if ( in_array( $category, self::$categories, true ) ) { continue; } self::$categories[] = $category; } } /** * @since 5.5.2 * * @param string $category * * @return bool */ private static function category_matches_a_license_type( $category ) { if ( str_contains( $category, '+Views' ) ) { return true; } return in_array( $category, FrmFormsHelper::get_license_types(), true ); } /** * @return array<string> */ public static function get_categories() { return self::$categories ?? array(); } /** * @return array */ public function as_js_object() { if ( ! is_array( self::$keys ) ) { return array(); } $application = array(); foreach ( self::$keys as $key ) { if ( ! isset( $this->api_data[ $key ] ) ) { continue; } $value = $this->api_data[ $key ]; if ( 'icon' === $key ) { // Icon is an array. The first array item is the image URL. $application[ $key ] = reset( $value ); } elseif ( 'categories' === $key ) { $application[ $key ] = array_values( array_filter( $value, function ( $category ) { return ! str_contains( $category, '+Views' ); } ) ); } else { if ( 'views' === $key ) { $key = 'viewCount'; } elseif ( 'forms' === $key ) { $key = 'formCount'; } if ( 'name' === $key && str_ends_with( $value, ' Template' ) ) { // Strip off the " Template" text at the end of the name as it takes up space. $value = substr( $value, 0, -9 ); } $application[ $key ] = $value; }//end if }//end foreach $application['hasLiteThumbnail'] = in_array( $application['key'], self::$keys_with_images, true ); $application['isWebp'] = in_array( $application['key'], self::get_template_keys_with_local_webp_images(), true ); if ( ! array_key_exists( 'url', $application ) ) { $application['requires'] = FrmFormsHelper::get_plan_required( $application ); if ( false === $application['requires'] ) { // Application is invalid if the URL is unavailable and there is no plan required. return array(); } $purchase_url = $this->is_available_for_purchase(); if ( false !== $purchase_url ) { $application['forPurchase'] = true; } $application['upgradeUrl'] = $this->get_admin_upgrade_link(); $application['link'] = $application['upgradeUrl']; } $application['isNew'] = $this->is_new(); $application['usedAddons'] = array(); if ( isset( $application['used_addons'] ) ) { // Change key to camel case. $application['usedAddons'] = $application['used_addons']; unset( $application['used_addons'] ); } return $application; } /** * @return bool */ private function is_available_for_purchase() { if ( ! array_key_exists( 'min_plan', $this->api_data ) ) { return false; } $license_type = ''; $api = new FrmFormApi(); $addons = $api->get_api_info(); if ( ! array_key_exists( 93790, $addons ) ) { return false; } $pro = $addons[93790]; if ( ! array_key_exists( 'type', $pro ) ) { return false; } $license_type = strtolower( $pro['type'] ); $args = array( 'license_type' => $license_type, 'plan_required' => $this->get_required_license(), ); return FrmFormsHelper::plan_is_allowed( $args ); } /** * Check if an application template is new. If it is, we include a "NEW" pill beside the title. * * @since 6.0 * * @return bool */ private function is_new() { return ! empty( $this->api_data['is_new'] ); } /** * @return string */ private function get_required_license() { $required_license = strtolower( $this->api_data['min_plan'] ); if ( 'plus' === $required_license ) { $required_license = 'personal'; } return $required_license; } /** * @return string */ private function get_admin_upgrade_link() { return FrmAppHelper::admin_upgrade_link( array( 'content' => 'upgrade', 'medium' => 'applications', ), 'view-templates/' . $this->api_data['slug'] ); } }