<?php

/**
 * The plugin bootstrap file
 *
 * This file is read by WordPress to generate the plugin information in the plugin
 * admin area. This file also includes all of the dependencies used by the plugin,
 * registers the activation and deactivation functions, and defines a function
 * that starts the plugin.
 *
 * @link              https://flothemes.com/
 * @since             1.0.0
 * @package           Flo_Flex_Builder
 *
 * @wordpress-plugin
 * Plugin Name:       Flex Block
 * Plugin URI:        https://flothemes.com/flo-flex-builder/
 * Description:       Drag and Drop builder for FloThemes
 * Version:           4.4.3
 * Author:            Flothemes
 * Author URI:        https://flothemes.com/
 * License:           GPL-2.0+
 * License URI:       http://www.gnu.org/licenses/gpl-2.0.txt
 * Text Domain:       flo-flex-builder
 * Domain Path:       /languages
 */

// If this file is called directly, abort.
if (!defined('WPINC')) {
  die;
}


/**
 * Currently plugin version.
 */
if (!function_exists('get_plugin_data')) {
  require_once(ABSPATH . 'wp-admin/includes/plugin.php');
}

$plugin_data = get_plugin_data(plugin_dir_path(__FILE__) . 'flo-flex-builder.php');

if (isset($plugin_data['Version'])) {
  $plugin_version = $plugin_data['Version'];
} else {
  $plugin_version = '1.0.0';
}
define('Flo_Flex_Builder_Version', $plugin_version);
define('S3_FLEX_BUCKET_ENDPOINT', 'https://bucket-flexblock-assets.s3.amazonaws.com');
/**
 * Currently plugin version.
 * Start at version 1.0.0 and use SemVer - https://semver.org
 * Rename this for your plugin and update it as you release new versions.
 */
$allowed_themes = ["mono", "june", "faro", "elise", "lyra", "velvet", "verso", "cotton", "nessa", "nomade", "zephyr", "ember"];

define('IS_PHP_NOT_COPATIBLE', !(version_compare(PHP_VERSION, '7.0.0') >= 0));


if (defined('IS_PHP_NOT_COPATIBLE') && IS_PHP_NOT_COPATIBLE) {
  $allowed_themes = implode("-", $allowed_themes);
}

define('FLEX_ALLOWED_THEMES', $allowed_themes);

if (!function_exists('flex_is_flo_theme')) {
  function flex_is_flo_theme() {
    $theme = wp_get_theme();
    $author = $theme->get('Author');
    $isFlothemes = strpos(strtolower($author), 'flo') !== false;
    return $isFlothemes;
  }
}

/**
 * Any old flo theme will not be compatible with gutenberg module
 * Looks in the theme author and tags
 */
if (!function_exists('flex_check_gutenberg_support')) {
  function flex_check_gutenberg_support() {
    $theme = wp_get_theme();
    $tags = $theme->get('Tags');
    $isFlothemes = flex_is_flo_theme();
    $hasNoGutSupport = strpos(strtolower(implode($tags)), 'gutenberg') === false;

    if ($isFlothemes && $hasNoGutSupport) {
      return false;
    }

    return true;
  }
}

// Using this as an environment config file
global $flex_constants;
$flex_constants = array(
  // 'gutenberg_enabled' => false,
  'dev_mode' => false,
  'dev_features_enabled' => false,
  'local_api_server' => false
);
if (file_exists(plugin_dir_path(__FILE__) . 'config.php')) {
  require_once plugin_dir_path(__FILE__) . 'config.php';
}
if (file_exists(plugin_dir_path(__FILE__) . 'showcase-config.php')) {
  define('FLEX_SHOW_CASE', true);
}

define('FLEX_GUTENBERG', flex_check_gutenberg_support());
define('Flex_Dev_Mode', $flex_constants['dev_mode']);
define('FLEX_DEV_FEATURES_ENABLED', $flex_constants['dev_features_enabled']);
define('FLEX_LOCAL_API', $flex_constants['local_api_server']);

/**
 * Sets a global for various used small options.
 * DEPRECATED: WP has exactly same instrument, no need to store it twice
 */
function flo_get_option_buffer($name) {
  // global $flex_global_buffer;
  // if (!is_array($flex_global_buffer)) $flex_global_buffer = array();
  // if (isset($flex_global_buffer[$name])) return $flex_global_buffer[$name];
  $option_result = get_option($name);
  // $flex_global_buffer[$name] = $option_result;
  return $option_result;
}

/**
 * Remoes new lines from a string
 */
