HTML Logo by World Wide Web Consortium (www.w3.org). Click to learn more about our commitment to accessibility and standards.

Moving forward with Composr

ocPortal has been relaunched as Composr CMS, which is now in beta. ocPortal 9 will be superseded by Composr 10.

Head over to compo.sr for our new site, and to our migration roadmap. Existing ocPortal member accounts have been mirrored.


Trying to write a compound Tempcode directive

Login / Search

 [ Join | More ]
 Add topic 
Posted
Rating:
#106892 (In Topic #20844)
Avatar

Well-settled

...and failing!

Greetings!

I've been trying to figure out a solution to the following problem:

My site's Downloads section comprises two categories, in both of which I want to be displaying the description text for entries to all users. One category is "open access" i.e. all users can activate "download now" link for each entry. The other category contains downloads available to paid-up usergroups only, so only they should be displayed the link.  

My approach has been to enclose the .download_now rule in DOWNLOAD_SCREEN.tpl within a conditional Tempcode directive. But for some reason, I can't get my head round the logical structuring of such a directive. I've tried for example:
{+START,IF,{$NOT,{$IS_IN_GROUP,10}$XOR,{$EQ,{$MATCH_KEY_MATCH,site:downloads:misc:3}}}}

but that has no effect on either category, regardless of usergroup. (Group 10 is the usergroup that is to be prevented from seeing the link in the "members only" category, and "3" is the "open access" category that should display the link to all usergroups.

Basic problem is, I guess, with the bracketing, especially for the $XOR/$OR (makes no difference in the above formula). Trouble is, I can't find in any template any example of a directive using a boolean operator that I could use as a model for the correct bracketing structure/syntax. (It would really help to have a section in the Tempcode Programming tutorial with 2 or 3 examples to demonstrate how!)

Please would anyone be able to guide me on this?

Thanks for reading!
Back to the top
 
Posted
Rating:
#106893
Avatar

You're pretty confused ;).

I doubt you want to use 'XOR', because that would say people who are both in that group, and in that category, couldn't access. XOR means "either or, not both". You just want 'OR'.

The Tempcode nesting is not like infix maths, the operator doesn't go between the operands. It's purely based on the same prefix/function-call notation all the way through.
i.e.
{$SYMBOL,param1,param2,param3,...}

I'm not sure what the 'NOT' is for, I think you want to grant to people in that group, not not in that group right?

Finally, 'MATCH_KEY_MATCH' is returning true or false (actually 1 or 0) so does not need an 'EQ' which itself just returns true or false. If you did use, 'EQ, you'd need to do it like {$EQ,...,1}, but as I say it's redundant.

So…

Code

{+START,IF,{$OR,{$IS_IN_GROUP,10},{$MATCH_KEY_MATCH,site:downloads:misc:3}}}


Become a fan of ocPortal on Facebook or add me as a friend. Add me on on Twitter.
Was I helpful?
  • If not, please let us know how we can do better (please try and propose any bigger ideas in such a way that they are fundable and scalable).
  • If so, please let others know about ocPortal whenever you see the opportunity.
  • If my reply is too Vulcan or expressed too much in business-strategy terms, and not particularly personal, I apologise. As a company & project maintainer, time is very limited to me, so usually when I write a reply I try and make it generic advice to all readers. I'm also naturally a joined-up thinker, so I always express my thoughts in combined business and technical terms. I recognise not everyone likes that, don't let my Vulcan-thinking stop you enjoying ocPortal on fun personal projects.
  • If my response can inspire a community tutorial, that's a great way of giving back to the project as a user.
Back to the top
 
Posted
Rating:
#106897
Avatar

Well-settled

Hi, Chris,

Many thanks for clarifying that - I think those few basic points ought to put me straight for any situation.

Naturally I applied your directive right away - and, well, got the inverse result to what I'm after, so I changed from testing against the non-paying usergroup to the paying ones (my reason for applying $NOT originally!) -with some improvement, but not totally. I've tabulated your result along with the best of the many I experimented with, as follows:

Desired effect:
(O.A.=Open Access=category id 3; M only=Paying Members=category id 2;
2-9=staff, paying members; 10=registered guests)
O.A. (2-9) 0.A. (10) M only (2-9) M only (10)
  Link  Link  Link No Link
 

Your directive:
{+START,IF,{$OR,{$IS_IN_GROUP,10},{MATCH_KEY_MATCH,site:downloads:misc:3}}}
Result
O.A. (2-9) 0.A. (10) M only (2-9) M only (10)
:( No link :thumbs: Link :( No link :( Link

My alternative, v.1:
{+START,IF,{$OR,{$IS_IN_GROUP,2-9},{MATCH_KEY_MATCH,site:downloads:misc:3}}}
Result
O.A. (2-9) 0.A. (10) M only (2-9) M only (10)
 :thumbs: Link  :( No Link :thumbs: Link  :thumbs: No link
 

My alternative, v.2
{+START,IF,{$NOR,{$IS_IN_GROUP,10},{$MATCH_KEY_MATCH,site:downloads:misc:2}}}
Result:
O.A. (2-9) 0.A. (10) M only (2-9) M only (10)
:thumbs: Link :( No Link :thumbs: Link :thumbs: No Link
Result was identical when cat id was changed to 3.

Actually, the cat id value in general has no impact on any results! In view of that I tried substituting $AND for the $OR versions, which resulted in no link displayed on any of the 4 cases. Finally I tried testing against the $MATCH_KEY_MATCH alone and got that same result, using either cat id. So it appears that $MATCH_KEY_MATCH directives simply aren't getting tested by the system. Which would account for getting nowhere with it in other past contexts, too. Am I correct?

Anyway, I do feel rather more confident about structuring directives after a couple of hours hard practice! So many thanks again for your rescuing me there.

Kind regards, 
Richard.
Back to the top
 
Posted
Rating:
#106898
Avatar

Community saint

If I am interpreting your desire correctly, you want all members (usergroups 2-10) to have download access to download category 3, and only payed members (usergroups 2-9) to have download access to download category 2. But you also want non-paying members (usergroup 10) to see the downloads in download category 2 but not be able to see the download link. The logic, in more worded terms, would look something like this:
 
(
 If (usergroup is 2-10)
     AND 
     (currently viewed download is in category id 3)
)

 
OR
 
(
 If (usergroup 2-9)
     AND
    (currently viewed download is in category id 2)
)

THEN provide download link

 
I agree, it looks like the match key is always returning false and so the whole expression only evaluates true or false based on the IS_IN_GROUP test. I'm guessing that by the time the user gets to the download screen, the match key is no longer going to match the URL. If that's the case, a new tempcode symbol that can test if a content ID belongs to a specific category ID would probably be needed.
 
In any case, using this method will only hide the download link from the non-paying registered members (group 10). It won't prevent them from trying to figure out the URL pattern needed from other working downloads to try to gain access to the payed-member downloads for free. What you probably should do is restrict the view permissions of category id 2 so usergroup 10 does not have view access. As you probably already know, the main problem with this approach is that it won't give the non-paying members a teaser of what is available, so you would have to provide that teaser somewhere else. I think, to truly accomplish what you are desiring, what would be needed is another layer of permissions that could be assigned to the actual download...separate permissions for each download that say who can view the download and who can download the download.
Back to the top
 
Posted
Rating:
#106899
Avatar

Well-settled

Hi Jason!

Thanks indeed for your kind and, as ever, deeply engaged reply! From past occasions when you've given me your time on this kind of Tempcoded permissions stuff, I'd already reached the point on this latest case of hoping you'd spot my topic and dive in yet again. So, yet again, I'm considering myself well and truly lucky!

Your estimation of the logical structuring is spot on, and describes my strategy so far.
What is baffling me is specifically the match key aspect. My rationale for using it is to test for the presence of a certain class (.download_now) that only pertains to URLs in Downloads categories 2 & 3 (which are my only categories with links evoking the template declaring that class, i.e., DOWNLOAD_SCREEN.tpl). All I'm requiring it to do is to confirm which of those two categories the template has been activated within. As I understand match keys, they don't specify matches to specific URI targets, but only matches to the part of the URL path they actually declare, and so should return a "true" value for all paths with matching instances. Well, that's not happening, even if I omit the category id; the closest match I can get to return "true" is site:downloads! If you were able to suggest any comments on that, I'd be really grateful!

I take your point that, if a match-key declaration isn't specific enough for one's purpose, another more closely specifying Tempcode symbol would have to be tied in. But if we're talking about ones that specify individual entries, that doesn't fit ocPortal's stated point that the Downloads system has been designed for accommodating very large numbers of entries, automated in-bulk adding etc.. Obviously, classifying of entries at category level, rather than individually, would be more consistent with that objective. (What's the justification for providing categories otherwise?)

I'm sure the huge palette of Tempcode symbols must offer alternative (perhaps more ingenious than obvious) ways of achieving my (hardly intricate) goal, and it's just a case of thinking them up. I'm going to start applying my gray matter to that, rather than hold myself back for the sake of an uncooperative match key. I'll be sure to post you back if and when I come up with anything successful!

Many thanks again, & best regards,
Richard.
Back to the top
 
Posted
Rating:
#106900
Avatar

Well-settled

Quick progress update:

I just tried this directive as an alternative to a match-key method:

{+START,IF,{$OR,{$IS_IN_GROUP,2-9},{$USERNAME,13}}}

where 13 is the member_id of a dummy user in GROUP 10.

This test returned "false" (like the match-key directives), so no link was displayed to this user (who was logged in).

Assuming the syntax (which follows Chris's) is correct, why should this not return "true"?

I'm not sure if this relates anyway at all to the problem, but I notice that when I open the contextual "Show template Edit Links" in a Downloads Screen page, the Edit Link or block boundary for DOWNLOADS_SCREEN.tpl is not displayed. However, the template's name does appear in the contextual "Templates" and "Template Tree" panes and the "View source" for the contextual "Template names as HTML comments" pane.

Just thought I'd mention that one on the offchance.

By the way, where/ how within ocP can I find member-id s listed?
Back to the top
 
Posted
Item has a rating of 5 (Liked by Chris Graham)  
Rating:
#106902
Avatar

Community saint

In your test using the {$USERNAME,13}, that tempcode would return the actual text of the user name for that user ID 13. You would probably have to use {$USER} and then use $EQ to test against the user ID. Try replacing {$USERNAME,13} with {$EQ,{$USER},13} and it should evaluate to true when that user (with ID 13) goes to that page.

I've setup some test downloads on my test site to play around with and have a couple of ideas. On my download entry page, the URL has the following components: page=downloads, type=entry, and id=download entry ID

As I suspected, once you get to the download entry screen, the ID of the category is no longer available to the match key. The match key only matches on the URL of that download entry page (as displayed in the browser address bar) and not on the location of that content within the site structure at that end point.

I'm not seeing any tempcode symbols or any other readily available options to give you the desired result. There may be some hidden or undocumented symbols in the sources\symbols.php file and in the hooks\systems\symbols directories in sources and sources_custom, but after quick scan through them, I didn't see anything obviously useful for this situation. The two easiest options I can think of would be to alter the download module to pass in the download category ID as a parameter to the DOWNLOAD_SCREEN.tpl template, or create a new tempcode symbol where you can pass in the current download ID and a target category ID and have the symbol return true or false based on if the current download entry is or isn't in the category you specified. Of those two options, creating a new tempcode symbol is probably the quickest way and least likely to break anything with future ocPortal upgrades.

New symbols can easily be created and added to the sources_custom/hooks/systems/symbols directory. This is something I would use on one of my sites, so I'll take a shot at creating this new tempcode symbol. Do you have any recommendations for an intuitive name? Does something like {$DOWNLOAD_MATCH_CATEGORY,download_id,category_id} make sense?

Once completed, using that new symbol, you could add something like this to the top of the DOWNLOAD_SCREEN.tpl template (I think I got the logic correct):

Code

{$INIT,download_allowed,false}
{+START,IF,{$OR,{$AND,{$IS_IN_GROUP,2-10},{$DOWNLOAD_MATCH_CATEGORY,{ID},3}},{$AND,{$IS_IN_GROUP,2-9},{$DOWNLOAD_MATCH_CATEGORY,{ID},2}}}}
 {$SET,download_allowed,true}
{+END}
{+START,IF,{$NOT,{$OR,{$AND,{$IS_IN_GROUP,2-10},{$DOWNLOAD_MATCH_CATEGORY,{ID},3}},{$AND,{$IS_IN_GROUP,2-9},{$DOWNLOAD_MATCH_CATEGORY,{ID},2}}}}}
 {$SET,download_allowed,false}
{+END}
​​​​​​​​​

That will define a download_allowed variable and set it to true or false based on your usergroup and category criteria. Then, further down in the template where the download link/button is displayed, you would integrate in this code:

Code

{+START,IF,{$EQ,{$GET,download_allowed},true}}
  place your download button/code here to download the file
{+END}
{+START,IF,{$EQ,{$GET,download_allowed},false}}
  place message or signup link here for members that don't have enough access to download this file
{+END}
Back to the top
 
Posted
Rating:
#106903
Avatar

Community saint

Ahh, possibly a mix-up here too… there are two places where the download link is displayed. In the download entry screen, which uses the DOWNLOAD_SCREEN.tpl template to display a single entry. And in the category page where it lists multiple downloads in a less detailed list, which uses DOWNLOAD_BOX.tpl template. The category page that lists multiple downloads has the More Info and Download Now links. The More Info link will go to the download entry screen where it uses the DOWNLOAD_SCREEN.tpl template.

You should be able to use the match key in DOWNLOAD_BOX.tpl template since the URL, at that point, does contain the category ID. But you would have to also remove the More Info link to prevent those users from getting to the entry page that also contains the download link. Otherwise you would still need a new tempcode symbol and change the DOWNLOAD_SCREEN.tpl template as I mentioned in the previous post. 

I'll also note again, this method would only hide the download links from the non-paying members and not actually prevent these non-paying members from downloading the files. It wouldn't take much poking around to figure out what the download URL pattern is and which download ID numbers are being hidden. Once that is figured out, a non-paying member could grab every single downloadable file for free. If you rely on payed memberships and downloads for income, use permissions to block access to the category...don't underestimate the tech-savviness of your web site visitors to find that little loophole. Some additional restrictions would need to be added, probably to the dload.php script that handles the download request. But they would probably have to be hard coded into the script and updated anytime there is a major change to usergroups or download categories.
Back to the top
 
Posted
Rating:
#106904
Avatar

Community saint

For locating the member ID, the easiest way might depend on whether you have enabled the ocPortal site option URL Monikers Enabled in Setup>Configuration>Site Options>Advanced. If that is disabled, you should be able to go the member list (Tools>Members>Edit Account) and hover over the member name and see their ID in the URL that pops up in the browser status bar. If the URL Monikers Enabled option is enabled, it's probably just easier to download the member list csv file at Tools>Members>Download Member Spreadsheet.
Back to the top
 
Posted
Item has a rating of 5 (Liked by Guest)  
Rating:
#106905
Avatar

Community saint

I think I've got a working DOWNLOAD_MATCH_CATEGORY tempcode symbol coded up. It shouldn't throw any errors if ID numbers are invalid. Instead it should return boolean value of FALSE.

Usage:

{$DOWNLOAD_MATCH_CATEGORY,download_id,category_id[,optional comma separated list of category IDs]}

download_id is normally going to come from the template parameters and should usually be {ID}.

category_id is the ID number of the category you want to test the download against.

If the download is in the category you specify with category_id, then the symbol will return boolean value of TRUE. If not in the specified category, the symbol will return FALSE. You can match against multiple category IDs by adding more IDs separated by commas to the end of the symbol parameters.

The attached DOWNLOAD_MATCH_CATEGORY.php file should be placed in the sources_custom\hooks\systems\symbols directory. The tempcode examples I posted a couple of posts up should work with both the DOWNLOAD_SCREEN.tpl and DOWNLOAD_BOX.tpl templates (but I haven't tested those specific tempcode examples). Let me know if it doesn't work.
Attachment
» Download: DOWNLOAD_MATCH_CATEGORY.php (1.38 Kb, 110 downloads so far)
Back to the top
 
Posted
Rating:
#106907
Avatar

Community saint

A couple of things I forgot to mention... I probably took your desired logic a bit too literally. The example tempcode posted above assumes you only have two download categories. If you have any additional download categories or sub-categories, some changes to the tempcode logic will be needed. The logic of the example tempcode will show/hide the download links base only on the desired logic for categories 2 and 3. If you have any other categories or sub-categories, those download links will always be hidden. You could change the {$INIT,download_allowed,false} to {$INIT,download_allowed,true} and then remove that whole first {+START,IF...}...{+END} block from that first example chunk of tempcode. Then change this line:

{+START,IF,{$NOT,{$OR,{$AND,{$IS_IN_GROUP,2-10},{$DOWNLOAD_MATCH_CATEGORY,{ID},3}},{$AND,{$IS_IN_GROUP,2-9},{$DOWNLOAD_MATCH_CATEGORY,{ID},2}}}}}

to this:

{+START,IF,{$AND,{$IS_IN_GROUP,10},{$DOWNLOAD_MATCH_CATEGORY,{ID},2}}}

Those three changes (changing the INIT line to true, removing the first START/END block, and changing the second START block) will have this logic: Only hide the download link if the member is in usergroup 10 and they are viewing a download in category 2.

And if you have sub-categories under category 2, you would append them to the end of the DOWNLOAD_MATCH_CATEGORY symbol. If category 2 had sub-categories 5, 6, 7, and 12, the line would be:

{+START,IF,{$AND,{$IS_IN_GROUP,10},{$DOWNLOAD_MATCH_CATEGORY,{ID},2,5,6,7,12}}}

That would hide download links for downloads that are in those additional categories/sub-categories for members in usergroup 10.
Back to the top
 
Posted
Rating:
#106908
Avatar

Well-settled

Hi Jason,

Wow - thanks indeed for such massive input into this! I'm truly indebted to you.

I've got to relay you my apologies for needing to delay replying properly for (I trust no more than) a day or two - I'm confined to bed today with 'flu, and so haven't yet installed your solution. Forgive me - I'll be back to you as soon as possible.

For now, a real big thank you!

Best regards,
Richard. 
Back to the top
 
Posted
Rating:
#106909
Avatar

@RichT sorry you're ill
@Jason yet another epic reply :)


Become a fan of ocPortal on Facebook or add me as a friend. Add me on on Twitter.
Was I helpful?
  • If not, please let us know how we can do better (please try and propose any bigger ideas in such a way that they are fundable and scalable).
  • If so, please let others know about ocPortal whenever you see the opportunity.
  • If my reply is too Vulcan or expressed too much in business-strategy terms, and not particularly personal, I apologise. As a company & project maintainer, time is very limited to me, so usually when I write a reply I try and make it generic advice to all readers. I'm also naturally a joined-up thinker, so I always express my thoughts in combined business and technical terms. I recognise not everyone likes that, don't let my Vulcan-thinking stop you enjoying ocPortal on fun personal projects.
  • If my response can inspire a community tutorial, that's a great way of giving back to the project as a user.
Back to the top
 
Posted
Rating:
#106910
Avatar

Community saint

No problem Rich, sorry you're not feeling well. If you run into any problems implementing this, post them here.
Back to the top
 
Posted
Rating:
#106919
Avatar

Well-settled

Hi Chris and Jason!

THANK YOU both so much for those kind good wishes - they're working!

R

Back to the top
 
Posted
Rating:
#106920
Avatar

Well-settled

Hi Jason!

Brilliant! Although I couldn't get your amended version to give the right results on the right pages, your original version with the two blocks works perfectly. I guess if I should ever need to add a further category, I'll be able to add to that code without too much head scratching. But since further categories aren't envisioned, mission accomplished and I'm thoroughly pleased.

All your generosity in working this out hasn't only met my need, but provided a real tutorial for me in Tempcode technique as well. It would be great to know how you acquired all your know-how - just by experimenting?

Hugely grateful for all your kind help, Jason.

Best regards,
Richard.
Back to the top
 
Posted
Item has a rating of 5 (Liked by Chris Graham)  
Rating:
#106927
Avatar

Community saint

Excellent!

How did I acquire my know-how? I started using ocPortal in the early half of 2011. And even with four years of part-time experience, there is still much more for me to learn. Over the past four years, I have done lots and lots of reading, re-reading, examining and stepping through existing code, experimenting, and trial-and-error. ocPortal (or should I now say Composr) is not just a CMS. It's a very flexible, very secure, and very thorough framework. I have jumped much further into the framework than most people probably every will, but most people looking for a CMS to quickly set up a web site won't need to jump too far in.

Here is a list of the pages I read, re-read, and constantly refer to:
http://ocportal.com/docs/tut_tempcode.htm
http://ocportal.com/forum/forumview/misc/themeing.htm - Jeans tutorials
http://ocportal.com/docs/tutorials.htm
http://ocportal.com/site/cedi.htm
http://ocportal.com/docs/tut_framework.htm
http://ocportal.com/docs/codebook.htm
http://ocportal.com/docs9/codebook_1.htm
http://ocportal.com/docs9/codebook_1b.htm
http://ocportal.com/docs9/codebook_2.htm
http://ocportal.com/docs9/codebook_3.htm
http://ocportal.com/docs/api/

I recommend the first four links for everybody that uses ocPortal. They provide excellent examples, tutorials, and documentation. The rest of the links are for anybody that really wants to jump into the framework to change features or add new features, but you will definitely want to be familiar with PHP (or willing to learn) or you will probably be easily lost.
Back to the top
 
Posted
Item has a rating of 5 (Liked by Jason Verhagen)  
Rating:
#106977
Avatar

Well-settled

Hi Jason!

Further thanks galore for all of that - on top of everything else! Grateful to you beyond words.

All good wishes to you,

Richard.
Back to the top
 
1 guests and 0 members have just viewed this: None
Control functions:

Quick reply   Contract

Your name:
Your message: