<commit_before><?php namespace Bkwld\Decoy\Models;

// Deps
use Croppa;
use Bkwld\Decoy\Markup\ImageElement;

/**
 * Polymorphic one to many class that stores images for any model.
 */
class Image extends Base {

	/**
	 * JSON serialization
	 *
	 * @var array
	 */
	protected $visible = ['low', 'medium', 'high', 'background_position', 'title'];
	protected $appends = ['low', 'medium', 'high', 'background_position'];

	/**
	 * The attributes that should be cast to native types.
	 *
	 * @var array
	 */
	protected $casts = [
		'file_size'   => 'integer',
		'width'       => 'integer',
		'height'      => 'integer',
		'crop'        => 'object',
		'focal_point' => 'object',
	];

	/**
	 * Validation rules
	 *
	 * @return array
	 */
	public static $rules = [
		'file' => 'image',
	];

	/**
	 * Uploadable attributes
	 *
	 * @var array
	 */
	protected $upload_attributes = ['file'];

	/**
	 * Stores config from chained transformations while a url or tag is generated
	 *
	 * @var array
	 */
	private $config = [];

	/**
	 * Register events
	 *
	 * @return void
	 */
	protected static function boot() {
		parent::boot();

		// Need to process file meta before Upchuck converts the UploadFile object
		// to a URL string
		static::saving(function(Image $image) {
			$image->populateFileMeta();
		}, config('upchuck.priority', 0) + 1);
	}

	/**
	 * Polymorphic relationship
	 */
	public function imageable() { return $this->morphTo(); }

	/**
	 * Store file meta info in the database
	 *
	 * @return void
	 */
	public function populateFileMeta() {
		$file = $this->getAttributeValue('file');
		$size = getimagesize($file->getPathname());
		$this->fill([
			'file_type' => $this->guessFileType($file),
			'file_size' => $file->getSize(),
			'width'     => $size[0],
			'height'    => $size[1],
		]);
	}

	/**
	 * Get file type
	 *
	 * @param Symfony\Component\HttpFoundation\File\UploadedFile
	 * @return string
	 */
	protected function guessFileType($file) {
		$type = $file->guessClientExtension();
		switch($type) {
			case 'jpeg': return 'jpg';
			default: return $type;
		}
	}

	/**
	 * Set the crop dimenions<commit_msg>Deleting crops and images when the image is nulled<commit_after><?php namespace Bkwld\Decoy\Models;

// Deps
use Croppa;
use Bkwld\Decoy\Markup\ImageElement;

/**
 * Polymorphic one to many class that stores images for any model.
 */
class Image extends Base {

	/**
	 * JSON serialization
	 *
	 * @var array
	 */
	protected $visible = ['low', 'medium', 'high', 'background_position', 'title'];
	protected $appends = ['low', 'medium', 'high', 'background_position'];

	/**
	 * The attributes that should be cast to native types.
	 *
	 * @var array
	 */
	protected $casts = [
		'file_size'   => 'integer',
		'width'       => 'integer',
		'height'      => 'integer',
		'crop'        => 'object',
		'focal_point' => 'object',
	];

	/**
	 * Validation rules
	 *
	 * @return array
	 */
	public static $rules = [
		'file' => 'image',
	];

	/**
	 * Uploadable attributes
	 *
	 * @var array
	 */
	protected $upload_attributes = ['file'];

	/**
	 * Stores config from chained transformations while a url or tag is generated
	 *
	 * @var array
	 */
	private $config = [];

	/**
	 * Register events
	 *
	 * @return void
	 */
	protected static function boot() {
		parent::boot();

		// Need to process file meta before Upchuck converts the UploadFile object
		// to a URL string.  If the image file attribute has been set to empty,
		// stop the save and immediately delete.
		static::saving(function(Image $image) {
			if ($image->deletedBecauseEmpty()) return false;
			$image->populateFileMeta();
		}, config('upchuck.priority', 0) + 1);

		// If the image is deleted, delete Croppa crops
		static::updating(function(Image $image) {
			if ($image->isDirty('file')) $image->deleteCrops();
		});
		static::deleted(function(Image $image) {
			$image->deleteCrops();
		});
	}

	/**
	 * Polymorphic relationship
	 */
	public function imageable() { return $this->morphTo(); }

	/**
	 * If the file attribtue is empty, this Image has been marked for deletion.
	 * Return true to signal the image was deleted
	 *
	 * @return bool
	 */
	public function deletedBecauseEmpty() {
		if ($file = $this->getAttributeValue('file')) return false;
		if ($this->exists) $this->delete();
		return true;
	}

	/**
	 * Store file meta info in the database
	 *
	 * @return void
	 */
	public function populateFileMeta() {
		$file = $this->getAttributeValue('file');
		$size = getimagesize($file->getPathname());
		$this->fill([
			'file_type' => $this->guessFileType($file),
			'file_size' => $file->getSize(),
			'width'     => $size[0],
			'height'    => $size[1],
		]);
	}

	/**
	 * Delete the crops that Croppa has made for the image
	 *
	 * @return void
	 */
	public function deleteCrops() {

		// Get at the file path using "original" so this function can be called as
		// part of an "updating" callback
		$file = $this->getOriginal('file');

		// Tell Croppa to delete the crops
		Croppa::reset($file);
	}

	/**
	 * Get file type
	 *
	 * @param Symfony\Component\HttpFoundation\File\UploadedFile
	 * @return string
	 */
	protected function guessFileType($file) {
		$type = $file->guessClientExtension();
		switch($type) {
			case 'jpeg': return 'jpg';
			default: return $type;
		}
	}

	/**
	 * Set the crop dimenions
{'fraction_non_alphanumeric': 0.1588855421686747, 'fraction_numerical': 0.0015060240963855422, 'mean_word_length': 3.1834645669291337, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 47, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5751734', 'n_tokens_mistral': 1881, 'n_tokens_neox': 1656, 'n_words': 484}