if (!function_exists("remove_new_lines")) {
  function remove_new_lines($string_with_new_lines) {
    $is_dev = Flex_Dev_Mode;
    return $is_dev ? $string_with_new_lines : trim(preg_replace('/\s\s+/', ' ', $string_with_new_lines));
  }
}
/**
 * Searches in $data on $address_arr path for value (for nested arrays)
 * @param $data array os any depth
 * @param $address_arr array with location, e.g. ['one', 'two', 'three'] will search as $data[one][two][three]
 * @param $default default value to return, if value not found
 * @return mixed|false
 */
function get_deep_value($data, $address_arr, $default = false) {
  if (!$data || !is_array($data) || !$address_arr || !is_array($address_arr)) {
    return $default !== false ? $default : false;
  }
  $curr_el = false;
  foreach ($address_arr as $nest_key) {

    if (!$curr_el && isset($data[$nest_key])) {
      $curr_el = $data[$nest_key];
    } else if (isset($curr_el[$nest_key])) {
      $curr_el = $curr_el[$nest_key];
    } else {
      $curr_el = 'not_found';
      break;
    }
  }

  if ($curr_el === 'not_found') {
    return $default !== false ? $default : false;
  }

  return $curr_el;
}

/**
 * Merges recursively array 2 in array 1
 */
function flex_array_merge_recursive(array $array1, array $array2) {
  $merged = $array1;

  foreach ($array2 as $key => &$value) {
    if (is_array($value) && isset($merged[$key]) && is_array($merged[$key])) {
      $merged[$key] = flex_array_merge_recursive($merged[$key], $value);
    } else if (is_numeric($key)) {
      if (!in_array($value, $merged)) {
        $merged[] = $value;
      }
    } else {
      $merged[$key] = $value;
    }
  }

  return $merged;
}

/**
 * The code that runs during plugin activation.
 * This action is documented in includes/class-flo-flex-builder-activator.php
 */
function activate_Flo_Flex_Builder() {
  require_once plugin_dir_path(__FILE__) . 'includes/class-flo-flex-builder-activator.php';
  Flo_Flex_Builder_Activator::activate();
}

/**
 * The code that runs during plugin update.
 * This action is documented in includes/class-flo-flex-builder-update.php
 * @param $upgrader_object Array
 * @param $options Array
 */

function flo_theme_upgrade_completed($upgrader_object, $options) {
  $allowed_themes = defined('FLEX_ALLOWED_THEMES') ? FLEX_ALLOWED_THEMES : [];

  delete_transient('stylekits_manifest');

  if ($options['action'] == 'update' && $options['type'] == 'theme' && isset($options['themes'])) {
    require_once plugin_dir_path(__FILE__) . 'includes/class-flo-flex-builder-update.php';
    foreach ($options['themes'] as $theme) {
      if (defined('IS_PHP_NOT_COPATIBLE') && IS_PHP_NOT_COPATIBLE) {
        if (strpos($allowed_themes, $searchNthemeame) !== false) {
          Flo_Flex_Builder_Update::handle_theme_update();
        }
      } else {
        if (in_array($theme, $allowed_themes)) {
          Flo_Flex_Builder_Update::handle_theme_update();
        }
      }
    }
  }
}
add_action('upgrader_process_complete', 'flo_theme_upgrade_completed', 10, 2);

/**
 * The code that runs during plugin deactivation.
 * This action is documented in includes/class-flo-flex-builder-deactivator.php
 */
function deactivate_Flo_Flex_Builder() {
  require_once plugin_dir_path(__FILE__) . 'includes/class-flo-flex-builder-deactivator.php';
  Flo_Flex_Builder_Deactivator::deactivate();
}

register_activation_hook(__FILE__, 'activate_Flo_Flex_Builder');
register_deactivation_hook(__FILE__, 'deactivate_Flo_Flex_Builder');

/**
 * The core plugin class that is used to define internationalization,
 * admin-specific hooks, and public-facing site hooks.
 */
require plugin_dir_path(__FILE__) . 'includes/class-flo-flex-builder.php';

/**
 * Begins execution of the plugin.
 *
 * Since everything within the plugin is registered via hooks,
 * then kicking off the plugin from this point in the file does
 * not affect the page life cycle.
 *
 * @since    1.0.0
 */
function run_Flo_Flex_Builder() {

  $plugin = new Flo_Flex_Builder();
  $plugin->run();
}
run_Flo_Flex_Builder();

add_action("admin_init", "include_flo_flex_builder_field");

if (!function_exists("include_flo_flex_builder_field")) {
  function include_flo_flex_builder_field() {
    include_once plugin_dir_path(__FILE__) . 'admin/partials/acf-flo-flex-builder/acf-flo-flex-builder.php';
  }
}

if (!function_exists("flex_meets_requirements")) {
  function flex_meets_requirements() {
    if (version_compare(phpversion(), '5.4.0', '<')) {
      return new WP_Error('broke', "Your current PHP version on the server is " . phpversion() . ". The minimum PHP version this plugin can work on is PHP 5.4.0. Please contact your hosting along this issue, or change the version in your cPanel.");
    }

    return true;
  }
}

