Setting the order of TYPO3 BE module - typo3

I registered successfully a BE module and submodule in Extbase extension with this common code and of course it works:
/** Myext modules group */
Tx_Extbase_Utility_Extension::registerModule($_EXTKEY, 'myext', '', ''
,array(),
array(
'icon' => 'EXT:' . $_EXTKEY .'/ext_icon.gif',
'access' => 'user,group',
'labels' => 'LLL:EXT:' . $_EXTKEY . '/Resources/Private/Language/locallang_myext.xml',
)
);
/** Myext items list mod */
Tx_Extbase_Utility_Extension::registerModule($_EXTKEY, 'myext', 'itemslist','',
array('Item' => 'list',),
array(
'icon' => 'EXT:' . $_EXTKEY . '/Resources/Public/Icons/mod_items.gif',
'access' => 'user,group',
'labels' => 'LLL:EXT:' . $_EXTKEY . '/Resources/Private/Language/locallang_myext_items.xml',
)
);
My problem is that I can't change its ordering in anyway, it always displays at the end of the left column (after Help section). The 4-th param of registerModule method is position anyway apparently it doesn't affect the main module, only submodules.
So how can I place Myext right after the web? in such case?
I'm working on TYPO3 ver.: 4.7

I am sorry, I missunderstood you. You mean your own category that you want to set a specified position.
There is no official way but you can manual reset the order with following code:
// add module before 'File'
if (!isset($TBE_MODULES['yourExtensionCategory'])) {
$temp_TBE_MODULES = array();
foreach($TBE_MODULES as $key => $val) {
if ($key == 'file') {
$temp_TBE_MODULES['yourExtensionCategory'] = '';
$temp_TBE_MODULES[$key] = $val;
} else {
$temp_TBE_MODULES[$key] = $val;
}
}
$TBE_MODULES = $temp_TBE_MODULES;
}

Following code will set the module link to a specified position:
Tx_Extbase_Utility_Extension::registerModule(
$_EXTKEY,
'web', // Make module a submodule of 'web'
'yourmodulem1', // Submodule key
'before:web_ViewpageView', // Position
array(
'Controller' => 'action1, action2'
),
array(
'access' => 'user,group',
'icon' => 'EXT:' . $_EXTKEY . '/Resources/Public/Icons/icon.png',
'labels' => 'LLL:EXT:' . $_EXTKEY . '/Resources/Private/Language/locallang_m1.xml',
)
);
You have set the second argument "mainModuleName" wrong, it is the category, your module belongs to. Valid values are web, files, user, tools, help. The fourth argument "position" can have following values after:module_id, before:module_id or top. Empty mean bottom and is default. To get the id of the module, simply inspect the link-element of the menu with your favourite web-developer-tool, the attribute id= descripes the module_id.
Heres the documentation of registerModule:
/**
* Registers an Extbase module (main or sub) to the backend interface.
* FOR USE IN ext_tables.php FILES
*
* #param string $extensionName The extension name (in UpperCamelCase) or the extension key (in lower_underscore)
* #param string $mainModuleName The main module key, $sub is the submodule key. So $main would be an index in the $TBE_MODULES array and $sub could be an element in the lists there. If $main is not set a blank $extensionName module is created
* #param string $subModuleName The submodule key. If $sub is not set a blank $main module is created
* #param string $position This can be used to set the position of the $sub module within the list of existing submodules for the main module. $position has this syntax: [cmd]:[submodule-key]. cmd can be "after", "before" or "top" (or blank which is default). If "after"/"before" then submodule will be inserted after/before the existing submodule with [submodule-key] if found. If not found, the bottom of list. If "top" the module is inserted in the top of the submodule list.
* #param array $controllerActions is an array of allowed combinations of controller and action stored in an array (controller name as key and a comma separated list of action names as value, the first controller and its first action is chosen as default)
* #param array $moduleConfiguration The configuration options of the module (icon, locallang.xml file)
* #return void
*/
Please note: if you have templavoila installed, the "page"-Module has not the id "page", it is "web_txtemplavoilaM1", because templavoila replaces the whole page module.

Related

After TYPO3 Update from 6.2 to 7.6 still errors in TCA?

