<commit_before><?php
namespace verbb\feedme\elements;

use verbb\feedme\base\Element;
use verbb\feedme\base\ElementInterface;
use verbb\feedme\events\FeedProcessEvent;
use verbb\feedme\helpers\AssetHelper;
use verbb\feedme\helpers\DuplicateHelper;
use verbb\feedme\services\Process;

use Craft;
use craft\db\Query;
use craft\elements\Asset as AssetElement;
use craft\helpers\Assets as AssetsHelper;
use craft\helpers\UrlHelper;

use yii\base\Event;
use Cake\Utility\Hash;

class Asset extends Element implements ElementInterface
{
    // Properties
    // =========================================================================

    public static $name = 'Asset';
    public static $class = 'craft\elements\Asset';

    public $element;


    // Templates
    // =========================================================================

    public function getGroupsTemplate()
    {
        return 'feed-me/_includes/elements/asset/groups';
    }

    public function getColumnTemplate()
    {
        return 'feed-me/_includes/elements/asset/column';
    }

    public function getMappingTemplate()
    {
        return 'feed-me/_includes/elements/asset/map';
    }


    // Public Methods
    // =========================================================================

    public function init()
    {
        // If we are adding a new asset, it has to be done before the content is populated on the element.
        // We of course, want content to be populated on the newly-created element, not one that won't be uploaded
        Event::on(Process::class, Process::EVENT_STEP_BEFORE_PARSE_CONTENT, function(FeedProcessEvent $event) {
            $this->_handleImageCreation($event);
        });
    }

    public function getGroups()
    {
        return Craft::$app->volumes->getAllVolumes();
    }

    public function getQuery($settings, $params = [])
    {
        $query = AssetElement::find();

        $criteria = array_merge([
            'status' => null,
            'volumeId' => $settings['elementGroup'][AssetElement::class],
            'includeSubfolders' => true,
        ], $params);

        $siteId = Hash::get($settings, 'siteId');

        if ($siteId) {
            $criteria['siteId'] = $siteId;
        }

        Craft::configure($query, $criteria);

        return $query;
    }

    public function setModel($settings)
    {
        $this->element = new AssetElement();
        $this->element->volumeId = $settings['elementGroup'][AssetElement::class];

        $siteId = Hash::get($settings, 'siteId');

        if ($siteId) {
            $this->element->siteId = $siteId;
        }

        return $this->element;
    }

    public function beforeSave($element, $settings)
    {
        parent::beforeSave($element, $settings);

        // If we don't have an ID for this element, we don't want to continue. The reason is that we only want Feed Me to 
        // update an asset, not create a new one. Instead, asset-creation (upload from remote) is handled earlier in processing.
        // If this were to proceed, we'd get invalid assets created.
        if (!$element->id) {
            return false;
        }

        return true;
    }


    // Private Methods
    // =========================================================================

