Get Page ID from Attribute controller [Help needed to debug new sub-cat attribute]

Permalink 1 user found helpful
I am working on a new attribute type and need to get the current page,

I am currently using $_REQUEST['cID'], but don't think thats the best way to do this. I was hoping I could hook into one of the objects that are called from within the attribute controller.

Is this possible and if so what do I need to be using?

//current implementation 
$page = Page::getByID($_REQUEST['cID']);
$page->setAttribute($ak,$value);
//within a attribute controller, 
//Page::getCurrentPage(); /returns blank


edit: I have attached my current attribute below (It's currently very buggy, and not to be used on a production site)

TheRealSean
 
JohntheFish replied on at Permalink Reply
JohntheFish
Page::getCurrentPage() may depend on when your attribute is viewed and the state of the cache.

For example, the current page is not actually worked out by c5 until after the on_start event has been processed.
TheRealSean replied on at Permalink Reply
TheRealSean
Hi John, thanks for your reply

I am calling this within the save_form of the attribute controller, the section I am at is page > properties > Custom attributes

I have an attribute, that I have added this also pulls in a parent attribute(a select attribute) that I would also like to save when I click on "Save"

What I have currently works, (sort of) but I would like to clean some of it up if possible.
JohntheFish replied on at Permalink Reply
JohntheFish
I don't have a ready answer for this. Perhaps someone else can chip in.
jshannon replied on at Permalink Reply
jshannon
Good luck with that. You're going to have to hack it. And, as John said, note the other contexts where you might need the data. Even if Page::getCurrentPage() works, what happens when someone tries to edit the attribute from the dashboard sitemap?

I had the same need for a file attribute. The attribute needed to do some stuff and needed to know what file it was attached to. Eventually the core team was asked on TRL how this could be done, or how it could be architected to be done. The answer was the somewhat standard, "We see no reason why that's necessary... Next."

I had to look at the $_GET variables to suss out the file id. My next step would have been to write some SQL, but that wouldn't have worked until after the first save.
aghouseh replied on at Permalink Reply
aghouseh
Yup, the AttributeType is object-agnostic, and right now does not have any way to determine the object for which it is being attached. The only method that exists is to scrape the $_REQUEST global for the default AttributeKeyCategories id (file = fID, user = uID, collection = cID).
TheRealSean replied on at Permalink Reply
TheRealSean
thanks for the info and you raise a good point I am trying to get this so that I can add the article from a composer page, and at this point in the process, the cID may not event exist.

I might need to go back to the drawing board for this one.

I was trying to get it so that I could add the single attribute, maybe I just need this to stay with two separate attributes and update the second according to the first choice via a selector and attempt an ajax post.
TheRealSean replied on at Permalink Reply 1 Attachment
TheRealSean
I have enclosed the work so far, its very rough at the moment. It still has all my debug code in there.

It does require another (select) attribute to exist. In my example I am using a hardcoded select attribute, "employment_category" set in the controller.

Also if you currently add a categories attribute, on the first add, the parent category can be chosen but does not update, until the next reload. (An issue with me calling a function before the page has finished loading) It does however save the parent category.

The premise for this attribute is to be able to have a Job(Parent Category) and then depending on the category chosen, have a list of sub-categories displayed.

The idea, once completed is to release it as a free atribute, there are a few other sites I would have liked an attribute like this for. Currently I use pages then sub pages for categorisation but I find that adds an extra level of complexity when you need to choose which of the 30+ pages you can publish an article under.

I would be really grateful if anyone was able to spare a little time and point out any glaring errors or any sections that you think can be improved. I'm really in over my head with the js and ajax in concrete but learning as I go.

Thanks
Sean
jshannon replied on at Permalink Reply
jshannon
I haven't looked at the code, so I'm not 100% sure on what you're doing, but couldn't this be done as a single attribute, that manages and creates two different selects?
TheRealSean replied on at Permalink Reply
TheRealSean
That was my first thought but the issue I had was, when I added the child category I was unable to get the previous parent elements. Each time I tried to grab the latest entries to populate the parent select box I broke the attribute page.

Creating two separate attributes enabled me to work around that particular issue by ensuring I am pulling in a list of results and not dynamically altering them as and when I added a new parent.

I may be over thinking this a little, it is possible that I could just set the child attribute and then by inheritance, work out the parent category, maybe I do not need to set parent attribute at all.

What I am trying to achieve is to have the following,
//Choose Cat A
Category A
    //Sub categories select box are filtered by Cat A
    Sub Category 1
    Sub Category 2
    Sub Category 3
// Or choose Cat B
Category B 
    //Sub categories select box are filtered by Cat B
    Sub Category 4
    Sub Category 5
    Sub Category 6
//Instead Of them being seperate
//Category is chosen
Category A

Thanks
Sean
TheRealSean replied on at Permalink Reply 1 Attachment
TheRealSean
My latest version is attached, I seem to be getting much closer now.

I have moved the setAttribute to be reliant on a request page object, otherwise it ignores that. The parent page is not to important for me as knowing the child category you can work back. (This could be an issue if you wanted to filter by the top level category as well?)

The dashboard attribute page actually appears to be loading the correct values and posting the correct content now, but needs cleaning up.

I'm using this with the Jobs Listing Package so have had to change the search page to accommodate the new attribute, so a block would need adding to actually filter the pages.

I'm going to go out on a limb an say this will not work within the dashboard page search area, using the category part of the attribute.

I'm trying to get this to a stage were I am happy placing it a clients site then will move the code to github,
Remo replied on at Permalink Reply
Remo
Why don't we change the core to forward the calling object?
Feels a lot cleaner to me, especially since I can call setAttribute almost anywhere and thus don't have $_REQUEST available

What do you guys think about that:
https://github.com/concrete5/concrete5/pull/1278...
TheRealSean replied on at Permalink Reply
TheRealSean
Thanks Remo, that sounds great to me.

If I could just clarify, to check I have this right?

When you save the Attribute, you store the appropriate object along with the Attribute. In my case the cID but could be a user/file object.

That way when the attribute is loaded (as long as you know the CallingObject type?) the object can be dealt with.

Do the objects(Collection/User/File) contain their type? or is it assumed if you are referring to the Calling Object you know the object type already?.
Remo replied on at Permalink Reply
Remo
It doesn't happen when the attribute is loaded, it happens a bit later when the save method is called. As mentioned on github, this isn't perfect.

The calling object is always an object, you can check it with something like instanceof