5

So I downloaded a wrapper class from this github link:

https://github.com/ignaciovazquez/Highrise-PHP-Api

and I'm just trying to get any response whatsoever. So far, I can't even authenticate with my credentials so I was wondering if any who has used the API could help me.

I tried running one of the test files on Terminal with no arguments and this is what it told me:

Usage: php users.test.php [account-name] [access-token]

Alright, so then decided to get my credentials. So this is what I understand, and, please, correct if I'm wrong:

the account-name is that part that goes in the url to your highrise account. So if your url is:

https://exampleaccount.highrisehq.com/

then your account name is: "exampleaccount"

and your access token is your authentication token that you can find by going clicking on My info > API token inside your Highrise account.

Is that right?

Well anyways, I enter this info and script terminates with a fatal error and this message:

Fatal error: Uncaught exception 'Exception' with message 'API for User returned Status Code: 0 Expected Code: 200' in /Users/me/Sites/sandbox/PHP/highrise_api_class/lib/HighriseAPI.class.php:137
Stack trace:
#0 /Users/me/Sites/sandbox/PHP/highrise_api_class/lib/HighriseAPI.class.php(166): HighriseAPI->checkForErrors('User')
#1 /Users/me/Sites/sandbox/PHP/highrise_api_class/test/users.test.php(13): HighriseAPI->findMe()
#2 {main}
  thrown in /Users/me/Sites/sandbox/PHP/highrise_api_class/lib/HighriseAPI.class.php on line 137

I'm complete n00b and I don't really understand what it's saying so I was wondering if any could help. It would be greatly appreciated.

The source of the test script (users.test.php) is:

<?php
require_once("../lib/HighriseAPI.class.php");

if (count($argv) != 3)
    die("Usage: php users.test.php [account-name] [access-token]\n");

$hr = new HighriseAPI();
$hr->debug = false;
$hr->setAccount($argv[1]);
$hr->setToken($argv[2]);

print "Finding my user...\n";
$user = $hr->findMe();
print_r($user);

print "Finding all users...\n";
$users = $hr->findAllUsers();
print_r($users);

?>

and the source to the Highrise API wrapper file (Highrise.API.class) is:

