1. Go to this page and download the library: Download getpop/component-model library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
// Layout on the left uses default configuration of thumbnail on top of the text
Component("post-layout")->setProp({
prop: "classes",
value: {
wrapper: "",
thumb: "",
contentbody: ""
}
});
// Layout on the center display a big thumbnail to the left of the text
Component("central-section")->setProp({
componentpath: ["post-layout"],
prop: "classes",
value: {
wrapper: "row",
thumb: "col-sm-4",
contentbody: "col-sm-8"
}
});
// Layout on the floating window display a small thumbnail to the left of the text
Component("floating-window")->setProp({
componentpath: ["post-layout"],
prop: "classes",
value: {
wrapper: "media",
thumb: "media-left",
contentbody: "media-body"
}
});
// Retrieve the PoP_ComponentProcessor_Manager object from the factory
$componentprocessor_manager = \PoP\Engine\ComponentProcessor_Manager_Factory::getInstance();
// Obtain the ComponentProcessor for component COMPONENT_SOMENAME
$processor = $componentprocessor_manager->getComponentProcessor(new \PoP\ComponentModel\Component\Component(SomeComponentProcessor::class, SomeComponentProcessor::COMPONENT_SOMENAME));
// Do something...
// $processor->...
class SomeComponentProcessor extends \PoP\Engine\AbstractComponentProcessor {
function foo($component)
{
// First obtain the value from the parent class
$ret = parent::foo($component);
// Add properties to the component
switch ($component->name)
{
case self::COMPONENT_SOMENAME1:
// Do something with $ret
// ...
break;
// These components share the same properties
case self::COMPONENT_SOMENAME2:
case self::COMPONENT_SOMENAME3:
// Do something with $ret
// ...
break;
}
return $ret;
}
}
class SomeComponentProcessor extends \PoP\Engine\AbstractComponentProcessor {
function foo($component, &$atts)
{
$ret = parent::foo($component, &$atts);
// ...
return $ret;
}
}
class SomeComponentProcessor extends \PoP\Engine\AbstractComponentProcessor {
function getSubcomponents($component)
{
$ret = parent::getSubcomponents($component);
switch ($component->name)
{
case self::COMPONENT_SOMENAME1:
$ret[] = self::COMPONENT_SOMENAME2;
break;
case self::COMPONENT_SOMENAME2:
case self::COMPONENT_SOMENAME3:
$ret[] = new \PoP\ComponentModel\Component\Component(LayoutComponentProcessor::class, LayoutComponentProcessor::COMPONENT_LAYOUT1);
$ret[] = new \PoP\ComponentModel\Component\Component(LayoutComponentProcessor::class, LayoutComponentProcessor::COMPONENT_LAYOUT2);
$ret[] = new \PoP\ComponentModel\Component\Component(LayoutComponentProcessor::class, LayoutComponentProcessor::COMPONENT_LAYOUT3);
break;
}
return $ret;
}
}
abstract class PostLayoutAbstractComponentProcessor extends \PoP\Engine\AbstractComponentProcessor {
function getSubcomponents($component) {
$ret = parent::getSubcomponents($component);
if ($thumbnail_component = $this->getThumbnailComponent($component))
{
$ret[] = $thumbnail_component;
}
if ($content_component = $this->getContentComponent($component))
{
$ret[] = $content_component;
}
if ($aftercontent_components = $this->getAftercontentComponents($component))
{
$ret = array_merge(
$ret,
$aftercontent_components
);
}
return $ret;
}
protected function getContentComponent($component)
{
// Must implement
return null;
}
protected function getThumbnailComponent($component)
{
// Default value
return self::COMPONENT_LAYOUT_THUMBNAILSMALL;
}
protected function getAftercontentComponents($component)
{
return array();
}
}
class PostLayoutComponentProcessor extends PostLayoutAbstractComponentProcessor {
protected function getContentComponent($component)
{
switch ($component->name)
{
case self::COMPONENT_SOMENAME1:
return self::COMPONENT_LAYOUT_POSTCONTENT;
case self::COMPONENT_SOMENAME2:
case self::COMPONENT_SOMENAME3:
return self::COMPONENT_LAYOUT_POSTEXCERPT;
}
return parent::getContentComponent($component);
}
protected function getThumbnailComponent($component)
{
switch ($component->name)
{
case self::COMPONENT_SOMENAME1:
return self::COMPONENT_LAYOUT_THUMBNAILBIG;
case self::COMPONENT_SOMENAME3:
return self::COMPONENT_LAYOUT_THUMBNAILMEDIUM;
}
return parent::getThumbnailComponent($component);
}
protected function getAftercontentComponents($component)
{
$ret = parent::getAftercontentComponents($component);
switch ($component->name)
{
case self::COMPONENT_SOMENAME2:
$ret[] = self::COMPONENT_LAYOUT_POSTLIKES;
break
}
return $ret;
}
}
// Initialize
new PostLayoutComponentProcessor();
function initModelProps($component, &$props)
{
// Set prop...
// Set prop...
// Set prop...
parent::initModelProps($component, $props);
}
function initModelProps($component, &$props)
{
switch ($component->name) {
case self::COMPONENT_MAP:
// Component "map" is setting the default value
$this->setProp($component, $props, 'orientation', 'vertical');
// Obtain the value from the prop
$orientation = $this->getProp($component, $props, 'orientation');
// Set the value on "map-inner"
$this->setProp([[SomeComponent::class, SomeComponent::COMPONENT_MAPINNER]], $props, 'orientation', $orientation);
break;
}
parent::initModelProps($component, $props);
}
function initModelProps($component, &$props)
{
switch ($component->name) {
case self::COMPONENT_MAPWRAPPER:
$this->setProp([[SomeComponent::class, SomeComponent::COMPONENT_MAP]], $props, 'orientation', 'horizontal');
break;
}
parent::initModelProps($component, $props);
}
function getDatasource($component, &$props)
{
switch ($component->name) {
case self::COMPONENT_WHOWEARE:
return \PoP\ComponentModel\Constants\DataSources::IMMUTABLE;
}
return parent::getDatasource($component, $props);
}
function getDbobjectIds($component, &$props, $data_properties)
{
switch ($component->name) {
case self::COMPONENT_WHOWEARE:
return [13, 54, 998];
}
return parent::getDbobjectIds($component, $props, $data_properties);
}
function getDataloader($component)
{
switch ($component->name) {
case self::COMPONENT_AUTHORARTICLES:
return [Dataloader::class, Dataloader::DATALOADER_POSTLIST];
}
return parent::getDataloader($component);
}
protected function getImmutableDataloadQueryArgs($component, $props)
{
$ret = parent::getImmutableDataloadQueryArgs($component, $props);
switch ($component->name) {
case self::COMPONENT_AUTHORARTICLES:
// 55: id of "Articles" category
$ret['cat'] = 55;
break;
}
return $ret;
}
protected function getMutableonrequestDataloadQueryArgs($component, $props)
{
$ret = parent::getMutableonrequestDataloadQueryArgs($component, $props);
switch ($component->name) {
case self::COMPONENT_AUTHORARTICLES:
// Set the logged-in user id
$cmsapi = \PoP\CMS\FunctionAPI_Factory::getInstance();
$ret['author'] = $cmsapi->getCurrentUserID();
break;
}
return $ret;
}
function getFilter($component)
{
switch ($component->name) {
case self::COMPONENT_AUTHORARTICLES:
return GD_FILTER_AUTHORARTICLES;
}
return parent::getFilter($component);
}
function getQueryhandler($component)
{
switch ($component->name) {
case self::COMPONENT_AUTHORARTICLES:
return GD_DATALOAD_QUERYHANDLER_LIST;
}
return parent::getQueryhandler($component);
}
function getImmutableHeaddatasetcomponentDataProperties($component, &$props)
{
$ret = parent::getImmutableHeaddatasetcomponentDataProperties($component, $props);
switch ($component->name) {
case self::COMPONENT_AUTHORARTICLES:
// Make it not fetch more results
$ret[GD_DATALOAD_QUERYHANDLERPROPERTY_LIST_STOPFETCHING] = true;
break;
}
return $ret;
}
function initModelProps($component, &$props)
{
switch ($component->name) {
case self::COMPONENT_AUTHORARTICLES:
// Set the content lazy
$this->setProp($component, $props, 'skip-data-load', true);
break;
}
parent::initModelProps($component, $props);
}
function getRelationalComponentFieldNodes($component)
{
$ret = parent::getRelationalComponentFieldNodes($component);
switch ($component->name) {
case self::COMPONENT_AUTHORARTICLES:
$ret['author'] = [
POP_CONSTANT_SUBCOMPONENTDATALOADER_DEFAULTFROMFIELD => [
new \PoP\ComponentModel\Component\Component(SomeComponentProcessor::class, SomeComponentProcessor::COMPONENT_AUTHORNAME),
]
];
$ret['comments'] = [
POP_CONSTANT_SUBCOMPONENTDATALOADER_DEFAULTFROMFIELD => [
new \PoP\ComponentModel\Component\Component(SomeComponentProcessor::class, SomeComponentProcessor::COMPONENT_COMMENTLAYOUT),
]
];
break;
}
return $ret;
}
function executeGetData($ids) {
$objects = array();
// Fetch all objects with IDs $ids
// ...
return $objects;
}
function executeGetData($ids) {
$cmsapi = \PoP\CMS\FunctionAPI_Factory::getInstance();
$query = array(
'
function getDatabaseKey()
{
return GD_DATABASE_KEY_POSTS;
}
function getFieldprocessor()
{
return GD_DATALOAD_FIELDPROCESSOR_POSTS;
}
function getDbobjectIds($data_properties) {
$ids = array();
// Find the IDs of the objects to be fetched
// ...
return $ids;
}
function getDbobjectIds($data_properties) {
// Simply return the global $post ID.
$vars = \PoP\ComponentModel\Engine_Vars::getVars();
return array($vars['global-state']['queried-object-id']);
}
function getQuery($query_args)
{
$query = array();
// Add all the conditions in $query, taking values from $query_args
// ...
return $query;
}
function executeQueryIDs($query) {
$ids = array();
// Find the IDs of the objects to be fetched
// ...
return $ids;
}
function getQuery($query_args) {
return $query_args;
}
function executeQueryIDs($query) {
$cmsapi = \PoP\CMS\FunctionAPI_Factory::getInstance();
return $cmsapi->getPosts($query, [QueryOptions::RETURN_TYPE => ReturnTypes::IDS]);
}
class ObjectTypeFieldResolver_Posts extends \PoP\Engine\AbstractObjectTypeFieldResolver {
function getValue($resultitem, $field) {
// First Check if there's a ObjectTypeFieldResolverExtension to implement this field
$hook_value = $this->getHookValue(GD_DATALOAD_FIELDPROCESSOR_POSTS, $resultitem, $field);
if (!\PoP\ComponentModel\GeneralUtils::isError($hook_value)) {
return $hook_value;
}
$cmsresolver = \PoP\CMS\ObjectPropertyResolver_Factory::getInstance();
$cmsapi = \PoP\CMS\FunctionAPI_Factory::getInstance();
$post = $resultitem;
switch ($field)
{
case 'tags' :
$value = $cmsapi->getCustomPostTags($this->getId($post), [], array('fields' => 'ids'));
break;
case 'title' :
$value = \PoP\CMS\HooksAPI_Factory::getInstance()->applyFilters('the_title', $cmsresolver->getPostTitle($post), $this->getId($post));
break;
case 'content' :
$value = $cmsresolver->getPostContent($post);
$value = \PoP\CMS\HooksAPI_Factory::getInstance()->applyFilters('pop_content_pre', $value, $this->getId($post));
$value = \PoP\CMS\HooksAPI_Factory::getInstance()->applyFilters('the_content', $value);
$value = \PoP\CMS\HooksAPI_Factory::getInstance()->applyFilters('pop_content', $value, $this->getId($post));
break;
case 'url' :
$value = $cmsapi->getPermalink($this->getId($post));
break;
case 'excerpt' :
$value = $cmsapi->getTheExcerpt($this->getId($post));
break;
case 'comments' :
$query = array(
'status' => 'approve',
'type' => 'comment',
'post_id' => $this->getId($post),
'order' => 'ASC',
'orderby' => 'comment_date_gmt',
);
$comments = $cmsapi->getComments($query);
$value = array();
foreach ($comments as $comment) {
$value[] = $cmsresolver->getCommentID($comment);
}
break;
case 'author' :
$value = $cmsresolver->getPostAuthor($post);
break;
default:
$value = parent::getValue($resultitem, $field);
break;
}
return $value;
}
}
function getFieldDefaultDataloader($field)
{
switch ($field)
{
case 'tags' :
return GD_DATALOADER_TAGLIST;
case 'comments' :
return GD_DATALOADER_COMMENTLIST;
case 'author' :
return GD_DATALOADER_CONVERTIBLEUSERLIST;
}
return parent::getFieldDefaultDataloader($field);
}
class ObjectTypeFieldResolver_Posts_Hook extends \PoP\Engine\ObjectTypeFieldResolver_HookBase {
function getClassesToAttachTo() {
return array(
[ObjectTypeFieldResolver::class, ObjectTypeFieldResolver::FIELDPROCESSOR_POSTS],
);
}
function getValue($resultitem, $field, $fieldprocessor)
{
$post = $resultitem;
switch ($field)
{
case 'disclaimer':
return \PoP\Engine\MetaManager::getCustomPostMeta($fieldprocessor->getId($post), "disclaimer", true);
}
return parent::getValue($resultitem, $field, $fieldprocessor);
}
}
class TextFilterInputs extends TextFormInputsBase implements \PoP\ComponentModel\DataloadQueryArgsFilter
{
public function filterDataloadQueryArgs(array &$query, $component, $value)
{
switch ($component->name)
{
case self::COMPONENT_FILTERINPUT_SEARCH:
$query['search'] = $value;
break;
}
}
}
function getActionExecuterClass($component) {
switch ($component->name) {
case self::COMPONENT_SOMENAME:
return SomeActionExecuter::class;
}
return parent::getActionExecuterClass($component);
}
function execute(&$data_properties) {
// Execute some operation and return the results
// ...
return $results;
}
class ActionExecuter_Logout extends \PoP\Engine\AbstractActionExecuter {
function execute(&$data_properties)
{
if ('POST' == \PoP\Root\App::server('REQUEST_METHOD')) {
// If the user is not logged in, then return the error
$vars = \PoP\ComponentModel\Engine_Vars::getVars();
if (!$vars['global-userstate']['is-user-logged-in'])
{
$error = __('You are not logged in.');
// Return error string
return array(
GD_DATALOAD_QUERYHANDLERRESPONSE_ERRORSTRINGS => array($error)
);
}
$cmsapi = \PoP\CMS\FunctionAPI_Factory::getInstance();
$cmsapi->logout();
return array(
GD_DATALOAD_QUERYHANDLERRESPONSE_SUCCESS => true
);
}
return parent::execute($data_properties);
}
}
function execute(&$data_properties)
{
if ('POST' == \PoP\Root\App::server('REQUEST_METHOD'))
{
// Function getFormData obtains the filled-in values in the form
$form_data = $this->getFormData();
$errors = array();
if (empty($form_data['post_id'])) {
$errors[] = __('We don\'t know what post the comment is for.');
}
if (empty($form_data['comment'])) {
$errors[] = __('The comment is empty.');
}
if ($errors)
{
return array(
GD_DATALOAD_QUERYHANDLERRESPONSE_ERRORSTRINGS => $errors
);
}
$cmsapi = \PoP\CMS\FunctionAPI_Factory::getInstance();
$comment_id = $cmsapi->insertComment($form_data);
// Save the result
$actionexecution_manager = \PoP\Engine\ActionExecution_Manager_Factory::getInstance();
$actionexecution_manager->setResult($this->get_name(), $comment_id);
// No errors => success
return array(
GD_DATALOAD_QUERYHANDLERRESPONSE_SUCCESS => true
);
}
return parent::execute($data_properties);
}
function prepareDataPropertiesAfterMutationExecution($component, &$props, &$data_properties) {
parent::prepareDataPropertiesAfterMutationExecution($component, $props, $data_properties);
switch ($component->name) {
case self::COMPONENT_ADDCOMMENT:
$actionexecution_manager = \PoP\Engine\ActionExecution_Manager_Factory::getInstance();
if ($comment_id = $actionexecution_manager->getResult(GD_DATALOAD_ACTIONEXECUTER_ADDCOMMENT))
{
$data_properties[GD_DATALOAD_QUERYARGS]['
function getDataAccessCheckpoints($component, &$props)
{
switch ($component->name) {
case self::COMPONENT_SOMECOMPONENT:
return [CHECKPOINT_WHITELISTEDIP];
}
return parent::getDataAccessCheckpoints($component, $props);
}
function getRelevantPage($component, &$props) {
switch ($component->name) {
case self::COMPONENT_MYPOSTS_SCROLL:
case self::COMPONENT_MYPOSTS_CAROUSEL:
case self::COMPONENT_MYPOSTS_TABLE:
return POP_PAGE_MYPOSTS;
}
return parent::getRelevantPage($component, $props);
}
class WhitelistedIPCheckpoint extends \PoP\Engine\AbstractCheckpoint {
function validateCheckpoint()
{
// Validate the user's IP
$ip = get_client_ip();
if (!$ip) {
return new \PoP\ComponentModel\Error\Error('ipempty');
}
$whitelisted_ips = array(...);
if (!in_array($ip, $whitelisted_ips)) {
return new \PoP\ComponentModel\Error\Error('ipincorrect');
}
return parent::validateCheckpoint();
}
}