I've made an update from TYPO3 CMS 6.2 to TYPO3 CMS 7.6.16. After a few problems with other extensions (tx_newsand third party ext.) and the changes in the TCA. Everything works fine after import live-dump ...
Upgrade wizard / Database compare
Update reference Index
Flush Cache and empty typo3temp
Deactivate and reactivate the Extensions with problems
Everything? Unfortunately, no. The extension doesn't work. I don't written the extension by myself. If I try to add a new data record in backend with this ext., I'll get this error:
An item in field form of table tx_blah_domain_model_job is not an array as expected
But the database comprare is finished. All tables are correct?!
Where's the problem? I know it's hard to analyze this without source code. There's a database field wrong, but why? It's the same database like before?
Where's the fault .. ext_tables.php or still sth. in TCA is wrong? I really need a tip .. its frustrating ..
EDIT: sys_log entry
Core: Exception handler (WEB): Uncaught TYPO3 Exception: #1439288036: An item in field form of table tx_blah_domain_model_job is not an array as expected | UnexpectedValueException thrown in file /typo3_src/typo3_src-7.6.16/typo3/sysext/backend/Classes/Form/FormDataProvider/AbstractItemProvider.php in line 1264.
EDIT 2: I think, there must be sth. in typo3conf/ext/blah/Configuration/TCA/tx_blah_domain_model_job.php
see TCA source code
and that's in line 1264
/**
* Sanitize incoming item array
*
* Used by TcaSelectItems and TcaSelectTreeItems data providers
*
* #param mixed $itemArray
* #param string $tableName
* #param string $fieldName
* #throws \UnexpectedValueException
* #return array
*/
public function sanitizeItemArray($itemArray, $tableName, $fieldName)
{
if (!is_array($itemArray)) {
$itemArray = [];
}
foreach ($itemArray as $item) {
if (!is_array($item)) {
throw new \UnexpectedValueException(
'An item in field ' . $fieldName . ' of table ' . $tableName . ' is not an array as expected',
1439288036
);
}
}
return $itemArray;
}
aTry to use this in the TCA tx_imappointments_domain_model_job.php
'form' => array(
'exclude' => 1,
'label' => 'LLL:EXT:im_appointments/Resources/Private/Language/locallang_db.xlf:tx_imappointments_domain_model_job.form',
'config' => array(
'type' => 'select',
'renderType' => 'selectSingle',
'items' => array(array('', 0)),
'foreign_table' => 'pages',
'foreign_table_where' => ' AND pages.pid = 293',
'minitems' => 0,
'maxitems' => 1,
),
),
'items' in 'form' has to be a array how your error message said:
https://docs.typo3.org/typo3cms/TCAReference/ColumnsConfig/Type/Select.html#items

Security Group subpanel doesn't exist for quotes, contrats, invoices, and events modules

