page/teasers list selected by tag

Permalink Browser Info Environment
I'm working on a Magic Data page or teasers list based on tag selection.

The setup: a page below which all my content pages are, each of which is tagged according to the content, and another page which has a setof tags and which will contain a block with MD which should produce the list of title/links/teasers of all pages in the first set which have one of the tags in the second set.

So far I have this but something is amiss. Here, "/about" is the root of the tagged content, and page 238 is a page tagged with what should be shown on it.

Could anyone more experienced at this take a look?

"/about" AS_PAGE LIST_ALL_PAGES 999 APPLY_EACH SAVE MYPAGE
        SET 0 SAVE MYFLAG
        SET MYPAGE RETRIEVE CONTEXT Page ATTRIBUTE Tags APPLY_EACH SAVE MYTAG
            SET MYTAG RETRIEVE IN_LIST ( SET 238 CONTEXT Page ATTRIBUTE Tags ) IF ( SET 1 SAVE MYFLAG ) ( )
        END_APPLY_EACH
        SET MYFLAG RETRIEVE EQ 1 IF ( SET MYPAGE CONTEXT Page RETRIEVE PAGE_LINK ) ( NULL )
    END_APPLY_EACH 
HTML_OL

Type: Discussion
Status: New
View Replies: View Best Answer
JohntheFish replied on at Permalink Best Answer Reply
JohntheFish
I can't test the following fully, but one way of doing it would be something like this:
SET 238 AS_PAGE ATTRIBUTE "Tags" AS_LIST SAVE "tags_to_match"
SET "/about" AS_PAGE LIST_ALL_PAGES 999 
APPLY_EACH 
    SAVE "mypage"
    SET "0" SAVE "myflag"
    SET "mypage" RETRIEVE ATTRIBUTE "Tags" AS_LIST
    APPLY_EACH 
        IN_LIST ( SET "tags_to_match"  RETRIEVE ) 
        END_ON_NULL
        SET 1 SAVE "myflag" 
    END_APPLY_EACH
    SET "myflag" RETRIEVE 
    END_ON_NULL
    SET "mypage" RETRIEVE PAGE_LINK
END_APPLY_EACH
JohntheFish replied on at Permalink Reply
JohntheFish
My usual advice on developing anything complex is to test as much as possible in simpler fragments and then put the fragments together. This is a bit complex to get working all in one go.

If you have Uber List, there are some extended listing symbols you may (or may not) find useful for speeding this up. '999' pages will take a long time to process piecemeal, whether you use Magic Data or PHP.
pumpapa replied on at Permalink Reply
Hey John,

> My usual advice on developing anything complex is to test in simpler fragments

Sure. I have several fragments that work splendidly, but putting them together fails.

> '999' pages will take a long time to process piecemeal

Hahaha. Yeah. It's going to be 20-30 at most in practice. The limit is optional, apparently, but that didn't seem to work.

> whether you use Magic Data or PHP

Well.... I was wondering if you've ever considered exposing the key MD symbols in JavaScript (which is the language I use mostly currenly).
It would mean (JS) programmers can use datastructures and control structures they are familiar with and still use the power of MD.
(Or indeed php, where it has to be server-side). Just a thought though.

Anyway. The snippet you provided doesn't seem to work, and I can't see if it's my unfamiliarity with the semantics, or a bug. The relevant part of the trace seems to be

