<commit_before><?php
/**
 * Represents release objects.
 *
 * @author <NAME>
 * @since  1.0
 */

namespace ITELIC;

use IronBound\Cache\Cache;
use IronBound\DB\Model;
use IronBound\DB\Table\Table;
use IronBound\DB\Manager;
use IronBound\DB\Exception as DB_Exception;
use ITELIC_API\Query\Activations;
use ITELIC_API\Query\Releases;
use ITELIC_API\Query\Updates;

/**
 * Class Release
 *
 * @package ITELIC
 */
class Release extends Model {

	/**
	 * Major releases. 1.5 -> 1.6
	 */
	const TYPE_MAJOR = 'major';

	/**
	 * Minor, bug fixing releases. 1.5.3 -> 1.5.4
	 */
	const TYPE_MINOR = 'minor';

	/**
	 * Security releases. Follows minor release version number syntax.
	 */
	const TYPE_SECURITY = 'security';

	/**
	 * Pre-releases. Alpha, beta, etc...
	 */
	const TYPE_PRERELEASE = 'pre-release';

	/**
	 * Restricted releases. Only distributed to a subset of customers.
	 */
	const TYPE_RESTRICTED = 'restricted';

	/**
	 * Draft status. Default. Not yet available.
	 */
	const STATUS_DRAFT = 'draft';

	/**
	 * Active releases.
	 */
	const STATUS_ACTIVE = 'active';

	/**
	 * A paused release.
	 */
	const STATUS_PAUSED = 'paused';

	/**
	 * An archived release.
	 */
	const STATUS_ARCHIVED = 'archived';

	/**
	 * @var int
	 */
	private $ID;

	/**
	 * @var Product
	 */
	private $product;

	/**
	 * @var int
	 */
	private $download;

	/**
	 * @var string
	 */
	private $version;

	/**
	 * @var string
	 */
	private $status;

	/**
	 * @var string
	 */
	private $type;

	/**
	 * @var string
	 */
	private $changelog;

	/**
	 * @var \DateTime|null
	 */
	private $start_date;

	/**
	 * Constructor.
	 *
	 * @param \stdClass $data
	 */
	public function __construct( \stdClass $data ) {
		$this->init( $data );
	}

	/**
	 * Init an object.
	 *
	 * @since 1.0
	 *
	 * @param \stdClass $data
	 */
	protected function init( \stdClass $data ) {
		$this->ID      = $data->ID;
		$this->product = itelic_get_product( $data->product );

		if ( ! $this->product ) {
			throw new \InvalidArgumentException( "Invalid product." );
		}

		$this->download = (int) $data->download;
		$this->version  = $data->version;

		if ( array_key_exists( $data->status, self::get_statuses() ) ) {
			$this->status = $data->status;
		} else {
			throw new \InvalidArgumentException( "Invalid status." );
		}

		if ( array_key_exists( $data->type, self::get_types() ) ) {
			$this->type = $data->type;
		} else {
			throw new \InvalidArgumentException( "Invalid type." );
		}

		$this->changelog = $data->changelog;

		if ( $data->start_date && $data->start_date != '0000-00-00 00:00:00' ) {
			$this->start_date = new \DateTime( $data->start_date );
		}
	}

