Skip to content

Commit

Permalink
add support for custom sources
Browse files Browse the repository at this point in the history
  • Loading branch information
i-just committed Sep 2, 2024
1 parent e28b876 commit 7192dc1
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 37 deletions.
38 changes: 34 additions & 4 deletions src/fields/Categories.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@
use Craft;
use craft\base\Element as BaseElement;
use craft\elements\Category as CategoryElement;
use craft\elements\conditions\ElementConditionInterface;
use craft\feedme\base\Field;
use craft\feedme\base\FieldInterface;
use craft\feedme\helpers\DataHelper;
use craft\feedme\Plugin;
use craft\fields\Categories as CategoriesField;
use craft\helpers\ArrayHelper;
use craft\helpers\Db;
use craft\helpers\ElementHelper;
use craft\helpers\Json;
use craft\services\ElementSources;

/**
*
Expand Down Expand Up @@ -90,9 +94,19 @@ public function parseField(): mixed
$node = Hash::get($this->fieldInfo, 'node');
$nodeKey = null;

$groupId = null;
$customSource = null;
// Get source id's for connecting
[, $groupUid] = explode(':', $source);
$groupId = Db::idByUid('{{%categorygroups}}', $groupUid);
if (str_starts_with($source, 'custom:')) {
$customSource = ElementHelper::findSource(CategoryElement::class, $source, ElementSources::CONTEXT_FIELD);
// make sure $create is nullified; we don't want to create categories for custom sources
// because of ensuring all the conditions are met
// for example, if there's condition level == 2, then how do we ensure that and (more importantly) how do we choose a parent
$create = null;
} else {
[, $groupUid] = explode(':', $source);
$groupId = Db::idByUid('{{%categorygroups}}', $groupUid);
}

$foundElements = [];

Expand Down Expand Up @@ -140,13 +154,29 @@ public function parseField(): mixed
}

$criteria['status'] = null;
$criteria['groupId'] = $groupId;
$criteria['limit'] = $limit;
$criteria['where'] = ['=', $columnName, $dataValue];

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

Plugin::info('Search for existing category with query `{i}`', ['i' => Json::encode($criteria)]);
if (!empty($customSource)) {
$conditionsService = Craft::$app->getConditions();
/** @var ElementConditionInterface $sourceCondition */
$sourceCondition = $conditionsService->createCondition($customSource['condition']);
$sourceCondition->modifyQuery($query);
}

// we're getting the criteria from conditions now too, so they are not included in the $criteria array;
// so, we get all the query criteria, filter out any empty or boolean ones and only show the ones that look to be filled out
$showCriteria = $criteria;
$allCriteria = $query->getCriteria();
foreach ($allCriteria as $key => $criterion) {
if (!empty($criterion) && !is_bool($criterion)) {
$showCriteria[$key] = $criterion;
}
}

Plugin::info('Search for existing category with query `{i}`', ['i' => Json::encode($showCriteria)]);

$ids = $query->ids();

Expand Down
48 changes: 44 additions & 4 deletions src/fields/Entries.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Cake\Utility\Hash;
use Craft;
use craft\base\Element as BaseElement;
use craft\elements\conditions\ElementConditionInterface;
use craft\elements\Entry as EntryElement;
use craft\errors\ElementNotFoundException;
use craft\feedme\base\Field;
Expand All @@ -13,7 +14,9 @@
use craft\feedme\Plugin;
use craft\fields\Entries as EntriesField;
use craft\helpers\Db;
use craft\helpers\ElementHelper;
use craft\helpers\Json;
use craft\services\ElementSources;
use Throwable;
use yii\base\Exception;

Expand Down Expand Up @@ -94,6 +97,7 @@ public function parseField(): mixed
$nodeKey = null;

$sectionIds = [];
$customSources = [];

if (is_array($sources)) {
foreach ($sources as $source) {
Expand All @@ -103,10 +107,21 @@ public function parseField(): mixed
$sectionIds[] = ($section->type == 'single') ? $section->id : '';
}
} else {
[, $uid] = explode(':', $source);
$sectionIds[] = Db::idByUid('{{%sections}}', $uid);
// if the source starts with "custom:", it's a custom source, and we can't treat it like a section
if (str_starts_with($source, 'custom:')) {
$customSources[] = ElementHelper::findSource(EntryElement::class, $source, ElementSources::CONTEXT_FIELD);
} else {
[, $uid] = explode(':', $source);
$sectionIds[] = Db::idByUid('{{%sections}}', $uid);
}
}
}

