Skip to content

Instantly share code, notes, and snippets.

@mdcpepper
Last active September 1, 2017 10:15
Show Gist options
  • Save mdcpepper/454a3184e79d96da1b58c46f478c4e4f to your computer and use it in GitHub Desktop.
Save mdcpepper/454a3184e79d96da1b58c46f478c4e4f to your computer and use it in GitHub Desktop.
<?php
/**
* Get the content of a field for use in BaseElementModel::setContentFromPost()
*
* @param BaseElementModel $sourceElement The element in the source locale
* @param BaseElementModel $targetElement The element in the target locale
* @param FieldModel $field The field to migrate
*/
private function _getMigratedFieldContent(BaseElementModel $sourceElement, BaseElementModel $targetElement = null, FieldModel $field, $force = false)
{
// If no target element has been passed, then we're getting the content for a new matrix
// block that doesn't yet exist on the target, so use the source element
if (!$targetElement)
{
$targetElement = $sourceElement;
}
$fieldHandle = $field->handle;
$fieldType = $field->type;
$sourceLocale = $sourceElement->locale;
$targetLocale = $targetElement->locale;
// Determine which element to get the content from, source or target.
// If the targetElement already has content for this field, don't migrate
// anything and use its already-existing content
if ($this->_isEmpty($targetElement, $field) || !!$force)
{
// The target element's content for this field is empty, or it's being forced, so pull the content from the source element
$element = $sourceElement;
}
else
{
// The target element already has content set for this field, so use that
$element = $targetElement;
}
switch ($fieldType)
{
// Fields that do not need any transforming and are returned as-is
case 'PlainText':
case 'Number':
case 'Lightswitch':
case 'PositionSelect':
{
return $element->$fieldHandle;
}
// Checkboxes are returned as an array of selected values
case 'Checkboxes':
{
$selected = array();
foreach($element->$fieldHandle->getOptions() as $option)
{
if ($option->selected)
{
$selected[] = $option->value;
}
}
return $selected;
}
// Dropdown fields return their selected value
case 'Dropdown':
{
if ($element->$fieldHandle)
{
return $element->$fieldHandle->value;
}
}
// Dates are returned in MYSQL_DATETIME format
case 'Date':
{
if ($element->$fieldHandle)
{
return $element->$fieldHandle->format(DateTime::MYSQL_DATETIME);
}
}
// RichText fields return the raw content with reference tags intact
case 'RichText':
{
if ($element->$fieldHandle instanceof RichTextData)
{
return $element->$fieldHandle->getRawContent();
}
}
// Matrix fields are a little more complicated..
case 'Matrix':
{
// to get all the content of the fields inside the Matrix
return $this->_getMatrixContent($element, $field, $sourceLocale, $targetLocale);
}
// Relation fields return an array of their related IDs
case 'Assets':
case 'Categories':
case 'Entries':
case 'Tags':
case 'Users':
{
$ids = $element->$fieldHandle->ids();
return empty($ids) ? null : $ids;
}
// Table fields return the col1, col2, etc values
case 'Table':
{
$table = array();
if ($element->$fieldHandle)
{
foreach($element->$fieldHandle as $row)
{
$newRow = array();
$numCols = count($row) / 2;
for ($i=1; $i <= $numCols; $i++)
{
$newRow['col'.$i] = $row['col'.$i];
}
$table[] = $newRow;
}
}
return $table;
}
}
/**
* Returns the content for a matrix field
*
* @param BaseElementModel $element
* @param FieldModel $field
* @param string $targetLocale
*
* @return array An array of blocks, or just null
*/
private function _getMatrixContent($element, $field, $targetLocale)
{
$fieldHandle = $field->handle;
// There's no blocks at all
if (null === $element->$fieldHandle)
{
return null;
}
$sourceBlocks = $element->$fieldHandle->status(null)->limit(null)->find();
$targetBlocks = array();
foreach($sourceBlocks as $index => $sourceBlock)
{
// Set the properties of the new block
$targetBlock = array(
'type' => $sourceBlock->getType()->handle,
'enabled' => (bool) $sourceBlock->enabled,
'locale' => $targetLocale,
'fields' => array(),
);
// For each of the fields in the source block's field layout
foreach($sourceBlock->getFieldLayout()->getFields() as $fieldLayoutField)
{
// Get the actual field
$field = $fieldLayoutField->getField();
// And the field handle
$fieldHandle = $field->handle;
// Get the value of the field for use in setContentFromPost.
$targetBlock['fields'][$fieldHandle] = $this->_getMigratedFieldContent($sourceBlock, null, $field);
}
$targetBlocks["new".($index+1)] = $targetBlock;
}
return $targetBlocks;
}
/**
* Determine whether a field has any content or not
*
* @param BaseElementModel $element
* @param FieldModel $field
*
* @return bool Whether the field has any content or not
*/
private function _isEmpty($element, FieldModel $field)
{
$elementId = $element->id;
$fieldHandle = $field->handle;
$fieldType = $field->type;
// If accessing the field directly returns a true or empty response,
// it's safe to consider it empty
if (is_null($element->$fieldHandle) || empty($element->$fieldHandle))
{
//EmigratePlugin::log("\n\n".$fieldHandle." in ".$element->locale." is empty\n");
return true;
}
// Relations / Matrix fields are empty if the result count is 0
if ($element->$fieldHandle instanceof ElementCriteriaModel)
{
if ($element->$fieldHandle->count() === 0)
{
return true;
}
else
{
return false;
}
}
// Rich Text fields return a \Twig_Markup object
if ($fieldType == 'RichText')
{
if ((string) TemplateHelper::getRaw($element->$fieldHandle) == '')
{
return true;
}
else
{
return false;
}
}
// TODO: Allow for plugins to determine whether a field is empty or not
return false;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment