gle string.
* @since 1.8.0
*/
public function getTestViews(PostBot $postBot, $postData, $viewVars = []) {
// Get a valid instance from the given value
$postSettings = $this->getPostSettingsImplInstanceFromPostBot($postBot);
// Add views defined for the custom post details
$postDetailViews = '';
$this->walkRegisteredFactories(function($factory) use (&$postData, &$postSettings, &$viewVars, &$postDetailViews) {
/** @var BasePostDetailFactory $factory */
// Check availability
if (!$factory->isAvailableForPost($postSettings)) return;
$detailTester = $factory->getTester();
if (!$detailTester || !is_a($detailTester, BasePostDetailTester::class)) return;
$detailView = $detailTester->getTesterView();
if (!$detailView) return;
// Inject required variables to the view, render, and combine with other views
$postDetailViews .= $detailView->with($viewVars)->with([
'detailData' => $factory->getDetailData(),
'postData' => $postData,
])->render();
}, $postBot);
return $postDetailViews;
}
/**
* Adds site tester assets of each available detail factory
*
* @since 1.8.0
*/
public function addSiteTesterAssets() {
$this->walkRegisteredFactories(function($factory) {
/** @var BasePostDetailFactory $factory */
$service = $factory->getService();
if (!$service || !is_a($service, BasePostDetailService::class)) return;
$service->addSiteTesterAssets();
});
}
/**
* Get duplicate check options from the factories.
*
* @param SettingsImpl $postSettings
* @return array|null An array having "values" and "defaults" keys, each having an array. If there is no option,
* returns null.
* @since 1.8.0
*/
public function getDuplicateOptions(SettingsImpl $postSettings) {
$allOptions = [
"values" => [],
"defaults" => [],
];
$this->walkRegisteredFactories(function($factory) use (&$postSettings, &$allOptions) {
/** @var BasePostDetailFactory $factory */
// Check availability
if (!$factory->isAvailableForPost($postSettings)) return;
// Get the duplicate checker
$duplicateChecker = $factory->getDuplicateChecker();
if (!$duplicateChecker) return;
// Get the options
$options = $duplicateChecker->getOptions();
if (!$options) return;
// Check for validity:
// 1. Values must exist
// 2. If defaults exist, they must have the same number of items as the values
// 3. If defaults exist, the values and the defaults have to have the same keys.
if (!isset($options["values"]) ||
(isset($options["defaults"]) && sizeof($options["values"]) !== sizeof($options["defaults"])) ||
(isset($options["defaults"]) && array_keys($options["values"]) !== array_keys($options["defaults"]))
) {
return;
}
// Get the values
$values = $options['values'];
// Get the defaults and prepare if they do not exist
$defaults = Utils::array_get($options, 'defaults');
if (!$defaults) {
$defaults = [];
foreach($values as $k => $v) {
$defaults[$k] = 0;
}
}
// Add the values and defaults to all options
$allOptions["values"] = array_merge($allOptions["values"], $values);
$allOptions["defaults"] = array_merge($allOptions["defaults"], $defaults);
});
// If the values array is not empty, return the results. Otherwise, return null.
return !empty($allOptions["values"]) ? $allOptions : null;
}
/**
* Calls the deleters of the registered factories.
*
* @since 1.8.0
* @param SettingsImpl $postSettings
* @param PostSaverData|null $saverData
*/
public function delete(SettingsImpl $postSettings, $saverData) {
$this->walkRegisteredFactories(function($factory) use (&$postSettings, $saverData) {
/** @var BasePostDetailFactory $factory */
// Check availability
if (!$factory->isAvailableForPost($postSettings)) return;
// Get the deleter
$deleter = $factory->getDeleter();
if (!$deleter || !is_a($deleter, BasePostDetailDeleter::class)) return;
// Check if the factory has any data
$detailData = $factory->getDetailData();
if (!$detailData || !is_a($detailData, BasePostDetailData::class)) return;
// Delete
$deleter->delete($postSettings, $detailData, $saverData);
});
}
/**
* Get category taxonomies defined by the post details
*
* @param null|SettingsImpl $postSettings
* @return array See {@link BasePostDetailService::getCategoryTaxonomies()}
* @since 1.8.0
*/
public function getCategoryTaxonomies($postSettings) {
$allTaxonomies = [];
$this->walkRegisteredFactories(function($factory) use (&$postSettings, &$allTaxonomies) {
/** @var BasePostDetailFactory $factory */
// Check availability
if ($postSettings && !$factory->isAvailableForPost($postSettings)) return;
// Get the service
$service = $factory->getService();
if (!$service || !is_a($service, BasePostDetailService::class)) return;
// Get the category taxonomies
$taxonomies = $service->getCategoryTaxonomies();
if (!$taxonomies) return;
// Collect them
$allTaxonomies = array_merge($allTaxonomies, $taxonomies);
});
return $allTaxonomies;
}
/**
* @param PostBot $postBot
* @param TranslatableTranslator $translator
* @since 1.8.0
*/
public function translate($postBot, $translator) {
// Get a valid instance from the given value
$postSettings = $this->getPostSettingsImplInstanceFromPostBot($postBot);
$this->walkRegisteredFactories(function($factory) use (&$postSettings, &$translator) {
/** @var BasePostDetailFactory $factory */
// Check availability
if ($postSettings && !$factory->isAvailableForPost($postSettings)) return;
// Get the data
$data = $factory->getDetailData();
if (!$data || !is_a($data, Translatable::class)) return;
// Try to translate
try {
/** @var Translatable $data */
$translator->setTranslatable($data);
$translator->translate();
} catch (\Exception $e) {
// Inform the user about the error
Informer::addError(
sprintf(_wpcc('Translation error for %1$s. Message: %2$s'), get_class($data), $e->getMessage())
)->setException($e)->addAsLog();
}
}, $postBot);
}
/**
* Invalidate all post detail factory instances
*
* @since 1.8.0
*/
public function invalidateFactoryInstances() {
BasePostDetailFactory::invalidateInstances();
}
/*
* PRIVATE METHODS
*/
/**
* @param callable $callbackGetMetaKeys Provide the meta keys to be merged using the detail settings. Returns a
* string array. For example: function(BasePostDetailSettings $settings) {
* return $settings->getSingleMetaKeys() }
* @param array $metaKeys Already-existing meta keys to which the meta keys retrieved from the
* settings will be added.
* @return array $metaKeys with the meta keys retrieved from the settings added
* @since 1.8.0
*/
private function addMetaKeys($callbackGetMetaKeys, $metaKeys = []) {
$this->walkRegisteredFactories(function($factory) use (&$callbackGetMetaKeys, &$metaKeys) {
/** @var BasePostDetailFactory $factory */
$settings = $factory->getSettings(null);
if (!$settings || !is_a($settings, BasePostDetailSettings::class)) return;
$detailMetaKeys = $callbackGetMetaKeys($settings);
if (!$detailMetaKeys) return;
$metaKeys = array_merge($metaKeys, $detailMetaKeys);
});
return $metaKeys;
}
/**
* Walks registered and available factories and calls the given callback.
*
* @param callable $callback A callback that will be called for each registered detail factory if it is available.
* It takes only one parameter $factory, which is a BasePostDetailFactory, and returns
* nothing. E.g. function($factory) {}
* @param null|PostBot $postBot See {@link BasePostDetailFactory::getRegisteredFactoryInstances()}
* @since 1.8.0
*/
private function walkRegisteredFactories($callback, $postBot = null) {
if (!$callback) return;
foreach(BasePostDetailFactory::getRegisteredFactoryInstances($postBot) as $factory) {
if (!$factory->isAvailable()) continue;
$callback($factory);
}
}
/**
* Get a post settings instance using a post bot
*
* @param PostBot $postBot
* @since 1.8.0
* @return SettingsImpl
*/
private function getPostSettingsImplInstanceFromPostBot($postBot) {
if ($postBot) return $postBot->getSettingsImpl();
return $this->getPostSettingsImplInstance(null);
}
/**
* @param SettingsImpl|array|null $postSettings
* @param bool $prepare True if the settings should be prepared. Otherwise, false.
* @return SettingsImpl
* @since 1.8.0
*/
private function getPostSettingsImplInstance($postSettings, $prepare = true) {
// If this is an instance, use it directly.
if (is_a($postSettings, SettingsImpl::class)) return $postSettings;
// Otherwise, make sure it is an array.
if (!$postSettings || !is_array($postSettings)) {
$postSettings = [];
}
// Create an instance
return new SettingsImpl($postSettings, Factory::postService()->getSingleMetaKeys(), $prepare);
}
}