× Joomla Facebook Connect support forum

Topic-icon Integrating Open Graph

11 years 3 months ago #29182 by chramb1
Okay, initial question -

Let's say I have a component, com_mi, which is my photo gallery. It has the concept of a "picture" which is a single photo. So I've done $this->addSupportedObject("Picture", "picture"); in the init() function. Now what? How is this object consumed? Do I need to create a corresponding configuration entry in the administration interface?

I then also created two actions in init() as such:
    $this->addSupportedAction("Collect", "collect");
    $this->addSupportedAction("Critique", "critique");

Again, what do I do now? The idea here is that users can "collect" an image, which is simply adding it to a list of their favorites. They can also leave a critique, which is a more detailed comment on the image (I use JReviews for this). In both cases, I have code injection points where these actions are complete and I have all the information about them.

Do I then trigger an event, like onCollectedPicture or onCompletedCritique and put that event handler in my OpenGraph plugin? This is a guess based on the onGroupJoin() event handler in the JomSocial plugin.

What is confusing is that it seems like this plugin simply sets up variables that represent OpenGraph actions but doesn't actually do anything. I'm lost on how setting up the object/actions actually happens and, more importantly, once that happens, what I actually do with them and how I trigger the action when I'm at a point in my code where I can say, "here is where the user has added the image to a collection, so let's trigger the action!"

See where I'm not quite there yet? :-)
The topic has been locked.
11 years 3 months ago #29185 by chramb1
Replied by chramb1 on topic Integrating Open Graph
I note that after I installed and published my plugin, I can see it in terms of adding actions and options on the administrative side, but on the open graph tab, I only see the content, custom, jomsocial and k2 plugins. Since K2 says "not installed," I can only presume that these are the ones you, as distributor, know about, and that new ones don't show up here.

You might want to change the display output to make this more apparent, because I was, at first, concerned I'd not written mine right since it didn't show up here.

Better, I'd like to see mine here, as well, that it's installed and active - that would require that you discover it instead of using a list of known plugins (especially because mine is custom/proprietary, as we have no intention of distributing our codebase, at least not right now).
The topic has been locked.
11 years 3 months ago #29196 by chramb1
Replied by chramb1 on topic Integrating Open Graph
Further along, I cloned the custom plugin for my own and put in the query parameters. After some serious time with print_r() debugging (grin), I figured out what was happening and got my plugin to respond properly in findObjectType() and return the type.

I see where it then calls setOpenGraphTags() to set the tags.

Problem: my og_open_graph_tags is empty. This causes a bug, in that you use explode on the returned parameter, which results in an array with one, empty element. That empty element causes the foreach to fire and then the call to addOpenGraphTag has no $pair[1] which throws a warning, Notice: Undefined offset: 1 in /var/www/modelinsider/html/plugins/opengraph/mi.php on line 91 (your line number will be different, of course)

You need to check $tags for empty before proceeding to the call to explode(); My code looks like this:
  protected function setOpenGraphTags()
  {
    $tags = $this->object->getParameter('og_open_graph_tags');

    if (!empty($tags))
    {
      $tags = explode("\n", $tags);

      foreach ($tags as $tag)
      {
        $pair = explode("=", $tag);

        // Add this open graph tag to the page. If the final parameter is false, other objects or {SCOpenGraph} tags can overwrite the value.
        // If true, this tag is final.

        $this->addOpenGraphTag($pair[0], trim($pair[1]), false);
      }
    }
  }

Next issue...

In looking at the object returned by findObjectType, I see that the "associatedActions" element is empty. It should not be. I've associated an action to this object. As such, I'm at a loss as to what should happen next. I've got my graph tags working properly (when I have some - and often I have none, choosing to use the {} notation in the template itself), but now I need to implement my action, and I'm not sure where that flows.

Is "associatedActions" not what I think it is?

How exactly do I code inside my plugin to publish an action?

Here's where I'm even more confused - I implemented checkActionAfterRoute(), and did a print_r() on $action. I see my action! I presume that this is because I've associated the action with the object, and it fires because the object is returned by virtue of the plugin realizing that the query parameters (option and view) are matches. But the user hasn't taken the action yet! The action is to "collect" a picture, which requires a click on their part.

Do I need to filter inside of checkActionAfterRoute() and also be looking for the task to equal "collect" and then I know that not only did the plugin action fire, but that the situation was correct for the plugin to note that the action actually took place? If so, then... I'm stuck, as no action is being published to Facebook. Here's my code - the call to triggerAction() doesn't seem to be doing anything.
    protected function checkActionAfterRoute($action)
    {
      if (JRequest::getCmd('option') == 'com_mi' && JRequest::getCmd('layout') == 'collect' && $action->system_name == 'collect')
      {
        $id = JRequest::getVar('id');

        $url = 'http://www.modelinsider.com/inline/' . $id;

        $this->triggerAction($action, $url);
      }
    }

