//check if there are dynamic fields in the filter
foreach ($this->filters->contrib_dynamic as $k => $cd) {
- if (is_array($cd)) {
+ $dyn_field = DynamicField::loadFieldType($zdb, (int)$k);
+ if ($dyn_field instanceof \Galette\DynamicFields\Choice) {
$hasCdfc = true;
$cdfcs[] = $k;
}
// choice dynamic fields
if ($hasCdfc === true) {
- $cdf_field = 'cdf.id';
- if (TYPE_DB === 'pgsql') {
- $cdf_field .= '::text';
- }
-
- $cdf_field = 'cdfc.id';
- if (TYPE_DB === 'pgsql') {
- $cdf_field .= '::text';
- }
foreach ($cdfcs as $cdf) {
- $rcdf_field = str_replace(
- 'cdfc.',
- 'cdfc' . $cdf . '.',
- $cdf_field
+ $rcdf_field = sprintf(
+ '%s.%s',
+ $zdb->platform->quoteIdentifier('cdfc' . $cdf),
+ $zdb->platform->quoteIdentifier('id')
);
+ if (TYPE_DB === 'pgsql') {
+ $rcdf_field = $rcdf_field . '::text';
+ }
+
$select->join(
array('cdfc' . $cdf => DynamicField::getFixedValuesTableName($cdf, true)),
- $rcdf_field . '=dfc.field_val',
+ new Expression(
+ sprintf(
+ '%s = %s.%s',
+ $rcdf_field,
+ $zdb->platform->quoteIdentifier('dfc'),
+ $zdb->platform->quoteIdentifier('field_val')
+ )
+ ),
array(),
$select::JOIN_LEFT
);
&& !isset($this->filters->contrib_dynamic['empty'])
) {
foreach ($this->filters->contrib_dynamic as $k => $cd) {
- $qry = '';
- $prefix = 'a.';
- $field = null;
$qop = ' LIKE ';
if (is_array($cd)) {
$qry = 'dfc.field_form = \'contrib\' AND ' .
'dfc.field_id = ' . $k . ' AND ';
$field = 'field_val';
- $qry .= 'LOWER(' . $prefix . $field . ') ' .
- $qop . ' ';
- $select->where($qry . $zdb->platform->quoteValue('%' . strtolower($cd) . '%'));
+
+ $dyn_field = DynamicField::loadFieldType($zdb, (int)$k);
+
+ if ($dyn_field instanceof \Galette\DynamicFields\Boolean) {
+ if ($cd == 1) {
+ $qry .= $field . ' = ' . (int)$cd;
+ }
+ $select->where($qry);
+ } elseif ($dyn_field instanceof \Galette\DynamicFields\Date) {
+ //dynamic dates are stored in their localized format :/
+ //use current lang format to query for now
+ //FIXME works with french formatted date only -_-
+ if ($zdb->isPostgres()) {
+ $qop = '=';
+ $store_fmt = __("Y-m-d") === 'Y-m-d' ? 'YYYY-MM-DD' : 'DD/MM/YYYY';
+ $cd = "to_date('" . $cd . "', '" . $store_fmt . "')";
+ $qry .= "to_date(" . $prefix . $field . ", '$store_fmt')";
+ } else {
+ $store_fmt = __("Y-m-d") === 'Y-m-d' ? '%Y-%m-%d' : '%d/%m/%Y';
+ $cd = "STR_TO_DATE('" . $cd . "', '" . $store_fmt . "')";
+ $qry .= 'STR_TO_DATE(' . $prefix . $field . ', \'' . $store_fmt . '\') ';
+ }
+ $qry .= $qop . ' ' . $cd;
+ $select->where($qry);
+ } else {
+ $qry .= 'LOWER(' . $prefix . $field . ') ' . $qop . ' ';
+ $select->where($qry . $zdb->platform->quoteValue('%' . strtolower($cd) . '%'));
+ }
}
}
}
} else {
//dynamic dates are stored in their localized format :/
//use current lang format to query for now
+ //FIXME works with french formatted date only -_-
if ($zdb->isPostgres()) {
- $fs['search'] = "to_date('" . $fs['search'] . "', 'YYYY-MM-DD')";
$store_fmt = __("Y-m-d") === 'Y-m-d' ? 'YYYY-MM-DD' : 'DD/MM/YYYY';
+ $fs['search'] = "to_date('" . $fs['search'] . "', '" . $store_fmt . "')";
$qry .= "to_date('" . $prefix . $fs['field'] . "', '$store_fmt')";
} else {
- $fs['search'] = "STR_TO_DATE('" . $fs['search'] . "', '%Y-%m-%d')";
$store_fmt = __("Y-m-d") === 'Y-m-d' ? '%Y-%m-%d' : '%d/%m/%Y';
+ $fs['search'] = "STR_TO_DATE('" . $fs['search'] . "', '" . $store_fmt . "')";
$qry .= 'STR_TO_DATE(' . $prefix . $fs['field'] . ', \'' . $store_fmt . '\') ';
}
{% else %}
{% set rid = "cds_" ~ fid %}
{% endif %}
+ {% if get_class(field) != "Galette\\DynamicFields\\Boolean" %}
<label for="cds{% if get_class(field) == "Galette\\DynamicFields\\Choice" %}c{% endif %}_{{ field.getId() }}">{{ field.getName() }}</label>
+ {% endif %}
{% if get_class(field) == "Galette\\DynamicFields\\Line" %}
- <input type="text" name="cds_{{ field.getId() }}" id="cds_{{ field.getId() }}" value="{% if attribute(filters.contrib_dynamic, rid) is defined %}{{ attribute(filters.contrib_dynamic, rid) }}{% endif %}" />
+ <input type="text" name="cds_{{ field.getId() }}" id="cds_{{ field.getId() }}" value="{% if attribute(filters.contrib_dynamic, fid) is defined %}{{ attribute(filters.contrib_dynamic, fid) }}{% endif %}" />
{% elseif get_class(field) == "Galette\\DynamicFields\\Text" %}
- <textarea name="cds_{{ field.getId() }}" id="cds_{{ field.getId() }}">{% if attribute(filters.contrib_dynamic, rid) is defined %}{{ attribute(filters.contrib_dynamic, rid) }}{% endif %}</textarea>
+ <textarea name="cds_{{ field.getId() }}" id="cds_{{ field.getId() }}">{% if attribute(filters.contrib_dynamic, fid) is defined %}{{ attribute(filters.contrib_dynamic, fid) }}{% endif %}</textarea>
{% elseif get_class(field) == "Galette\\DynamicFields\\Choice" %}
<select name="cdsc_{{ field.getId() }}[]" id="cdsc_{{ field.getId() }}" multiple="multiple" class="ui dropdown nochosen">
<option value="">{{ _T('Select') }}</option>
{% for k, choice in field.getValues() %}
- <option value="{{ k }}"{% if cds.field is defined and cds.field == rid %} selected="selected"{% endif %}>{{ choice }}</option>
+ <option value="{{ k }}"{% if attribute(filters.contrib_dynamic, fid) is defined and k in attribute(filters.contrib_dynamic, fid) %} selected="selected"{% endif %}>{{ choice }}</option>
{% endfor %}
</select>
+ {% elseif get_class(field) == "Galette\\DynamicFields\\Boolean" %}
+ <div class="ui right aligned toggle checkbox">
+ <input type="checkbox" name="cds_{{ field.getId() }}" id="cds_{{ field.getId() }}" value="1" {% if attribute(filters.contrib_dynamic, fid) is defined %} checked="checked"{% endif %}/>
+ <label for="cds_{{ field.getId() }}">{{ field.getName() }}</label>
+ </div>
+ {% elseif get_class(field) == "Galette\\DynamicFields\\Date" %}
+ <div class="ui calendar" id="cds_{{ field.getId() }}-rangeend">
+ <div class="ui input left icon">
+ <i class="calendar icon"></i>
+ <input id="cds_{{ field.getId() }}" name="cds_{{ field.getId() }}" type="text" class="due_date" maxlength="10" size="10" value="{% if attribute(filters.contrib_dynamic, fid) is defined %}{{ attribute(filters.contrib_dynamic, fid) }}{% endif %}" placeholder="{{ _T('(yyyy-mm-dd format)') }}"/>
+ </div>
+ </div>
{% endif %}
</div>
{% endfor %}
protected int $seed = 335689;
private array $mids = [];
+ private ?string $contents_table = null;
+
/**
* Set up tests
*
public function setUp(): void
{
parent::setUp();
+ $this->contents_table = null;
$this->createMembers();
}
$this->deleteGroups();
$this->deleteMembers();
+
+ $delete = $this->zdb->delete(\Galette\Entity\DynamicFieldsHandle::TABLE);
+ $this->zdb->execute($delete);
+ $delete = $this->zdb->delete(\Galette\DynamicFields\DynamicField::TABLE);
+ $this->zdb->execute($delete);
+ //cleanup dynamic translations
+ $delete = $this->zdb->delete(\Galette\Core\L10n::TABLE);
+ $delete->where([
+ 'text_orig' => [
+ 'Dynamic choice field',
+ 'Dynamic date field',
+ 'Dynamic text field'
+ ]
+ ]);
+ $this->zdb->execute($delete);
+
+ if ($this->contents_table !== null) {
+ $this->zdb->drop($this->contents_table);
+ }
}
/**
$this->assertTrue($member->store());
$mids[] = $member->id;
- //set first member displayed publically an active and up to date member
+ //set first member displayed publicly an active and up-to-date member
if ($member->appearsInMembersList() && !$member->isDueFree() && $first === true) {
$first = false;
$contrib = new \Galette\Entity\Contribution($this->zdb, $this->login);
$this->assertSame(0, $list->count());
}
+ /**
+ * Test getList with contribution dynamic fields
+ *
+ * @return void
+ */
+ public function testGetListContributionDynamics()
+ {
+ // Advanced search on contributions dynamic fields
+
+ //add dynamic fields on contributions
+ $field_data = [
+ 'form_name' => 'contrib',
+ 'field_name' => 'Dynamic text field',
+ 'field_perm' => \Galette\DynamicFields\DynamicField::PERM_USER_WRITE,
+ 'field_type' => \Galette\DynamicFields\DynamicField::TEXT,
+ 'field_required' => 1,
+ 'field_repeat' => 1
+ ];
+
+ $tdf = \Galette\DynamicFields\DynamicField::getFieldType($this->zdb, $field_data['field_type']);
+
+ $stored = $tdf->store($field_data);
+ $error_detected = $tdf->getErrors();
+ $warning_detected = $tdf->getWarnings();
+ $this->assertTrue(
+ $stored,
+ implode(
+ ' ',
+ $tdf->getErrors() + $tdf->getWarnings()
+ )
+ );
+ $this->assertEmpty($error_detected, implode(' ', $tdf->getErrors()));
+ $this->assertEmpty($warning_detected, implode(' ', $tdf->getWarnings()));
+
+ //new dynamic field, of type choice.
+ $values = [
+ 'First value',
+ 'Second value',
+ 'Third value'
+ ];
+ $field_data = [
+ 'form_name' => 'contrib',
+ 'field_name' => 'Dynamic choice field',
+ 'field_perm' => \Galette\DynamicFields\DynamicField::PERM_USER_WRITE,
+ 'field_type' => \Galette\DynamicFields\DynamicField::CHOICE,
+ 'field_required' => 0,
+ 'field_repeat' => 1,
+ 'fixed_values' => implode("\n", $values)
+ ];
+
+ $cdf = \Galette\DynamicFields\DynamicField::getFieldType($this->zdb, $field_data['field_type']);
+
+ $stored = $cdf->store($field_data);
+ $error_detected = $cdf->getErrors();
+ $warning_detected = $cdf->getWarnings();
+ $this->assertTrue(
+ $stored,
+ implode(
+ ' ',
+ $cdf->getErrors() + $cdf->getWarnings()
+ )
+ );
+ $this->assertEmpty($error_detected, implode(' ', $cdf->getErrors()));
+ $this->assertEmpty($warning_detected, implode(' ', $cdf->getWarnings()));
+ //cleanup dynamic choices table
+ $this->contents_table = $cdf->getFixedValuesTableName($cdf->getId());
+
+ //new dynamic field, of type date.
+ $field_data = [
+ 'form_name' => 'contrib',
+ 'field_name' => 'Dynamic date field',
+ 'field_perm' => \Galette\DynamicFields\DynamicField::PERM_USER_WRITE,
+ 'field_type' => \Galette\DynamicFields\DynamicField::DATE,
+ 'field_required' => 0,
+ 'field_repeat' => 1
+ ];
+
+ $ddf = \Galette\DynamicFields\DynamicField::getFieldType($this->zdb, $field_data['field_type']);
+
+ $stored = $ddf->store($field_data);
+ $error_detected = $ddf->getErrors();
+ $warning_detected = $ddf->getWarnings();
+ $this->assertTrue(
+ $stored,
+ implode(
+ ' ',
+ $ddf->getErrors() + $ddf->getWarnings()
+ )
+ );
+ $this->assertEmpty($error_detected, implode(' ', $ddf->getErrors()));
+ $this->assertEmpty($warning_detected, implode(' ', $ddf->getWarnings()));
+
+ //search on contribution dynamic text field
+ $filters = new \Galette\Filters\AdvancedMembersList();
+ $filters->contrib_dynamic = [$tdf->getId() => 'text value'];
+ $members = new \Galette\Repository\Members($filters);
+ $list = $members->getList();
+
+ $this->assertSame(0, $list->count());
+
+ $contrib = new \Galette\Entity\Contribution($this->zdb, $this->login);
+
+ $now = new \DateTime();
+ $begin_date = clone $now;
+ $begin_date->sub(new \DateInterval('P1D'));
+ $due_date = clone $begin_date;
+ $due_date->sub(new \DateInterval('P1D'));
+ $due_date->add(new \DateInterval('P1Y'));
+
+ $cdata = [
+ \Galette\Entity\Adherent::PK => $this->mids[0],
+ 'type_paiement_cotis' => \Galette\Entity\PaymentType::CASH,
+ 'montant_cotis' => 20,
+ 'date_enreg' => $begin_date->format('Y-m-d'),
+ 'date_debut_cotis' => $begin_date->format('Y-m-d'),
+ 'date_fin_cotis' => $due_date->format('Y-m-d'),
+ \Galette\Entity\ContributionsTypes::PK => 4, //donation in kind
+ 'info_field_' . $tdf->getId() . '_1' => 'A contribution with a dynamic text value set on it'
+ ];
+ $this->assertTrue($contrib->check($cdata, [], []));
+ $this->assertTrue($contrib->store());
+
+ $list = $members->getList();
+ $this->assertSame(1, $list->count());
+
+ //search on contribution dynamic date field
+ $filters = new \Galette\Filters\AdvancedMembersList();
+ $ddate = new \DateTime('2020-01-01');
+ $filters->contrib_dynamic = [$ddf->getId() => $ddate->format(__('Y-m-d'))];
+ $members = new \Galette\Repository\Members($filters);
+ $list = $members->getList();
+
+ $this->assertSame(0, $list->count());
+
+ $cdata += [
+ 'id_cotis' => $contrib->id,
+ 'info_field_' . $ddf->getId() . '_1' => $ddate->format(__('Y-m-d'))
+ ];
+ $this->assertTrue($contrib->check($cdata, [], []));
+ $this->assertTrue($contrib->store());
+
+ $list = $members->getList();
+ $this->assertSame(1, $list->count());
+
+ //search on contribution dynamic choice field
+ $filters = new \Galette\Filters\AdvancedMembersList();
+ $filters->contrib_dynamic = [$cdf->getId() => 2]; //3rd options is selected
+ $members = new \Galette\Repository\Members($filters);
+ $list = $members->getList();
+
+ $this->assertSame(0, $list->count());
+
+ $cdata += [
+ 'id_cotis' => $contrib->id,
+ 'info_field_' . $cdf->getId() . '_1' => 2
+ ];
+ $this->assertTrue($contrib->check($cdata, [], []));
+ $this->assertTrue($contrib->store());
+
+ $list = $members->getList();
+ $this->assertSame(1, $list->count());
+
+ //search on multiple contribution dynamic choice field
+ $filters = new \Galette\Filters\AdvancedMembersList();
+ $filters->contrib_dynamic = [$cdf->getId() => [0, 2]]; //1st OR 3rd options are selected
+ $members = new \Galette\Repository\Members($filters);
+ $list = $members->getList();
+
+ $this->assertSame(1, $list->count());
+ }
+
/**
* Test getPublicList
*