	/**
	 * Create a new release record.
	 *
	 * If status is set to active, the start date will automatically be set to
	 * now.
	 *
	 * @since 1.0
	 *
	 * @param \IT_Exchange_Product $product
	 * @param \WP_Post             $file Attachment of the download
	 * @param string               $version
	 * @param string               $type
	 * @param string               $status
	 * @param string               $changelog
	 *
	 * @return Release|null
	 * @throws DB_Exception
	 */
	public static function create( \IT_Exchange_Product $product, \WP_Post $file, $version, $type, $status = '', $changelog = '' ) {

		if ( empty( $status ) ) {
			$status = self::STATUS_DRAFT;
		}

		if ( ! array_key_exists( $status, self::get_statuses() ) ) {
			throw new \InvalidArgumentException( "Invalid status." );
		}

		if ( ! array_key_exists( $type, self::get_types() ) ) {
			throw new \InvalidArgumentException( "Invalid type." );
		}

		if ( get_post_type( $file ) != 'attachment' ) {
			throw new \InvalidArgumentException( "Invalid update file." );
		}

		if ( ! it_exchange_product_has_feature( $product->ID, 'licensing' ) ) {
			throw new \InvalidArgumentException( "Product given does not have the licensing feature enabled." );
		}

		$current_version = it_exchange_get_product_feature( $product->ID, 'licensing', array( 'field' => 'version' ) );

		if ( version_compare( $version, $current_version, '<=' ) ) {
			throw new \InvalidArgumentException( "New release version must be greater than the current product's version." );
		}

		$data = array(
			'product'   => $product->ID,
			'download'  => $file->ID,
			'version'   => $version,
			'type'      => $type,
			'status'    => $status,
			'changelog' => wp_kses_post( $changelog )
		);

		if ( $status == self::STATUS_ACTIVE ) {
			$data['start_date'] = current_time( 'mysql' );
		}

		$db = Manager::make_simple_query_object( 'itelic-releases' );
		$ID = $db->insert( $data );

		$release = self::get( $ID );

		if ( $release ) {

			/**
			 * Fires when a release is created.
			 *
			 * @since 1.0
			 *
			 * @param Release $release
			 */
			do_action( 'itelic_create_release', $release );

			if ( $status == self::STATUS_ACTIVE ) {

				/**
				 * Fires when a release is activated.
				 *
				 * @since 1.0
				 *
				 * @param Release $release
				 */
				do_action( 'itelic_activate_release', $release );

				if ( $type != self::TYPE_PRERELEASE ) {
					self::do_activation( $product, $file, $version );
				}
			}

			if ( in_array( $status, array( self::STATUS_ACTIVE, self::STATUS_ARCHIVED ) ) ) {
				wp_cache_delete( $product->ID, 'itelic-changelog' );
			}

			Cache::add( $release );
		}

		return $release;
	}

	/**
	 * Perform the activation.
	 *
	 * Updates the version in product meta, and store the previous version.
	 * Updates the file in the download meta, and store the previous file.
	 *
	 * @since 1.0
	 *
	 * @param \IT_Exchange_Product $product
	 * @param \WP_Post             $file
	 * @param string               $version
	 */
	protected static function do_activation( \IT_Exchange_Product $product, \WP_Post $file, $version ) {

		$download_id   = it_exchange_get_product_feature( $product->ID, 'licensing', array( 'field' => 'update-file' ) );
		$download_data = get_post_meta( $download_id, '_it-exchange-download-info', true );

		// update the download url
		$download_data['source'] = wp_get_attachment_url( $file->ID );

		// save the new download
		update_post_meta( $download_id, '_it-exchange-download-info', $download_data );

		it_exchange_update_product_feature( $product->ID, 'licensing', array(
			'version' => $version
		) );
	}

	/**
	 * Activate this release.
	 *
	 * @since 1.0
	 */
	public function activate() {

		if ( $this->status != self::STATUS_ACTIVE ) {
			$this->status = self::STATUS_ACTIVE;
			$this->update( 'status', self::STATUS_ACTIVE );
		}

		if ( ! $this->get_start_date() ) {
			$this->set_start_date( new \DateTime() );
		}

		if ( $this->get_type() != self::TYPE_PRERELEASE ) {
			self::do_activation( $this->get_product(), $this->get_download(), $this->get_version() );
		}

		wp_cache_delete( $this->get_product()->ID, 'itelic-changelog' );

		/**
		 * Fires when a release is activated.
		 *
		 * @since 1.0
		 *
		 * @param Release $this
		 */
		do_action( 'itelic_activate_release', $this );
	}

