Skip to content

Commit

Permalink
Resolves #122 by falling back to a full-spec YAML parser by default
Browse files Browse the repository at this point in the history
  • Loading branch information
JohnathonKoster committed Nov 8, 2020
1 parent f706f57 commit 2cf6119
Show file tree
Hide file tree
Showing 8 changed files with 225 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/Addon.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class Addon
public const CODE_ADDON_NAME = 'meerkat';
public const ROUTE_PREFIX = 'meerkat';
public const ADDON_ID = 'stillat/meerkat';
public const VERSION = '2.1.5-beta2';
public const VERSION = '2.1.6-beta2';

/**
* Gets the addon API prefix.
Expand Down
11 changes: 11 additions & 0 deletions src/Core/Comments/Comment.php
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,17 @@ public function getStorableAttributes()
return $this->getAttributesToSave();
}

/**
* Indicates that runtime attributes should already be considered resolved.
*
* @internal
* @since 2.1.6
*/
public function flagRuntimeAttributesResolved()
{
$this->runTimeAttributesResolved = true;
}

/**
* Parses the raw attributes and reloads the current attributes.
*
Expand Down
14 changes: 14 additions & 0 deletions src/Core/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,20 @@ class Configuration extends ConfigurationContainer
*/
public $addressToSendEmailTo = [];

/**
* Indicates if a full, or off-spec, parser should be used for comment prototype parsing.
*
* If all comments of a site adhere to Meerkat's recommended structure, this can be
* set to `true` to receive comment parsing and loading performance improvements.
*
* Leave this set to `false` if you are doing weird things with your data,
* or are having issues with migrating comments from old Meerkat versions.
*
* @since 2.1.6
* @var bool
*/
public $useSlimCommentPrototypeParser = false;

