Skip to content

Instantly share code, notes, and snippets.

@bigin
Created January 27, 2019 10:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bigin/7ace7c26314fc394b83a38498c3a0c09 to your computer and use it in GitHub Desktop.
Save bigin/7ace7c26314fc394b83a38498c3a0c09 to your computer and use it in GitHub Desktop.
<?php
$thisfile = basename(__FILE__, '.php');
register_plugin(
$thisfile,
'ItemManager\'s Extension',
'0.1',
'Your name',
'https://your-site.com',
'An ItemManger admin extension.',
'',
''
);
add_action('ImActivated', 'im_action');
function im_action($manager) {
if(!class_exists('AdminExtended'))
{
class AdminExtended extends Admin
{
protected function callModelMethod($method, $args)
{
if($method == 'saveItem') {
$this->beforeItemSave($args);
parent::callModelMethod($method, $args);
} elseif($method == 'deleteItem') {
$this->beforeItemDelete($args[0], $args[1]);
parent::callModelMethod($method, $args);
} else {
parent::callModelMethod($method, $args);
}
}
/**
* Here you can override native item-editor view of the ItemManager
* admin area.
*/
protected function buildItemEditor()
{
// Get the item ID
$id = !empty($this->input['edit']) ? (int) $this->input['edit'] :
(isset($this->input['iid']) ? (int) $this->input['iid'] : null);
// Get current category
$category = $this->manager->getCategoryMapper()->getCategory($this->manager->cp->currentCategory());
// Run a native IM method if this isn't an item of a different category
if(!isset($category) || $category->name != 'Countries') {
return parent::buildItemEditor();
}
////////////////////////////////////////////////////////////////////////////////////////////
//
// OK, this seems to be an item of the category where you want to show your dropdown field.
// Below you could write your own code to show the Admin-Editor for the items, but I will
// just copy most of the code from the original function and only partly add my own logic
// to it.
//
////////////////////////////////////////////////////////////////////////////////////////////
// Get our templates
$itemeditor = $this->tpl->getTemplates('itemeditor');
// We comment default 'form' template out, since we will use our own - See below 'getEditorWrapper()'
// method.
//$form = $this->tpl->getTemplate('form', $itemeditor);
$fieldarea = $this->tpl->getTemplate('fieldarea', $itemeditor);
$infotext = $this->tpl->getTemplate('infotext', $itemeditor);
$required = $this->tpl->getTemplate('required', $itemeditor);
$categoryid = $category->id;
$backpage = !empty($this->input['page']) ? intval($this->input['page']) : 1;
$stamp = !empty($this->input['timestamp']) ? $this->input['timestamp'] : time();
$ic = $this->manager->getItemMapper();
$ic->limitedInit($categoryid, $id);
$curitem = !empty($ic->items[$id]) ? $ic->items[$id] : null;
// Is a new item
if(!$curitem) {
$curitem = new Item($categoryid);
$active = $this->manager->config->backend->itemactive;
} else {
$active = $curitem->active;
}
//
// Let's start building our dropdown right here:
// First we get all items from the category 'Cities' to display them in a dropdown field.
//
$citiesCategory = $this->manager->getCategoryMapper()->getCategory('name=Cities');
$ic->alloc($citiesCategory->id);
// Get the value of the hidden field 'data' to retrieve already selected cities
$selected = !empty($curitem->fields->data->value) ?
unserialize(base64_decode($curitem->fields->data->value)) : [];
// Now, we're going through all the cities and build our dropdown list.
$options = '';
if($ic->simpleItems) {
foreach($ic->simpleItems as $city) {
$options .= '<option value="'.$city->id.'"'.
(array_key_exists($city->id, $selected) ? ' selected': '').'>'.$city->name.'</option>';
}
}
// Initialize the category fields
$fc = new FieldMapper();
$fc->init($categoryid);
$fields = $fc->filterFields('position', 'asc');
$tplfields = '';
if($fields)
{
foreach($fields as $fieldname => $field)
{
// Input
$inputClassName = 'Input'.ucfirst($field->type);
$InputType = new $inputClassName($fields[$fieldname]);
$output = $InputType->prepareOutput();
// Field
$fieldClassName = 'Field'.ucfirst($field->type);
$fieldType = new $fieldClassName($this->tpl);
$fieldType->name = $fieldname;
$fieldType->id = $fieldType->name;
if(!empty($field->configs))
{
foreach($field->configs as $key => $val)
{
$fieldType->configs->$key = $val;
}
}
// Hidden
if($field->type == 'hidden') continue;
// Dropdown
if($field->type == 'dropdown') $fieldType->options = $field->options;
// File upload
if($field->type == 'fileupload') {
$fieldType->categoryid = $categoryid;
$fieldType->itemid = $id;
$fieldType->realid = $field->id;
$fieldType->timestamp = $stamp;
}
foreach($output as $outputkey => $outputvalue)
{
$fieldType->class = empty($field->fieldclass) ? $field->type.'-field' : $field->fieldclass;
if(!empty($field->fieldcss))
$fieldType->style = $field->fieldcss;
if(is_array($outputvalue))
{
$fieldType->$outputkey = array();
$counter = 0;
if(!isset($curitem->fields->$fieldname->$outputkey))
continue;
foreach($curitem->fields->$fieldname->$outputkey as $arrkey => $arrval)
{
$fieldType->{$outputkey}[] =
(string) $curitem->fields->$fieldname->{$outputkey}[$counter];
$counter++;
}
} else
$fieldType->$outputkey = !empty($curitem->fields->$fieldname->$outputkey) ?
(string) $curitem->fields->$fieldname->$outputkey : '';
if(MsgReporter::isError())
$fieldType->$outputkey = !empty($this->input[$fieldType->name]) ?
$this->input[$fieldType->name] : '';
}
// Set default field values
if(empty($fieldType->value) && !empty($field->default))
$fieldType->value = (string) $field->default;
$tplinfotext = '';
if(!empty($field->info))
$tplinfotext = $this->tpl->render($infotext, array('infotext' => $field->info));
$tplrequired = '';
if(!empty($field->required) && $field->required == 1)
$tplrequired = $this->tpl->render($required, array());
if($field->type != 'chunk')
{
$tplfields .= $this->tpl->render($fieldarea, array(
'fieldid' => $field->name,
'label' => $field->label,
'infotext' => $tplinfotext,
'area-class' => !empty($field->areaclass) ? $field->areaclass : 'fieldarea',
'area-style' => !empty($field->areacss) ? ' style="'.$field->areacss.'"' : '',
'label-class' => !empty($field->labelclass) ? $field->labelclass : '',
'label-style' => !empty($field->labelcss) ? ' style="'.$field->labelcss.'"' : '',
'required' => $tplrequired,
'field' => $fieldType->render())
);
} else
{
$tplfields .= $fieldType->render();
}
}
}
//
// Take a look at this, here we use our modified wrapper template.
//
return $this->getEditorWrapper([
'action_edit' => !is_null($id) ? $id : '',
'action_page' => $backpage,
'item-id' => $id,
'position' => !empty($curitem->position) ? $curitem->position : '',
'checked' => ($active > 0) ? ' checked ' : '',
'back-page' => $backpage,
'timestamp' => $stamp,
'infotext' => '',
'currentcategory' => $this->manager->cp->currentCategory(),
'itemname' => !empty($curitem->name) ? $curitem->name : '',
'options' => $options,
'custom-fields' => $tplfields,
'created' => ((int) $curitem->created > 0) ?
date((string) $this->manager->config->backend->timeformat, (int) $curitem->created) : '',
'updated' => ($curitem->updated > 0) ?
date((string) $this->manager->config->backend->timeformat, (int) $curitem->updated) : ''
]
);
}
/**
* Here you can write your own method that will be executed after
* someone saves an item via ItemManager's backend.
*
*/
protected function beforeItemSave(& $input)
{
// First check if this is the right category we want to edit, if not, we skip the function.
$category = $this->manager->getCategoryMapper()->getCategory($this->manager->cp->currentCategory());
if(!isset($category) || $category->name != 'Countries') return;
// Now, catch the value of our dropdown field and
// prepare its contents for saving into the hidden field.
$selected = [];
if(isset($input['cities']) && !empty($input['cities'])) {
// Get our cities, because we also want to adopt the city names in our array
$mapper = $this->manager->getItemMapper();
$citiesCategory = $this->manager->getCategoryMapper()->getCategory('name=Cities');
if(!$citiesCategory) return;
$mapper->alloc($citiesCategory->id);
if($mapper->simpleItems) {
foreach($mapper->simpleItems as $city) {
if(in_array($city->id, $input['cities'])) {
$selected[$city->id] = $city->name;
}
}
}
}
// Serialize the $selected arry to save it as hidden field value.
$input['data'] = base64_encode(serialize($selected));
}
/**
* Here you can write your own method that will be executed before
* someone deletes an item via ItemManager's backend.
*
* Something troublesome is if we want to delete a city from our cities list,
* since we now have to go through all our countries to remove the deleted
* city ID from the selected cities array again.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* MOTE: If there are many items (Countries), it can slow down the script
* extremely, because we have to unserialize every single data field value
* to check its contents
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
protected function beforeItemDelete($id, $catid)
{
// First check if this is the right category we want to edit, if not, we skip the function.
$category = $this->manager->getCategoryMapper()->getCategory($this->manager->cp->currentCategory());
if(!isset($category) || $category->name != 'Cities') return;
// Now let's retrieve all the countries and in case there is the deleted
// city there, we will delete this out there.
$countryCategory = $this->manager->getCategoryMapper()->getCategory('name=Countries');
if(!$countryCategory) return;
$mapper = $this->manager->getItemMapper();
$mapper->init($countryCategory->id);
$mapper->alloc($countryCategory->id);
$countries = $mapper->items;
if(!$countries) return;
foreach($countries as $country) {
$selected = !empty($country->fields->data->value) ?
unserialize(base64_decode($country->fields->data->value)) : [];
// Remove deletet city from the array
if(array_key_exists($id, $selected))
{
unset($selected[$id]);
$country->fields->data->value = base64_encode(serialize($selected));
$country->save();
$mapper->simplify($country);
$mapper->save();
}
}
}
private function getEditorWrapper(array $data = [])
{
ob_start();
?>
<div class="manager-wrapper">
<h3 class="menuglava">Create / Edit Item</h3>
<form class="largeform" action="load.php?id=imanager&edit=<?php echo $data['action_edit'];
?>&page=<?php echo $data['action_page']; ?>" method="post" enctype="multipart/form-data"
accept-charset="utf-8">
<input name="iid" type="hidden" value="<?php echo $data['item-id']; ?>">
<input name="page" type="hidden" value="<?php echo $data['back-page']; ?>" >
<input name="categoryid" type="hidden" value="<?php echo $data['currentcategory']; ?>">
<input name="timestamp" type="hidden" value="<?php echo $data['timestamp']; ?>">
<div>
<div class="fieldarea">
<label for="catid" class="im-left">ID</label>
<p id="catid" class="im-cat-info"><?php echo $data['item-id']; ?></p>
</div>
<div class="fieldarea">
<label for="title">Title</label>
<div class="field-wrapper">
<input id="title" class="im-title" name="name" type="text"
value="<?php echo $data['itemname']; ?>">
</div>
</div>
<!-- [ DROPDOWN ] -->
<div class="fieldarea">
<label for="title">Cities</label>
<div class="field-wrapper">
<select name="cities[]" style="background:none" multiple>
<?php echo $data['options']; ?>
</select>
</div>
</div>
<!-- [ /DROPDOWN ] -->
<div class="fieldarea">
<label for="position">Position</label>
<div class="field-wrapper">
<input id="position" name="itempos" type="number" value="<?php
echo $data['position']; ?>">
</div>
</div>
<div class="fieldarea">
<label for="active">Enabled</label>
<div class="field-wrapper">
<input id="active" name="active" type="checkbox" value="1" <?php
echo $data['checked']; ?>>
</div>
</div>
<?php echo $data['custom-fields']; ?>
<div class="fieldarea">
<label for="itemcreated" >Created date</label>
<div class="field-wrapper"><?php echo $data['created']; ?></div>
</div>
<div class="fieldarea">
<label for="itemcreated" >Modified</label>
<div class="field-wrapper"><?php echo $data['updated']; ?></div>
</div>
<p><input name="submit" type="submit" class="submit" value="Save"></p>
</div>
</form>
</div>
<?php return ob_get_clean();
}
}
$newbackend = new \AdminExtended;
$manager->setAdmin($newbackend);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment