Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add caching to custom fields #506

Merged
merged 13 commits into from Mar 21, 2019
2 changes: 1 addition & 1 deletion CHANGELOG.md
Expand Up @@ -5,7 +5,7 @@
Upgrading to 3.6.x versions requires that you upgrade to latest 3.5.x version first.

- Add jQuery chosen to quick filter (@glensc, #493)
- Refactor Custom Fields to use Interfaces and Doctrine Models (@glensc, #466)
- Refactor Custom Fields to use Interfaces and Doctrine Models (@glensc, #466, #506)
- Initialize `usr_id`, needed for preferences (@glensc, #498, #499, #500)
- Add more events to handle Workflow calls (@glensc, #497)
- Debugbar: Add Doctrine queries Tab (@glensc, #505)
Expand Down
20 changes: 13 additions & 7 deletions lib/eventum/class.custom_field.php
Expand Up @@ -277,16 +277,22 @@ public static function getOptions(int $fld_id, array $cfo_ids = []): array
*/
public static function getFieldsToBeListed(int $prj_id): array
{
static $cache;
$role_id = Auth::getCurrentRole();
$repo = Doctrine::getCustomFieldRepository();
$fields = $repo->getListByProject($prj_id, $role_id, CustomField::LIST_DISPLAY);

$res = [];
foreach ($fields as $field) {
$res[$field->getId()] = $field->getTitle();
}
$initialize = function (int $prj_id) use ($role_id) {
$repo = Doctrine::getCustomFieldRepository();
$fields = $repo->getListByProject($prj_id, $role_id, CustomField::LIST_DISPLAY);

return $res;
$res = [];
foreach ($fields as $field) {
$res[$field->getId()] = $field->getTitle();
}

return $res;
};

return $cache[$prj_id][$role_id] ?? $cache[$prj_id][$role_id] = $initialize($prj_id);
}

/**
Expand Down
32 changes: 20 additions & 12 deletions lib/eventum/class.search.php
Expand Up @@ -396,7 +396,7 @@ public static function getListing($prj_id, $options, $current_row = 0, $max = 5)
$column_headings = [];
$columns_to_display = Display_Column::getColumnsToDisplay($prj_id, 'list_issues');
foreach ($columns_to_display as $col_key => $column) {
if ($col_key === 'custom_fields' && count($custom_fields) > 0) {
if ($col_key === 'custom_fields' && $custom_fields) {
foreach ($custom_fields as $fld_id => $fld_title) {
$column_headings['cstm_' . $fld_id] = $fld_title;
}
Expand Down Expand Up @@ -432,17 +432,8 @@ public static function getListing($prj_id, $options, $current_row = 0, $max = 5)
case 'iss_customer_id':
$col_key = 'customer_title';break;
}
if ($col_key === 'custom_fields' && count($custom_fields) > 0) {
$custom_field_values = Custom_Field::getListByIssue($prj_id, $row['iss_id']);
foreach ($custom_field_values as $cf) {
if (!empty($custom_fields[$cf['fld_id']])) {
$formattedValue = Custom_Field::formatValue($cf['value'], $cf['fld_id'], $row['iss_id']);
$cf['formatted_value'] = $formattedValue;

$row['custom_field'][$cf['fld_id']] = $cf;
$fields[] = $cf['value'];
}
}
if ($col_key === 'custom_fields' && $custom_fields) {
self::applyCustomFields($custom_fields, $row, $fields, $prj_id, $issue_id);
} else {
$fields[] = $row[$col_key] ?? '';
}
Expand Down Expand Up @@ -485,6 +476,23 @@ public static function getListing($prj_id, $options, $current_row = 0, $max = 5)
];
}

private static function applyCustomFields(array $custom_fields, array &$row, array &$fields, int $prj_id, int $iss_id): void
{
$custom_field_values = Custom_Field::getListByIssue($prj_id, $iss_id);

foreach ($custom_field_values as $cf) {
if (empty($custom_fields[$cf['fld_id']])) {
continue;
}

$formattedValue = Custom_Field::formatValue($cf['value'], $cf['fld_id'], $iss_id);
$cf['formatted_value'] = $formattedValue;

$row['custom_field'][$cf['fld_id']] = $cf;
$fields[] = $cf['value'];
}
}

/**
* Method used to get the list of issues to be displayed in the grid layout.
*
Expand Down
65 changes: 23 additions & 42 deletions src/Model/Entity/CustomField.php
Expand Up @@ -22,16 +22,19 @@
use Eventum\CustomField\Factory;
use Eventum\CustomField\Fields\ListInterface;
use Eventum\CustomField\Proxy;
use Eventum\Model\Repository\Traits\GetOneTrait;
use Eventum\Monolog\Logger;
use InvalidArgumentException;
use RuntimeException;
use User;

/**
* @ORM\Table(name="custom_field")*
* @ORM\Entity(repositoryClass="Eventum\Model\Repository\CustomFieldRepository")
*/
class CustomField
{
use GetOneTrait;

public const LIST_DISPLAY = 'list_display';

public const FORM_TYPES = [
Expand All @@ -44,19 +47,21 @@ class CustomField
'edit_form' => null,
];

public const TYPE_TEXT = 'text';

private const OPTION_TYPES = [
'checkbox',
'combo',
'multiple',
];

private const TEXT_TYPES = [
'text',
self::TYPE_TEXT,
'textarea',
];

private const OTHER_TYPES = [
'text',
self::TYPE_TEXT,
'textarea',
'date',
'integer',
Expand Down Expand Up @@ -92,61 +97,61 @@ class CustomField
* @var bool
* @ORM\Column(name="fld_report_form", type="boolean", nullable=false)
*/
private $showReportForm;
private $showReportForm = false;

/**
* @var bool
* @ORM\Column(name="fld_report_form_required", type="boolean", nullable=false)
*/
private $isReportFormRequired;
private $isReportFormRequired = false;

/**
* @var bool
* @ORM\Column(name="fld_anonymous_form", type="boolean", nullable=false)
*/
private $showAnonymousForm;
private $showAnonymousForm = false;

/**
* @var bool
* @ORM\Column(name="fld_anonymous_form_required", type="boolean", nullable=false)
*/
private $isAnonymousFormRequired;
private $isAnonymousFormRequired = false;

/**
* @var bool
* @ORM\Column(name="fld_close_form", type="boolean", nullable=false)
*/
private $showCloseForm;
private $showCloseForm = false;

/**
* @var bool
* @ORM\Column(name="fld_close_form_required", type="boolean", nullable=false)
*/
private $isCloseFormRequired;
private $isCloseFormRequired = false;

/**
* @var bool
* @ORM\Column(name="fld_edit_form_required", type="boolean", nullable=false)
*/
private $isEditFormRequired;
private $isEditFormRequired = false;

/**
* @var bool
* @ORM\Column(name="fld_list_display", type="boolean", nullable=false)
*/
private $showListDisplay;
private $showListDisplay = false;

/**
* @var int
* @ORM\Column(name="fld_min_role", type="integer", nullable=false)
*/
private $minRole;
private $minRole = User::ROLE_VIEWER;

/**
* @var bool
* @ORM\Column(name="fld_min_role_edit", type="integer", nullable=false)
*/
private $minRoleEdit;
private $minRoleEdit = User::ROLE_VIEWER;

/**
* @var int
Expand All @@ -167,7 +172,7 @@ class CustomField
* @var string
* @ORM\Column(name="fld_order_by", type="string", length=20, nullable=false)
*/
private $orderBy;
private $orderBy = 'cfo_id ASC';

/**
* @var CustomFieldOption[]|PersistentCollection
Expand Down Expand Up @@ -528,16 +533,13 @@ public function addOptionValue(string $value, int $rank): CustomFieldOption

public function getOptionById(int $cfo_id): ?CustomFieldOption
{
$expr = new Comparison('id', '=', $cfo_id);
$criteria = Criteria::create()->where($expr);

return $this->getOne($this->options, $criteria);
return $this->getOne($this->options, 'id', '=', $cfo_id);
}

/**
* @return ProjectCustomField[]|Collection
*/
public function getProjectCustomFields(): Collection
public function getProjectCustomFields(): ?Collection
{
return $this->projects;
}
Expand All @@ -552,18 +554,12 @@ public function addProjectCustomField(ProjectCustomField $pcf): self

public function getProjectCustomFieldById(int $prj_id): ?ProjectCustomField
{
$expr = new Comparison('projectId', '=', $prj_id);
$criteria = Criteria::create()->where($expr);

return $this->getOne($this->projects, $criteria);
return $this->getOne($this->projects, 'projectId', '=', $prj_id);
}

public function getIssueCustomField(int $issue_id): ?IssueCustomField
{
$expr = new Comparison('issueId', '=', $issue_id);
$criteria = Criteria::create()->where($expr);

return $this->getOne($this->issues, $criteria) ?: null;
return $this->getOne($this->issues, 'issueId', '=', $issue_id);
}

/**
Expand All @@ -577,21 +573,6 @@ public function getIssueCustomFields(int $issue_id): Collection
return $this->issues->matching($criteria);
}

private function getOne(PersistentCollection $collection, Criteria $criteria)
{
$matches = $collection->matching($criteria);
if ($matches->isEmpty()) {
return null;
}

if ($matches->count() !== 1) {
$count = $matches->count();
throw new RuntimeException("Expected one element, got $count");
}

return $matches->first();
}

public function getDisplayValue(int $issue_id): string
{
$values = $this->getIssueCustomFields($issue_id)
Expand Down
2 changes: 1 addition & 1 deletion src/Model/Entity/UserPreference.php
Expand Up @@ -294,7 +294,7 @@ public function getProjects(): ?Collection

public function getProjectById(int $prj_id): ?UserProjectPreference
{
return $this->getOne($this->projects, 'projectId', '=', $prj_id) ?: null;
return $this->getOne($this->projects, 'projectId', '=', $prj_id);
}

public function findOrCreateProjectById(int $prj_id): UserProjectPreference
Expand Down
10 changes: 5 additions & 5 deletions src/Model/Repository/IssueAssociationRepository.php
Expand Up @@ -15,6 +15,7 @@

use DB_Helper;
use Doctrine\ORM\EntityRepository;
use Ds\Set;
use Eventum\Model\Entity;
use History;
use InvalidArgumentException;
Expand Down Expand Up @@ -50,15 +51,14 @@ public function getAssociatedIssues($issue_id): array
);
$query->execute([':issue_id' => $issue_id]);

$res = [];
$set = new Set();
while (($id = $query->fetchColumn()) !== false) {
$res[] = (int)$id;
$set->add((int)$id);
}

// and sort
asort($res);
$set->sort();

return array_values($res);
return $set->toArray();
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/Model/Repository/Traits/GetOneTrait.php
Expand Up @@ -39,6 +39,6 @@ private function getOne(?PersistentCollection $collection, string $field, string
throw new RuntimeException("Expected one element, got $count");
}

return $matches->first();
return $matches->first() ?: null;
}
}
16 changes: 4 additions & 12 deletions tests/CustomField/CustomFieldTest.php
Expand Up @@ -14,10 +14,7 @@
namespace Eventum\Test\CustomField;

use Eventum\CustomField\Converter;
use Eventum\Db\Doctrine;
use Eventum\EventDispatcher\EventManager;
use Eventum\Model\Entity\CustomField;
use Eventum\Test\TestCase;
use User;

/**
Expand All @@ -27,9 +24,7 @@ class CustomFieldTest extends TestCase
{
public function testGetCustomField(): void
{
$repo = Doctrine::getCustomFieldRepository();
/** @var CustomField $cf */
$cf = $repo->findById(2);
$cf = $this->repo->findById(2);
dump($cf !== null);
}

Expand All @@ -43,8 +38,7 @@ public function testGetListByIssue(): void
$min_role = User::ROLE_VIEWER;
$forEdit = false;
$formType = 'edit_form';
$repo = Doctrine::getCustomFieldRepository();
$customFields = $repo->getListByIssue($prj_id, $iss_id, $min_role, $formType, $forEdit);
$customFields = $this->repo->getListByIssue($prj_id, $iss_id, $min_role, $formType, $forEdit);

dump(count($customFields));

Expand All @@ -67,8 +61,7 @@ public function testGetListByProject(): void
$forEdit = false;
$formType = 'edit_form';
$fieldType = 'multiple';
$repo = Doctrine::getCustomFieldRepository();
$customFields = $repo->getListByProject($prj_id, $min_role, $formType, $fieldType, $forEdit);
$customFields = $this->repo->getListByProject($prj_id, $min_role, $formType, $fieldType, $forEdit);

dump(count($customFields));

Expand All @@ -90,7 +83,6 @@ public function testUpdateCustomFieldOptions(): void
2 => 'option2',
];

$repo = Doctrine::getCustomFieldRepository();
$repo->updateCustomFieldOptions($fld_id, $options, $new_options);
$this->repo->updateCustomFieldOptions($fld_id, $options, $new_options);
}
}