<?php

    /*
        * http://developer.37signals.com/highrise/people
        *
        * TODO LIST:
        * Add Tasks support
        * Get comments for Notes / Emails
        * findPeopleByTagName
        * Get Company Name, etc proxy
        * Convenience methods for saving Notes $person->saveNotes() to check if notes were modified, etc.
        * Add Tags to Person
    */

    class HighriseAPI
    {
        public $account;
        public $token;
        protected $curl;
        public $debug;

        public function __construct()
        {
            $this->curl = curl_init();
            curl_setopt($this->curl,CURLOPT_RETURNTRANSFER,true);

        curl_setopt($this->curl, CURLOPT_HTTPHEADER, array('Accept: application/xml', 'Content-Type: application/xml'));
            // curl_setopt($curl,CURLOPT_POST,true);
            curl_setopt($this->curl,CURLOPT_SSL_VERIFYPEER,0);
            curl_setopt($this->curl,CURLOPT_SSL_VERIFYHOST,0);  
        }

        public function setAccount($account)
        {
            $this->account = $account;
        }

        public function setToken($token)
        {
            $this->token = $token;
            curl_setopt($this->curl,CURLOPT_USERPWD,$this->token.':x');
        }

        protected function postDataWithVerb($path, $request_body, $verb = "POST")
        {
            $this->curl = curl_init();

            $url = "https://" . $this->account . ".highrisehq.com" . $path;

            if ($this->debug)
                print "postDataWithVerb $verb $url ============================\n";


            curl_setopt($this->curl, CURLOPT_URL,$url);
            curl_setopt($this->curl, CURLOPT_POSTFIELDS, $request_body);
            if ($this->debug == true)
                curl_setopt($this->curl, CURLOPT_VERBOSE, true);

            curl_setopt($this->curl, CURLOPT_HTTPHEADER, array('Accept: application/xml', 'Content-Type: application/xml'));
          curl_setopt($this->curl, CURLOPT_USERPWD,$this->token.':x');
            curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER,0);
            curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST,0);
            curl_setopt($this->curl, CURLOPT_RETURNTRANSFER,true);


            if ($verb != "POST")
              curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, $verb);
            else
                curl_setopt($this->curl, CURLOPT_POST, true);

            $ret = curl_exec($this->curl);

            if ($this->debug == true)
                print "Begin Request Body ============================\n" . $request_body . "End Request Body ==============================\n";

            curl_setopt($this->curl,CURLOPT_HTTPGET, true);

            return $ret;
        }

        protected function getURL($path)
        {
            curl_setopt($this->curl, CURLOPT_HTTPHEADER, array('Accept: application/xml', 'Content-Type: application/xml'));
          curl_setopt($this->curl, CURLOPT_USERPWD,$this->token.':x');
            curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER,0);
            curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST,0);
            curl_setopt($this->curl, CURLOPT_RETURNTRANSFER,true);

            $url = "https://" . $this->account . ".highrisehq.com" . $path;

            if ($this->debug == true)
                curl_setopt($this->curl, CURLOPT_VERBOSE, true);


            curl_setopt($this->curl,CURLOPT_URL,$url);
            $response = curl_exec($this->curl);

            if ($this->debug == true)
                print "Response: =============\n" . $response . "============\n";

            return $response;

        }

        protected function getLastReturnStatus()
        {
            return curl_getinfo($this->curl, CURLINFO_HTTP_CODE); 
        }

        protected function getXMLObjectForUrl($url)
        {
            $xml = $this->getURL($url);
            $xml_object = simplexml_load_string($xml);
            return $xml_object;
        }

        protected function checkForErrors($type, $expected_status_codes = 200)
        {
            if (!is_array($expected_status_codes))
                $expected_status_codes = array($expected_status_codes);

            if (!in_array($this->getLastReturnStatus(), $expected_status_codes))
            {
                switch($this->getLastReturnStatus())
                {
                    case 404:
                        throw new Exception("$type not found");
                        break;
                    case 403:
                        throw new Exception("Access denied to $type resource");
                        break;
                    case 507:
                        throw new Exception("Cannot create $type: Insufficient storage in your Highrise Account");
                        break;

                    default:
                        throw new Exception("API for $type returned Status Code: " . $this->getLastReturnStatus() . " Expected Code: " . implode(",", $expected_status_codes));
                        break;
                }               
            }
        }

        /* Users */

        public function findAllUsers()
        {
            $xml = $this->getUrl("/users.xml");
            $this->checkForErrors("User");

            $xml_object = simplexml_load_string($xml);

            $ret = array();
            foreach($xml_object->user as $xml_user)
            {
                $user = new HighriseUser();
                $user->loadFromXMLObject($xml_user);
                $ret[] = $user;
            }

            return $ret;
        }

        public function findMe()
        {
            $xml = $this->getUrl("/me.xml");
            $this->checkForErrors("User");

            $xml_obj = simplexml_load_string($xml);
            $user = new HighriseUser();
            $user->loadFromXMLObject($xml_obj);
            return $user;
        }

        /* Tasks */

        public function findCompletedTasks()
        {
            $xml = $this->getUrl("/tasks/completed.xml");
            $this->checkForErrors("Tasks");
            return $this->parseTasks($xml);
        }

        public function findAssignedTasks()
        {
            $xml = $this->getUrl("/tasks/assigned.xml");
            $this->checkForErrors("Tasks");
            return $this->parseTasks($xml);
        }


        public function findUpcomingTasks()
        {
            $xml = $this->getUrl("/tasks/upcoming.xml");
            $this->checkForErrors("Tasks");
            return $this->parseTasks($xml);
        }

        private function parseTasks($xml)
        {
            $xml_object = simplexml_load_string($xml);          
            $ret = array();
            foreach($xml_object->task as $xml_task)
            {
                $task = new HighriseTask($this);
                $task->loadFromXMLObject($xml_task);
                $ret[] = $task;
            }

            return $ret;

        }

        public function findTaskById($id)
        {
            $xml = $this->getURL("/tasks/$id.xml");
            $this->checkForErrors("Task");
            $task_xml = simplexml_load_string($xml);
            $task = new HighriseTask($this);
            $task->loadFromXMLObject($task_xml);
            return $task;

        }

        /* Notes & Emails */

        public function findEmailById($id)
        {
            $xml = $this->getURL("/emails/$id.xml");
            $this->checkForErrors("Email");
            $email_xml = simplexml_load_string($xml);
            $email = new HighriseEmail($this);
            $email->loadFromXMLObject($email_xml);
            return $email;
        }

        public function findNoteById($id)
        {
            $xml = $this->getURL("/notes/$id.xml");
            $this->checkForErrors("Note");
            $note_xml = simplexml_load_string($xml);
            $note = new HighriseNote($this);
            $note->loadFromXMLObject($note_xml);
            return $note;
        }

        public function findPersonById($id)
        {
            $xml = $this->getURL("/people/$id.xml");

            $this->checkForErrors("Person");


            $xml_object = simplexml_load_string($xml);

            $person = new HighrisePerson($this);
            $person->loadFromXMLObject($xml_object);
            return $person;
        }

        public function findAllTags()
        {
            $xml = $this->getUrl("/tags.xml");
            $this->checkForErrors("Tags");

            $xml_object = simplexml_load_string($xml);          
            $ret = array();
            foreach($xml_object->tag as $tag)
            {
                $ret[(string)$tag->name] = new HighriseTag((string)$tag->id, (string)$tag->name);
            }

            return $ret;
        }

        public function findAllPeople()
        {
            return $this->parsePeopleListing("/people.xml");    
        }

        public function findPeopleByTagName($tag_name)
        {
            $tags = $this->findAllTags();
            foreach($tags as $tag)
            {
                if ($tag->name == $tag_name)
                    $tag_id = $tag->id;
            }

            if (!isset($tag_id))
                throw new Excepcion("Tag $tag_name not found");

            return $this->findPeopleByTagId($tag_id);
        }

        public function findPeopleByTagId($tag_id)
        {
            $url = "/people.xml?tag_id=" . $tag_id;
            $people = $this->parsePeopleListing($url);
            return $people; 
        }

        public function findPeopleByEmail($email)
        {
         return $this->findPeopleBySearchCriteria(array("email"=>$email));
        }

        public function findPeopleByTitle($title)
        {
            $url = "/people.xml?title=" . urlencode($title);

            $people = $this->parsePeopleListing($url);
            return $people;
        }



        public function findPeopleByCompanyId($company_id)
        {
            $url = "/companies/" . urlencode($company_id) . "/people.xml";
            $people = $this->parsePeopleListing($url);
            return $people;
        }

        public function findPeopleBySearchTerm($search_term)
        {
            $url = "/people/search.xml?term=" . urlencode($search_term);
            $people = $this->parsePeopleListing($url, 25);
            return $people;
        }

        public function findPeopleBySearchCriteria($search_criteria)
        {
            $url = "/people/search.xml";

            $sep = "?";
            foreach($search_criteria as $criteria=>$value)
            {
                $url .= $sep . "criteria[" . urlencode($criteria) . "]=" . urlencode($value);
                $sep = "&";
            }

            $people = $this->parsePeopleListing($url, 25);
            return $people;
        }

        public function findPeopleSinceTime($time)
        {
            $url = "/people/search.xml?since=" . urlencode($time);
            $people = $this->parsePeopleListing($url);
            return $people;
        }
        public function parsePeopleListing($url, $paging_results = 500)
        {
            if (strstr($url, "?"))
                $sep = "&";
            else
                $sep = "?";

            $offset = 0;
            $return = array();
            while(true) // pagination
            {
                $xml_url = $url . $sep . "n=$offset";
                // print $xml_url;
                $xml = $this->getUrl($xml_url);
                $this->checkForErrors("People");
                $xml_object = simplexml_load_string($xml);

                foreach($xml_object->person as $xml_person)
                {
                    // print_r($xml_person);
                    $person = new HighrisePerson($this);
                    $person->loadFromXMLObject($xml_person);
                    $return[] = $person;
                }

                if (count($xml_object) != $paging_results)
                    break;

                $offset += $paging_results;
            }

            return $return;
        }

    }

