Error when creating page from external app

Permalink
Hello everyone.

I'm currently working on a script that will allow me to create a new page in C5 from an external app, but I'm running into a bit of a snag. I've been looking at the following forum posts:

http://www.concrete5.org/community/forums/customizing_c5/page-impor...
http://www.concrete5.org/developers/bugs/5-4-2-1/c5_integration-wit...
http://stackoverflow.com/questions/15041252/bootstrapping-c5-from-a...

This has given me a good start, but I'm getting the following error

include(Concrete5_Helper_File.php): failed to open stream: No such file or directory

Here is my code:

define('C5_ENVIRONMENT_ONLY', true);
      include (realpath(__DIR__ .'/../../c5/index.php'));
      Loader::model('collection_types');
      return "start";
      $pr = Page::getByPath('/dashboard/test_page');
      $data = array();
      $data['cName'] = "New page";
      $data['cDescription'] = "New page";
      $data['cDatePublic'] = date_create();
      $ct = CollectionType::getByHandle('right_sidebar');
      $id = $pr->add($ct, $data);
      return $id;


The error is getting thrown at the include statement, and the stack trace shows it's occurring inside concrete/helpers/file.php when it extends the Concrete5_Helper_File. I'm thinking this is happening because of where the script is being called from. Since the require statements inside dispatcher.php are getting added, but the extends statement is not, I'm thinking it could be a file-path issue, but I'm not sure. My file structure is as follows:

Root
->externalApp
--->script

->c5
--->index.php

Any help that can be given would be greatly appreciated, thanks!!

 
hugmungus replied on at Permalink Reply
Still having this issue. Dispatcher.php get's included, then inside of "file_permissions_config" at line 4, it starts looking for a helper file it can't find. It looks like it might be trying to extend itself, but I'm not sure on this:
class FileHelper extends Concrete5_Helper_File {} //concrete/helpers/file.php line 24
spl_autoload_call("Concrete5_Helper_File"); // calls YiiBase::autoload
include($className.'.php'); //Yiibase line 427 - $className = Concrete5_Helper_File.php - throws error


I'm not really sure on what the helper file does, or if I need it. If anyone has any ideas, I could really use the help!
JohntheFish replied on at Permalink Reply
JohntheFish
You could place the script in library and use the library from a tool file. That way you won't need any includes or such, just the Loader::library and some wrapping code in the tool. The c5 environment only stuff is then already handled for you.
hugmungus replied on at Permalink Reply
Hi JohntheFish,

Thanks for the reply! I'm currently trying to load C5 from an external app to give me access to its API, so I've been putting this code in a controller in my external app (I'm using Yii to be specific). Do you mean I should write a script, and load it in the libraries folder inside of C5? Would I then load this script from my external app instead of going through dispatcher.php? Thank you for your help, and clarification, I really appreciate it.
JohntheFish replied on at Permalink Best Answer Reply
JohntheFish
What I mean is the best context within which to run
such code is within a tool.

Putting the bulk of it in a library is just a convenient way of structuring it.

So external stuff calls a tool URL with whatever get/put parameters.

The tool code validates its caller, loads the library, and calls a method in the library class where your code really does its stuff.

The dispatcher is still involved in setting up c5 for the tool, but only in an environment only way. However, because tools take care of that, you don't need to.
hugmungus replied on at Permalink Reply
So you mean call the library inside of C5 through a PUT/POST/GET request from my Yii app instead of trying to load everything by including Dispatcher.php, right? I'll give that a shot this week and report back with the results, thanks.
hugmungus replied on at Permalink Reply
Ok, so here is the POST request I've setup to call my tool, located inside of "root/tools"

$url =  "http://localhost/~hugmungus/Yii/concrete/tools/tool.php";
      $myvars = 'myvar1=' . 'one' . '&myvar2=' . 'two';
      $ch = curl_init( $url );
      curl_setopt( $ch, CURLOPT_POST, 1);
      curl_setopt( $ch, CURLOPT_POSTFIELDS, $myvars);
      curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 1);
      curl_setopt( $ch, CURLOPT_HEADER, 0);
      curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1);
      $response = curl_exec( $ch );
      print_r($response);die();


I have an echo statement inside of the tool that I should see once it receives the POST, but all I'm getting back is "Access Denied." Is there some permissions I need to setup somewhere to allow for external http requests? Thanks again for the help JohntheFish.
hugmungus replied on at Permalink Reply
Ok, finally got it working. This issue I was having was I had the standard "defined('C5_EXECUTE') or die("Access Denied.");" at the top of my tool file(duh).

Now I just need to work on my calls, and doing the second part of what Mr. theFish recommended.

"The tool code validates its caller, loads the library, and calls a method in the library class where your code really does its stuff."

Thanks again!
hugmungus replied on at Permalink Reply
I might have been a bit premature on accepting the answer. I can post into the tool, but I don't think it's loading Concrete5 with it (hence the Access Denied return value on the defined('C5_EXECUTE') or die statement). I'm trying to use the Loader class to load my library but I'm getting the following error:

Class 'Loader' not found.
JohntheFish replied on at Permalink Reply
JohntheFish
I am not sure if pretty urls work with tools, so you had best call the tool through the usual dispatcher.

yoursite/index.php/tools/toolname.php

As a test that the tool is loading and running, just try a tool with a dump of $_REQUEST.

Another catch with tools is they need to end with an "exit;" or the script will return to the dispatcher and try to render a page.