	/**
	 * Pause this release.
	 *
	 * @since 1.0
	 */
	public function pause() {

		$current_version = it_exchange_get_product_feature( $this->get_product()->ID, 'licensing', array( 'field' => 'version' ) );

		if ( version_compare( $this->get_version(), $current_version, '<=' ) && $this->get_type() != self::TYPE_PRERELEASE ) {
			throw new \InvalidArgumentException( "New release version must be greater than the current product's version." );
		}

		if ( $this->status != self::STATUS_PAUSED ) {
			$this->status = self::STATUS_PAUSED;
			$this->update( 'status', self::STATUS_PAUSED );
		}

		if ( $this->get_type() != self::TYPE_PRERELEASE ) {

			$query = new Releases( array(
				'items_per_page'      => 1,
				'page'                => 1,
				'sql_calc_found_rows' => false,
				'product'             => $this->get_product()->ID,
				'type'                => array( self::TYPE_MAJOR, self::TYPE_MINOR, self::TYPE_SECURITY ),
				'status'              => array( self::STATUS_ACTIVE, self::STATUS_ARCHIVED ),
				'order'               => array(<commit_msg>Remove bad check for version number before pausing<commit_after><?php
/**
 * Represents release objects.
 *
 * @author <NAME>
 * @since  1.0
 */

namespace ITELIC;

use IronBound\Cache\Cache;
use IronBound\DB\Model;
use IronBound\DB\Table\Table;
use IronBound\DB\Manager;
use IronBound\DB\Exception as DB_Exception;
use ITELIC_API\Query\Activations;
use ITELIC_API\Query\Releases;
use ITELIC_API\Query\Updates;

/**
 * Class Release
 *
 * @package ITELIC
 */
class Release extends Model {

	/**
	 * Major releases. 1.5 -> 1.6
	 */
	const TYPE_MAJOR = 'major';

	/**
	 * Minor, bug fixing releases. 1.5.3 -> 1.5.4
	 */
	const TYPE_MINOR = 'minor';

	/**
	 * Security releases. Follows minor release version number syntax.
	 */
	const TYPE_SECURITY = 'security';

	/**
	 * Pre-releases. Alpha, beta, etc...
	 */
	const TYPE_PRERELEASE = 'pre-release';

	/**
	 * Restricted releases. Only distributed to a subset of customers.
	 */
	const TYPE_RESTRICTED = 'restricted';

	/**
	 * Draft status. Default. Not yet available.
	 */
	const STATUS_DRAFT = 'draft';

	/**
	 * Active releases.
	 */
	const STATUS_ACTIVE = 'active';

	/**
	 * A paused release.
	 */
	const STATUS_PAUSED = 'paused';

	/**
	 * An archived release.
	 */
	const STATUS_ARCHIVED = 'archived';

	/**
	 * @var int
	 */
	private $ID;

	/**
	 * @var Product
	 */
	private $product;

	/**
	 * @var int
	 */
	private $download;

	/**
	 * @var string
	 */
	private $version;

	/**
	 * @var string
	 */
	private $status;

	/**
	 * @var string
	 */
	private $type;

	/**
	 * @var string
	 */
	private $changelog;

	/**
	 * @var \DateTime|null
	 */
	private $start_date;

	/**
	 * Constructor.
	 *
	 * @param \stdClass $data
	 */
	public function __construct( \stdClass $data ) {
		$this->init( $data );
	}

	/**
	 * Init an object.
	 *
	 * @since 1.0
	 *
	 * @param \stdClass $data
	 */
	protected function init( \stdClass $data ) {
		$this->ID      = $data->ID;
		$this->product = itelic_get_product( $data->product );

		if ( ! $this->product ) {
			throw new \InvalidArgumentException( "Invalid product." );
		}

		$this->download = (int) $data->download;
		$this->version  = $data->version;

		if ( array_key_exists( $data->status, self::get_statuses() ) ) {
			$this->status = $data->status;
		} else {
			throw new \InvalidArgumentException( "Invalid status." );
		}

		if ( array_key_exists( $data->type, self::get_types() ) ) {
			$this->type = $data->type;
		} else {
			throw new \InvalidArgumentException( "Invalid type." );
		}

		$this->changelog = $data->changelog;

		if ( $data->start_date && $data->start_date != '0000-00-00 00:00:00' ) {
			$this->start_date = new \DateTime( $data->start_date );
		}
	}

	/**
	 * Create a new release record.
	 *
	 * If status is set to active, the start date will automatically be set to
	 * now.
	 *
	 * @since 1.0
	 *
	 * @param \IT_Exchange_Product $product
	 * @param \WP_Post             $file Attachment of the download
	 * @param string               $version
	 * @param string               $type
	 * @param string               $status
	 * @param string               $changelog
	 *
	 * @return Release|null
	 * @throws DB_Exception
	 */
	public static function create( \IT_Exchange_Product $product, \WP_Post $file, $version, $type, $status = '', $changelog = '' ) {

		if ( empty( $status ) ) {
			$status = self::STATUS_DRAFT;
		}

		if ( ! array_key_exists( $status, self::get_statuses() ) ) {
			throw new \InvalidArgumentException( "Invalid status." );
		}

		if ( ! array_key_exists( $type, self::get_types() ) ) {
			throw new \InvalidArgumentException( "Invalid type." );
		}

		if ( get_post_type( $file ) != 'attachment' ) {
			throw new \InvalidArgumentException( "Invalid update file." );
		}

		if ( ! it_exchange_product_has_feature( $product->ID, 'licensing' ) ) {
			throw new \InvalidArgumentException( "Product given does not have the licensing feature enabled." );
		}

		$current_version = it_exchange_get_product_feature( $product->ID, 'licensing', array( 'field' => 'version' ) );

		if ( version_compare( $version, $current_version, '<=' ) ) {
			throw new \InvalidArgumentException( "New release version must be greater than the current product's version." );
		}

		$data = array(
			'product'   => $product->ID,
			'download'  => $file->ID,
			'version'   => $version,
			'type'      => $type,
			'status'    => $status,
			'changelog' => wp_kses_post( $changelog )
		);

		if ( $status == self::STATUS_ACTIVE ) {
			$data['start_date'] = current_time( 'mysql' );
		}

		$db = Manager::make_simple_query_object( 'itelic-releases' );
		$ID = $db->insert( $data );

		$release = self::get( $ID );

		if ( $release ) {

			/**
			 * Fires when a release is created.
			 *
			 * @since 1.0
			 *
			 * @param Release $release
			 */
			do_action( 'itelic_create_release', $release );

			if ( $status == self::STATUS_ACTIVE ) {

				/**
				 * Fires when a release is activated.
				 *
				 * @since 1.0
				 *
				 * @param Release $release
				 */
				do_action( 'itelic_activate_release', $release );

				if ( $type != self::TYPE_PRERELEASE ) {
					self::do_activation( $product, $file, $version );
				}
			}

			if ( in_array( $status, array( self::STATUS_ACTIVE, self::STATUS_ARCHIVED ) ) ) {
				wp_cache_delete( $product->ID, 'itelic-changelog' );
			}

			Cache::add( $release );
		}

		return $release;
	}

	/**
	 * Perform the activation.
	 *
	 * Updates the version in product meta, and store the previous version.
	 * Updates the file in the download meta, and store the previous file.
	 *
	 * @since 1.0
	 *
	 * @param \IT_Exchange_Product $product
	 * @param \WP_Post             $file
	 * @param string               $version
	 */
	protected static function do_activation( \IT_Exchange_Product $product, \WP_Post $file, $version ) {

		$download_id   = it_exchange_get_product_feature( $product->ID, 'licensing', array( 'field' => 'update-file' ) );
		$download_data = get_post_meta( $download_id, '_it-exchange-download-info', true );

		// update the download url
		$download_data['source'] = wp_get_attachment_url( $file->ID );

		// save the new download
		update_post_meta( $download_id, '_it-exchange-download-info', $download_data );

		it_exchange_update_product_feature( $product->ID, 'licensing', array(
			'version' => $version
		) );
	}

	/**
	 * Activate this release.
	 *
	 * @since 1.0
	 */
	public function activate() {

		if ( $this->status != self::STATUS_ACTIVE ) {
			$this->status = self::STATUS_ACTIVE;
			$this->update( 'status', self::STATUS_ACTIVE );
		}

		if ( ! $this->get_start_date() ) {
			$this->set_start_date( new \DateTime() );
		}

		if ( $this->get_type() != self::TYPE_PRERELEASE ) {
			self::do_activation( $this->get_product(), $this->get_download(), $this->get_version() );
		}

		wp_cache_delete( $this->get_product()->ID, 'itelic-changelog' );

		/**
		 * Fires when a release is activated.
		 *
		 * @since 1.0
		 *
		 * @param Release $this
		 */
		do_action( 'itelic_activate_release', $this );
	}

	/**
	 * Pause this release.
	 *
	 * @since 1.0
	 */
	public function pause() {

		if ( $this->status != self::STATUS_PAUSED ) {
			$this->status = self::STATUS_PAUSED;
			$this->update( 'status', self::STATUS_PAUSED );
		}

		if ( $this->get_type() != self::TYPE_PRERELEASE ) {

			$query = new Releases( array(
				'items_per_page'      => 1,
				'page'                => 1,
				'sql_calc_found_rows' => false,
				'product'             => $this->get_product()->ID,
				'type'                => array( self::TYPE_MAJOR, self::TYPE_MINOR, self::TYPE_SECURITY ),
				'status'              => array( self::STATUS_ACTIVE, self::STATUS_ARCHIVED ),
				'order'               => array(
{'fraction_non_alphanumeric': 0.15963069086278256, 'fraction_numerical': 0.005603311047437122, 'mean_word_length': 2.892441140024783, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 142, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 34, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3342224', 'n_tokens_mistral': 6017, 'n_tokens_neox': 5189, 'n_words': 1231}