I've verified that triggerAction() is being called, so the filter logic is good. It's 1am, so I'm off to crash. Tomorrow, I'll start tracing through that call to triggerAction() and see what's happening unless you have some advice or a "hey, no, here's what you're doing wrong" response ;)
The topic has been locked.
Support Specialist
11 years 3 months ago #29213 by alzander
Replied by alzander on topic Integrating Open Graph
Christopher,
There's no hard-coded of the actions that are shown in the "New" popup, they are all discovered at run time. If you're seeing K2 actions there, but the K2 plugin isn't enabled, something fishy is going on. Any new actions should show up there, custom created by you or not.

As for the setOpenGraphTags function, yeah, we should check for if the array is empty first.. however, that whole plugins purpose is to set custom tags, so if they're not set, you shouldn't be using it. If you're modifying it to your will, you can gut that whole function if you want :)

Now, to the meat of your problem.. the associatedActions. These are the actions you've created in the admin area of JFBConnect Open Graph and clicked the 'check' next to the objects you want that action to be available on. The checkActionAfterRoute call is called on every action that is created in the Admin area of JFBConnect. It does not mean that the action is going to trigger. That function is meant to 'check' the 'action' to see if it *should* fire on the current object/page. If you look at the content.php plugin, the checkActionAfterRoute function checks to see if the current page is in com_content and the task is a vote (for instance). If so, then it calls triggerAction. That function will do the verification that the action is allowed to be performed on the object (page) based on whether the 2 have been associated in the admin area or not.

Hope that helps explain a bit more. If that's still not triggering for you, you should go into the models/opengraphaction.php file and investigate the triggeraction call. Specifically, print out the $queryVars variable and make sure the url you're trying to trigger against there is set to the proper object for the /inline/$id page.

Thanks,
Alex
The topic has been locked.
11 years 3 months ago #29222 by chramb1
Replied by chramb1 on topic Integrating Open Graph
The plugins showing in "new" are all correct. The issue is with the plugins that show on the main Open Graph configuration page. The headers are: Open Graph Plugins, Installed, Available, Status. I suspect that you've hard-coded just those plugins that you know about. K2 shows as "not installed" because I never installed it. When I do a "new," K2 does not show up and my plugin does. It's just this summary on the main page that doesn't show mine and shows K2 as not installed.

For tags, I think there's a scenario here where new plugins have no tags right away, but might, in time. Mine are coded on the template, so I have none, even though I'm using the plugin for actions. I might add tags later, and would like to keep the functions in there so I know where to do it rather than remove them.

So if I'm looking at the object and I see that associatedActions is empty, what should I take away from that? Because checkActionAfterRoute is firing properly and I now see where I filter on query strings and also the $action variable in checkActionAfterRoute. All appears to be working in my plugin, so I suspect I'm just looking at the object in findObjectType() when it is firing on something that is not the action I'm looking for.

So my plugin appears to be working correctly, and I just need to trace into triggerAction() as called within checkActionAfterRoute() to find out why I'm not seeing anything on Facebook. I suspect there's an error somewhere in the execution that's being masked. I'll let you know ;)
The topic has been locked.
11 years 3 months ago #29224 by chramb1
Replied by chramb1 on topic Integrating Open Graph
The call to triggerAction() in the example "custom" plugin that I cloned didn't consume the return information. So I'm consuming it now and here's what it's telling me:

stdClass Object
(
[status] =>
[message] => Action is not associated to the object type of this page.
)

Yet I've absolutely associated my "picture" object with my "collect" action.
The topic has been locked.
11 years 3 months ago #29226 by chramb1
Replied by chramb1 on topic Integrating Open Graph
Okay, here's the problem.

When triggerAction() is called, it makes another call into findObjectType() inside of JFBConnectModelOpenGraphAction::triggerAction()

Initially, my URL looks like option=com_mi&view=inline which are my query filters. This returns the object properly. But! When a user chooses to collect a picture, the URL they hit is built as option=com_mi&view=collect because it's a different controller that handles collections.

So I need findObjectType() to return the object for EITHER view=inline or view=collect ... but if one view is set, the other will fail, and so findObjectType() will never return the object.

There's no way to have a plugin use the example code in "custom" for situations where a parameter comparison is not all-or-nothing.