0. Symbols: [IN_LIST ( SET tags_to_match RETRIEVE ) END_ON_NULL SET 1 SAVE myflag]
1. Evaluating symbol [IN_LIST] using previous result [null] in context [Page]; Remaining: [( SET tags_to_match RETRIEVE ) END_ON_NULL SET 1 SAVE myflag]
2. Symbol [IN_LIST] returned [null]; Remaining: [( SET tags_to_match RETRIEVE ) END_ON_NULL SET 1 SAVE myflag]
3. Evaluating symbol [(] using previous result [null] in context [Page]; Remaining: [SET tags_to_match RETRIEVE ) END_ON_NULL SET 1 SAVE myflag]
4. Symbol [(] returned [Buurthuis]; Remaining: [END_ON_NULL SET 1 SAVE myflag]
5. Evaluating symbol [END_ON_NULL] using previous result [Buurthuis] in context [Page]; Remaining: [SET 1 SAVE myflag]
6. Symbol [END_ON_NULL] returned [Buurthuis]; Remaining: [SET 1 SAVE myflag]
7. Evaluating symbol [SET] using previous result [Buurthuis] in context [Page]; Remaining: [1 SAVE myflag]
8. Symbol [SET] returned [1]; Remaining: [SAVE myflag]
9. Evaluating symbol [SAVE] using previous result [1] in context [Page]; Remaining: [myflag]
10. Symbol [SAVE] returned [1]; Remaining: []


In line 1 it says "Evaluating symbol [IN_LIST] using previous result [null] " which for that page is right: no tags.
Then in 2 it says "Symbol [IN_LIST] returned [null]" which I can't interpret, not knowing the engine. I would expect the list to be evaluated before IN_LIST can be.
In 4 it has evaluated the list, providing the proper value [Buurthuis], which in 6 is considered by END_ON_NULL and is taken to mean non-null

It seems that APPLY_EACH is applied at least once even if the list is empty. Do you know if that is the case?

I've created the following horrible code that does at least work;

SET 238 AS_PAGE ATTRIBUTE "Tags" AS_LIST SAVE "tags_to_match"
SET "/about" AS_PAGE LIST_ALL_PAGES 999 
APPLY_EACH 
    SAVE "mypage"
    SET 0 SAVE "myflag"
    SET "mypage" RETRIEVE ATTRIBUTE "Tags" AS_LIST SAVE "page_tags"
    SET "page_tags" RETRIEVE
    APPLY_EACH 
        SAVE "this_tag"
        SET "page_tags" RETRIEVE
        END_ON_NULL
        SET "this_tag" RETRIEVE
        IN_LIST ( SET "tags_to_match"  RETRIEVE ) 
        END_ON_NULL
        SET 1 SAVE "myflag"


Any improvement would be appreciated.

And, thanks again.
JohntheFish replied on at Permalink Reply
JohntheFish
I think you could be correct about APPLY_EACH looping once for null lists. Maybe I need to fix that (or maybe it is desirable behaviour and a user could depend on it).

The optional limit defaults to 1 (in MD 1.0 it defaulted to infinite!)

My expression above was untested, so I am not surprised that it needed some work.

You working expression looks OK. What you are doing is pretty heavy stuff for Magic Data. You could maybe insert an extra END_ON_NULL where there are opportunities to abort APPLY_EACH early and improve efficiency.

The debug trace at the moment is generated recursively as subexpressions are entered and completed, so sequence can be hard to follow at this level of complexity. I have been working today on an upgrade to the symbol tester that creates a flattened trace that is strictly sequential and hence easier to follow. You will see that in the next MD release, maybe tomorrow.

Further down my roadmap for MD is AJAX execution from a callback in the browser to the server, tieing Magic Data in with Blocks By Ajax. So not a full port to JavaScript, but it will enable MD to be used to script in-browser responsive actions.

Before then I have Black Magic Data (on this forum), some ideas for includes so you can set up a library of snippets in the dashboard and pull them in all over the place, pulling content by creating some MD symbols for Universal Content Puller, a forms integration with symbols to get results from the core forms or any of the forms addons, deeper integration for Magic Data Developer, ajax optimisation for Uber List pagination ...... its a big list. So many users are coming up with new ideas in all sorts of directions.
JohntheFish replied on at Permalink Reply
JohntheFish
PS.

IN_LIST looks for an item in a following list. There is a complementary symbol LIST_CONTAINS that works the other way round.

You may be able to optimise your expression using INTERSECT and COUNT to look for the number of items comparing the 2 lists.

That could avoid one level of APPLY_EACH loop.
pumpapa replied on at Permalink Reply
All clear. Thanks again for helping me.
JohntheFish replied on at Permalink Reply
JohntheFish
Blocks By Ajax now includes symbols for Magic Data integration including delayed evaluation of expressions by an ajax callback to the server.
JohntheFish replied on at Permalink Reply
JohntheFish
APPLY_EACH now completely skips empty lists (v2.1+)

concrete5 Environment Information

Browser User-Agent String

Hide Post Content

This will replace the post content with the message: "Content has been removed by an Administrator"

Hide Content

Request Refund

You have not specified a license for this support ticket. You must have a valid license assigned to a support ticket to request a refund.