For example:
<?php 
defined('C5_EXECUTE') or die("Access Denied.");
echo "<pre>";
echo "********************\n";
echo htmlentities(print_r($_REQUEST,true));
echo "\n====================";
echo "</pre>";
exit;
hugmungus replied on at Permalink Reply
Hmm, I don't seem to be getting anything back data-wise, though my response is a 200. I changed the url to:
http://localhost/~hugmungus/Yii/concrete/index.php/tools/tool.php

and I no longer get the Access Denied Response. Even when I simply try and echo back a hard-coded string, I still have a result of null.
hugmungus replied on at Permalink Reply
After some further investigating, it looks like it's trying to access the script in the wrong tools folder. I setup a couple of echo statements inside of the class root/concrete/startup/tools.php, and here's where it's looking

/Users/Hugmungus/Sites/Yii/concrete/concrete/tools/tool.php

which is the core scripts folder. I've put my script at

/Users/joe119911/Sites/SF2/concrete/tools/tool.php

If I move my script file into the core tools file at root/concrete/tools, it works. Should I move it down into the core Tools folder? or is there a way to have it look inside of the other tool folder too?
JohntheFish replied on at Permalink Reply
JohntheFish
Please describe your directory structure in more detail. What you have above makes no sense to me.
hugmungus replied on at Permalink Reply
Sorry for the confusion.

I'm testing this on a localhost server on my Mac, so my root directory is located at:
http://localhost/~hugmungus/Yii

Going there brings up the Yii index.php. Inside of that webroot is the C5 webroot, so to access C5's index.php, I go to:
http://localhost/~hugmungus/Yii/concrete

I have my tool file inside of the top level tools directory in C5, so
users/~hugmungus/Yii/concrete/tools

But when I use this url:
http://localhost/~hugmungus/Yii/concrete/index.php/tools/tool.php

It goes looking for tools inside the core tools folder, ie
users/~hugmungus/Yii/concrete/concrete/tools

If I move my script there, it works, but I feel like it should be checking the top-level folder too. Instead, I'm just getting a 404 when it looks inside of the core tools folder. Is it because I have two directories named concrete? should I name the top level one something else?

Let me know if you need anymore clarification. Thanks for your help and patience!
JohntheFish replied on at Permalink Reply
JohntheFish
All clear now. For any tool name the core searches a list of locations. Where you have the tool in the siteroot tools folder should take priority over all others.

The dispatcher works by pattern matching in the path and then looking for files that match that pattern, so too many 'concrete' s in the path may be confusing it. Calling it tool.php could also be throwing it for the same sort of reasons. So trying a different path and name is a good next step.
hugmungus replied on at Permalink Reply
Ok, renamed my top-level concrete folder to c5 and my tool.php file to spam.php. Now I'm calling the url
http://localhost/~hugmungus/yii/c5/index.php/tools/spam.php

It's still not finding the tool file unfortunately. I looked at my print statements inside of concrete/startup/tools.php, and it's still looking inside:
users/hugmungus/yii/c5/concrete/tools/spam.php

When it can't find it, it gives up. It builds the search path with this line(11):
$r = $env->getPath(DIRNAME_TOOLS . '/' . $co->getFilename());

When I do a print_r on $r, it's the root tools url. DIRNAME_TOOLS is "tools", so it should pull up both directories right? I also noticed that for case "CONCRETE_TOOL"(switch statement inside of concrete/startup/tools.php lines 8-26) there is no code written, and instead it just runs the "TOOL" case (which is the custom directory). Does this sound like a bug? or am I just seeing it since I don't understand the whole process?

Anyway, thank you for your help. I'd like to keep this as clean as possible, but I do have a workaround to keep me occupied in the meantime.
JohntheFish replied on at Permalink Reply
JohntheFish
I use tools in packages a lot and the dispatcher has no trouble finding them. So if you want to keep trying, you experiment with putting the tool in a small tool-only package.

An example of a tool in a package (for ajax, but that makes no difference) can be found in the ajax lessons howto & addon example.

You could see if that works on your dev system. That will tell you if there is anything about your c5 setup preventing it from working.
dsfgwegerhreh replied on at Permalink Reply
Hello,

There are a lot of useful replies on here addressing the OP's problem, but I think there is a lot of misunderstanding about what the OP wants.

After scratching my head for about five minutes, I've thought of an "out of the box" solution which will set you in the right direction. I haven't tested this as it's a bit involved.

OP, and to everyone else, what the OP wants is to be able to access his tools scripts from an external website without compromising on security.

Firstly, there is a script to access the right tools file. I think this part's done. The part which isn't done is getting past that dreaded C5_ENVIRONMENT_ONLY barricade which is only possible if you're logged in.

Do this. Make sure you're logged out of your C5 site and go to the base page of your website. Then go to the login page which is usually likewww.www.sitename.co.uk/index.php/login/....

Next, go to the source code of the username, password and "Sign in" button. Find the part that says "<form method="post" action="/index.php/login/do_login/" class="form-horizontal">". Use this information so you can login using Ajax from your external site and then run the PHP file straight after you've logged in remotely.

Hope this helps.
JohntheFish replied on at Permalink Reply
JohntheFish
User permission is a very good point when calling a tool externally and may also be part of the specific tool issue I was helping with.
sharadkap replied on at Permalink Reply
Did anyone manage to get this working? I am also looking to work on a mobile app where I can add pages. Is this possible? Any help in this regard would be highly appreciated.

Thanks!