    private function _handleImageCreation($event)
    {
        $feed = $event->feed;
        $feedData = $event->feedData;

        // If we're not adding new assets, skip this altogether
        if (!DuplicateHelper::isAdd($feed)) {
            return;
        }

        $fieldInfo = $feed['fieldMapping']['urlOrPath'] ?? [];

        // Just in case...
        if (!$fieldInfo) {
            return;
        }

        $value = $this->fetchSimpleValue($feedData, $fieldInfo);
        $folderId = $this->parseFolderId($feedData, $fieldInfo);

        $conflict = Hash::get($fieldInfo, 'options.conflict');
        
        // Do we want to match existing element? If one exists, we need to set our element to be that
        if ($conflict === AssetElement::SCENARIO_INDEX) {
            // Make sure to parse the URL into a filename to find the asset by
            $filename = $this->_getFilename($value);

            $filename = AssetsHelper::prepareAssetName($filename);

            $foundElement = AssetElement::find()
                ->folderId($folderId)<commit_msg>Fix assets not actually using the correct folder mapping config<commit_after><?php
namespace verbb\feedme\elements;

use verbb\feedme\base\Element;
use verbb\feedme\base\ElementInterface;
use verbb\feedme\events\FeedProcessEvent;
use verbb\feedme\helpers\AssetHelper;
use verbb\feedme\helpers\DuplicateHelper;
use verbb\feedme\services\Process;

use Craft;
use craft\db\Query;
use craft\elements\Asset as AssetElement;
use craft\helpers\Assets as AssetsHelper;
use craft\helpers\UrlHelper;

use yii\base\Event;
use Cake\Utility\Hash;

class Asset extends Element implements ElementInterface
{
    // Properties
    // =========================================================================

    public static $name = 'Asset';
    public static $class = 'craft\elements\Asset';

    public $element;


    // Templates
    // =========================================================================

    public function getGroupsTemplate()
    {
        return 'feed-me/_includes/elements/asset/groups';
    }

    public function getColumnTemplate()
    {
        return 'feed-me/_includes/elements/asset/column';
    }

    public function getMappingTemplate()
    {
        return 'feed-me/_includes/elements/asset/map';
    }


    // Public Methods
    // =========================================================================

    public function init()
    {
        // If we are adding a new asset, it has to be done before the content is populated on the element.
        // We of course, want content to be populated on the newly-created element, not one that won't be uploaded
        Event::on(Process::class, Process::EVENT_STEP_BEFORE_PARSE_CONTENT, function(FeedProcessEvent $event) {
            $this->_handleImageCreation($event);
        });
    }

    public function getGroups()
    {
        return Craft::$app->volumes->getAllVolumes();
    }

    public function getQuery($settings, $params = [])
    {
        $query = AssetElement::find();

        $criteria = array_merge([
            'status' => null,
            'volumeId' => $settings['elementGroup'][AssetElement::class],
            'includeSubfolders' => true,
        ], $params);

        $siteId = Hash::get($settings, 'siteId');

        if ($siteId) {
            $criteria['siteId'] = $siteId;
        }

        Craft::configure($query, $criteria);

        return $query;
    }

    public function setModel($settings)
    {
        $this->element = new AssetElement();
        $this->element->volumeId = $settings['elementGroup'][AssetElement::class];

        $siteId = Hash::get($settings, 'siteId');

        if ($siteId) {
            $this->element->siteId = $siteId;
        }

        return $this->element;
    }

    public function beforeSave($element, $settings)
    {
        parent::beforeSave($element, $settings);

        // If we don't have an ID for this element, we don't want to continue. The reason is that we only want Feed Me to 
        // update an asset, not create a new one. Instead, asset-creation (upload from remote) is handled earlier in processing.
        // If this were to proceed, we'd get invalid assets created.
        if (!$element->id) {
            return false;
        }

        return true;
    }


    // Private Methods
    // =========================================================================

    private function _handleImageCreation($event)
    {
        $feed = $event->feed;
        $feedData = $event->feedData;

        // If we're not adding new assets, skip this altogether
        if (!DuplicateHelper::isAdd($feed)) {
            return;
        }

        $fieldInfo = $feed['fieldMapping']['urlOrPath'] ?? [];

        // Just in case...
        if (!$fieldInfo) {
            return;
        }

        $folderIdInfo = $feed['fieldMapping']['folderId'] ?? [];

        $value = $this->fetchSimpleValue($feedData, $fieldInfo);
        $folderId = $this->parseFolderId($feedData, $folderIdInfo);

        $conflict = Hash::get($fieldInfo, 'options.conflict');
        
        // Do we want to match existing element? If one exists, we need to set our element to be that
        if ($conflict === AssetElement::SCENARIO_INDEX) {
            // Make sure to parse the URL into a filename to find the asset by
            $filename = $this->_getFilename($value);

            $filename = AssetsHelper::prepareAssetName($filename);

            $foundElement = AssetElement::find()
                ->folderId($folderId)
{'fraction_non_alphanumeric': 0.1785512487286699, 'fraction_numerical': 0.0, 'mean_word_length': 2.627049180327869, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 41, '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': '5794785', 'n_tokens_mistral': 2404, 'n_tokens_neox': 2285, 'n_words': 624}