Sorry it's such a long file but if it helps, then so be it.

EDIT: So I guess I got it to work. I should've said that I was trying to test this library out on my local server and for some reason it would keep failing but when I moved the script to my development server on Rackspace cloud then it would work. This just puzzles me. Both servers have support for PHP curl so I can't really understand where the problem is.

EDIT: I'm not sure what the difference between the two server configurations could be but anyways here's a couple of screenshots from my phpinfo function output from both servers of my curl configuration:

Localhost server:

enter image description here

and the rackspace cloud server:

enter image description here

racl101
  • 3,760
  • 4
  • 34
  • 33
  • Have you tried with http? what resource are you trying to get (People, Categories .... ) – jjchiw May 24 '11 at 21:27
  • Um people I guess. I'm just trying to test it out to see if my credentials even work. What do you mean by trying with http? – racl101 May 24 '11 at 21:31

3 Answers3

2

The fork of the API at... https://github.com/AppSaloon/Highrise-PHP-Api ...seems more developed and better maintained.

Not so much as to provide an answer, but more a better starting point.

AndyGaskell
  • 542
  • 6
  • 20
  • I used this version as I needed Company support. It does seem more mature and reworked quite a bit from the original in terms of code structure, though I couldn't get the custom field support to work. – bigendian Sep 11 '12 at 06:45