// disable flex if current theme is not compatible with interface
add_action("admin_init", "flex_check_if_compatible", 1);
function flex_check_if_compatible() {
  $req = flex_meets_requirements();
  if (is_wp_error($req)) {
    require_once(ABSPATH . 'wp-admin/includes/plugin.php');
    deactivate_plugins(plugin_basename(__FILE__));
    header("Refresh:0");
    die($req->get_error_message());
  }
}

if (!function_exists('flex_get_theme')) {
  function flex_get_theme() {
    $active = wp_get_theme();
    $name = strtolower(str_replace(' Child', '', $active->Name));
    return $name;
  }
}

/**
 * Fallback for ACF get_field option, in case it's unninstalled
 */
if (!function_exists('flex_get_field')) {
  function flex_get_field($op, $source = 'options') {
    if (function_exists('get_field')) {
      return get_field($op, $source);
    }
    return false;
  }
}

if (!function_exists('flex_get_default_menu_id')) {
  function flex_get_default_menu_id() {
    $locations = get_nav_menu_locations();
    if (is_array($locations) && !empty($locations)) {
      return  array_values($locations)[0];
    }

    return false;
  }
}

/**
 * debug
 */

if (!function_exists('deb')) {

  function deb($data, $label = '') {

    print '<pre style="margin:10px; max-width: 90vw; border:1px dashed #999999; padding:10px; color:#333; background:#ffffff;">';
    $bt = debug_backtrace();
    $caller = array_shift($bt);

    print "--------------------------------------------------------------\n";
    if ($label) echo $label . ". ";
    echo "Data type: " . gettype($data) . ". Result below:\n";
    print_r($data);
    print "</pre>";
  }
}

if (!function_exists('debr')) {

  function debr($data) {
    print '<pre style="margin:10px; max-width: 70vw; margin-right: 165px; border:1px dashed #999999; padding:10px; color:#333; background:#ffffff; float: right; left: 234px; position: relative;">';
    $bt = debug_backtrace();
    $caller = array_shift($bt);

    print "--------------------------------------------------------------\n";
    print_r($data);
    print "</pre>";
  }
}

/**
 * Check if the theme activated is a classic ACF one
 */

if (!function_exists('is_classic_theme')) {
  function  is_classic_theme() {
    if (defined('_FLO_CORE_') && !defined('FLEX_THEME')) {
      return true;
    } else {
      return false;
    }
  }
}

/**
 * When image is cropped, take into consideration cases when images is far wider
 * then the image container. In this case, ignore container, and calculate ration between image and container
 */
function flex_get_image_width_patch($element_data) {
  $element_width = $element_data['elementWidth'];
  $element_height = $element_data['elementHeight'];

  if (isset($element_data['user_data']['cropImage']) && $element_data['user_data']['cropImage']) {
    // Increase width size by multiplying element height with image's real ratio
    if (
      isset($element_data['user_data']['imgSize']['w'])
      && isset($element_data['user_data']['imgSize']['h'])
      && (int) $element_data['user_data']['imgSize']['w'] > 0
      && (int) $element_data['user_data']['imgSize']['h'] > 0
    ) {

      $image_width = (int) $element_data['user_data']['imgSize']['w'];
      $image_height = (int) $element_data['user_data']['imgSize']['h'];
      $image_ratio = $image_width / $image_height;

      $mask_ratio = $element_data['elementWidth'] / $element_data['elementHeight'];

      $is_image_portrait = $image_ratio < 1;
      $is_image_landscape = $image_ratio > 1;

      $is_mask_portrait = $mask_ratio < 1;
      $is_mask_landscape = $mask_ratio > 1;
      $is_mask_square = $mask_ratio == 1;

      // For landscape
      if ($is_image_landscape) {
        if ($is_mask_square || $is_mask_portrait || ($is_mask_landscape && $mask_ratio < $image_ratio)) {
          $element_width = $element_height * $image_ratio;
        }
        // For portrait
      } else if ($is_image_portrait) {
        if ($is_mask_portrait && $mask_ratio < $image_ratio) {
          $element_width = $element_height * $image_ratio;
        }
      }
    }
  }

  return $element_width;
}
/**
 * Generates srcsets and size attributes for image tags
 * Skip size generation with "stopsizes" GET param
 *
 * @param array {$element} - original element data
 * @param array {$img_data} - results from flexGetImageUrl() function
 * @return string - image tag markup with srcsets and sizes attribute
 */