I think that this is a case where the example code for "custom" is contemplated to be pretty simple and do a single, all-or-nothing comparison. Since my code is a bit more complex, I think I've outgrown the example code and, instead, need to make a configuration variable specific to the task. Instead of a list of query parameters to match, I'm going to make one for the option and then a list of views, any one of which should trigger the object return.

You may want to add something when you document this that says, in essence, the example code is pretty basic, and if you need more complex logic, you should know that you'll need to do it on your own to suit your needs ;)
The topic has been locked.
11 years 3 months ago #29227 by chramb1
Replied by chramb1 on topic Integrating Open Graph
Getting closer, but this is confusing:

in JFBConnectModelOpenGraphAction::triggerAction() you get the objects from a triggered event of type onOpenGraphFindObjectType. That works, and returns an array with the object as well as some empty array elements. The empty elements, I presume, are failed calls to event handlers for the other plugins who dutifully return NULL because they're not appropriate. I'm cool with that.

You then do an array_filter on the returned array, getting rid of these empty elements. Good.

But then why the array_shift call? At this point, my array has one and only one element and it's in the zero-th position. Doing this array_shift shifts it off the edge and I now have an empty array!

Bug?
The topic has been locked.
11 years 3 months ago #29228 by chramb1
Replied by chramb1 on topic Integrating Open Graph
SUCCESS!

I removed the array_shift and still had problems, but then, in looking at the Facebook response message, saw that Autotune had picked up a different application when I'd initially configured it and I'd not changed it to my test platform. That was my fault. I re-ran Autotune and it worked. I now have an action post on my timeline!

www.facebook.com/christopher.ambler/posts/10151345371440935

Now, here's the only thing going on that I don't like - in order to make this work, the URL I pass into the call to $this->triggerAction() must be a Joomla URL. That is, I have to pass in:

$url = 'www.element67.com/index.php?option=com_mi&view=inline&id=' . $id;

And I cannot use this:

$url = 'www.element67.com/inline/' . $id;

That second URL format is rewritten in my .htaccess file and allows for a MUCH cleaner and more SEF URL to images on my site. But going through the process of creating a unique key and all of the other code, the URL is eventually non-parsed and destroyed somewhere along the line such that it eventually gets to the findObjectType() function as an empty array.

Looks like if you want to use URLs as keys and switches, you have to use Joomla long-form style. This makes the URL passed to Facebook the ugly one. Using a clean URL breaks your code which needs to parse it out to determine the view, task, layout, or whatever you're switching on. And again, somewhere in your code it would appear that if there's no "?" in the URL, it's not parsed properly and returns null.

I could hack your core code and add a "pretty url" parameter that gets passed along side everything and, at the last moment, in the final triggerAction() call in opengraphaction.php uses the pretty one in the call to api() ... but that's a hack.

I suspect I'm going to do that anyway :-)
The topic has been locked.
Support Specialist
11 years 3 months ago #29233 by alzander
Replied by alzander on topic Integrating Open Graph
Will take the posts in order as best I can..
Yes, the version check on the Open Graph page is hard-coded. At some point, we'd like to have an XML file that's loaded from our site stating what's available, but for now, we hard-code to check for specific plugins that we know about... there's always more to do :D

The empty elements, I presume, are failed calls to event handlers for the other plugins who dutifully return NULL because they're not appropriate. I'm cool with that.
You then do an array_filter on the returned array, getting rid of these empty elements. Good.

Correct. Joomla 2.5 actually removes the nulls for us, which was something we had to figure out when back-porting OGA's to J1.5... just a sidenote..

Now, on to the big sticky-wicket.. SEF URLs should definitely work. We just ran into a similar issue on this site (still on J1.5 for another month or so) when trying to get OGA's to work.. they parsing of the SEF URLs for checking if the object is associated to the action is returning the wrong information for some actions. We're looking into why. One super quick option, (that will surely need some debugging that you seem up for) is to edit the /models/opengraphaction.php file's triggerAction function. Look for the following line:
$args[strtolower($object->type)] = $url;
Update that to:
$args[strtolower($object->type)] = JRoute::_($url);
Then, just pass the non-SEF URL like you tested with (if possible). You may need to strip out the domain first so the JRoute works on the index.php?.. portion only and some other hijinx, but it's the quick idea I have.

Let me know how that goes and we'll be doing more SEF tests. We did a ton of SEF tests on J2.5 but for the J1.5 release, I think we just did non-SEF testing.

One final note, we're using sh404SEF on this site. Are you? Just checking if that may be a possible cause as well.

Thanks!
Alex
The topic has been locked.