/**
* The comment length limit. If this limit is reached when
* reading the comment's content data will be truncated.
Expand Down
50 changes: 50 additions & 0 deletions src/Core/Contracts/Parsing/PrototypeParserContract.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace Stillat\Meerkat\Core\Contracts\Parsing;

use Stillat\Meerkat\Core\Configuration;

/**
* Interface PrototypeParserContract
*
* Represents a parser capable of converting a YAML
* text file into a Meerkat Comment prototype.
*
* @package Stillat\Meerkat\Core\Contracts\Parsing
* @since 2.1.6
*/
interface PrototypeParserContract
{

/**
* Sets the comment's truthy prototype elements.
*
* @param array $elements The truthy prototype elements.
*/
public function setTruthyElements($elements);

/**
* Sets the Meerkat Core configuration instance.
*
* @param Configuration $configuration The configuration.
*/
public function setConfig(Configuration $configuration);

/**
* Sets the prototype elements.
*
* @param array $elements The prototype elements.
*/
public function setPrototypeElements($elements);

/**
* Retrieves only the core meta-data for the comment.
*
* Supplemental data and content are ignored during this phase.
*
* @param string $path The full path to the comment data.
* @return array
*/
public function getCommentPrototype($path);

}
3 changes: 2 additions & 1 deletion src/Core/Parsing/CommentPrototypeParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Exception;
use Stillat\Meerkat\Core\Configuration;
use Stillat\Meerkat\Core\Contracts\Comments\CommentContract;
use Stillat\Meerkat\Core\Contracts\Parsing\PrototypeParserContract;
use Stillat\Meerkat\Core\Errors;
use Stillat\Meerkat\Core\Logging\ExceptionLoggerFactory;
use Stillat\Meerkat\Core\Logging\LocalErrorCodeRepository;
Expand All @@ -20,7 +21,7 @@
* @package Stillat\Meerkat\Core\Parsing
* @since 2.0.11
*/
class CommentPrototypeParser
class CommentPrototypeParser implements PrototypeParserContract
{
const UNIX_EPOCH_ID = '0000000000';

Expand Down
129 changes: 129 additions & 0 deletions src/Core/Parsing/FullCommentPrototypeParser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
<?php

namespace Stillat\Meerkat\Core\Parsing;

use Stillat\Meerkat\Core\Configuration;
use Stillat\Meerkat\Core\Contracts\Comments\CommentContract;
use Stillat\Meerkat\Core\Contracts\Parsing\PrototypeParserContract;
use Stillat\Meerkat\Core\Contracts\Parsing\YAMLParserContract;
use Stillat\Meerkat\Core\Storage\Drivers\Local\LocalCommentStorageManager;

/**
* Class FullCommentPrototypeParser
*
* Utilizes a full YAML-spec parser to produce a comment prototype.
*
* This prototype parser produces the most consistent results across a wide
* range of Comment data structures, but with a higher performance cost.
*
* @package Stillat\Meerkat\Core\Parsing
* @since 2.1.6
*/
class FullCommentPrototypeParser implements PrototypeParserContract
{

/**
* The prototype comment elements to parse.
*
* @var array
*/
protected $prototypeElements = [];

/**
* The Meerkat Core configuration.
*
* @var Configuration
*/
protected $config = null;

/**
* The prototype elements that should be converted to boolean values.
*
* @var array
*/
protected $truthyPrototypeElements = [];

/**
* The YAMLParserContract implementation instance.
*
* @var YAMLParserContract
*/
protected $yamlParser = null;

public function __construct(YAMLParserContract $yamlParser)
{
$this->yamlParser = $yamlParser;
}

/**
* Sets the comment's truthy prototype elements.
*
* @param array $elements The truthy prototype elements.
*/
public function setTruthyElements($elements)
{
$this->truthyPrototypeElements = $elements;
}

/**
* Sets the Meerkat Core configuration instance.
*
* @param Configuration $configuration The configuration.
*/
public function setConfig(Configuration $configuration)
{
$this->config = $configuration;
}

/**
* Sets the prototype elements.
*
* @param array $elements The prototype elements.
*/
public function setPrototypeElements($elements)
{
$this->prototypeElements = $elements;
}

/**
* Retrieves only the core meta-data for the comment.
*
* Supplemental data and content are ignored during this phase.
*
* @param string $path The full path to the comment data.
* @return array
*/
public function getCommentPrototype($path)
{
$contents = file_get_contents($path);
$parsedComment = $this->yamlParser->parseDocument($contents);
$commentContent = '';
$alreadyFoundContent = false;

if (array_key_exists(CommentContract::KEY_LEGACY_COMMENT, $parsedComment)) {
$commentContent = $parsedComment[CommentContract::KEY_LEGACY_COMMENT];
$alreadyFoundContent = true;

unset($parsedComment[CommentContract::KEY_LEGACY_COMMENT]);
} else if (array_key_exists(CommentContract::KEY_CONTENT, $parsedComment)) {
$commentContent = $parsedComment[CommentContract::KEY_CONTENT];

unset($parsedComment[CommentContract::KEY_CONTENT]);
}

// Reset some types.
if (array_key_exists(CommentContract::KEY_ID, $parsedComment)) {
if (is_int($parsedComment[CommentContract::KEY_ID])) {
$parsedComment[CommentContract::KEY_ID] = strval($parsedComment[CommentContract::KEY_ID]);
}
}

return [
LocalCommentStorageManager::KEY_HEADERS => $parsedComment,
LocalCommentStorageManager::KEY_RAW_HEADERS => $parsedComment,
LocalCommentStorageManager::KEY_CONTENT => $commentContent,
LocalCommentStorageManager::KEY_NEEDS_MIGRATION => $alreadyFoundContent
];
}

}
18 changes: 15 additions & 3 deletions src/Core/Storage/Drivers/Local/LocalCommentStorageManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use Stillat\Meerkat\Core\Contracts\Comments\CommentMutationPipelineContract;
use Stillat\Meerkat\Core\Contracts\Identity\IdentityManagerContract;
use Stillat\Meerkat\Core\Contracts\Parsing\MarkdownParserContract;
use Stillat\Meerkat\Core\Contracts\Parsing\PrototypeParserContract;
use Stillat\Meerkat\Core\Contracts\Parsing\YAMLParserContract;
use Stillat\Meerkat\Core\Contracts\Storage\CommentChangeSetStorageManagerContract;
use Stillat\Meerkat\Core\Contracts\Storage\CommentStorageManagerContract;
Expand All @@ -31,6 +32,7 @@
use Stillat\Meerkat\Core\Exceptions\MutationException;
use Stillat\Meerkat\Core\Logging\ExceptionLoggerFactory;
use Stillat\Meerkat\Core\Parsing\CommentPrototypeParser;
use Stillat\Meerkat\Core\Parsing\FullCommentPrototypeParser;
use Stillat\Meerkat\Core\Paths\PathUtilities;
use Stillat\Meerkat\Core\RuntimeStateGuard;
use Stillat\Meerkat\Core\Storage\Data\CommentAuthorRetriever;
Expand Down Expand Up @@ -219,9 +221,9 @@ class LocalCommentStorageManager implements CommentStorageManagerContract
private $changeSetManager = null;

/**
* The CommentPrototypeParser instance.
* The PrototypeParserContract implementation instance.
*
* @var CommentPrototypeParser
* @var PrototypeParserContract
*/
private $commentParser = null;

Expand All @@ -235,7 +237,13 @@ public function __construct(
IdentityManagerContract $identityManager,
CommentChangeSetStorageManagerContract $changeSetManager)
{
$this->commentParser = new CommentPrototypeParser();

if ($config->useSlimCommentPrototypeParser === false) {
$this->commentParser = new FullCommentPrototypeParser($yamlParser);
} else {
$this->commentParser = new CommentPrototypeParser();
}

$this->commentShadowIndex = new ShadowIndex($config);
$this->commentStructureResolver = new LocalCommentStructureResolver();
$this->authorRetriever = $authorRetriever;
Expand Down Expand Up @@ -395,6 +403,10 @@ private function getThreadHierarchy($threadPath, $threadId, $commentPaths)
$comment->setDataAttribute(CommentContract::INTERNAL_STRUCTURE_NEEDS_MIGRATION, true);
}

if ($this->config->useSlimCommentPrototypeParser === false) {
$comment->flagRuntimeAttributesResolved();
}

$commentPrototypes[$commentId] = $comment;
}

Expand Down
3 changes: 3 additions & 0 deletions src/ServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,9 @@ private function registerMeerkatGlobalConfiguration()
$globalConfiguration->searchableAttributes = $this->getConfig('search.attributes', []);
$globalConfiguration->onlyAcceptCommentsFromAuthenticatedUser = $this->getConfig('publishing.only_accept_comments_from_authenticated_users', false);

// Internal parser configuration.
$globalConfiguration->useSlimCommentPrototypeParser = $this->getConfig('internals.useFasterSlimCommentParser', false);

// Storage directories.
$globalConfiguration->storageDirectory = PathProvider::contentPath();
$globalConfiguration->indexDirectory = storage_path('meerkat/index');
Expand Down

0 comments on commit 2cf6119

Please sign in to comment.