// if there's only one source, and it's a custom source, make sure $create is nullified;
// we don't want to create entries for custom sources because of ensuring all the conditions are met
if (count($sources) == 1 && !empty($customSources)) {
$create = null;
}
} elseif ($sources === '*') {
$sectionIds = null;
}
Expand Down Expand Up @@ -157,13 +172,38 @@ public function parseField(): mixed
}

$criteria['status'] = null;
$criteria['sectionId'] = $sectionIds;
$criteria['limit'] = $limit;
$criteria['where'] = ['=', $columnName, $dataValue];

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

Plugin::info('Search for existing entry with query `{i}`', ['i' => Json::encode($criteria)]);
// if we have any custom sources, we want to modify the query to account for those
if (!empty($customSources)) {
$conditionsService = Craft::$app->getConditions();
foreach ($customSources as $customSource) {
/** @var ElementConditionInterface $sourceCondition */
$sourceCondition = $conditionsService->createCondition($customSource['condition']);
$sourceCondition->modifyQuery($query);
}
}

if (!empty($sectionIds)) {
// now that the custom sources have been accounted for,
// we can adjust the section id to include any regular, section sources (section ids)
$query->sectionId = array_merge($query->sectionId ?? [], $sectionIds);
}

// we're getting the criteria from conditions now too, so they are not included in the $criteria array;
// so, we get all the query criteria, filter out any empty or boolean ones and only show the ones that look to be filled out
$showCriteria = $criteria;
$allCriteria = $query->getCriteria();
foreach ($allCriteria as $key => $criterion) {
if (!empty($criterion) && !is_bool($criterion)) {
$showCriteria[$key] = $criterion;
}
}

Plugin::info('Search for existing entry with query `{i}`', ['i' => Json::encode($showCriteria)]);

$ids = $query->ids();

Expand Down
48 changes: 43 additions & 5 deletions src/fields/Users.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Cake\Utility\Hash;
use Craft;
use craft\base\Element as BaseElement;
use craft\elements\conditions\ElementConditionInterface;
use craft\elements\db\UserQuery;
use craft\elements\User as UserElement;
use craft\errors\ElementNotFoundException;
Expand All @@ -14,7 +15,9 @@
use craft\feedme\Plugin;
use craft\fields\Users as UsersField;
use craft\helpers\Db;
use craft\helpers\ElementHelper;
use craft\helpers\Json;
use craft\services\ElementSources;
use Throwable;
use yii\base\Exception;

Expand Down Expand Up @@ -86,12 +89,16 @@ public function parseField(): mixed

// Get source id's for connecting
$groupIds = [];
$customSources = [];
$isAdmin = false;
$status = null;

if (is_array($sources)) {
// go through sources that start with "group:" and get group uid for those
foreach ($sources as $source) {
if (str_starts_with($source, 'custom:')) {
$customSources[] = ElementHelper::findSource(UserElement::class, $source, ElementSources::CONTEXT_MODAL);
}
if (str_starts_with($source, 'group:')) {
[, $uid] = explode(':', $source);
$groupIds[] = Db::idByUid('{{%usergroups}}', $uid);
Expand All @@ -111,6 +118,12 @@ public function parseField(): mixed
if (in_array(UserElement::STATUS_INACTIVE, $sources, true)) {
$status[] = UserElement::STATUS_INACTIVE;
}

// if there's only one source, and it's a custom source, make sure $create is nullified;
// we don't want to create users for custom sources because of ensuring all the conditions are met
if (count($sources) == 1 && !empty($customSources)) {
$create = null;
}
} elseif ($sources === '*') {
$groupIds = null;
}
Expand Down Expand Up @@ -147,13 +160,12 @@ public function parseField(): mixed

$ids = [];
$criteria['status'] = null;
$criteria['groupId'] = $groupIds;
$criteria['limit'] = $limit;
$criteria['where'] = ['=', $columnName, $dataValue];

// If the only source for the Users field is "admins" we don't have to bother with this query.
if (!($isAdmin && empty($groupIds))) {
$ids = $this->_findUsers($criteria);
if (!($isAdmin && empty($groupIds) && empty($customSources))) {
$ids = $this->_findUsers($criteria, $groupIds, $customSources);
$foundElements = array_merge($foundElements, $ids);
}

Expand Down Expand Up @@ -250,12 +262,38 @@ private function _createElement($dataValue, $groupId): ?int
* @param $criteria
* @return array|int[]
*/
private function _findUsers($criteria): array
private function _findUsers($criteria, $groupIds = null, $customSources = null): array
{
$query = UserElement::find();
Craft::configure($query, $criteria);

Plugin::info('Search for existing user with query `{i}`', ['i' => json_encode($criteria)]);
// if we have any custom sources, we want to modify the query to account for those
if (!empty($customSources)) {
$conditionsService = Craft::$app->getConditions();
foreach ($customSources as $customSource) {
/** @var ElementConditionInterface $sourceCondition */
$sourceCondition = $conditionsService->createCondition($customSource['condition']);
$sourceCondition->modifyQuery($query);
}
}

if (!empty($groupIds)) {
// now that the custom sources have been accounted for,
// we can adjust the group id to include any regular, group sources (group ids)
$query->groupId = array_merge($query->groupId ?? [], $groupIds);
}

// we're getting the criteria from conditions now too, so they are not included in the $criteria array;
// so, we get all the query criteria, filter out any empty or boolean ones and only show the ones that look to be filled out
$showCriteria = $criteria;
$allCriteria = $query->getCriteria();
foreach ($allCriteria as $key => $criterion) {
if (!empty($criterion) && !is_bool($criterion)) {
$showCriteria[$key] = $criterion;
}
}

Plugin::info('Search for existing user with query `{i}`', ['i' => json_encode($showCriteria)]);

$ids = $query->ids();

Expand Down
20 changes: 12 additions & 8 deletions src/templates/_includes/fields/categories.html
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,16 @@
}) }}
</div>

