As per requirement, I need to not list in backoffice the Orders with CANCELED and FAILED status for all the employees except Admin, is there any way to modify the backoffice logic in order to not show the orders with particular statuses?
Achieved using SearchRestriction:
INSERT_UPDATE SearchRestriction; code[unique = true] ; name[lang = en]; restrictedType(code); principal(uid) ; active; generate; query
; order_status_estricted ; ; Order ; vendoradministratorgroup ; true ; true ; {status} IN ( {{ SELECT {os.pk} FROM {OrderStatus as os} WHERE {os.code} NOT IN ('CANCELED') }} )
You can use Flex Search Restriction for this. Restrictions automaticly adding where conditions to every flex query by item type. Also you can use session variables in this restrictions.
Related
I have a context menu in CKEditor 4 with many items, that I hide or show based on the divs' classes. I tried to show and hide items by menu group, e.g.
editor.addMenuGroup('odt') ;
editor.addMenuItem('item_1', {
label: 'Item 1',
group: 'odt',
order: 100,
command: command_1,
} ;
// More items follow...
editor.contextMenu.addListener(function(element, selection, path) {
let rv = {} ;
// The following is just an example, my logic is more involved
rv['odt'] = CKEDITOR.TRISTATE_OFF ;
return rv ;
}) ;
This doesn't work, i.e., the items belonging to the group I return from the listener are not added to the menu.
Debugging the problem I found out with surprise that the group field in the menuItems inside the editor is set to the menu order, for example
>> Object.entries(CKEDITOR.instances)[0][1]._.menuItems.item_1.group
100
Digging in the code, I found the following surprising lines in ckeditor4/plugins/menu/plugin.js:
CKEDITOR.menuItem = CKEDITOR.tools.createClass( {
$: function( editor, name, definition ) {
[...]
// Transform the group name into its order number.
this.group = editor._.menuGroups[ this.group ];
Therefore, even without knowing if setting CKEDITOR.TRISTATE_OFF on the group name would work, I know for sure that the group name will not be used.
Am I missing something?
Did anybody ever manage to show / hide menu items in CKEditor 4 by menu groups?
Why the group name is transformed to group order in the internal data???
I have a site that uses Wayfinder to display the latest 3 entries from an Articles blog. Now, I want to only consider those blog entries that are tagged Highlights.
My original Wayfinder call looks like this, nothing spectacular:
[[!Wayfinder? &startId=`296` &level=`1`
&outerTpl=`emptyTpl`
&innerTpl=``
&rowTpl=`thumbnails_formatter`
&ignoreHidden=`1`
&sortBy=`menuindex`
&sortOrder=`DESC`
&limit=`3`
&cacheResults=`0`
]]
as Articles tags are managed via the articlestags TV, I thought that a &where might do the trick, but with no luck yet:
&where=`[{"articlestags:LIKE":"%Highlights%"}]`
does not yield anything. As a sanity check, I tried [{"pagetitle:LIKE":"%something%"}], which worked. Obviously, the problem is that articlestags is not a column of modx_site_content, but I'm not sure about how to put the subquery.
SELECT contentid
FROM modx_site_tmplvar_contentvalues
WHERE tmplvarid=17
AND value LIKE '%Highlights%'
Gave me the right IDs on the sql prompt, but adding it to the Wayfinder call like this gave an empty result again:
&where=`["id IN (SELECT contentid FROM modx_site_tmplvar_contentvalues WHERE tmplvarid=17 AND value LIKE '%Highlights%')"]`
Any ideas on how to achieve this? I'd like to stay with Wayfinder for consistency, but other solutions are welcome as well.
You can just use pdomenu (part of pdoTools) instead Wayfinder
[[!PdoMenu?
&startId=`296`
&level=`1`
&outerTpl=`emptyTpl`
&innerTpl=``
&rowTpl=`thumbnails_formatter`
&ignoreHidden=`1`
&sortBy=`menuindex`
&sortOrder=`DESC`
&limit=`3`
&cacheResults=`0`
&includeTVs=`articlestags`
&where=`[{"TVarticlestags.value:LIKE":"%filter%"}]`
]]
Take a peek at some of the config files [core/components/wayfinder/configs ] - I have not tried it, but it looks as if you can run your select query right in the config & pass the tmplvarid array to the $where variable.
A little playing around led me to a solution: I needed to include the class name (not table name) when referring to the ID:
&where=`["modResource.id IN (SELECT contentid FROM modx_site_tmplvar_contentvalues WHERE tmplvarid=17 AND value LIKE '%Highlights%')"]`
a small test showed that even a simple
&where=`["id = 123"]`
does not work without modResource..
A look at wayfinder.class.php shows the following line, which seems to be the "culprit":
$c->select($this->modx->getSelectColumns('modResource','modResource'));
This method aliases the selected columns - relevant code is in xpdoobject.class.php. The first parameter is the class name, the second a table alias. The effect is that the query selects id AS modResource.id, and so on.
EDIT: final version of my query:
&where=`["modResource.id IN (
SELECT val.contentid
FROM modx_site_tmplvars AS tv
JOIN modx_site_tmplvar_contentvalues AS val
ON tv.id = val.tmplvarid
WHERE tv.name = 'articlestags' AND (
val.value = 'Highlights'
OR val.value LIKE 'Highlights,%'
OR val.value LIKE '%,Highlights'
OR val.value LIKE '%,Highlights,%'
)
)"]`
I don't claim this query is particularly efficient (I seem to recall that OR conditions are bad). Also, MODx won't work with this one if the newlines aren't stripped out. Still, I prefer to publish the query in its well-formatted form.
I used snippet as a parameter for the includeDocs of wayfinder, In my case it was useful because I was need different resources in menu depend on user browser (mobile or desktop)
[[!Wayfinder?
&startId=`4`
&level=`1`
&includeDocs=`[[!menu_docs?&startId=`4`]]`
&outerTpl=`home_menu_outer`
&rowTpl=`menu_row`
]]
and then menu_docs snippet
<?php
if (empty ($startId))
return;
if (!isMobileDevice())
return;
$query = $modx->newQuery('modResource');
$query->innerJoin('modTemplateVarResource','TemplateVarResources');
$query->where(array(
'TemplateVarResources.tmplvarid' => 3,
'TemplateVarResources.value:LIKE' => 'yes',
'modResource.parent' => $startId,
'modResource.deleted' => 0,
'modResource.published' => 1,
'modResource.hidemenu' => 0
));
$resources = $modx->getCollection('modResource', $query);
$ouput = array();
foreach ($resources as $resource)
$output[] = $resource->get('id');
return implode (',', $output);
I don't understand why my code is not allowed.
#If(#DbLookup("":"nocache";#DbName;"GPA";1)="GPnum";#Failure(#Command([FileSave])&#Command([CloseWindow]));#Success)`
Please help me. Thank you.
#If(#DbLookup("":"nocache";#DbName;"GPA";1)="GPnum"
your code should have 1 more parameter.
from help
#DbLookup( class : cache ; server : database ; view ; key ; fieldName ; keywords )
So you have "GPA" as view and then you need to specify Key and field/column you wish to return. Also for DbLookup I would recommend you to use [FAILSILENT] as keywords, in this case you will not need to check result for #IsError
However probably you just need to use #DbColumn instead of #DbLookup.
as I understood you need to verify if some value exists in database/view, try this code:
#If(#DbColumn("":"NoCache";#DbName;"GPA";1)="GPnum"; #Failure(#Command([FileSave]) : #Command([CloseWindow])); #Success)
or
#If(#DbLookup("":"NoCache";#DbName;"GPA"; "GPnum"; 1; [FAILSILENT])<>""; #Failure(#Command([FileSave]) : #Command([CloseWindow])); #Success)
Edit: I add a code for button action that save the current doc (see author comment below)
The editable field in which the user enters the value we check is called GPnum. A view "GPA" is sorted by its first col an display GPnum value.
t:=#DbLookup("":"nocache";#DbName;"GPA"; GPnum ; 1 ; [FailSilent] );
#If(#IsError(t) ; #Prompt([Ok]; "DB has a problem:";#Text(t)) ;
t = "" ; #Do(#Command([FileSave]);#Command([CloseWindow])) ;
#Prompt([Ok] ; "unable to save" ; "The key already exists") )
original response
t:=#DbLookup("":"nocache";#DbName;"GPA"; #ThisValue ; 1 );
#If(#IsError(t) ; #Failure("DB has a problem:"+#Text(t)) ; t = "" ; #Success ; #Failure("The key already exists") )
If you use #failure/#success you MUST be in an editable field in a form (validation).
As I understand you check that your value does not ALREADY exists.
so:
first add #thisValue as the key you search in the DBLOOKUP,
as told above DBLOOKUP could return an error thus check #isError(t)
second failure just BLOCK the validation of the form, I never tried (an it doesn't make sense) to make it save the form
Hope it helps
I am making some changes to a site using ExpressionEngine, there is a concept I can't seem to quite understand and am probably coding workarounds that have pre-provided methods.
Specifically with channels and members, the original creator has added several custom fields. I am from a traditional database background where each column in a table has a specific meaningful name. I am also used to extending proprietary data by adding a related table joined with a unique key, again, field names in the related table are meaningful.
However, in EE, when you add custom fields, it creates them in the table as field_id_x and puts an entry into another table telling you what these are.
Now this is all nice from a UI point of view for giving power to an administrator but this is a total headache when writing any code.
Ok, there's template tags but I tend not to use them and they are no good in a database query anyway.
Is there a simple way to do a query on say the members table and then address m_field_1 as what its really called - in my case "addresslonglat".
There are dozens of these fields in the table I am working on and at the moment I am addressing them with fixed names like "m_field_id_73" which means nothing.
Anybody know of an easy way to bring the data and its field names together easily?
Ideally i'd like to do the following:
$result = $this->EE->db->query("select * from exp_member_data where member_id = 123")->row();
echo $result->addresslonglat;
Rather than
echo $result->m_field_id_73;
This should work for you:
<?php
$fields = $data = array();
$member_fields = $this->EE->db->query("SELECT m_field_id, m_field_name FROM exp_member_fields");
foreach($member_fields->result_array() as $row)
{
$fields['m_field_id_'.$row['m_field_id']] = $row['m_field_name'];
}
$member_data = $this->EE->db->query("SELECT * FROM exp_member_data WHERE member_id = 1")->row();
foreach($member_data as $k => $v)
{
if($k != 'member_id')
{
$data[$fields[$k]] = $v;
}
}
print_r($data);
?>
Then just use your new $data array.
How do we sort using the database class in expressionengine. orderby and sort are given an error and do not seem to work. I can't seem to find anything in the documantation about sorting results. This is what i have.
$results = $this->EE->db->query("
SELECT plan_name
FROM exp__plans
WHERE member_id='1002' AND orderby="id" sort="desc" LIMIT 1
");
$x = $results->row('plan_name')
;
There are issues with your query.
try:
$results = $this->EE->db->query("
SELECT plan_name
FROM exp_plans
WHERE member_id = '1002'
ORDER BY id DESC LIMIT 1
");
I would recommend trying to run your query directly against the database if you're having trouble with it. 90% of the time it will be an issue with your SQL.
Also, you are writing this in a add-on... right? if you're trying to get this to work within a template I would recommend checking out the query module.
You can also use Active Record in order to create your query:
$this->EE->db->select('plan_name')
->from('plans')
->where('member_id', '1002')
->order_by("id", "desc")
->limit(1)
->get();
All the doc is on the Codeigniter website.