1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-25 07:41:30 +02:00

Add support for export/import of comments fields (FieldtypeComments)

This commit is contained in:
Ryan Cramer
2017-08-17 09:38:06 -04:00
parent b30c6a4ec8
commit 74a2b001cc
4 changed files with 260 additions and 12 deletions

View File

@@ -758,6 +758,49 @@ function wireClassParents($className, $autoload = true) {
return $a;
}
/**
* Does given instance (or class) represent an instance of the given className (or class names)?
*
* @param object|string $instance Object instance to test (or string of its class name).
* @param string|array $className Class name or array of class names to test against.
* @param bool $autoload
* @return bool|string Returns one of the following:
* - boolean false if not an instance (whether $className argument is string or array).
* - boolean true if given a single $className (string) and $instance is an instance of it.
* - string of first matching class name if $className was an array of classes to test.
*
*/
function wireInstanceOf($instance, $className, $autoload = true) {
if(is_array($className)) {
$returnClass = true;
$classNames = $className;
} else {
$returnClass = false;
$classNames = array($className);
}
$matchClass = null;
$instanceParents = null;
foreach($classNames as $className) {
$className = wireClassName($className, true); // with namespace
if(is_object($instance) && class_exists($className, $autoload)) {
if($instance instanceof $className) $matchClass = $className;
} else {
if(is_null($instanceParents)) {
$instanceParents = wireClassParents($instance, $autoload);
$instanceClass = is_string($instance) ? $instance : wireClassName($instance, true);
$instanceParents[$instanceClass] = 1;
}
if(isset($parents[$className])) $matchClass = $className;
}
if($matchClass !== null) break;
}
return $returnClass ? $matchClass : ($matchClass !== null);
}
/**
* ProcessWire namespace aware version of PHP's is_callable() function
*

View File

@@ -755,12 +755,8 @@ class PagesExportImport extends Wire {
);
// fake-commit for more verbose testing of certain fieldtypes
$fakeCommit = false;
if(!$options['commit']) {
// we fake-commit Page refs so that validity is tested and errors known before commit
if($field->type instanceof FieldtypePage) $fakeCommit = true;
if($field->type instanceof FieldtypeRepeater) $fakeCommit = true;
}
$fakeCommitTypes = array('FieldtypePage', 'FieldtypeRepeater', 'FieldtypeComments');
$fakeCommit = $options['commit'] || wireInstanceOf($field->type, $fakeCommitTypes);
if($page->get('_importType') == 'create' && !$options['commit'] && !$fakeCommit) {
// test import on a new page, so value will always be used
@@ -1141,11 +1137,14 @@ class PagesExportImport extends Wire {
$exportable = true;
$reason = '';
if($fieldtype instanceof FieldtypeFile) {
// files are allowed
} else if($fieldtype instanceof FieldtypeRepeater) {
// repeaters are allowed
$extraType = wireInstanceOf($fieldtype, array(
'FieldtypeFile',
'FieldtypeRepeater',
'FieldtypeComments',
));
if($extraType) {
// extra identified types are allowed
} else if($fieldtype instanceof FieldtypeFieldsetOpen || $fieldtype instanceof FieldtypeFieldsetClose) {
// fieldsets not exportable

View File

@@ -119,6 +119,14 @@ class Comment extends WireData {
*/
protected $_parent = null;
/**
* Quiet mode, when true actions like notification emails aren't triggered when applicable
*
* @var bool
*
*/
protected $quiet = false;
/**
* Construct a Comment and set defaults
*
@@ -375,6 +383,22 @@ class Comment extends WireData {
return $comments->renderStars(false, $options);
}
/**
* Get or set quiet mode
*
* When quiet mode is active, comment additions/changes don't trigger notifications and such.
*
* @param bool $quiet Specify only if setting
* @return bool The current quiet mode
*
*/
public function quiet($quiet = null) {
if(is_bool($quiet)) $this->quiet = $quiet;
return $this->quiet;
}
}

View File