<div class="element-create">
{{ feedMeMacro.checkbox({
label: 'Create categories if they do not exist'|t('feed-me'),
name: 'options[create]',
value: 1,
checked: hash_get(feed.fieldMapping, optionsPath ~ '.create') ?: '',
}) }}
</div>
{# don't allow crating new categories if the source is custom, because we can't ensure all the conditions will be met;
e.g. level, date created or updated etc #}
{% if field is defined and field is not empty and field.source starts with 'custom:' == false %}
<div class="element-create">
{{ feedMeMacro.checkbox({
label: 'Create categories if they do not exist'|t('feed-me'),
name: 'options[create]',
value: 1,
checked: hash_get(feed.fieldMapping, optionsPath ~ '.create') ?: '',
}) }}
</div>
{% endif %}
{% endblock %}
19 changes: 11 additions & 8 deletions src/templates/_includes/fields/entries.html
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,17 @@
}) }}
</div>

<div class="element-create">
{{ feedMeMacro.checkbox({
label: 'Create entries if they do not exist'|t('feed-me'),
name: 'options[create]',
value: 1,
checked: hash_get(feed.fieldMapping, optionsPath ~ '.create') ?: '',
}) }}
</div>
{# don't allow crating new entries if the only selected source is custom, because we can't ensure all the conditions will be met #}
{% if field is defined and field is not empty and field.sources|length == 1 and field.sources.0 starts with 'custom:' == false %}
<div class="element-create">
{{ feedMeMacro.checkbox({
label: 'Create entries if they do not exist'|t('feed-me'),
name: 'options[create]',
value: 1,
checked: hash_get(feed.fieldMapping, optionsPath ~ '.create') ?: '',
}) }}
</div>
{% endif %}

{% if field %}
<div class="element-groups">
Expand Down
19 changes: 11 additions & 8 deletions src/templates/_includes/fields/users.html
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,15 @@
}) }}
</div>

<div class="element-create">
{{ feedMeMacro.checkbox({
label: 'Create users if they do not exist'|t('feed-me'),
name: 'options[create]',
value: 1,
checked: hash_get(feed.fieldMapping, optionsPath ~ '.create') ?: '',
}) }}
</div>
{# don't allow crating new entries if the only selected source is custom, because we can't ensure all the conditions will be met #}
{% if field is defined and field is not empty and field.sources|length == 1 and field.sources.0 starts with 'custom:' == false %}
<div class="element-create">
{{ feedMeMacro.checkbox({
label: 'Create users if they do not exist'|t('feed-me'),
name: 'options[create]',
value: 1,
checked: hash_get(feed.fieldMapping, optionsPath ~ '.create') ?: '',
}) }}
</div>
{% endif %}
{% endblock %}

0 comments on commit 7192dc1

Please sign in to comment.