1

Ah, since there is really no HTTP error code 0 I expect that your request isn't being made to Highrise's website, or you are not correctly passing in the account name and token to the class. Can you include the source of your users.test.php class?

EDIT: tested the class and your code, and it works for me. You probably either copied the library file wrong or have your token copied wrong.

Femi
  • 64,273
  • 8
  • 118
  • 148
  • Could you tell me if you tested the code on your browser or the terminal and if you tested it on your terminal how you called the command (of course with fake token values and account name)? I still can't get it to work and I need to get this working for me. Any help would be appreciated. – racl101 May 25 '11 at 03:08
  • I got it to work but on my online development server on Rackspace cloud. See I was trying to test it out on my localhost server and it wouldn't work there no matter what I did. – racl101 May 25 '11 at 03:41
  • Tested it in the terminal: my file was called `p1.php` and I invoked it using `php p1.php {username} {token}`. It dumps out a HighriseUser object and an Array with a single HighriseUser object (as my highrise account only has one user in it). I'm using your code completely unmodified, except for the library location (I have the Highrise PHP file in the same folder), but otherwise you made no mistakes in your code. – Femi May 25 '11 at 03:43
  • AH. You're probably missing a dependency or have your local php misconfigured somehow. If you create a php file with ` – Femi May 25 '11 at 03:44
  • I just checked and I do have both curl and simplexml enabled on both servers. However, the configuration on the Rackspace cloud is says OpenSSL. I have couple of screenshots above. I don't know if that matters. It might. – racl101 May 25 '11 at 04:07
  • 1
    Ah, yes: if you are missing OpenSSL it won't work. They don't allow you to login without using SSL. – Femi May 25 '11 at 04:22
0

I had the same issue. I definitely had the wrong account. I had https://foo.highrisehq.com instead of just foo.

BFTrick
  • 5,211
  • 6
  • 24
  • 28