@@ -246,6 +246,8 @@ class FieldtypeComments extends FieldtypeMulti {
*
*/
protected function checkExistingComment(Page $page, Field $field, Comment $comment) {
if($comment->quiet()) return;
$submitSpam = false;
$submitHam = false;
@@ -312,7 +314,7 @@ class FieldtypeComments extends FieldtypeMulti {
*/
protected function checkNewComment(Page $page, Field $field, Comment $comment) {
if($comment->id) return;
if($comment->id || $comment->quiet()) return;
$this->checkCommentCodes($comment);
@@ -1511,5 +1513,185 @@ class FieldtypeComments extends FieldtypeMulti {
parent::___renamedField($field, $prevName);
}
/**
* Export Comment to array
*
* @param Comment|array $comment
* @return array
*
*/
protected function exportComment($comment) {
if(is_object($comment)) $comment = $comment->getArray();
if(isset($comment['created_users_id'])) {
$u = $this->wire('users')->get((int) $comment['created_users_id']);
$comment['created_user'] = $u->name;
unset($comment['created_users_id']);
}
return $comment;
}
/**
* Export Comments to array
*
* @param CommentArray|array $comments
* @return array
*
*/
protected function exportComments($comments) {
$commentsArray = array();
$exportComments = array();
foreach($comments as $comment) {
if($comment['status'] == Comment::statusSpam) continue; // don't export spam
$commentsArray[(int) $comment['id']] = $comment; // index by comment id
}
foreach($commentsArray as $id => $comment) {
$key = $this->getCommentExportKey($comment);
$comment = $this->exportComment($comment);
if(!empty($comment['parent_id'])) {
$parentID = (int) $comment['parent_id'];
$parent = isset($commentsArray[$parentID]) ? $commentsArray[$parentID] : null;
if($parent) $comment['parent_key'] = $this->getCommentExportKey($parent);
}
$exportComments[$key] = $comment;
}
return $exportComments;
}
/**
* Get key used for exporting a comment
*
* @param Comment|array $comment
* @return string
*
*/
protected function getCommentExportKey($comment) {
return "$comment[created] $comment[email]";
}
/**
* Export value
*
* @param Page $page
* @param Field $field
* @param array|int|object|string $value
* @param array $options
* @return array|string
*
*/
public function ___exportValue(Page $page, Field $field, $value, array $options = array()) {
$exportValue = array_values($this->exportComments($value));
return $exportValue;
}
/**
* Import value
*
* Note: importValue does not delete comments, only insert or update.
*
* @param Page $page
* @param Field $field
* @param array $value
* @param array $options
* @return array|string
*
*/
public function ___importValue(Page $page, Field $field, $value, array $options = array()) {
$value = $this->exportComments($value);
$comments = $page->get($field->name);
$commentsArray = array();
$addComments = array();
$updateComments = array();
$skipImportComments = array();
$updatePropertyCounts = array();
$skipUpdateProperties = array('id', 'created_user', 'created_users_id');
foreach($comments as $comment) {
if($comment->status == Comment::statusSpam) continue;
$key = $this->getCommentExportKey($comment);
$commentsArray[$key] = $comment;
}
foreach($value as $key => $importCommentArray) {
if(!empty($importCommentArray['parent_key'])) {
$parentKey = $importCommentArray['parent_key'];
if(!isset($commentsArray[$parentKey])) {
$skipImportComments[$key] = $importCommentArray;
continue;
}
$importCommentArray['parent_id'] = $commentsArray[$parentKey]['id'];
unset($importCommentArray['parent_key']);
}
if(!isset($commentsArray[$key])) {
$addComments[$key] = $importCommentArray;
continue;
}
$comment = $commentsArray[$key];
$commentArray = $this->exportComment($comment);
foreach($skipUpdateProperties as $property) {
unset($commentArray[$property]);
unset($importCommentArray[$property]);
}
if($commentArray == $importCommentArray) continue; // no changes
foreach($importCommentArray as $k => $v) {
if(isset($commentArray[$k]) && $commentArray[$k] == $v) continue;
$comment->set($k, $v);
$comment->quiet(true);
$updateComments[$key] = $comment;
if(!isset($updatePropertyCounts[$k])) $updatePropertyCounts[$k] = 0;
$updatePropertyCounts[$k]++;
}
}
foreach($addComments as $commentArray) {
unset($commentArray['id']);
$u = $this->wire('users')->get("name=" . $this->wire('sanitizer')->pageName($commentArray['created_user']));
$commentArray['created_users_id'] = $u->id;
unset($commentArray['created_user']);
$comment = $this->makeComment($page, $field, $commentArray);
$comment->quiet(true);
$comments->add($comment);
}
$numAddComments = count($addComments);
$numUpdateComments = count($updateComments);
$numSkipComments = count($skipImportComments);
if($numAddComments) {
$comments->message("$field->name: $numAddComments new added");
}
if($numUpdateComments) {
$counts = array();
foreach($updatePropertyCounts as $property => $count) {
$counts[] = "$property ($count)";
}
$comments->message("$field->name: $numUpdateComments updated - " . implode(', ', $counts));
$comments->trackChange('value');
}
if($numSkipComments) {
$comments->warning(
"$field->name: $numSkipComments skipped because parent comment(s) not yet present (run import again)"
);
}
return $comments;
}
}