Skip to content

Commit

Permalink
Abstract association formatting to a more general formatting stack
Browse files Browse the repository at this point in the history
  • Loading branch information
KorvinSzanto committed Aug 1, 2017
1 parent bc4e096 commit 7788091
Show file tree
Hide file tree
Showing 6 changed files with 189 additions and 19 deletions.
64 changes: 45 additions & 19 deletions concrete/src/Express/Association/Formatter/AbstractFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,66 @@
use Concrete\Core\Entity\Express\Association;
use Concrete\Core\Entity\Express\Control\AssociationControl;
use Concrete\Core\Entity\Express\Entry;
use Concrete\Core\Express\Entry\Formatter\EntryFormatterInterface;
use Concrete\Core\Support\Facade\Application;

abstract class AbstractFormatter implements FormatterInterface
{
protected $association;
protected $entryFormatter;

public function __construct(Association $association)
{
$this->association = $association;
}

/**
* Get the display label for an entry
* @param \Concrete\Core\Entity\Express\Control\AssociationControl $control
* @param \Concrete\Core\Entity\Express\Entry $entry
* @return null|string
*/
public function getEntryDisplayName(AssociationControl $control, Entry $entry)
{
$formatter = $this->getEntryFormatter();
$name = null;

// Do we have a custom display mask? If so, we try to use that
if ($control->getAssociationEntityLabelMask()) {
try {
return preg_replace_callback('/%(.*?)%/i', function ($matches) use ($entry) {
$attribute = $entry->getAttribute($matches[1]);
if ($attribute) {
return $attribute;
}

$association = $entry->getAssociation($matches[1]);
if (is_object($association)) {
return $association->getSelectedEntry()->getLabel();
}
}, $control->getAssociationEntityLabelMask());
} catch (\Exception $e) {
}
if ($mask = $control->getAssociationEntityLabelMask()) {
$name = $formatter->format($mask, $entry);
}

if (!$name && $mask = $entry->getEntity()->getLabelMask()) {
$name = $formatter->format($mask, $entry);
}
$targetEntity = $this->association->getTargetEntity();
$attribute = $targetEntity->getAttributes()[0];
if (is_object($attribute)) {
return $entry->getAttribute($attribute);

if ($name = trim($name)) {
return $name;
}

return $entry->getID();
}

/**
* Supploy the entry formatter we should use
* @param \Concrete\Core\Express\Entry\Formatter\EntryFormatterInterface $formatter
*/
public function setEntryFormatter(EntryFormatterInterface $formatter)
{
$this->entryFormatter = $formatter;
}

/**
* Get the entry formatter to use
* @return \Concrete\Core\Express\Entry\Formatter\EntryFormatterInterface
*/
protected function getEntryFormatter()
{
if (!$this->entryFormatter) {
$this->entryFormatter = Application::getFacadeApplication()->make(EntryFormatterInterface::class);
}

return $this->entryFormatter;
}

public function getDisplayName()
Expand Down
19 changes: 19 additions & 0 deletions concrete/src/Express/Entry/Formatter/EntryFormatterInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace Concrete\Core\Express\Entry\Formatter;

use Concrete\Core\Entity\Express\Entry;

interface EntryFormatterInterface
{
/**
* Format a mask given an entry
*
* Mask format will typically be something like `Example %attribute_key% %association_handle`
*
* @param string $mask
* @param \Concrete\Core\Entity\Express\Entry $entry
* @return string|null
*/
public function format($mask, Entry $entry);
}
40 changes: 40 additions & 0 deletions concrete/src/Express/Entry/Formatter/LabelFormatter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace Concrete\Core\Express\Entry\Formatter;

use Concrete\Core\Entity\Express\Entry;
use Concrete\Core\Express\Formatter\FormatterInterface;

class LabelFormatter implements EntryFormatterInterface
{

/** @var \Concrete\Core\Express\Formatter\FormatterInterface */
protected $formatter;

public function __construct(FormatterInterface $formatter)
{
$this->formatter = $formatter;
}

/**
* Format a mask given an entry
* @param string $mask
* @param \Concrete\Core\Entity\Express\Entry $entry
* @return string|null
*/
public function format($mask, Entry $entry)
{
return $this->formatter->format($mask, function($key) use ($entry) {
$attribute = $entry->getAttribute($key);
if ($attribute) {
return $attribute;
}

$association = $entry->getAssociation($key);
if (is_object($association)) {
return $association->getSelectedEntry()->getLabel();
}
});
}

}
7 changes: 7 additions & 0 deletions concrete/src/Express/ExpressServiceProvider.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
<?php
namespace Concrete\Core\Express;

use Concrete\Core\Express\Entry\Formatter\EntryFormatterInterface;
use Concrete\Core\Express\Entry\Formatter\LabelFormatter as EntryLabelFormatter;
use Concrete\Core\Express\Formatter\FormatterInterface;
use Concrete\Core\Express\Formatter\LabelFormatter;
use Concrete\Core\Foundation\Service\Provider as ServiceProvider;

class ExpressServiceProvider extends ServiceProvider
Expand All @@ -19,5 +23,8 @@ public function register()
return $app->make('Concrete\Core\Express\ObjectManager');
});
$this->app->singleton('Concrete\Core\Express\Controller\Manager');

$this->app->bind(FormatterInterface::class, LabelFormatter::class);
$this->app->bind(EntryFormatterInterface::class, EntryLabelFormatter::class);
}
}
18 changes: 18 additions & 0 deletions concrete/src/Express/Formatter/FormatterInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace Concrete\Core\Express\Formatter;

interface FormatterInterface
{
/**
* Format a mask using the standard format given a callable
*
* Ex: if you have attributes with handles `student_first_name` and `student_last_name`
* `%student_last_name%, %student_first_name%`
*
* @param $mask
* @param callable $matchHandler
* @return mixed
*/
public function format($mask, callable $matchHandler);
}
60 changes: 60 additions & 0 deletions concrete/src/Express/Formatter/LabelFormatter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

namespace Concrete\Core\Express\Formatter;

use Psr\Log\LoggerInterface;

class LabelFormatter implements FormatterInterface
{

/** @var \Psr\Log\LoggerInterface */
protected $logger;

public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}

/**
* Format a mask using the standard format given a callable
*
* Ex: if you have attributes with handles `student_first_name` and `student_last_name`
* `%student_last_name%, %student_first_name%`
*
* @param $mask
* @param callable $matchHandler
* @return mixed
*/
public function format($mask, callable $matchHandler)
{
try {
// Run a regular expression to match the mask
return preg_replace_callback('/%(.*?)%/i', function ($matches) use ($matchHandler) {
// Return the result returned from the matchHandler
return $this->getResult($matches[1], $matchHandler) ?: '';
}, $mask);
} catch (\Exception $e) {
// Log any failures
$this->logger->debug(
'Failed to format express mask "{mask}": {message}',
['mask' => $mask, 'message' => $e->getMessage(), 'exception' => $e]
);
}
}

/**
* Get a result given a key
* @param $key
* @param callable $matchHandler
* @return string
*/
private function getResult($key, callable $matchHandler)
{
if ($key = trim($key)) {
return $matchHandler($key) ?: '';
}

return '';
}

}

0 comments on commit 7788091

Please sign in to comment.