I am using suiteCRM 7.7.4 (Sugar Version 6.5.24) and I need to use Security group subpanel in quotes, contracts, invoices and events modules, but for some reasons I can't find it ! I did some researches and I found that this subpanel doesn't appear by default for custom modules.. some developers recommand to do not use the studio to build this kind of relationship, because simply it will not work ! for paid version of sugarCRM they say that there was a tool called "hookup tool" that creates the relationship for you... but As I am using a free version I can't use it !
Do you have any idea ?
Thank you very much !
I finaly find a solution :
Adding this few lines to "modules/AOS_Contracts/metadata/subpaneldefs.php" :
'securitygroups' => array(
'top_buttons' => array(array('widget_class' => 'SubPanelTopSelectButton', 'popup_module' => 'SecurityGroups', 'mode' => 'MultiSelect'),),
'order' => 900,
'sort_by' => 'name',
'sort_order' => 'asc',
'module' => 'SecurityGroups',
'refresh_page' => 1,
'subpanel_name' => 'default',
'get_subpanel_data' => 'SecurityGroups',
'add_subpanel_data' => 'securitygroup_id',
'title_key' => 'LBL_SECURITYGROUPS_SUBPANEL_TITLE',
),
QRR
Verifying permissions.
follow this following steps:
1. Go to Admin
2. Go to studio
3. Select your module where you want subpanel like "invoices"
4. Go to relationship
5. Add 1 to many relationship with Security group module.
6. Now repair rebuild you will find the subapnel in invoice module.
When you create 1 to many relationship with any module it will create the subpanel.
IF its not working then go for custom subpanel.
Refer this linnk I put code from same link it worked for me
This tutorial should hopefully help you to create a new subpanel under the Contacts module in Sugar using a custom link class and driven by SugarCRM 7's new SugarQuery API.
Create a new link class
This should go into custom/modules/<YourModule>/YourNewLink.php and this class will act as the custom functionality that will build your link between the two records.
<?php
/**
* Custom filtered link
*/
class YourNewLink extends Link2
{
/**
* DB
*
* #var DBManager
*/
protected $db;
public function __construct($linkName, $bean, $linkDef = false)
{
$this->focus = $bean;
$this->name = $linkName;
$this->db = DBManagerFactory::getInstance();
if (empty($linkDef)) {
$this->def = $bean->field_defs[$linkName];
} else {
$this->def = $linkDef;
}
}
/**
* Returns false if no relationship was found for this link
*
* #return bool
*/
public function loadedSuccesfully()
{
// this link always loads successfully
return true;
}
/**
* #see Link2::getRelatedModuleName()
*/
public function getRelatedModuleName()
{
return '<Your_Module>';
}
/**
*
* #see Link2::buildJoinSugarQuery()
*/
public function buildJoinSugarQuery($sugar_query, $options = array())
{
$joinParams = array('joinType' => isset($options['joinType']) ? $options['joinType'] : 'INNER');
$jta = 'active_other_invites';
if (!empty($options['joinTableAlias'])) {
$jta = $joinParams['alias'] = $options['joinTableAlias'];
}
$sugar_query->joinRaw($this->getCustomJoin($options), $joinParams);
return $sugar_query->join[$jta];
}
/**
* Builds main join subpanel
* #param string $params
* #return string JOIN clause
*/
protected function getCustomJoin($params = array())
{
$bean_id = $this->db->quoted($this->focus->id);
$sql = " INNER JOIN(";
$sql .= "SELECT id FROM accounts WHERE id={$bean_id}"; // This is essentially a select statement that will return a set of ids that you can match with the existing sugar_query
$sql .= ") accounts_result ON accounts_result.id = sugar_query_table.id";
return $sql;
}
}
The argument $sugar_query is a new SugarQuery object, the details of which are documented here. What you essentially need to do is extend this query with whatever join/filters you wish to add. This is done in the inner join I've specified.
Note: The inner join can get really complicated, so if you want a real working example, checkout modules/Emails/ArchivedEmailsLink.php and how the core sugar team use this. I can confirm however that this does work with custom joins.
Here is the getEmailsJoin to help you understand what you can actually produce via this custom join.
/**
* Builds main join for archived emails
* #param string $params
* #return string JOIN clause
*/
protected function getEmailsJoin($params = array())
{
$bean_id = $this->db->quoted($this->focus->id);
if (!empty($params['join_table_alias'])) {
$table_name = $params['join_table_alias'];
} else {
$table_name = 'emails';
}
return "INNER JOIN (\n".
// directly assigned emails
"select eb.email_id, 'direct' source FROM emails_beans eb where eb.bean_module = '{$this->focus->module_dir}'
AND eb.bean_id = $bean_id AND eb.deleted=0\n" .
" UNION ".
// Related by directly by email
"select DISTINCT eear.email_id, 'relate' source from emails_email_addr_rel eear INNER JOIN email_addr_bean_rel eabr
ON eabr.bean_id = $bean_id AND eabr.bean_module = '{$this->focus->module_dir}' AND
eabr.email_address_id = eear.email_address_id and eabr.deleted=0 where eear.deleted=0\n" .
") email_ids ON $table_name.id=email_ids.email_id ";
}
Add a new vardef entry for the link field.
For this example, I'm going to create the custom link on the contacts module. So this code goes in custom/Extension/modules/Contacts/Ext/Vardefs/your_field_name.php
<?php
$dictionary["Contact"]["fields"]["your_field_name"] = array(
'name' => 'active_other_invites',
'type' => 'link',
'link_file' => 'custom/modules/<YourModule>/YourNewLink.php',
'link_class' => 'YourNewLink',
'source' => 'non-db',
'vname' => 'LBL_NEW_LINK',
'module' => '<YourModule>',
'link_type' => 'many',
'relationship' => '',
);
Add the new link as a subpanel
This goes under custom/Extension/modules/Contacts/Ext/clients/base/layouts/subpanels/your_subpanel_name.php
<?php
$viewdefs['Contacts']['base']['layout']['subpanels']['components'][] = array (
'layout' => 'subpanel',
'label' => 'LBL_NEW_LINK',
'context' =>
array (
'link' => 'your_field_name',
),
);
Add the label
Under
custom/Extension/modules/Contacts/Ext/Language/en_us.new_link.php
<?php
$mod_strings['LBL_ACTIVE_OTHER_INVITES'] = 'Your New Link';
Quick Repair and Rebuild
That should hopefully get you started. Keep an eye on the sugarlogs while you're debugging your queries. I also found using xdebug and SugarQueries compileSql function invaluable in figuring out what I needed to do to get a working INNER JOIN statement.
I've found this to be a surprisingly powerful solution, it means that if you need to show information related to a module that might be a few joins away, this allows you to create the links manually without having to create pointless related fields in-between the two.