function flex_get_srcsets($element, $img_data = array()) {

  $markup = '';

  global $flex_desktop_font_size;
  global $flex_mobile_font_size;

  if (!isset($flex_desktop_font_size)) $flex_desktop_font_size = 1.25;
  if (!isset($flex_mobile_font_size))  $flex_mobile_font_size = ($flex_desktop_font_size * (1280 / 100)) / (375 / 100);

  if (!isset($_GET['stopsizes'])) {

    $element_width = flex_get_image_width_patch($element['data']);
    $mobile_element_width = $element_width;

    if (isset($element['mobile_element']['data']['elementWidth'])) {
      $mobile_element_width = flex_get_image_width_patch($element['mobile_element']['data']);
    }

    $sizes = 'sizes="(max-width: 767px) calc(' . $mobile_element_width . ' * ' . $flex_mobile_font_size . 'vw), calc(' . $element_width . ' * ' . $flex_desktop_font_size . 'vw)"';
    $markup .= $sizes;
  }

  $prevent_lazyload = isset($element['data']['user_data']['preventLazyload']) && $element['data']['user_data']['preventLazyload'];

  $prefix = $prevent_lazyload ? 'srcset' : 'data-srcset';

  if (isset($img_data['srcset']) && strlen($img_data['srcset'])) {
    $srcset = $prefix . '="' . $img_data['srcset'] . '"';
    $markup .= $srcset;
  }

  return $markup;
}

/**
 * Generate srcsets giving image size.
 * Add 'mobile_element' arr for mobile devices
 * 
 			$image_element = [
        'width' => $element['data']['elementWidth'],
        'height' =>  $element['data']['elementHeight'],
        'url' => $imageURL,
        'id' => isset($image['id']) ? $image['id'] : false
      ];
      if (isset($element['mobile_element'])) {
        $image_element['mobile_element'] = [
          'width' => $element['mobile_element']['data']['elementWidth'],
          'height' =>  $element['mobile_element']['data']['elementHeight'],
          'url' => $imageURL,
          'id' => isset($image['id']) ? $image['id'] : false
        ];
      }
			$img_srcsets = flex_get_image_srcsets_size_tags($image_element);
 */
function flex_get_image_srcsets_size_tags($data_arr) {

  if (!isset($data_arr['width']) || !isset($data_arr['height']) || !isset($data_arr['url'])) return '';

  $image_element = [
    'data' => [
      'elementWidth' => $data_arr['width'],
      'elementHeight' => $data_arr['height'],
      'user_data' => [
        'backgroundImage' => $data_arr['url'],
        'imgId' => isset($data_arr['id']) ? $data_arr['id'] : false,
        'cropImage' => false,
      ],
    ]
  ];

  if (isset($data_arr['mobile_element'])) {
    $image_element['mobile_element'] = [
      'data' => [
        'elementWidth' => $data_arr['mobile_element']['width'], // $element['data']['elementWidth'],
        'elementHeight' => $data_arr['mobile_element']['height'], // $element['data']['elementHeight'],
        'user_data' => [
          'backgroundImage' => $data_arr['mobile_element']['url'],
          'imgId' => isset($data_arr['mobile_element']['id']) ? $data_arr['mobile_element']['id'] : false,
          'cropImage' => false,
        ],
      ]
    ];
  }

  $img_data = flexGetImageUrl($image_element);

  $img_srcsets = '';
  if (isset($img_data['srcset']) && strlen($img_data['srcset'])) {
    $img_srcsets = flex_get_srcsets($image_element, $img_data);
  }
  return $img_srcsets;
}

add_action("init", "flex_stylekits_manifest");
function flex_stylekits_manifest() {
  if (defined('FLEX_SHOW_CASE')) {
    delete_transient('stylekits_manifest');
  }

  if (false ===  get_transient('stylekits_manifest')) {
    $url = S3_FLEX_BUCKET_ENDPOINT . '/stylekits/blocks_library/manifest.json';
    $manifest_blocks = fetch_manifest_from_avs($url);
    set_transient('stylekits_manifest', $manifest_blocks, 24 * HOUR_IN_SECONDS);

    $all_s = get_option('flex_all_stylekits_obj') ? get_option('flex_all_stylekits_obj') :  [];
    $all_s['manifest']['blocks'] = $manifest_blocks;
    update_option('flex_all_stylekits_obj', $all_s);
  }
};

function fetch_manifest_from_avs($url) {

  $request = wp_safe_remote_get($url);

  /**
   * Get response code of the request.
   */
  $response_code = wp_remote_retrieve_response_code($request);

  /**
   * Check if request is not valid and return the $transient.
   * Otherwise get the data body.
   */
  if (is_wp_error($request) || 200 !== $response_code) {
    return;
  } else {
    $response = wp_remote_retrieve_body($request);
  }

  /**
   * Decode json.
   */
  $data = json_decode($response);


  if (isset($data)) {
    return ($data);
  }

  return false;
}