magento 1.9.2.2 add to cart with custom option image not working

I have a script which adds a product in cart with custom option image and it was working perfect till CE 1.9.2.1 but after up gradation to latest version it troughs exception that Please specify the product's required option(s).
Below is code, please guide me if something has to change for newer version .
<?php
$productId = xxx;
$image = 'path to image(tested image exists)';
$product = Mage::getModel('catalog/product')->load($product_id);
$cart = Mage::getModel('checkout/cart');
$cart->init();
$params = array(
'product' => $productId,
'qty' => 1,
'options' => array(
$optionId3inmycase => array(
'type' => 'image/tiff',
'title' => $image,
'quote_path' => '/media/custom/' . $image,
'order_path' => '/media/custom/' . $image,
'fullpath' => Mage::getBaseDir() . '/media/custom/' . $image,
'secret_key' => substr(md5(file_get_contents(Mage::getBaseDir() . '/media/custom/' . $image)), 0, 20)),
)
);
$request = new Varien_Object();
$request->setData($params);
$cart->addProduct($product, $request);
$cart->save();
if ($itemId > 0) {
$cartHelper = Mage::helper('checkout/cart');
$cartHelper->getCart()->removeItem($itemId)->save();
}
Mage::getSingleton('checkout/session')->setCartWasUpdated(true);
$this->_redirect('checkout/cart/');
?>
One quick solution is to rewrite Mage_Catalog_Model_Product_Option_Type_File class and change validateUserValue() function.
around line 129, replace
$fileInfo = $this->_getCurrentConfigFileInfo();
with
$fileInfo = null;
if (isset($values[$option->getId()]) && is_array($values[$option->getId()])) {
// Legacy style, file info comes in array with option id index
$fileInfo = $values[$option->getId()];
} else {
/*
* New recommended style - file info comes in request processing parameters and we
* sure that this file info originates from Magento, not from manually formed POST request
*/
$fileInfo = $this->_getCurrentConfigFileInfo();
}
but its old code and will have APPSEC-1079 security issue.
and to download image this uploaded image in order detail etc. add this function in same model class.
/**
* changed the image save address as we are saving image in custom
* Main Destination directory
*
* #param boolean $relative If true - returns relative path to the webroot
* #return string
*/
public function getTargetDir($relative = false)
{
$fullPath = Mage::getBaseDir('media') . DS . 'custom';
return $relative ? str_replace(Mage::getBaseDir(), '', $fullPath) : $fullPath;
}

Changing the height of ckeditor from a zend form

I am trying to set the height of a ckeditor I am using. Here is what I currently have:
$this->addElement('textarea', 'text_field', array(
'filters' => array('StringTrim'),
'validators' => array(
array('StringLength', true, array(0, 3000)),
),
'decorators' => array('ViewHelper'),
'required' => false,
'attribs' => array('class' => 'ckeditor'),
'label' => 'Please enter text below',
'value' => isset($this->_text_data[0]['text']) ? $this->_text_data[0]['text'] : ''
));
This comes from my form, this is then called in my .phtml file by the following:
<?=$this->element->getElement('text_field')?>
I have looked everywhere and tried adding:
'height' => '100px',
and:
'config' => array(
'toolbar' => 'Full',
'width' => '550px',
'height' => '100px',
),
But neither of these have worked. The main reason I need this is I have a text area (using the ckeditor in order to allow the input information to be formatted in a particular way) which is quite long (the default height I am assuming) but it is only ever a few lines input into the box, hence the reason I want it smaller as it takes up too much space on the page.
Thanks in advance
Iain
I made a form element and a helper using ZendX_JQuery_View_Helper_UiWidget to create a CKEditor with the jQuery adapter. Here's the code of both files :
ZendExt_Form_Element_CKEditor :
class ZendExt_Form_Element_CKEditor extends ZendX_JQuery_Form_Element_UiWidget
{
/**
* Use formCKeditor view helper by default
* #var string
*/
public $helper = 'formCKEditor';
/**
* Default ckeditor options
*
* #var array
*/
public $jQueryParams = array(
'toolbar' => 'Basic'
);
}
And ZendExt_View_Helper_FormCKEditor :
class ZendExt_View_Helper_FormCKEditor extends ZendX_JQuery_View_Helper_UiWidget
{
static $set = false;
public function formCKEditor($name, $value = null, $params = null, $attribs = null)
{
$hTextA = new Zend_View_Helper_FormTextarea();
$hTextA -> setView($this -> view);
$xhtml = $hTextA -> formTextarea($name, $value, $attribs);
$xhtml .= '<script type="text/javascript">$(document).ready(function(){$("#' . $this->_normalizeId($name) . '").ckeditor(' . (!is_null($params) ? 'function(){},' . Zend_Json_Encoder::encode($params) : '') . ')});</script>';
if (self::$set == false) {
$this -> view -> headScript() -> appendFile($this -> view -> baseUrl() . '/js/ckeditor/ckeditor.js');
$this -> view -> headScript() -> appendFile($this -> view -> baseUrl() . '/js/ckeditor/adapters/jquery.js');
self::$set = true;
}
return $xhtml;
}
}
You can use it as any other ZF form element once you copied these 2 files into :
* libraries/ZendExt/Form/Element/ for ZendExt_Form_Element_CKEditor class
* libraries/ZendExt/View/Helper/ for ZendExt_View_Helper_FormCKEditor class
and added the ZendExt namespace in your configuration file (or if you already have a library of yours and want to use it, just put both files in it and change the name of the classes to reflect yours). Then, you'll have tel ZF that ZendExt/View/Helper is a directory to look in for view helpers (in a .ini config file it would look like : resources.view.helperPath.ZendExt_View_Helper = "ZendExt/View/Helper").
Then in your code, just call $ckEditor = new ZendExt_Form_Element_CKEditor(); to create a new CKEditor. You may then add all params you want to the element using $ckEditor -> setJQueryParam($key, $value); as specified in the documentation here : http://framework.zend.com/manual/fr/zendx.jquery.html . For example : $ckEditor -> setJQueryParam('height', '100px');. I understand it's not a jQuery component, but it was the easiest way to be able to make it as everything needed is available there.
To display it, in your view just do <?=$this -> ckEditor?> and you're good.
Make sure you put your ckeditor.js and adapters/jquery.js in your public directory under /js/ckeditor/ or change the path accordingly in the helper.
You'll need to specify the dimensions of the editor when you create it (i.e., in the Javascript part). CKEditor replaces the original form element with its own code, so your changes in the dimensions will be lost.
For instance, if you create it using the jQuery interface, it would be something like the following:
var config = {
width: '550px',
height: '100px'
};
// Initialize the editor.
$('.jquery_ckeditor').ckeditor(config);
Hope that helps...

Render view from Zend_form

I try it via my Zend_form:
$output .= $this->_view->render('admin/form.phtml'
, array('id' => $this->getName()
, 'action' => $this->getAction()
, 'method' => $this->getMethod()
, 'enctype' => $this->getEnctype()
, 'data' => array('code' => $code
, 'name' => $name
, 'description' => $description)));
but when i <?php echo $this->enctype; ?> in admin/form.phtml i got nothing.
admin/form.phtml is rendered correctly
Choosing render just displays the output, Zend does not pass your data to the view. But Using view partials, you could achieve that.
From the documentation,
The Partial view helper is used to render a specified template within
its own variable scope. The primary use is for reusable template
fragments with which you do not need to worry about variable name
clashes. Additionally, they allow you to specify partial view scripts
from specific modules.