diff --git a/composer.json b/composer.json
index 59b8785..f7a7042 100644
--- a/composer.json
+++ b/composer.json
@@ -29,6 +29,11 @@
}
],
"autoload": {
- "classmap": ["src/piplapis/", "src/piplapis/data/"]
+ "classmap": [
+ "src/piplapis/",
+ "src/piplapis/models/",
+ "src/piplapis/models/fields/",
+ "src/piplapis/models/containers/"
+ ]
}
}
diff --git a/src/piplapis/data/containers.php b/src/piplapis/data/containers.php
deleted file mode 100644
index aa0b8fb..0000000
--- a/src/piplapis/data/containers.php
+++ /dev/null
@@ -1,536 +0,0 @@
- 'names',
- 'PiplApi_Address' => 'addresses',
- 'PiplApi_Phone' => 'phones',
- 'PiplApi_Email' => 'emails',
- 'PiplApi_Job' => 'jobs',
- 'PiplApi_Ethnicity' => 'ethnicities',
- 'PiplApi_OriginCountry' => 'origin_countries',
- 'PiplApi_Language' => 'languages',
- 'PiplApi_Education' => 'educations',
- 'PiplApi_Image' => 'images',
- 'PiplApi_Username' => 'usernames',
- 'PiplApi_UserID' => 'user_ids',
- 'PiplApi_URL' => 'urls'
- );
-
- protected $singular_fields = array(
- 'PiplApi_DOB' => 'dob',
- 'PiplApi_Gender' => 'gender',
- );
-
- function __construct($fields=array())
- {
- // `fields` is an array of field objects from
- // fields.php.
- $this->add_fields($fields);
- }
-
- public function add_fields($fields)
- {
- // Add the fields to their corresponding container.
- // `fields` is an array of field objects from fields.php
- if (empty($fields))
- {
- return;
- }
-
- foreach ($fields as $field)
- {
- $cls = is_object($field) ? get_class($field) : NULL;
-
- if (array_key_exists($cls, $this->CLASS_CONTAINER))
- {
- $container = $this->CLASS_CONTAINER[$cls];
- $this->{$container}[] = $field;
- } elseif(array_key_exists($cls, $this->singular_fields)) {
- $this->{$this->singular_fields[$cls]} = $field;
- } else {
- $type = empty($cls) ? gettype($field) : $cls;
- throw new InvalidArgumentException('Object of type ' . $type . ' is an invalid field');
- }
- }
- }
-
- public function all_fields()
- {
- // An array with all the fields contained in this object.
- $allfields = array();
- foreach (array_values($this->CLASS_CONTAINER) as $val){
- $allfields = array_merge($allfields, $this->{$val});
- }
- foreach (array_values($this->singular_fields) as $val){
- if($this->{$val}) {
- $allfields[] = $this->{$val};
- }
- }
-
- return $allfields;
- }
-
- public function fields_from_array($d)
- {
- // Load the fields from the dict, return an array with all the fields.
-
- $fields = array();
-
- foreach (array_keys($this->CLASS_CONTAINER) as $field_cls){
- $container = $this->CLASS_CONTAINER[$field_cls];
- if (array_key_exists($container, $d)) {
- $field_array = $d[$container];
- foreach ($field_array as $x) {
- $from_array_func = method_exists($field_cls, 'from_array') ? array($field_cls, 'from_array') : array('PiplApi_Field', 'from_array');
- $fields[] = call_user_func($from_array_func, $field_cls, $x);
- }
- }
- }
- foreach (array_keys($this->singular_fields) as $field_cls){
- $container = $this->singular_fields[$field_cls];
- if (array_key_exists($container, $d)) {
- $field_array = $d[$container];
- $from_array_func = method_exists($field_cls, 'from_array') ? array($field_cls, 'from_array') : array('PiplApi_Field', 'from_array');
- $fields[] = call_user_func($from_array_func, $field_cls, $field_array);
- }
- }
- return $fields;
- }
-
- public function fields_to_array(){
- // Transform the object to an array and return it.
- $d = array();
-
- foreach (array_values($this->CLASS_CONTAINER) as $container){
- $fields = $this->{$container};
- if (!empty($fields)){
- $all_fields = array();
- foreach($fields as $field) {
- $all_fields[] = $field->to_array();
- }
- if (count($all_fields) > 0){
- $d[$container] = $all_fields;
- }
- }
- }
- foreach (array_values($this->singular_fields) as $container){
- $field = $this->{$container};
- if (!empty($field)){
- $d[$container] = $field->to_array();
- }
- }
- return $d;
- }
-
- /**
- * Specify data which should be serialized to JSON
- * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
- * @return mixed data which can be serialized by json_encode,
- * which is a value of any type other than a resource.
- * @since 5.4.0
- */
- function jsonSerialize()
- {
- return $this->to_array();
- }
-}
-
-class PiplApi_Source extends PiplApi_FieldsContainer
-{
- // A source is a single source of data.
- //
- // Every source object is based on the URL of the
- // page where the data is available, and the data itself that comes as field
- // objects (Name, Address, Email etc. see fields.php).
- //
- // Each type of field has its own container (note that Source is a subclass
- // of FieldsContainer).
- //
- // Sources come as results for a query and therefore they have attributes that
- // indicate if and how much they match the query. They also have a validity
- // timestamp available as an attribute.
-
- private $extended_containers = array(
- 'PiplApi_Relationship' => 'relationships',
- 'PiplApi_Tag' => 'tags'
- );
- public $name;
- public $category;
- public $origin_url;
- public $sponsored;
- public $domain;
- public $person_id;
- public $id;
- public $premium;
- public $match;
- public $valid_since;
- public $relationships = array();
- public $tags = array();
-
- function __construct($fields = array(), $match = NULL, $name = NULL, $category = NULL, $origin_url = NULL,
- $sponsored = NULL, $domain = NULL, $person_id = NULL, $id = NULL,
- $premium = NULL, $valid_since = NULL){
- // Extend FieldsContainer::__construct and set the record's source
- // and attributes.
- //
- // Args:
- // $fields -- an array of fields
- // $match -- A float between 0.0 and 1.0 that indicates how likely it is that this source holds data about
- // the person from the query. Higher value means higher likelihood, value of 1.0
- // means "this is definitely him". This value is based on Pipl's statistical algorithm that takes
- // into account many parameters like the popularity of the name/address
- // (if there was a name/address in the query) etc.
- // $name -- A string, the source name
- // $category -- A string, the source category
- // $origin_url -- A string, the URL where Pipl's crawler found this data
- // $sponsored -- A boolean, whether the source is a sponsored result or not
- // $domain -- A string, the domain of this source
- // $person_id -- A string, the person's unique ID
- // $source_id -- A string, the source ID
- // $premium -- A boolean, whether this is a premium source
- // $valid_since -- A DateTime object, this is the first time Pipl's crawlers saw this source.
- $this->CLASS_CONTAINER = array_merge($this->CLASS_CONTAINER, $this->extended_containers);
- parent::__construct($fields);
- $this->name = $name;
- $this->category = $category;
- $this->origin_url = $origin_url;
- $this->sponsored = $sponsored;
- $this->domain = $domain;
- $this->person_id = $person_id;
- $this->id = $id;
- $this->premium = $premium;
- $this->match = $match;
- $this->valid_since = $valid_since;
- }
-
- public static function from_array($params)
- {
- // Transform the dict to a record object and return the record.
- $name = !empty($params['@name']) ? $params['@name'] : NULL;
- $match = !empty($params['@match']) ? $params['@match'] : NULL;
- $category = !empty($params['@category']) ? $params['@category'] : NULL;
- $origin_url = !empty($params['@origin_url']) ? $params['@origin_url'] : NULL;
- $sponsored = !empty($params['@sponsored']) ? $params['@sponsored'] : NULL;
- $domain = !empty($params['@domain']) ? $params['@domain'] : NULL;
- $person_id = !empty($params['@person_id']) ? $params['@person_id'] : NULL;
- $source_id = !empty($params['@id']) ? $params['@id'] : NULL;
- $premium = !empty($params['@premium']) ? $params['@premium'] : NULL;
- $valid_since = !empty($params['@valid_since']) ? $params['@valid_since'] : NULL;
- if (!empty($valid_since)){ $valid_since = PiplApi_Utils::piplapi_str_to_datetime($valid_since); }
-
- $instance = new self(array(), $match, $name, $category, $origin_url, $sponsored, $domain, $person_id,
- $source_id, $premium, $valid_since);
- $instance->add_fields($instance->fields_from_array($params));
- return $instance;
- }
-
- public function to_array()
- {
- // Return an array representation of the record.
- $d = array();
- if (!empty($this->valid_since)){ $d['@valid_since'] = PiplApi_Utils::piplapi_datetime_to_str($this->valid_since); }
- if (!empty($this->match)){ $d['@match'] = $this->match; }
- if (!empty($this->category)){ $d['@category'] = $this->category; }
- if (!empty($this->origin_url)){ $d['@origin_url'] = $this->origin_url; }
- if (!empty($this->sponsored)){ $d['@sponsored'] = $this->sponsored; }
- if (!empty($this->domain)){ $d['@domain'] = $this->domain; }
- if (!empty($this->person_id)){ $d['@person_id'] = $this->person_id; }
- if (!empty($this->id)){ $d['@source_id'] = $this->id; }
- if (!empty($this->premium)){ $d['@premium'] = $this->premium; }
-
- return array_merge($d, $this->fields_to_array());
- }
-}
-
-
-class PiplApi_Person extends PiplApi_FieldsContainer
-{
- // A Person object is all the data available on an individual.
- //
- // The Person object is essentially very similar in its structure to the
- // Source object, the main difference is that data about an individual can
- // come from multiple sources.
- //
- // The person's data comes as field objects (Name, Address, Email etc. see fields.php).
- // Each type of field has its on container (note that Person is a subclass of FieldsContainer).
- //
- // For example:
- //
- // require_once dirname(__FILE__) . '/data/containers.php';
- // $fields = array(new PiplApi_Email(array('address' => 'clark.kent@example.com')), new PiplApi_Phone(array('number' => 9785550145)));
- // $person = new PiplApi_Person(array('fields' => $fields));
- // print implode(', ', $person->emails); // Outputs "clark.kent@example.com"
- // print implode(', ', $person->phones); // Outputs "+1-9785550145"
- //
- // Note that a person object is used in the Search API in two ways:
- // - It might come back as a result for a query (see PiplApi_SearchAPIResponse).
- // - It's possible to build a person object with all the information you
- // already have about the person you're looking for and send this object as
- // the query (see PiplApi_SearchAPIRequest).
-
- private $extended_containers = array(
- 'PiplApi_Relationship' => 'relationships'
- );
- public $id;
- public $search_pointer;
- public $match;
- public $inferred;
- public $relationships = array();
-
- function __construct($fields = array(), $id = NULL, $search_pointer = NULL, $match = NULL, $inferred = false)
- {
- // Extend FieldsContainer.initialize and set the record's sources
- // and query_params_match attribute.
- //
- // Args:
- //
- // $fields -- An array of fields (fields.php).
- // $match -- A float value, the person's match score.
- // $id -- GUID. The person's ID.
- // $search_pointer -- string. Can be used for drill down searches.
- $this->CLASS_CONTAINER = array_merge($this->CLASS_CONTAINER, $this->extended_containers);
- parent::__construct($fields);
- $this->search_pointer = $search_pointer;
- $this->match = $match;
- $this->id = $id;
- $this->inferred = $inferred;
- }
-
- public function is_searchable()
- {
- // A bool value that indicates whether the person has enough data and
- // can be sent as a query to the API.
- $all = array_merge($this->names, $this->emails, $this->phones, $this->usernames, $this->user_ids, $this->urls);
- $searchable = array_filter($all, function($field) {
- return $field->is_searchable();
- });
- $searchable_address = array_filter($this->addresses, function($field) {
- return $field->is_sole_searchable();
- });
- return $searchable_address or $this->search_pointer or count($searchable) > 0;
- }
-
- public function unsearchable_fields()
- {
- // An array of all the fields that are invalid and won't be used in the search.
-
- // For example: names/usernames that are too short, emails that are
- // invalid etc.
- $all = array_merge($this->names, $this->emails, $this->phones, $this->usernames, $this->addresses,
- $this->user_ids, $this->urls, array($this->dob));
- $unsearchable = array_filter($all, function($field) {
- return $field && !$field->is_searchable();
- });
- return $unsearchable;
- }
-
- public static function from_array($params)
- {
- // Transform the array to a person object and return it.
- $id = !empty($params['@id']) ? $params['@id'] : NULL;
- $search_pointer = !empty($params['@search_pointer']) ? $params['@search_pointer'] : NULL;
- $match = !empty($params['@match']) ? $params['@match'] : NULL;
- $inferred = !empty($params['@inferred']) ? $params['@inferred'] : false;
-
- $instance = new self(array(), $id, $search_pointer, $match, $inferred);
- $instance->add_fields($instance->fields_from_array($params));
- return $instance;
- }
-
- public function to_array()
- {
- // Return an array representation of the person.
- $d = array();
-
- if (!empty($this->id)){ $d['@id'] = $this->id; }
- if (!is_null($this->match)){ $d['@match'] = $this->match; }
- if (!empty($this->search_pointer)){ $d['@search_pointer'] = $this->search_pointer; }
- if ($this->inferred){ $d['@inferred'] = $this->inferred; }
-
- return array_merge($d, $this->fields_to_array());
- }
-
-}
-
-class PiplApi_Relationship extends PiplApi_FieldsContainer
-{
- // Name of another person related to this person.
-
- protected $types_set = array('friend', 'family', 'work', 'other');
-
- public $type;
- public $subtype;
- public $valid_since;
- public $inferred;
-
- function __construct($fields = array(), $type = NULL, $subtype = NULL, $valid_since = NULL, $inferred = NULL)
- {
- parent::__construct($fields);
-
- // `fields` is an array of data fields (see fields.php)
- //
- // `type` and `subtype` should both be strings.
- // `type` is one of PiplApi_Relationship::$types_set.
- //
- // `subtype` is not restricted to a specific list of possible values (for
- // example, if type is "family" then subtype can be "Father", "Mother",
- // "Son" and many other things).
- //
- // `valid_since` is a DateTime object, it's the first time Pipl's
- // crawlers found this data on the page.
- // `inferred` is a boolean, indicating whether this field includes inferred data.
- $this->type = $type;
- $this->subtype = $subtype;
- $this->valid_since = $valid_since;
- $this->inferred = $inferred;
- }
-
- public static function from_array($class_name, $params)
- {
- // Transform the array to a person object and return it.
- $type = !empty($params['@type']) ? $params['@type'] : NULL;
- $subtype = !empty($params['@subtype']) ? $params['@subtype'] : NULL;
- $valid_since = !empty($params['@valid_since']) ? $params['@valid_since'] : NULL;
- $inferred = !empty($params['@inferred']) ? $params['@inferred'] : NULL;
-
- $instance = new self(array(), $type, $subtype, $valid_since, $inferred);
- $instance->add_fields($instance->fields_from_array($params));
- return $instance;
- }
- public function __toString(){
- return count($this->names) > 0 && $this->names[0]->first ? $this->names[0]->first : "";
- }
- public function to_array()
- {
- // Return an array representation of the person.
- $d = array();
-
- if (!empty($this->valid_since)){ $d['@valid_since'] = $this->valid_since; }
- if (!empty($this->inferred)){ $d['@inferred'] = $this->inferred; }
- if (!empty($this->type)){ $d['@type'] = $this->type; }
- if (!empty($this->subtype)){ $d['@subtype'] = $this->subtype; }
-
- return array_merge($d, $this->fields_to_array());
- }
-
-
-}
-
-class PiplApi_AvailableData
-{
- function __construct($basic = NULL, $premium = NULL)
- {
- $this->basic = $basic ? PiplApi_FieldCount::from_array($basic) : NULL;
- $this->premium = $premium ? PiplApi_FieldCount::from_array($premium) : NULL;
-
- }
- public static function from_array($params) {
- $basic = !empty($params['basic']) ? $params['basic'] : NULL;
- $premium = !empty($params['premium']) ? $params['premium'] : NULL;
- $instance = new self($basic, $premium);
- return $instance;
- }
- public function to_array() {
- $res = array();
- if ($this->basic != NULL)
- $res['basic'] = $this->basic->to_array();
- if ($this->premium != NULL)
- $res['premium'] = $this->premium->to_array();
- return $res;
- }
-}
-
-class PiplApi_FieldCount
-{
- protected $attributes = array(
- 'addresses', 'ethnicities', 'emails', 'dobs', 'genders', 'user_ids', 'social_profiles',
- 'educations', 'jobs', 'images', 'languages', 'origin_countries', 'names', 'phones',
- 'relationships', 'usernames', 'mobile_phones', 'landline_phones'
- );
- function __construct($dobs = NULL, $images = NULL, $educations = NULL, $addresses = NULL, $jobs = NULL,
- $genders = NULL, $ethnicities = NULL, $phones = NULL, $origin_countries = NULL,
- $usernames = NULL, $languages = NULL, $emails = NULL, $user_ids = NULL, $relationships = NULL,
- $names = NULL, $social_profiles = NULL, $mobile_phones = NULL, $landline_phones = NULL)
- {
- $this->dobs = $dobs;
- $this->images = $images;
- $this->educations = $educations;
- $this->addresses = $addresses;
- $this->jobs = $jobs;
- $this->genders = $genders;
- $this->ethnicities = $ethnicities;
- $this->phones = $phones;
- $this->origin_countries = $origin_countries;
- $this->usernames = $usernames;
- $this->languages = $languages;
- $this->emails = $emails;
- $this->user_ids = $user_ids;
- $this->relationships = $relationships;
- $this->names = $names;
- $this->social_profiles = $social_profiles;
- $this->mobile_phones = $mobile_phones;
- $this->landline_phones = $landline_phones;
- }
-
- public static function from_array($params)
- {
- $dobs = !empty($params['dobs']) ? $params['dobs'] : NULL;
- $images = !empty($params['images']) ? $params['images'] : NULL;
- $educations = !empty($params['educations']) ? $params['educations'] : NULL;
- $addresses = !empty($params['addresses']) ? $params['addresses'] : NULL;
- $jobs = !empty($params['jobs']) ? $params['jobs'] : NULL;
- $genders = !empty($params['genders']) ? $params['genders'] : NULL;
- $ethnicities = !empty($params['ethnicities']) ? $params['ethnicities'] : NULL;
- $phones = !empty($params['phones']) ? $params['phones'] : NULL;
- $origin_countries = !empty($params['origin_countries']) ? $params['origin_countries'] : NULL;
- $usernames = !empty($params['usernames']) ? $params['usernames'] : NULL;
- $languages = !empty($params['languages']) ? $params['languages'] : NULL;
- $emails = !empty($params['emails']) ? $params['emails'] : NULL;
- $user_ids = !empty($params['user_ids']) ? $params['user_ids'] : NULL;
- $relationships = !empty($params['relationships']) ? $params['relationships'] : NULL;
- $names = !empty($params['names']) ? $params['names'] : NULL;
- $social_profiles = !empty($params['social_profiles']) ? $params['social_profiles'] : NULL;
- $landline_phones = !empty($params['landline_phones']) ? $params['landline_phones'] : NULL;
- $mobile_phones = !empty($params['mobile_phones']) ? $params['mobile_phones'] : NULL;
-
- $instance = new self($dobs, $images, $educations, $addresses, $jobs,
- $genders, $ethnicities, $phones, $origin_countries,
- $usernames, $languages, $emails, $user_ids, $relationships,
- $names, $social_profiles, $mobile_phones, $landline_phones);
- return $instance;
- }
-
- public function to_array()
- {
- $res = array();
- foreach ($this->attributes as $attr) {
- if ($this->$attr > 0)
- $res[$attr] = $this->$attr;
- }
- return $res;
- }
-}
\ No newline at end of file
diff --git a/src/piplapis/data/fields.php b/src/piplapis/data/fields.php
deleted file mode 100644
index c86f032..0000000
--- a/src/piplapis/data/fields.php
+++ /dev/null
@@ -1,1318 +0,0 @@
-valid_since = $valid_since;
- }
- if (!empty($inferred))
- {
- $this->inferred = $inferred;
- }
- // API v5
- if (!empty($last_seen))
- {
- $this->last_seen = $last_seen;
- }
- if (!empty($current))
- {
- $this->current = $current;
- }
-
- }
-
- public function __set($name, $val)
- {
- if (in_array($name, $this->attributes) ||
- in_array($name, $this->children) ||
- ($name == 'valid_since') ||
- ($name == 'last_seen') ||
- ($name == 'current') ||
- ($name == 'inferred'))
- {
- if ($name == 'type')
- {
- $this->validate_type($val);
- }
- $this->internal_params[$name] = $val;
- }
- }
-
- public function __get($name)
- {
- if (in_array($name, $this->attributes) ||
- in_array($name, $this->children) ||
- ($name == 'valid_since') ||
- ($name == 'inferred') ||
- ($name == 'current') ||
- ($name == 'last_seen'))
- {
- if (array_key_exists($name, $this->internal_params))
- {
- return $this->internal_params[$name];
- }
- }
- return NULL;
- }
-
- public function __isset($name)
- {
- return ((in_array($name, $this->attributes) ||
- in_array($name, $this->children) ||
- ($name == 'valid_since') || ($name == "inferred") || ($name == 'current') || ($name == "last_seen")) &&
- array_key_exists($name, $this->internal_params));
- }
-
- public function __unset($name)
- {
- if (in_array($name, $this->attributes) ||
- in_array($name, $this->children) ||
- ($name == 'valid_since') || ($name == "inferred") || ($name == 'current') || ($name == "last_seen")
- )
- {
- unset($this->internal_params[$name]);
- }
- }
-
- public function __toString()
- {
- return isset($this->display) ? $this->display : "";
- }
-
- public function get_representation(){
- // Return a string representation of the object.
- $allattrs = array_merge($this->attributes, $this->children);
- array_push($allattrs, "valid_since");
-
- $allattrsvalues = array_map(array($this, 'internal_mapcb_buildattrslist'), $allattrs);
-
- // $allattrsvalues is now a multidimensional array
- $args = array_reduce($allattrsvalues, array($this, 'internal_reducecb_buildattrslist'));
- $args = substr_replace($args, "", -2);
-
- return get_class($this) . '(' . $args . ')';
- }
-
- private function internal_mapcb_buildattrslist($attr)
- {
- if (isset($this->internal_params[$attr]))
- {
- return array($attr => $this->internal_params[$attr]);
- }
- else
- {
- return NULL;
- }
- }
-
- private function internal_reducecb_buildattrslist($res, $x)
- {
- if (is_array($x) && count($x) > 0)
- {
- $keys = array_keys($x);
- if (isset($x[$keys[0]]))
- {
- $val = $x[$keys[0]];
-
- if ($val instanceof DateTime)
- {
- $val = PiplApi_Utils::piplapi_datetime_to_str($val);
- }
- else if (is_array($val))
- {
- $val = '[' . implode(', ', $val) . ']';
- }
- else
- {
- $val = (string)$val;
- }
-
- $newval = $keys[0] . '=' . $val . ', ';
- // This is a bit messy, but gets around the weird fact that array_reduce
- // can only accept an initial integer.
- if (empty($res))
- {
- $res = $newval;
- }
- else
- {
- $res .= $newval;
- }
- }
- }
- return $res;
- }
-
- public function validate_type($type)
- {
- // Take an string `type` and raise an InvalidArgumentException if it's not
- // a valid type for the object.
-
- // A valid type for a field is a value from the types_set attribute of
- // that field's class.
-
- if (!empty($type) && !in_array($type, $this->types_set))
- {
- throw new InvalidArgumentException('Invalid type for ' . get_class($this) . ' ' . $type);
- }
- }
-
- public static function from_array($clsname, $d)
- {
- // Transform the dict to a field object and return the field.
- $newdict = array();
-
- foreach ($d as $key => $val)
- {
- if (PiplApi_Utils::piplapi_string_startswith($key, '@'))
- {
- $key = substr($key, 1);
- }
-
- if ($key == 'last_seen')
- {
- $val = PiplApi_Utils::piplapi_str_to_datetime($val);
- }
-
- if ($key == 'valid_since')
- {
- $val = PiplApi_Utils::piplapi_str_to_datetime($val);
- }
-
- if ($key == 'date_range')
- {
- // PiplApi_DateRange has its own from_array implementation
- $val = PiplApi_DateRange::from_array($val);
- }
-
- $newdict[$key] = $val;
- }
-
- return new $clsname($newdict);
- }
-
- private function internal_mapcb_attrsarr($attr)
- {
- return array($attr => '@');
- }
-
- private function internal_mapcb_childrenarr($attr)
- {
- return array($attr => '');
- }
-
- public function to_array()
- {
- // Return a dict representation of the field.
- $d = array();
- if (!empty($this->valid_since))
- {
- $d['@valid_since'] = PiplApi_Utils::piplapi_datetime_to_str($this->valid_since);
- }
- if (!empty($this->last_seen))
- {
- $d['@last_seen'] = PiplApi_Utils::piplapi_datetime_to_str($this->last_seen);
- }
- $newattr = array_map(array($this, "internal_mapcb_attrsarr"), $this->attributes);
- $newchild = array_map(array($this, "internal_mapcb_childrenarr"), $this->children);
-
- // $newattr and $newchild are multidimensionals- this is used to iterate over them
- // we first merge the two arrays and then create an iterator that flattens them
- $it = new RecursiveIteratorIterator(new RecursiveArrayIterator(array_merge($newattr, $newchild)));
-
- foreach ($it as $key => $prefix)
- {
- if (array_key_exists($key, $this->internal_params))
- {
- $value = $this->internal_params[$key];
-
- if (isset($value) && is_object($value) && method_exists($value, 'to_array'))
- {
- $value = $value->to_array();
- }
-
- if (isset($value))
- {
- $d[$prefix . $key] = $value;
- }
- }
- }
-
- return $d;
- }
-
- public function is_searchable(){
- return true;
- }
-}
-
-class PiplApi_Name extends PiplApi_Field
-{
- // A name of a person.
-
- protected $attributes = array('type');
- protected $children = array('first', 'middle', 'last', 'prefix', 'suffix', 'raw', 'display');
- protected $types_set = array('present', 'maiden', 'former', 'alias', 'alternative', 'autogenerated');
-
- function __construct($params=array())
- {
- extract($params);
- parent::__construct($params);
- // `prefix`, `first`, `middle`, `last`, `suffix`, `raw`, `type`,
- // should all be strings.
- //
- // `raw` is an unparsed name like "Clark Joseph Kent", usefull when you
- // want to search by name and don't want to work hard to parse it.
- // Note that in response data there's never name.raw, the names in
- // the response are always parsed, this is only for querying with
- // an unparsed name.
- //
- // `type` is one of PiplApi_Name::$types_set.
-
- if (!empty($prefix))
- {
- $this->prefix = $prefix;
- }
- if (!empty($first))
- {
- $this->first = $first;
- }
- if (!empty($middle))
- {
- $this->middle = $middle;
- }
- if (!empty($last))
- {
- $this->last = $last;
- }
- if (!empty($suffix))
- {
- $this->suffix = $suffix;
- }
- if (!empty($raw))
- {
- $this->raw = $raw;
- }
- if (!empty($type))
- {
- $this->type = $type;
- }
- if (!empty($display))
- {
- $this->display = $display;
- }
- }
-
- public function is_searchable()
- {
- // A bool value that indicates whether the name is a valid name to
- // search by.
- $first = PiplApi_Utils::piplapi_alpha_chars(!empty($this->first) ? $this->first : '');
- $last = PiplApi_Utils::piplapi_alpha_chars(!empty($this->last) ? $this->last : '');
- $raw = PiplApi_Utils::piplapi_alpha_chars(!empty($this->raw) ? $this->raw : '');
-
- $func = function_exists("mb_strlen") ? "mb_strlen" : "strlen";
- return ($func($first) >= 2 && $func($last) >= 2) || $func($raw) >= 4;
- }
-}
-
-class PiplApi_Address extends PiplApi_Field
-{
- // An address of a person.
-
- protected $attributes = array('type');
- protected $children = array('country', 'state', 'city', 'po_box', 'zip_code', 'street', 'house', 'apartment', 'raw', 'display');
- protected $types_set = array('home', 'work', 'old');
-
- function __construct($params=array())
- {
- extract($params);
- parent::__construct($params);
- // `country`, `state`, `city`, `po_box`, `zip_code`, `street`, `house`, `apartment`,
- // `raw`, `type`, should all be strings.
- //
- // `country` and `state` are country code (like "US") and state code
- // (like "NY"), note that the full value is available as
- // address.country_full and address.state_full.
- //
- // `raw` is an unparsed address like "123 Marina Blvd, San Francisco,
- // California, US", usefull when you want to search by address and don't
- // want to work hard to parse it.
- // Note that in response data there's never address.raw, the addresses in
- // the response are always parsed, this is only for querying with
- // an unparsed address.
- //
- // `type` is one of PiplApi_Address::$types_set.
- //
-
- if (!empty($country))
- {
- $this->country = $country;
- }
- if (!empty($state))
- {
- $this->state = $state;
- }
- if (!empty($city))
- {
- $this->city = $city;
- }
- if (!empty($po_box))
- {
- $this->po_box = $po_box;
- }
- if (!empty($zip_code))
- {
- $this->zip_code = $zip_code;
- }
- if (!empty($street))
- {
- $this->street = $street;
- }
- if (!empty($house))
- {
- $this->house = $house;
- }
- if (!empty($apartment))
- {
- $this->apartment = $apartment;
- }
- if (!empty($raw))
- {
- $this->raw = $raw;
- }
- if (!empty($type))
- {
- $this->type = $type;
- }
- if (!empty($display))
- {
- $this->display = $display;
- }
- }
- public function is_sole_searchable() {
- return (!empty($this->raw) or (!empty($this->city) and !empty($this->street) and !empty($this->house)));
- }
- public function is_searchable()
- {
- // A bool value that indicates whether the address is a valid address
- // to search by.
- return (!empty($this->raw) || !empty($this->city) || !empty($this->state) || !empty($this->country));
- }
-
- public function is_valid_country()
- {
- // A bool value that indicates whether the object's country is a valid
- // country code.
- return (!empty($this->country) &&
- array_key_exists(strtoupper($this->country), PiplApi_Utils::$piplapi_countries));
- }
-
- public function is_valid_state()
- {
- // A bool value that indicates whether the object's state is a valid
- // state code.
- return ($this->is_valid_country() &&
- array_key_exists(strtoupper($this->country), PiplApi_Utils::$piplapi_states) &&
- !empty($this->state) &&
- array_key_exists(strtoupper($this->state), PiplApi_Utils::$piplapi_states[strtoupper($this->country)]));
-
- }
-
- public function country_full()
- {
- // the full name of the object's country.
-
- // $address = new PiplApi_Address(array('country' => 'FR'));
- // print $address->country; // Outputs "FR"
- // print $address->country_full(); // Outputs "France"
- if (!empty($this->country))
- {
- $uppedcoutnry = strtoupper($this->country);
-
- return array_key_exists($uppedcoutnry, PiplApi_Utils::$piplapi_countries) ?
- PiplApi_Utils::$piplapi_countries[$uppedcoutnry] :
- NULL;
- }
- return;
- }
-
- public function state_full()
- {
- // The full name of the object's state.
-
- // $address = new PiplApi_Address(array('country' => 'US', 'state' => 'CO'));
- // print $address->state; // Outputs "CO"
- // print $address->state_full(); // Outputs "Colorado"
-
- if ($this->is_valid_state())
- {
- return PiplApi_Utils::$piplapi_states[strtoupper($this->country)][strtoupper($this->state)];
- }
- return;
- }
-}
-
-class PiplApi_Phone extends PiplApi_Field
-{
- // A phone number of a person.
-
- protected $attributes = array('type');
- protected $children = array('country_code', 'number', 'extension', 'raw', 'display', 'display_international');
- protected $types_set = array('mobile', 'home_phone', 'home_fax', 'work_phone', 'work_fax', 'pager');
-
- function __construct($params=array())
- {
- extract($params);
- parent::__construct($params);
-
- // `country_code`, `number` and `extension` should all be int/long.
- // `type` is one of PiplApi_Phone::$types_set.
-
- if (!empty($country_code))
- {
- $this->country_code = $country_code;
- }
- if (!empty($number))
- {
- $this->number = $number;
- }
- if (!empty($extension))
- {
- $this->extension = $extension;
- }
- if (!empty($raw))
- {
- $this->raw = $raw;
- }
- if (!empty($type))
- {
- $this->type = $type;
- }
- if (!empty($display))
- {
- $this->display = $display;
- }
- if (!empty($display_international))
- {
- $this->display_international = $display_international;
- }
- }
-
- public function is_searchable()
- {
- // A bool value that indicates whether the phone is a valid phone
- // to search by.
- return (!empty($this->raw) || (!empty($this->number) && (empty($this->country_code) || $this->country_code == 1)));
- }
-
- public static function from_text($text)
- {
- return new PiplApi_Phone(array('raw' => $text));
- }
-
-}
-
-class PiplApi_Email extends PiplApi_Field
-{
- // An email address of a person with the md5 of the address, might come
- // in some cases without the address itself and just the md5 (for privacy
- // reasons).
-
- protected $attributes = array('type', "disposable", "email_provider");
- protected $children = array('address', 'address_md5');
- protected $types_set = array('personal', 'work');
- private $re_email = '/^[a-zA-Z0-9\'._%\-+]+@[a-zA-Z0-9._%\-]+\.[a-zA-Z]{2,24}$/';
-
- function __construct($params=array())
- {
- extract($params);
- parent::__construct($params);
-
- // `address`, `address_md5`, `type` should be strings.
- // `type` is one of PiplApl_Email::$types_set.
-
- if (!empty($address))
- {
- $this->address = $address;
- }
- if (!empty($address_md5))
- {
- $this->address_md5 = $address_md5;
- }
- if (!empty($type))
- {
- $this->type = $type;
- }
- if (!empty($disposable)) {
- $this->disposable = $disposable;
- }
- if (!empty($email_provider))
- {
- $this->email_provider = $email_provider;
- }
- }
-
- public function is_valid_email()
- {
- // A bool value that indicates whether the address is a valid
- // email address.
-
- return (!empty($this->address) && preg_match($this->re_email, $this->address));
- }
-
- public function is_searchable()
- {
- // A bool value that indicates whether the email is a valid email
- // to search by.
- return !empty($this->address_md5) || $this->is_valid_email();
- }
-
- // Needed to catch username and domain
- public function __get($name)
- {
- if (0 == strcasecmp($name, 'username'))
- {
- // string, the username part of the email or None if the email is
- // invalid.
-
- // $email = new PiplApi_Email(array('address' => 'eric@cartman.com'));
- // print $email->username; // Outputs "eric"
-
- if ($this->is_valid_email())
- {
- $all = explode('@', $this->address);
- return $all[0];
- }
- }
- else if (0 == strcasecmp($name, 'domain'))
- {
- // string, the domain part of the email or None if the email is
- // invalid.
-
- // $email = new PiplApi_Email(array('address' => 'eric@cartman.com'));
- // print $email->domain; // Outputs "cartman.com"
-
- if ($this->is_valid_email())
- {
- $all = explode('@', $this->address);
- return $all[1];
- }
- }
- return parent::__get($name);
- }
-
- public function __toString(){
- return $this->address ? $this->address : "";
- }
-}
-
-class PiplApi_Username extends PiplApi_Field
-{
- // A username/screen-name associated with the person.
-
- // Note that even though in many sites the username uniquely identifies one
- // person it's not guarenteed, some sites allow different people to use the
- // same username.
-
- protected $children = array('content');
-
- function __construct($params=array())
- {
- extract($params);
- parent::__construct($params);
-
- // `content` is the username itself, it should be a string.
-
-
- if (!empty($content))
- {
- $this->content = $content;
- }
- }
-
- public function is_searchable()
- {
- // A bool value that indicates whether the username is a valid username
- // to search by.
- $st = !empty($this->content) ? $this->content : '';
- $clean = PiplApi_Utils::piplapi_alnum_chars($st);
- $func = function_exists("mb_strlen") ? "mb_strlen" : "strlen";
- return ($func($clean) >= 3);
- }
-
- public function __toString(){
- return $this->content;
- }
-}
-
-class PiplApi_UserID extends PiplApi_Field
-{
- // An ID associated with a person.
-
- // The ID is a string that's used by the site to uniquely identify a person,
- // it's guaranteed that in the site this string identifies exactly one person.
-
- protected $children = array('content');
-
- function __construct($params=array())
- {
- extract($params);
- parent::__construct($params);
-
- // `content` is the ID itself, it should be a string.
-
-
- if (!empty($content))
- {
- $this->content = $content;
- }
- }
-
- public function is_searchable()
- {
- return (!empty($this->content)) && preg_match('/(.)@(.)/', $this->content);
- }
-
- public function __toString(){
- return $this->content;
- }
-}
-
-class PiplApi_DOB extends PiplApi_Field
-{
- // Date-of-birth of A person.
- // Comes as a PiplApi_DateRange (the exact date is within the range, if the exact
- // date is known the range will simply be with start=end).
-
- protected $children = array('date_range', 'display');
-
- function __construct($params=array())
- {
- extract($params);
- parent::__construct($params);
-
- // `date_range` is A DateRange object (PiplApi_DateRange),
- // the date-of-birth is within this range.
-
-
- if (!empty($date_range))
- {
- $this->date_range = $date_range;
- }
- if (!empty($display))
- {
- $this->display = $display;
- }
- }
-
- public function is_searchable()
- {
- return (!empty($this->date_range));
- }
-
- public function age()
- {
- // int, the estimated age of the person.
-
- // Note that A DOB object is based on a date-range and the exact date is
- // usually unknown so for age calculation the the middle of the range is
- // assumed to be the real date-of-birth.
-
- if (!empty($this->date_range))
- {
- $dob = $this->date_range->middle();
- $today = new DateTime('now', new DateTimeZone('GMT'));
-
- $diff = $today->format('Y') - $dob->format('Y');
-
- if ($dob->format('z') > $today->format('z'))
- {
- $diff -= 1;
- }
-
- return $diff;
- }
- return;
- }
-
- public function age_range()
- {
- // An array of two ints - the minimum and maximum age of the person.
- if (empty($this->date_range)){
- return array(NULL, NULL);
- }
- if(empty($this->date_range->start) || empty($this->date_range->end)){
- return array($this->age(), $this->age());
- }
-
- $start_date = new PiplApi_DateRange($this->date_range->start, $this->date_range->start);
- $end_date = new PiplApi_DateRange($this->date_range->end, $this->date_range->end);
- $start_age = new PiplApi_DOB(array('date_range' => $start_date));
- $start_age = $start_age->age();
- $end_age = new PiplApi_DOB(array('date_range' => $end_date));
- $end_age = $end_age->age();
-
- return (array($end_age, $start_age));
- }
-
- public static function from_birth_year($birth_year)
- {
- // Take a person's birth year (int) and return a new DOB object
- // suitable for him.
- if (!($birth_year > 0))
- {
- throw new InvalidArgumentException('birth_year must be positive');
- }
-
- $date_range = PiplApi_DateRange::from_years_range($birth_year, $birth_year);
- return (new PiplApi_DOB(array('date_range' => $date_range)));
- }
-
- public static function from_birth_date($birth_date)
- {
- // Take a person's birth date (Date) and return a new DOB
- // object suitable for him.
- if (!($birth_date <= new DateTime('now', new DateTimeZone('GMT'))))
- {
- throw new InvalidArgumentException('birth_date can\'t be in the future');
- }
-
- $date_range = new PiplApi_DateRange($birth_date, $birth_date);
- return (new PiplApi_DOB(array('date_range' => $date_range)));
- }
-
- public static function from_age($age)
- {
- # Take a person's age (int) and return a new DOB object
- # suitable for him.
- return (PiplApi_DOB::from_age_range($age, $age));
- }
-
- public static function from_age_range($start_age, $end_age)
- {
- // Take a person's minimal and maximal age and return a new DOB object
- // suitable for him.
- if (!($start_age >= 0 && $end_age >= 0))
- {
- throw new InvalidArgumentException('start_age and end_age can\'t be negative');
- }
-
- if ($start_age > $end_age)
- {
- $t = $end_age;
- $end_age = $start_age;
- $start_age = $t;
- }
-
- $start_date = new DateTime('now', new DateTimeZone('GMT'));
- $end_date = new DateTime('now', new DateTimeZone('GMT'));
-
- $start_date->modify('-' . $end_age . ' year');
- $start_date->modify('-1 year');
- $start_date->modify('+1 day');
- $end_date->modify('-' . $start_age . ' year');
-
- $date_range = new PiplApi_DateRange($start_date, $end_date);
- return (new PiplApi_DOB(array('date_range' => $date_range)));
- }
-}
-
-class PiplApi_Image extends PiplApi_Field
-{
- // A URL of an image of a person.
-
- protected $children = array('url', 'thumbnail_token');
-
- function __construct($params=array())
- {
- extract($params);
- parent::__construct($params);
-
- // `url` should be a string.
- // `thumbnail_token` is a string used to create the URL for Pipl's thumbnail service.
-
-
- if (!empty($url))
- {
- $this->url = $url;
- }
- if (!empty($thumbnail_token))
- {
- $this->thumbnail_token = $thumbnail_token;
- }
- }
-
- public function is_valid_url()
- {
- // A bool value that indicates whether the image URL is a valid URL.
- return (!empty($this->url) && PiplApi_Utils::piplapi_is_valid_url($this->url));
- }
- public function get_thumbnail_url($width=100, $height=100, $zoom_face=true, $favicon=true, $use_https=false){
- if(!empty($this->thumbnail_token)){
- return self::generate_redundant_thumbnail_url($this);
- }
- return NULL;
- }
- public static function generate_redundant_thumbnail_url($first_image, $second_image=NULL, $width=100, $height=100,
- $zoom_face=true, $favicon=true, $use_https=false){
- if (empty($first_image) && empty($second_image))
- throw new InvalidArgumentException('Please provide at least one image');
-
-
- if ((!empty($first_image) && !($first_image instanceof PiplApi_Image)) ||
- (!empty($second_image) && !($second_image instanceof PiplApi_Image)))
- {
- throw new InvalidArgumentException('Please provide PiplApi_Image Object');
- }
-
- $images = array();
-
- if (!empty($first_image->thumbnail_token))
- $images[] = $first_image->thumbnail_token;
-
- if (!empty($second_image->thumbnail_token))
- $images[] = $second_image->thumbnail_token;
-
- if (empty($images))
- throw new InvalidArgumentException("You can only generate thumbnail URLs for image objects with a thumbnail token.");
-
- if (sizeof($images) == 1)
- $tokens = $images[0];
- else {
- foreach ($images as $key=>$token) {
- $images[$key] = preg_replace("/&dsid=\d+/i","", $token);
- }
- $tokens = join(",", array_values($images));
- }
-
- $prefix = $use_https ? "https" : "http";
- $params = array("width" => $width, "height" => $height, "zoom_face" => $zoom_face, "favicon" => $favicon);
- $url = $prefix . "://thumb.pipl.com/image?tokens=" . $tokens . "&" . http_build_query($params);
- return $url;
- }
- public function __toString(){
- return $this->url;
- }
-}
-
-class PiplApi_Job extends PiplApi_Field
-{
- // Job information of a person.
-
- protected $children = array('title', 'organization', 'industry', 'date_range', 'display');
-
- function __construct($params=array())
- {
- extract($params);
- parent::__construct($params);
-
- // `title`, `organization`, `industry`, should all be strings.
- // `date_range` is A DateRange object (PiplApi_DateRange),
- // that's the time the person held this job.
-
- if (!empty($title))
- {
- $this->title = $title;
- }
- if (!empty($organization))
- {
- $this->organization = $organization;
- }
- if (!empty($industry))
- {
- $this->industry = $industry;
- }
- if (!empty($display))
- {
- $this->display = $display;
- }
- if (!empty($date_range))
- {
- $this->date_range = $date_range;
- }
- }
-
-}
-
-class PiplApi_Education extends PiplApi_Field
-{
- // Education information of a person.
-
- protected $children = array('degree', 'school', 'date_range', 'display');
-
- function __construct($params=array())
- {
- extract($params);
- parent::__construct($params);
-
- // `degree` and `school` should both be strings.
- // `date_range` is A DateRange object (PiplApi_DateRange),
- // that's the time the person was studying.
-
- if (!empty($degree))
- {
- $this->degree = $degree;
- }
- if (!empty($school))
- {
- $this->school = $school;
- }
- if (!empty($date_range))
- {
- $this->date_range = $date_range;
- }
- if (!empty($display))
- {
- $this->display = $display;
- }
- }
-}
-
-class PiplApi_Gender extends PiplApi_Field
-{
-
-// An gender field.
- protected $children = array('content');
-
- function __construct($params=array())
- {
- extract($params);
- parent::__construct($params);
-
- // `content` is the gender value - "Male"/"Female"
-
- if (!empty($content))
- {
- $this->content = $content;
- }
- }
-
- public function __toString()
- {
- return $this->content ? ucwords($this->content) : "";
- }
-
-}
-
-class PiplApi_Ethnicity extends PiplApi_Field
-{
-
-// An ethnicity field.
-// The content will be a string with one of the following values (based on US census definitions)
-// 'white', 'black', 'american_indian', 'alaska_native',
-// 'chinese', 'filipino', 'other_asian', 'japanese',
-// 'korean', 'viatnamese', 'native_hawaiian', 'guamanian',
-// 'chamorro', 'samoan', 'other_pacific_islander', 'other'.
- protected $children = array('content');
-
- function __construct($params=array())
- {
- extract($params);
- parent::__construct($params);
-
- // `content` is the ethnicity value.
-
- if (!empty($content))
- {
- $this->content = $content;
- }
- }
-
- public function __toString()
- {
- return $this->content ? ucwords(str_replace("_", " ", $this->content)) : "";
- }
-}
-
-class PiplApi_Language extends PiplApi_Field
-{
-// A language the person is familiar with.
- protected $children = array('language', "region", "display");
-
- function __construct($params=array())
- {
- extract($params);
- parent::__construct($params);
-
- // `language` is the language code itself. For example "en"
- // `region` is the language region. For example "US"
- // `display` is a display value. For example "en_US"
-
-
- if (!empty($language))
- {
- $this->language = $language;
- }
- if (!empty($display))
- {
- $this->display = $display;
- }
- if (!empty($region))
- {
- $this->region = $region;
- }
- }
-}
-
-class PiplApi_OriginCountry extends PiplApi_Field
-{
-// An origin country of the person.
- protected $children = array('country');
-
- function __construct($params=array())
- {
- extract($params);
- parent::__construct($params);
-
- // `country` is a two letter country code.
-
- if (!empty($country))
- {
- $this->country = $country;
- }
- }
-
- public function __toString(){
- if (!empty($this->country))
- {
- $uppedcoutnry = strtoupper($this->country);
- return array_key_exists($uppedcoutnry, PiplApi_Utils::$piplapi_countries) ?
- PiplApi_Utils::$piplapi_countries[$uppedcoutnry] : NULL;
- }
- return "";
- }
-}
-
-class PiplApi_URL extends PiplApi_Field
-{
- // A URL that's related to a person. Can either be a source of data
- // about the person, or a URL otherwise related to the person.
-
- protected $attributes = array('category', 'sponsored', 'source_id', 'name', 'domain');
- protected $children = array('url');
-
- function __construct($params=array())
- {
- extract($params);
- parent::__construct($params);
-
- // `url` is the URL address itself
- // `domain` is the URL's domain
- // `name` is the website name
- // `category` is the URL's category.
- //
- // `url`, `category`, `domain` and `name` should all be strings.
- //
- // `sponsored` is a boolean - whether the URL is sponsored or not
-
- if (!empty($url))
- {
- $this->url = $url;
- }
- if (!empty($category))
- {
- $this->category = $category;
- }
- if (!empty($source_id))
- {
- $this->source_id = $source_id;
- }
- if (!empty($name))
- {
- $this->name = $name;
- }
- if (!empty($domain))
- {
- $this->domain = $domain;
- }
- if (!empty($sponsored))
- {
- $this->sponsored = $sponsored;
- }
- }
-
- public function is_valid_url()
- {
- // A bool value that indicates whether the URL is a valid URL.
- return (!empty($this->url) && PiplApi_Utils::piplapi_is_valid_url($this->url));
- }
-
- public function is_searchable()
- {
- return (!empty($this->url));
- }
-
- public function __toString(){
- return $this->url ? $this->url : $this->name;
- }
-}
-
-class PiplApi_Tag extends PiplApi_Field
-{
- // A general purpose element that holds any meaningful string that's
- // related to the person.
- // Used for holding data about the person that either couldn't be clearly
- // classified or was classified as something different than the available
- // data fields.
-
- protected $attributes = array('classification');
- protected $children = array('content');
-
- function __construct($params=array())
- {
- extract($params);
- parent::__construct($params);
-
- // `content` is the tag itself, both `content` and `classification`
- // should be strings.
-
-
- if (!empty($content))
- {
- $this->content = $content;
- }
- if (!empty($classification))
- {
- $this->classification = $classification;
- }
- }
-
- public function __toString()
- {
- return $this->content;
- }
-}
-
-class PiplApi_DateRange
-{
- // A time intervel represented as a range of two dates.
- // DateRange objects are used inside DOB, Job and Education objects.
-
- public $start;
- public $end;
-
- function __construct($start, $end)
- {
- // `start` and `end` are DateTime objects, at least one is required.
-
- // For creating a DateRange object for an exact date (like if exact
- // date-of-birth is known) just pass the same value for `start` and `end`.
-
- if (!empty($start))
- {
- $this->start = $start;
- }
- if (!empty($end))
- {
- $this->end = $end;
- }
-
- if (empty($this->start) && empty($this->end))
- {
- throw new InvalidArgumentException('Start/End parameters missing');
- }
-
- if (($this->start && $this->end) && ($this->start > $this->end))
- {
- $t = $this->end;
- $this->end = $this->start;
- $this->start = $t;
- }
- }
-
- public function __toString()
- {
- // Return a representation of the object.
- if($this->start && $this->end) {
- return sprintf('%s - %s', PiplApi_Utils::piplapi_date_to_str($this->start),
- PiplApi_Utils::piplapi_date_to_str($this->end));
- } elseif($this->start) {
- return PiplApi_Utils::piplapi_date_to_str($this->start);
- }
- return PiplApi_Utils::piplapi_date_to_str($this->end);
- }
-
- public function is_exact()
- {
- // True if the object holds an exact date (start=end),
- // False otherwise.
- return ($this->start == $this->end);
- }
-
- public function middle()
- {
- // The middle of the date range (a DateTime object).
- if($this->start && $this->end) {
- $diff = ($this->end->format('U') - $this->start->format('U')) / 2;
- $newts = $this->start->format('U') + $diff;
- $newdate = new DateTime('@' . $newts, new DateTimeZone('GMT'));
- return $newdate;
- }
- return $this->start ? $this->start : $this->end;
- }
-
- public function years_range()
- {
- // A tuple of two ints - the year of the start date and the year of the
- // end date.
- if(!($this->start && $this->end)){
- return NULL;
- }
- return array($this->start->format('Y'), $this->end->format('Y'));
- }
-
- public static function from_years_range($start_year, $end_year)
- {
- // Transform a range of years (two ints) to a DateRange object.
- $newstart = new DateTime($start_year . '-01-01', new DateTimeZone('GMT'));
- $newend = new DateTime($end_year . '-12-31', new DateTimeZone('GMT'));
- return new PiplApi_DateRange($newstart, $newend);
- }
-
- public static function from_array($d)
- {
- // Transform the dict to a DateRange object.
- $newstart = !empty($d['start']) ? $d['start'] : NULL;
- $newend = !empty($d['end']) ? $d['end'] : NULL;
- if($newstart) {
- $newstart = PiplApi_Utils::piplapi_str_to_date($newstart);
- }
- if($newend){
- $newend = PiplApi_Utils::piplapi_str_to_date($newend);
- }
- return new PiplApi_DateRange($newstart, $newend);
- }
-
- public function to_array()
- {
- // Transform the date-range to a dict.
- $d = array();
- if($this->start) {
- $d['start'] = PiplApi_Utils::piplapi_date_to_str($this->start);
- }
- if($this->end){
- $d['end'] = PiplApi_Utils::piplapi_date_to_str($this->end);
- }
- return $d;
- }
-}
-
-
diff --git a/src/piplapis/error.php b/src/piplapis/models/api_error.php
similarity index 92%
rename from src/piplapis/error.php
rename to src/piplapis/models/api_error.php
index 493af28..1456a7d 100644
--- a/src/piplapis/error.php
+++ b/src/piplapis/models/api_error.php
@@ -1,98 +1,110 @@
-error = $error;
- $this->warnings = $warnings;
- $this->http_status_code = $http_status_code;
-
- // qps_allotted- int | The number of queries you are allowed to do per second.
- // qps_current- int | The number of queries you have run this second.
- // quota_allotted- int | Your quota limit.
- // quota_current- int | Your used quota.
- // quota_reset- DateTime Object | The time (in UTC) that your quota will be reset.
- // qps_live_allotted - Your permitted queries per second
- // qps_live_current - The number of queries that you've run in the same second as this one.
- // qps_demo_allotted - Your permitted queries per second
- // qps_demo_current - The number of queries that you've run in the same second as this one.
- // demo_usage_allotted - Your permitted demo queries
- // demo_usage_current - The number of demo queries that you've already run
- // demo_usage_expiry - The expiry time of your demo usage
-
-
- $this->qps_allotted = $qps_allotted;
- $this->qps_current = $qps_current;
- $this->qps_live_allotted = $qps_live_allotted;
- $this->qps_live_current = $qps_live_current;
- $this->qps_demo_allotted = $qps_demo_allotted;
- $this->qps_demo_current = $qps_demo_current;
- $this->quota_allotted = $quota_allotted;
- $this->quota_current = $quota_current;
- $this->quota_reset = $quota_reset;
- $this->demo_usage_allotted = $demo_usage_allotted;
- $this->demo_usage_current = $demo_usage_current;
- $this->demo_usage_expiry = $demo_usage_expiry;
- }
-
- public function is_user_error()
- {
- // A bool that indicates whether the error is on the user's side.
- return in_array($this->http_status_code, range(400, 499));
- }
-
- public function is_pipl_error()
- {
- // A bool that indicates whether the error is on Pipl's side.
- return !$this->is_user_error();
- }
-
- public static function from_array($d, $headers=array())
- {
- // Transform the dict to a error object and return the error.
-
- $qps_allotted = !empty($headers['x-qps-allotted']) ? intval($headers['x-qps-allotted']) : null;
- $qps_current = !empty($headers['x-qps-current']) ? intval($headers['x-qps-current']) : null;
- $quota_allotted = !empty($headers['x-apikey-quota-allotted']) ? intval($headers['x-apikey-quota-allotted']) : null;
- $quota_current = !empty($headers['x-apikey-quota-current']) ? intval($headers['x-apikey-quota-current']) : null;
- $quota_reset = !empty($headers['x-quota-reset']) ?
- DateTime::createFromFormat(PiplApi_Utils::PIPLAPI_DATE_QUOTA_RESET, $headers['x-quota-reset']) : null;
- $qps_live_allotted = !empty($headers['x-qps-live-allotted']) ? intval($headers['x-qps-live-allotted']) : null;
- $qps_live_current = !empty($headers['x-qps-live-current']) ? intval($headers['x-qps-live-current']) : null;
- $qps_demo_allotted = !empty($headers['x-qps-demo-allotted']) ? intval($headers['x-qps-demo-allotted']) : null;
- $qps_demo_current = !empty($headers['x-qps-demo-current']) ? intval($headers['x-qps-demo-current']) : null;
- $demo_usage_allotted = !empty($headers['x-demo-usage-allotted']) ? intval($headers['x-demo-usage-allotted']) : null;
- $demo_usage_current = !empty($headers['x-demo-usage-current']) ? intval($headers['x-demo-usage-current']) : null;
- $demo_usage_expiry = !empty($headers['x-demo-usage-expiry']) ?
- DateTime::createFromFormat(PiplApi_Utils::PIPLAPI_DATE_QUOTA_RESET, $headers['x-demo-usage-expiry']) : null;
-
- $error = !empty($d['error']) ? $d['error'] : "";
- $warnings = !empty($d['warnings']) ? $d['warnings'] : "";
- $http_status_code = !empty($d['@http_status_code']) ? $d['@http_status_code'] : 0;
-
- return new self($error, $warnings, $http_status_code, $qps_allotted, $qps_current,
- $quota_allotted, $quota_current, $quota_reset, $qps_live_allotted, $qps_live_current,
- $qps_demo_allotted, $qps_demo_current, $demo_usage_allotted, $demo_usage_current, $demo_usage_expiry);
- }
-
- public function to_array()
- {
- // Return a dict representation of the error.
- return array('error' => $this->error,
- '@http_status_code' => $this->http_status_code, 'warnings' => $this->warnings);
- }
-}
+error = $error;
+ $this->warnings = $warnings;
+ $this->http_status_code = $http_status_code;
+
+ // qps_allotted- int | The number of queries you are allowed to do per second.
+ // qps_current- int | The number of queries you have run this second.
+ // quota_allotted- int | Your quota limit.
+ // quota_current- int | Your used quota.
+ // quota_reset- DateTime Object | The time (in UTC) that your quota will be reset.
+ // qps_live_allotted - Your permitted queries per second
+ // qps_live_current - The number of queries that you've run in the same second as this one.
+ // qps_demo_allotted - Your permitted queries per second
+ // qps_demo_current - The number of queries that you've run in the same second as this one.
+ // demo_usage_allotted - Your permitted demo queries
+ // demo_usage_current - The number of demo queries that you've already run
+ // demo_usage_expiry - The expiry time of your demo usage
+
+
+ $this->qps_allotted = $qps_allotted;
+ $this->qps_current = $qps_current;
+ $this->qps_live_allotted = $qps_live_allotted;
+ $this->qps_live_current = $qps_live_current;
+ $this->qps_demo_allotted = $qps_demo_allotted;
+ $this->qps_demo_current = $qps_demo_current;
+ $this->quota_allotted = $quota_allotted;
+ $this->quota_current = $quota_current;
+ $this->quota_reset = $quota_reset;
+ $this->demo_usage_allotted = $demo_usage_allotted;
+ $this->demo_usage_current = $demo_usage_current;
+ $this->demo_usage_expiry = $demo_usage_expiry;
+ }
+
+ public function is_user_error()
+ {
+ // A bool that indicates whether the error is on the user's side.
+ return in_array($this->http_status_code, range(400, 499));
+ }
+
+ public function is_pipl_error()
+ {
+ // A bool that indicates whether the error is on Pipl's side.
+ return !$this->is_user_error();
+ }
+
+ public static function from_array($d, $headers=array())
+ {
+ // Transform the dict to a error object and return the error.
+
+ $qps_allotted = !empty($headers['x-qps-allotted']) ? intval($headers['x-qps-allotted']) : null;
+ $qps_current = !empty($headers['x-qps-current']) ? intval($headers['x-qps-current']) : null;
+ $quota_allotted = !empty($headers['x-apikey-quota-allotted']) ? intval($headers['x-apikey-quota-allotted']) : null;
+ $quota_current = !empty($headers['x-apikey-quota-current']) ? intval($headers['x-apikey-quota-current']) : null;
+ $quota_reset = !empty($headers['x-quota-reset']) ?
+ DateTime::createFromFormat(PiplApi_Utils::PIPLAPI_DATE_QUOTA_RESET, $headers['x-quota-reset']) : null;
+ $qps_live_allotted = !empty($headers['x-qps-live-allotted']) ? intval($headers['x-qps-live-allotted']) : null;
+ $qps_live_current = !empty($headers['x-qps-live-current']) ? intval($headers['x-qps-live-current']) : null;
+ $qps_demo_allotted = !empty($headers['x-qps-demo-allotted']) ? intval($headers['x-qps-demo-allotted']) : null;
+ $qps_demo_current = !empty($headers['x-qps-demo-current']) ? intval($headers['x-qps-demo-current']) : null;
+ $demo_usage_allotted = !empty($headers['x-demo-usage-allotted']) ? intval($headers['x-demo-usage-allotted']) : null;
+ $demo_usage_current = !empty($headers['x-demo-usage-current']) ? intval($headers['x-demo-usage-current']) : null;
+ $demo_usage_expiry = !empty($headers['x-demo-usage-expiry']) ?
+ DateTime::createFromFormat(PiplApi_Utils::PIPLAPI_DATE_QUOTA_RESET, $headers['x-demo-usage-expiry']) : null;
+
+ $error = !empty($d['error']) ? $d['error'] : "";
+ $warnings = !empty($d['warnings']) ? $d['warnings'] : "";
+ $http_status_code = !empty($d['@http_status_code']) ? $d['@http_status_code'] : 0;
+
+ return new self($error, $warnings, $http_status_code, $qps_allotted, $qps_current,
+ $quota_allotted, $quota_current, $quota_reset, $qps_live_allotted, $qps_live_current,
+ $qps_demo_allotted, $qps_demo_current, $demo_usage_allotted, $demo_usage_current, $demo_usage_expiry);
+ }
+
+ public function to_array()
+ {
+ // Return a dict representation of the error.
+ return array('error' => $this->error,
+ '@http_status_code' => $this->http_status_code, 'warnings' => $this->warnings);
+ }
+}
diff --git a/src/piplapis/models/containers/available_data.php b/src/piplapis/models/containers/available_data.php
new file mode 100644
index 0000000..1456b52
--- /dev/null
+++ b/src/piplapis/models/containers/available_data.php
@@ -0,0 +1,30 @@
+basic = $basic ? PiplApi_FieldCount::from_array($basic) : NULL;
+ $this->premium = $premium ? PiplApi_FieldCount::from_array($premium) : NULL;
+
+ }
+ public static function from_array($params) {
+ $basic = !empty($params['basic']) ? $params['basic'] : NULL;
+ $premium = !empty($params['premium']) ? $params['premium'] : NULL;
+ $instance = new self($basic, $premium);
+ return $instance;
+ }
+ public function to_array() {
+ $res = array();
+ if ($this->basic != NULL)
+ $res['basic'] = $this->basic->to_array();
+ if ($this->premium != NULL)
+ $res['premium'] = $this->premium->to_array();
+ return $res;
+ }
+}
\ No newline at end of file
diff --git a/src/piplapis/models/containers/field_count.php b/src/piplapis/models/containers/field_count.php
new file mode 100644
index 0000000..ff493a0
--- /dev/null
+++ b/src/piplapis/models/containers/field_count.php
@@ -0,0 +1,94 @@
+dobs = $dobs;
+ $this->images = $images;
+ $this->educations = $educations;
+ $this->addresses = $addresses;
+ $this->jobs = $jobs;
+ $this->genders = $genders;
+ $this->ethnicities = $ethnicities;
+ $this->phones = $phones;
+ $this->origin_countries = $origin_countries;
+ $this->usernames = $usernames;
+ $this->languages = $languages;
+ $this->emails = $emails;
+ $this->user_ids = $user_ids;
+ $this->relationships = $relationships;
+ $this->names = $names;
+ $this->social_profiles = $social_profiles;
+ $this->mobile_phones = $mobile_phones;
+ $this->landline_phones = $landline_phones;
+ }
+
+ public static function from_array($params)
+ {
+ $dobs = !empty($params['dobs']) ? $params['dobs'] : NULL;
+ $images = !empty($params['images']) ? $params['images'] : NULL;
+ $educations = !empty($params['educations']) ? $params['educations'] : NULL;
+ $addresses = !empty($params['addresses']) ? $params['addresses'] : NULL;
+ $jobs = !empty($params['jobs']) ? $params['jobs'] : NULL;
+ $genders = !empty($params['genders']) ? $params['genders'] : NULL;
+ $ethnicities = !empty($params['ethnicities']) ? $params['ethnicities'] : NULL;
+ $phones = !empty($params['phones']) ? $params['phones'] : NULL;
+ $origin_countries = !empty($params['origin_countries']) ? $params['origin_countries'] : NULL;
+ $usernames = !empty($params['usernames']) ? $params['usernames'] : NULL;
+ $languages = !empty($params['languages']) ? $params['languages'] : NULL;
+ $emails = !empty($params['emails']) ? $params['emails'] : NULL;
+ $user_ids = !empty($params['user_ids']) ? $params['user_ids'] : NULL;
+ $relationships = !empty($params['relationships']) ? $params['relationships'] : NULL;
+ $names = !empty($params['names']) ? $params['names'] : NULL;
+ $social_profiles = !empty($params['social_profiles']) ? $params['social_profiles'] : NULL;
+ $landline_phones = !empty($params['landline_phones']) ? $params['landline_phones'] : NULL;
+ $mobile_phones = !empty($params['mobile_phones']) ? $params['mobile_phones'] : NULL;
+
+ $instance = new self($dobs, $images, $educations, $addresses, $jobs,
+ $genders, $ethnicities, $phones, $origin_countries,
+ $usernames, $languages, $emails, $user_ids, $relationships,
+ $names, $social_profiles, $mobile_phones, $landline_phones);
+ return $instance;
+ }
+
+ public function to_array()
+ {
+ $res = array();
+ foreach ($this->attributes as $attr) {
+ if ($this->$attr > 0)
+ $res[$attr] = $this->$attr;
+ }
+ return $res;
+ }
+}
\ No newline at end of file
diff --git a/src/piplapis/models/containers/fields_container.php b/src/piplapis/models/containers/fields_container.php
new file mode 100644
index 0000000..e2a8fff
--- /dev/null
+++ b/src/piplapis/models/containers/fields_container.php
@@ -0,0 +1,173 @@
+ 'names',
+ 'PiplApi_Address' => 'addresses',
+ 'PiplApi_Phone' => 'phones',
+ 'PiplApi_Email' => 'emails',
+ 'PiplApi_Job' => 'jobs',
+ 'PiplApi_Ethnicity' => 'ethnicities',
+ 'PiplApi_OriginCountry' => 'origin_countries',
+ 'PiplApi_Language' => 'languages',
+ 'PiplApi_Education' => 'educations',
+ 'PiplApi_Image' => 'images',
+ 'PiplApi_Username' => 'usernames',
+ 'PiplApi_UserID' => 'user_ids',
+ 'PiplApi_URL' => 'urls'
+ );
+
+ protected $singular_fields = array(
+ 'PiplApi_DOB' => 'dob',
+ 'PiplApi_Gender' => 'gender',
+ );
+
+ function __construct($fields=array())
+ {
+ // `fields` is an array of field objects from
+ // fields.php.
+ $this->add_fields($fields);
+ }
+
+ public function add_fields($fields)
+ {
+ // Add the fields to their corresponding container.
+ // `fields` is an array of field objects from fields.php
+ if (empty($fields))
+ {
+ return;
+ }
+
+ foreach ($fields as $field)
+ {
+ $cls = is_object($field) ? get_class($field) : NULL;
+
+ if (array_key_exists($cls, $this->CLASS_CONTAINER))
+ {
+ $container = $this->CLASS_CONTAINER[$cls];
+ $this->{$container}[] = $field;
+ } elseif(array_key_exists($cls, $this->singular_fields)) {
+ $this->{$this->singular_fields[$cls]} = $field;
+ } else {
+ $type = empty($cls) ? gettype($field) : $cls;
+ throw new InvalidArgumentException('Object of type ' . $type . ' is an invalid field');
+ }
+ }
+ }
+
+ public function all_fields()
+ {
+ // An array with all the fields contained in this object.
+ $allfields = array();
+ foreach (array_values($this->CLASS_CONTAINER) as $val){
+ $allfields = array_merge($allfields, $this->{$val});
+ }
+ foreach (array_values($this->singular_fields) as $val){
+ if($this->{$val}) {
+ $allfields[] = $this->{$val};
+ }
+ }
+
+ return $allfields;
+ }
+
+ public function fields_from_array($d)
+ {
+ // Load the fields from the dict, return an array with all the fields.
+
+ $fields = array();
+
+ foreach (array_keys($this->CLASS_CONTAINER) as $field_cls){
+ $container = $this->CLASS_CONTAINER[$field_cls];
+ if (array_key_exists($container, $d)) {
+ $field_array = $d[$container];
+ foreach ($field_array as $x) {
+ $from_array_func = method_exists($field_cls, 'from_array') ? array($field_cls, 'from_array') : array('PiplApi_Field', 'from_array');
+ $fields[] = call_user_func($from_array_func, $field_cls, $x);
+ }
+ }
+ }
+ foreach (array_keys($this->singular_fields) as $field_cls){
+ $container = $this->singular_fields[$field_cls];
+ if (array_key_exists($container, $d)) {
+ $field_array = $d[$container];
+ $from_array_func = method_exists($field_cls, 'from_array') ? array($field_cls, 'from_array') : array('PiplApi_Field', 'from_array');
+ $fields[] = call_user_func($from_array_func, $field_cls, $field_array);
+ }
+ }
+ return $fields;
+ }
+
+ public function fields_to_array(){
+ // Transform the object to an array and return it.
+ $d = array();
+
+ foreach (array_values($this->CLASS_CONTAINER) as $container){
+ $fields = $this->{$container};
+ if (!empty($fields)){
+ $all_fields = array();
+ foreach($fields as $field) {
+ $all_fields[] = $field->to_array();
+ }
+ if (count($all_fields) > 0){
+ $d[$container] = $all_fields;
+ }
+ }
+ }
+ foreach (array_values($this->singular_fields) as $container){
+ $field = $this->{$container};
+ if (!empty($field)){
+ $d[$container] = $field->to_array();
+ }
+ }
+ return $d;
+ }
+
+ /**
+ * Specify data which should be serialized to JSON
+ * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
+ * @return mixed data which can be serialized by json_encode,
+ * which is a value of any type other than a resource.
+ * @since 5.4.0
+ */
+ function jsonSerialize()
+ {
+ return $this->to_array();
+ }
+}
\ No newline at end of file
diff --git a/src/piplapis/models/containers/person.php b/src/piplapis/models/containers/person.php
new file mode 100644
index 0000000..31ce6f3
--- /dev/null
+++ b/src/piplapis/models/containers/person.php
@@ -0,0 +1,113 @@
+ 'clark.kent@example.com')), new PiplApi_Phone(array('number' => 9785550145)));
+ // $person = new PiplApi_Person(array('fields' => $fields));
+ // print implode(', ', $person->emails); // Outputs "clark.kent@example.com"
+ // print implode(', ', $person->phones); // Outputs "+1-9785550145"
+ //
+ // Note that a person object is used in the Search API in two ways:
+ // - It might come back as a result for a query (see PiplApi_SearchAPIResponse).
+ // - It's possible to build a person object with all the information you
+ // already have about the person you're looking for and send this object as
+ // the query (see PiplApi_SearchAPIRequest).
+
+ private $extended_containers = array(
+ 'PiplApi_Relationship' => 'relationships'
+ );
+ public $id;
+ public $search_pointer;
+ public $match;
+ public $inferred;
+ public $relationships = array();
+
+ function __construct($fields = array(), $id = NULL, $search_pointer = NULL, $match = NULL, $inferred = false)
+ {
+ // Extend FieldsContainer.initialize and set the record's sources
+ // and query_params_match attribute.
+ //
+ // Args:
+ //
+ // $fields -- An array of fields (fields.php).
+ // $match -- A float value, the person's match score.
+ // $id -- GUID. The person's ID.
+ // $search_pointer -- string. Can be used for drill down searches.
+ $this->CLASS_CONTAINER = array_merge($this->CLASS_CONTAINER, $this->extended_containers);
+ parent::__construct($fields);
+ $this->search_pointer = $search_pointer;
+ $this->match = $match;
+ $this->id = $id;
+ $this->inferred = $inferred;
+ }
+
+ public function is_searchable()
+ {
+ // A bool value that indicates whether the person has enough data and
+ // can be sent as a query to the API.
+ $all = array_merge($this->names, $this->emails, $this->phones, $this->usernames, $this->user_ids, $this->urls);
+ $searchable = array_filter($all, function($field) {
+ return $field->is_searchable();
+ });
+ $searchable_address = array_filter($this->addresses, function($field) {
+ return $field->is_sole_searchable();
+ });
+ return $searchable_address or $this->search_pointer or count($searchable) > 0;
+ }
+
+ public function unsearchable_fields()
+ {
+ // An array of all the fields that are invalid and won't be used in the search.
+
+ // For example: names/usernames that are too short, emails that are
+ // invalid etc.
+ $all = array_merge($this->names, $this->emails, $this->phones, $this->usernames, $this->addresses,
+ $this->user_ids, $this->urls, array($this->dob));
+ $unsearchable = array_filter($all, function($field) {
+ return $field && !$field->is_searchable();
+ });
+ return $unsearchable;
+ }
+
+ public static function from_array($params)
+ {
+ // Transform the array to a person object and return it.
+ $id = !empty($params['@id']) ? $params['@id'] : NULL;
+ $search_pointer = !empty($params['@search_pointer']) ? $params['@search_pointer'] : NULL;
+ $match = !empty($params['@match']) ? $params['@match'] : NULL;
+ $inferred = !empty($params['@inferred']) ? $params['@inferred'] : false;
+
+ $instance = new self(array(), $id, $search_pointer, $match, $inferred);
+ $instance->add_fields($instance->fields_from_array($params));
+ return $instance;
+ }
+
+ public function to_array()
+ {
+ // Return an array representation of the person.
+ $d = array();
+
+ if (!empty($this->id)){ $d['@id'] = $this->id; }
+ if (!is_null($this->match)){ $d['@match'] = $this->match; }
+ if (!empty($this->search_pointer)){ $d['@search_pointer'] = $this->search_pointer; }
+ if ($this->inferred){ $d['@inferred'] = $this->inferred; }
+
+ return array_merge($d, $this->fields_to_array());
+ }
+
+}
\ No newline at end of file
diff --git a/src/piplapis/models/containers/relationship.php b/src/piplapis/models/containers/relationship.php
new file mode 100644
index 0000000..3cd2b1f
--- /dev/null
+++ b/src/piplapis/models/containers/relationship.php
@@ -0,0 +1,67 @@
+type = $type;
+ $this->subtype = $subtype;
+ $this->valid_since = $valid_since;
+ $this->inferred = $inferred;
+ }
+
+ public static function from_array($class_name, $params)
+ {
+ // Transform the array to a person object and return it.
+ $type = !empty($params['@type']) ? $params['@type'] : NULL;
+ $subtype = !empty($params['@subtype']) ? $params['@subtype'] : NULL;
+ $valid_since = !empty($params['@valid_since']) ? $params['@valid_since'] : NULL;
+ $inferred = !empty($params['@inferred']) ? $params['@inferred'] : NULL;
+
+ $instance = new self(array(), $type, $subtype, $valid_since, $inferred);
+ $instance->add_fields($instance->fields_from_array($params));
+ return $instance;
+ }
+ public function __toString(){
+ return count($this->names) > 0 && $this->names[0]->first ? $this->names[0]->first : "";
+ }
+ public function to_array()
+ {
+ // Return an array representation of the person.
+ $d = array();
+
+ if (!empty($this->valid_since)){ $d['@valid_since'] = $this->valid_since; }
+ if (!empty($this->inferred)){ $d['@inferred'] = $this->inferred; }
+ if (!empty($this->type)){ $d['@type'] = $this->type; }
+ if (!empty($this->subtype)){ $d['@subtype'] = $this->subtype; }
+
+ return array_merge($d, $this->fields_to_array());
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/piplapis/models/containers/source.php b/src/piplapis/models/containers/source.php
new file mode 100644
index 0000000..cec0dac
--- /dev/null
+++ b/src/piplapis/models/containers/source.php
@@ -0,0 +1,111 @@
+ 'relationships',
+ 'PiplApi_Tag' => 'tags'
+ );
+ public $name;
+ public $category;
+ public $origin_url;
+ public $sponsored;
+ public $domain;
+ public $person_id;
+ public $id;
+ public $premium;
+ public $match;
+ public $valid_since;
+ public $relationships = array();
+ public $tags = array();
+
+ function __construct($fields = array(), $match = NULL, $name = NULL, $category = NULL, $origin_url = NULL,
+ $sponsored = NULL, $domain = NULL, $person_id = NULL, $id = NULL,
+ $premium = NULL, $valid_since = NULL){
+ // Extend FieldsContainer::__construct and set the record's source
+ // and attributes.
+ //
+ // Args:
+ // $fields -- an array of fields
+ // $match -- A float between 0.0 and 1.0 that indicates how likely it is that this source holds data about
+ // the person from the query. Higher value means higher likelihood, value of 1.0
+ // means "this is definitely him". This value is based on Pipl's statistical algorithm that takes
+ // into account many parameters like the popularity of the name/address
+ // (if there was a name/address in the query) etc.
+ // $name -- A string, the source name
+ // $category -- A string, the source category
+ // $origin_url -- A string, the URL where Pipl's crawler found this data
+ // $sponsored -- A boolean, whether the source is a sponsored result or not
+ // $domain -- A string, the domain of this source
+ // $person_id -- A string, the person's unique ID
+ // $source_id -- A string, the source ID
+ // $premium -- A boolean, whether this is a premium source
+ // $valid_since -- A DateTime object, this is the first time Pipl's crawlers saw this source.
+ $this->CLASS_CONTAINER = array_merge($this->CLASS_CONTAINER, $this->extended_containers);
+ parent::__construct($fields);
+ $this->name = $name;
+ $this->category = $category;
+ $this->origin_url = $origin_url;
+ $this->sponsored = $sponsored;
+ $this->domain = $domain;
+ $this->person_id = $person_id;
+ $this->id = $id;
+ $this->premium = $premium;
+ $this->match = $match;
+ $this->valid_since = $valid_since;
+ }
+
+ public static function from_array($params)
+ {
+ // Transform the dict to a record object and return the record.
+ $name = !empty($params['@name']) ? $params['@name'] : NULL;
+ $match = !empty($params['@match']) ? $params['@match'] : NULL;
+ $category = !empty($params['@category']) ? $params['@category'] : NULL;
+ $origin_url = !empty($params['@origin_url']) ? $params['@origin_url'] : NULL;
+ $sponsored = !empty($params['@sponsored']) ? $params['@sponsored'] : NULL;
+ $domain = !empty($params['@domain']) ? $params['@domain'] : NULL;
+ $person_id = !empty($params['@person_id']) ? $params['@person_id'] : NULL;
+ $source_id = !empty($params['@id']) ? $params['@id'] : NULL;
+ $premium = !empty($params['@premium']) ? $params['@premium'] : NULL;
+ $valid_since = !empty($params['@valid_since']) ? $params['@valid_since'] : NULL;
+ if (!empty($valid_since)){ $valid_since = PiplApi_Utils::piplapi_str_to_datetime($valid_since); }
+
+ $instance = new self(array(), $match, $name, $category, $origin_url, $sponsored, $domain, $person_id,
+ $source_id, $premium, $valid_since);
+ $instance->add_fields($instance->fields_from_array($params));
+ return $instance;
+ }
+
+ public function to_array()
+ {
+ // Return an array representation of the record.
+ $d = array();
+ if (!empty($this->valid_since)){ $d['@valid_since'] = PiplApi_Utils::piplapi_datetime_to_str($this->valid_since); }
+ if (!empty($this->match)){ $d['@match'] = $this->match; }
+ if (!empty($this->category)){ $d['@category'] = $this->category; }
+ if (!empty($this->origin_url)){ $d['@origin_url'] = $this->origin_url; }
+ if (!empty($this->sponsored)){ $d['@sponsored'] = $this->sponsored; }
+ if (!empty($this->domain)){ $d['@domain'] = $this->domain; }
+ if (!empty($this->person_id)){ $d['@person_id'] = $this->person_id; }
+ if (!empty($this->id)){ $d['@source_id'] = $this->id; }
+ if (!empty($this->premium)){ $d['@premium'] = $this->premium; }
+
+ return array_merge($d, $this->fields_to_array());
+ }
+}
\ No newline at end of file
diff --git a/src/piplapis/models/fields/address.php b/src/piplapis/models/fields/address.php
new file mode 100644
index 0000000..1053d69
--- /dev/null
+++ b/src/piplapis/models/fields/address.php
@@ -0,0 +1,141 @@
+country = $country;
+ }
+ if (!empty($state))
+ {
+ $this->state = $state;
+ }
+ if (!empty($city))
+ {
+ $this->city = $city;
+ }
+ if (!empty($po_box))
+ {
+ $this->po_box = $po_box;
+ }
+ if (!empty($zip_code))
+ {
+ $this->zip_code = $zip_code;
+ }
+ if (!empty($street))
+ {
+ $this->street = $street;
+ }
+ if (!empty($house))
+ {
+ $this->house = $house;
+ }
+ if (!empty($apartment))
+ {
+ $this->apartment = $apartment;
+ }
+ if (!empty($raw))
+ {
+ $this->raw = $raw;
+ }
+ if (!empty($type))
+ {
+ $this->type = $type;
+ }
+ if (!empty($display))
+ {
+ $this->display = $display;
+ }
+ }
+ public function is_sole_searchable() {
+ return (!empty($this->raw) or (!empty($this->city) and !empty($this->street) and !empty($this->house)));
+ }
+ public function is_searchable()
+ {
+ // A bool value that indicates whether the address is a valid address
+ // to search by.
+ return (!empty($this->raw) || !empty($this->city) || !empty($this->state) || !empty($this->country));
+ }
+
+ public function is_valid_country()
+ {
+ // A bool value that indicates whether the object's country is a valid
+ // country code.
+ return (!empty($this->country) &&
+ array_key_exists(strtoupper($this->country), PiplApi_Utils::$piplapi_countries));
+ }
+
+ public function is_valid_state()
+ {
+ // A bool value that indicates whether the object's state is a valid
+ // state code.
+ return ($this->is_valid_country() &&
+ array_key_exists(strtoupper($this->country), PiplApi_Utils::$piplapi_states) &&
+ !empty($this->state) &&
+ array_key_exists(strtoupper($this->state), PiplApi_Utils::$piplapi_states[strtoupper($this->country)]));
+
+ }
+
+ public function country_full()
+ {
+ // the full name of the object's country.
+
+ // $address = new PiplApi_Address(array('country' => 'FR'));
+ // print $address->country; // Outputs "FR"
+ // print $address->country_full(); // Outputs "France"
+ if (!empty($this->country))
+ {
+ $uppedcoutnry = strtoupper($this->country);
+
+ return array_key_exists($uppedcoutnry, PiplApi_Utils::$piplapi_countries) ?
+ PiplApi_Utils::$piplapi_countries[$uppedcoutnry] :
+ NULL;
+ }
+ return;
+ }
+
+ public function state_full()
+ {
+ // The full name of the object's state.
+
+ // $address = new PiplApi_Address(array('country' => 'US', 'state' => 'CO'));
+ // print $address->state; // Outputs "CO"
+ // print $address->state_full(); // Outputs "Colorado"
+
+ if ($this->is_valid_state())
+ {
+ return PiplApi_Utils::$piplapi_states[strtoupper($this->country)][strtoupper($this->state)];
+ }
+ return;
+ }
+}
+
diff --git a/src/piplapis/models/fields/date_of_birth.php b/src/piplapis/models/fields/date_of_birth.php
new file mode 100644
index 0000000..3beae1d
--- /dev/null
+++ b/src/piplapis/models/fields/date_of_birth.php
@@ -0,0 +1,142 @@
+date_range = $date_range;
+ }
+ if (!empty($display))
+ {
+ $this->display = $display;
+ }
+ }
+
+ public function is_searchable()
+ {
+ return (!empty($this->date_range));
+ }
+
+ public function age()
+ {
+ // int, the estimated age of the person.
+
+ // Note that A DOB object is based on a date-range and the exact date is
+ // usually unknown so for age calculation the the middle of the range is
+ // assumed to be the real date-of-birth.
+
+ if (!empty($this->date_range))
+ {
+ $dob = $this->date_range->middle();
+ $today = new DateTime('now', new DateTimeZone('GMT'));
+
+ $diff = $today->format('Y') - $dob->format('Y');
+
+ if ($dob->format('z') > $today->format('z'))
+ {
+ $diff -= 1;
+ }
+
+ return $diff;
+ }
+ return;
+ }
+
+ public function age_range()
+ {
+ // An array of two ints - the minimum and maximum age of the person.
+ if (empty($this->date_range)){
+ return array(NULL, NULL);
+ }
+ if(empty($this->date_range->start) || empty($this->date_range->end)){
+ return array($this->age(), $this->age());
+ }
+
+ $start_date = new PiplApi_DateRange($this->date_range->start, $this->date_range->start);
+ $end_date = new PiplApi_DateRange($this->date_range->end, $this->date_range->end);
+ $start_age = new PiplApi_DOB(array('date_range' => $start_date));
+ $start_age = $start_age->age();
+ $end_age = new PiplApi_DOB(array('date_range' => $end_date));
+ $end_age = $end_age->age();
+
+ return (array($end_age, $start_age));
+ }
+
+ public static function from_birth_year($birth_year)
+ {
+ // Take a person's birth year (int) and return a new DOB object
+ // suitable for him.
+ if (!($birth_year > 0))
+ {
+ throw new InvalidArgumentException('birth_year must be positive');
+ }
+
+ $date_range = PiplApi_DateRange::from_years_range($birth_year, $birth_year);
+ return (new PiplApi_DOB(array('date_range' => $date_range)));
+ }
+
+ public static function from_birth_date($birth_date)
+ {
+ // Take a person's birth date (Date) and return a new DOB
+ // object suitable for him.
+ if (!($birth_date <= new DateTime('now', new DateTimeZone('GMT'))))
+ {
+ throw new InvalidArgumentException('birth_date can\'t be in the future');
+ }
+
+ $date_range = new PiplApi_DateRange($birth_date, $birth_date);
+ return (new PiplApi_DOB(array('date_range' => $date_range)));
+ }
+
+ public static function from_age($age)
+ {
+ # Take a person's age (int) and return a new DOB object
+ # suitable for him.
+ return (PiplApi_DOB::from_age_range($age, $age));
+ }
+
+ public static function from_age_range($start_age, $end_age)
+ {
+ // Take a person's minimal and maximal age and return a new DOB object
+ // suitable for him.
+ if (!($start_age >= 0 && $end_age >= 0))
+ {
+ throw new InvalidArgumentException('start_age and end_age can\'t be negative');
+ }
+
+ if ($start_age > $end_age)
+ {
+ $t = $end_age;
+ $end_age = $start_age;
+ $start_age = $t;
+ }
+
+ $start_date = new DateTime('now', new DateTimeZone('GMT'));
+ $end_date = new DateTime('now', new DateTimeZone('GMT'));
+
+ $start_date->modify('-' . $end_age . ' year');
+ $start_date->modify('-1 year');
+ $start_date->modify('+1 day');
+ $end_date->modify('-' . $start_age . ' year');
+
+ $date_range = new PiplApi_DateRange($start_date, $end_date);
+ return (new PiplApi_DOB(array('date_range' => $date_range)));
+ }
+}
\ No newline at end of file
diff --git a/src/piplapis/models/fields/date_range.php b/src/piplapis/models/fields/date_range.php
new file mode 100644
index 0000000..4aea01d
--- /dev/null
+++ b/src/piplapis/models/fields/date_range.php
@@ -0,0 +1,119 @@
+start = $start;
+ }
+ if (!empty($end))
+ {
+ $this->end = $end;
+ }
+
+ if (empty($this->start) && empty($this->end))
+ {
+ throw new InvalidArgumentException('Start/End parameters missing');
+ }
+
+ if (($this->start && $this->end) && ($this->start > $this->end))
+ {
+ $t = $this->end;
+ $this->end = $this->start;
+ $this->start = $t;
+ }
+ }
+
+ public function __toString()
+ {
+ // Return a representation of the object.
+ if($this->start && $this->end) {
+ return sprintf('%s - %s', PiplApi_Utils::piplapi_date_to_str($this->start),
+ PiplApi_Utils::piplapi_date_to_str($this->end));
+ } elseif($this->start) {
+ return PiplApi_Utils::piplapi_date_to_str($this->start);
+ }
+ return PiplApi_Utils::piplapi_date_to_str($this->end);
+ }
+
+ public function is_exact()
+ {
+ // True if the object holds an exact date (start=end),
+ // False otherwise.
+ return ($this->start == $this->end);
+ }
+
+ public function middle()
+ {
+ // The middle of the date range (a DateTime object).
+ if($this->start && $this->end) {
+ $diff = ($this->end->format('U') - $this->start->format('U')) / 2;
+ $newts = $this->start->format('U') + $diff;
+ $newdate = new DateTime('@' . $newts, new DateTimeZone('GMT'));
+ return $newdate;
+ }
+ return $this->start ? $this->start : $this->end;
+ }
+
+ public function years_range()
+ {
+ // A tuple of two ints - the year of the start date and the year of the
+ // end date.
+ if(!($this->start && $this->end)){
+ return NULL;
+ }
+ return array($this->start->format('Y'), $this->end->format('Y'));
+ }
+
+ public static function from_years_range($start_year, $end_year)
+ {
+ // Transform a range of years (two ints) to a DateRange object.
+ $newstart = new DateTime($start_year . '-01-01', new DateTimeZone('GMT'));
+ $newend = new DateTime($end_year . '-12-31', new DateTimeZone('GMT'));
+ return new PiplApi_DateRange($newstart, $newend);
+ }
+
+ public static function from_array($d)
+ {
+ // Transform the dict to a DateRange object.
+ $newstart = !empty($d['start']) ? $d['start'] : NULL;
+ $newend = !empty($d['end']) ? $d['end'] : NULL;
+ if($newstart) {
+ $newstart = PiplApi_Utils::piplapi_str_to_date($newstart);
+ }
+ if($newend){
+ $newend = PiplApi_Utils::piplapi_str_to_date($newend);
+ }
+ return new PiplApi_DateRange($newstart, $newend);
+ }
+
+ public function to_array()
+ {
+ // Transform the date-range to a dict.
+ $d = array();
+ if($this->start) {
+ $d['start'] = PiplApi_Utils::piplapi_date_to_str($this->start);
+ }
+ if($this->end){
+ $d['end'] = PiplApi_Utils::piplapi_date_to_str($this->end);
+ }
+ return $d;
+ }
+}
\ No newline at end of file
diff --git a/src/piplapis/models/fields/education.php b/src/piplapis/models/fields/education.php
new file mode 100644
index 0000000..1f93270
--- /dev/null
+++ b/src/piplapis/models/fields/education.php
@@ -0,0 +1,37 @@
+degree = $degree;
+ }
+ if (!empty($school))
+ {
+ $this->school = $school;
+ }
+ if (!empty($date_range))
+ {
+ $this->date_range = $date_range;
+ }
+ if (!empty($display))
+ {
+ $this->display = $display;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/piplapis/models/fields/email.php b/src/piplapis/models/fields/email.php
new file mode 100644
index 0000000..01e571d
--- /dev/null
+++ b/src/piplapis/models/fields/email.php
@@ -0,0 +1,97 @@
+address = $address;
+ }
+ if (!empty($address_md5))
+ {
+ $this->address_md5 = $address_md5;
+ }
+ if (!empty($type))
+ {
+ $this->type = $type;
+ }
+ if (!empty($disposable)) {
+ $this->disposable = $disposable;
+ }
+ if (!empty($email_provider))
+ {
+ $this->email_provider = $email_provider;
+ }
+ }
+
+ public function is_valid_email()
+ {
+ // A bool value that indicates whether the address is a valid
+ // email address.
+
+ return (!empty($this->address) && preg_match($this->re_email, $this->address));
+ }
+
+ public function is_searchable()
+ {
+ // A bool value that indicates whether the email is a valid email
+ // to search by.
+ return !empty($this->address_md5) || $this->is_valid_email();
+ }
+
+ // Needed to catch username and domain
+ public function __get($name)
+ {
+ if (0 == strcasecmp($name, 'username'))
+ {
+ // string, the username part of the email or None if the email is
+ // invalid.
+
+ // $email = new PiplApi_Email(array('address' => 'eric@cartman.com'));
+ // print $email->username; // Outputs "eric"
+
+ if ($this->is_valid_email())
+ {
+ $all = explode('@', $this->address);
+ return $all[0];
+ }
+ }
+ else if (0 == strcasecmp($name, 'domain'))
+ {
+ // string, the domain part of the email or None if the email is
+ // invalid.
+
+ // $email = new PiplApi_Email(array('address' => 'eric@cartman.com'));
+ // print $email->domain; // Outputs "cartman.com"
+
+ if ($this->is_valid_email())
+ {
+ $all = explode('@', $this->address);
+ return $all[1];
+ }
+ }
+ return parent::__get($name);
+ }
+
+ public function __toString(){
+ return $this->address ? $this->address : "";
+ }
+}
\ No newline at end of file
diff --git a/src/piplapis/models/fields/ethnicity.php b/src/piplapis/models/fields/ethnicity.php
new file mode 100644
index 0000000..0e9bc4f
--- /dev/null
+++ b/src/piplapis/models/fields/ethnicity.php
@@ -0,0 +1,33 @@
+content = $content;
+ }
+ }
+
+ public function __toString()
+ {
+ return $this->content ? ucwords(str_replace("_", " ", $this->content)) : "";
+ }
+}
\ No newline at end of file
diff --git a/src/piplapis/models/fields/field.php b/src/piplapis/models/fields/field.php
new file mode 100644
index 0000000..053eee2
--- /dev/null
+++ b/src/piplapis/models/fields/field.php
@@ -0,0 +1,265 @@
+valid_since = $valid_since;
+ }
+ if (!empty($inferred))
+ {
+ $this->inferred = $inferred;
+ }
+ // API v5
+ if (!empty($last_seen))
+ {
+ $this->last_seen = $last_seen;
+ }
+ if (!empty($current))
+ {
+ $this->current = $current;
+ }
+
+ }
+
+ public function __set($name, $val)
+ {
+ if (in_array($name, $this->attributes) ||
+ in_array($name, $this->children) ||
+ ($name == 'valid_since') ||
+ ($name == 'last_seen') ||
+ ($name == 'current') ||
+ ($name == 'inferred'))
+ {
+ if ($name == 'type')
+ {
+ $this->validate_type($val);
+ }
+ $this->internal_params[$name] = $val;
+ }
+ }
+
+ public function __get($name)
+ {
+ if (in_array($name, $this->attributes) ||
+ in_array($name, $this->children) ||
+ ($name == 'valid_since') ||
+ ($name == 'inferred') ||
+ ($name == 'current') ||
+ ($name == 'last_seen'))
+ {
+ if (array_key_exists($name, $this->internal_params))
+ {
+ return $this->internal_params[$name];
+ }
+ }
+ return NULL;
+ }
+
+ public function __isset($name)
+ {
+ return ((in_array($name, $this->attributes) ||
+ in_array($name, $this->children) ||
+ ($name == 'valid_since') || ($name == "inferred") || ($name == 'current') || ($name == "last_seen")) &&
+ array_key_exists($name, $this->internal_params));
+ }
+
+ public function __unset($name)
+ {
+ if (in_array($name, $this->attributes) ||
+ in_array($name, $this->children) ||
+ ($name == 'valid_since') || ($name == "inferred") || ($name == 'current') || ($name == "last_seen")
+ )
+ {
+ unset($this->internal_params[$name]);
+ }
+ }
+
+ public function __toString()
+ {
+ return isset($this->display) ? $this->display : "";
+ }
+
+ public function get_representation(){
+ // Return a string representation of the object.
+ $allattrs = array_merge($this->attributes, $this->children);
+ array_push($allattrs, "valid_since");
+
+ $allattrsvalues = array_map(array($this, 'internal_mapcb_buildattrslist'), $allattrs);
+
+ // $allattrsvalues is now a multidimensional array
+ $args = array_reduce($allattrsvalues, array($this, 'internal_reducecb_buildattrslist'));
+ $args = substr_replace($args, "", -2);
+
+ return get_class($this) . '(' . $args . ')';
+ }
+
+ private function internal_mapcb_buildattrslist($attr)
+ {
+ if (isset($this->internal_params[$attr]))
+ {
+ return array($attr => $this->internal_params[$attr]);
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+
+ private function internal_reducecb_buildattrslist($res, $x)
+ {
+ if (is_array($x) && count($x) > 0)
+ {
+ $keys = array_keys($x);
+ if (isset($x[$keys[0]]))
+ {
+ $val = $x[$keys[0]];
+
+ if ($val instanceof DateTime)
+ {
+ $val = PiplApi_Utils::piplapi_datetime_to_str($val);
+ }
+ else if (is_array($val))
+ {
+ $val = '[' . implode(', ', $val) . ']';
+ }
+ else
+ {
+ $val = (string)$val;
+ }
+
+ $newval = $keys[0] . '=' . $val . ', ';
+ // This is a bit messy, but gets around the weird fact that array_reduce
+ // can only accept an initial integer.
+ if (empty($res))
+ {
+ $res = $newval;
+ }
+ else
+ {
+ $res .= $newval;
+ }
+ }
+ }
+ return $res;
+ }
+
+ public function validate_type($type)
+ {
+ // Take an string `type` and raise an InvalidArgumentException if it's not
+ // a valid type for the object.
+
+ // A valid type for a field is a value from the types_set attribute of
+ // that field's class.
+
+ if (!empty($type) && !in_array($type, $this->types_set))
+ {
+ throw new InvalidArgumentException('Invalid type for ' . get_class($this) . ' ' . $type);
+ }
+ }
+
+ public static function from_array($clsname, $d)
+ {
+ // Transform the dict to a field object and return the field.
+ $newdict = array();
+
+ foreach ($d as $key => $val)
+ {
+ if (PiplApi_Utils::piplapi_string_startswith($key, '@'))
+ {
+ $key = substr($key, 1);
+ }
+
+ if ($key == 'last_seen')
+ {
+ $val = PiplApi_Utils::piplapi_str_to_datetime($val);
+ }
+
+ if ($key == 'valid_since')
+ {
+ $val = PiplApi_Utils::piplapi_str_to_datetime($val);
+ }
+
+ if ($key == 'date_range')
+ {
+ // PiplApi_DateRange has its own from_array implementation
+ $val = PiplApi_DateRange::from_array($val);
+ }
+
+ $newdict[$key] = $val;
+ }
+
+ return new $clsname($newdict);
+ }
+
+ private function internal_mapcb_attrsarr($attr)
+ {
+ return array($attr => '@');
+ }
+
+ private function internal_mapcb_childrenarr($attr)
+ {
+ return array($attr => '');
+ }
+
+ public function to_array()
+ {
+ // Return a dict representation of the field.
+ $d = array();
+ if (!empty($this->valid_since))
+ {
+ $d['@valid_since'] = PiplApi_Utils::piplapi_datetime_to_str($this->valid_since);
+ }
+ if (!empty($this->last_seen))
+ {
+ $d['@last_seen'] = PiplApi_Utils::piplapi_datetime_to_str($this->last_seen);
+ }
+ $newattr = array_map(array($this, "internal_mapcb_attrsarr"), $this->attributes);
+ $newchild = array_map(array($this, "internal_mapcb_childrenarr"), $this->children);
+
+ // $newattr and $newchild are multidimensionals- this is used to iterate over them
+ // we first merge the two arrays and then create an iterator that flattens them
+ $it = new RecursiveIteratorIterator(new RecursiveArrayIterator(array_merge($newattr, $newchild)));
+
+ foreach ($it as $key => $prefix)
+ {
+ if (array_key_exists($key, $this->internal_params))
+ {
+ $value = $this->internal_params[$key];
+
+ if (isset($value) && is_object($value) && method_exists($value, 'to_array'))
+ {
+ $value = $value->to_array();
+ }
+
+ if (isset($value))
+ {
+ $d[$prefix . $key] = $value;
+ }
+ }
+ }
+
+ return $d;
+ }
+
+ public function is_searchable(){
+ return true;
+ }
+}
+
diff --git a/src/piplapis/models/fields/gender.php b/src/piplapis/models/fields/gender.php
new file mode 100644
index 0000000..66b89b0
--- /dev/null
+++ b/src/piplapis/models/fields/gender.php
@@ -0,0 +1,29 @@
+content = $content;
+ }
+ }
+
+ public function __toString()
+ {
+ return $this->content ? ucwords($this->content) : "";
+ }
+
+}
\ No newline at end of file
diff --git a/src/piplapis/models/fields/image.php b/src/piplapis/models/fields/image.php
new file mode 100644
index 0000000..1aadb47
--- /dev/null
+++ b/src/piplapis/models/fields/image.php
@@ -0,0 +1,82 @@
+url = $url;
+ }
+ if (!empty($thumbnail_token))
+ {
+ $this->thumbnail_token = $thumbnail_token;
+ }
+ }
+
+ public function is_valid_url()
+ {
+ // A bool value that indicates whether the image URL is a valid URL.
+ return (!empty($this->url) && PiplApi_Utils::piplapi_is_valid_url($this->url));
+ }
+ public function get_thumbnail_url($width=100, $height=100, $zoom_face=true, $favicon=true, $use_https=false){
+ if(!empty($this->thumbnail_token)){
+ return self::generate_redundant_thumbnail_url($this);
+ }
+ return NULL;
+ }
+ public static function generate_redundant_thumbnail_url($first_image, $second_image=NULL, $width=100, $height=100,
+ $zoom_face=true, $favicon=true, $use_https=false){
+ if (empty($first_image) && empty($second_image))
+ throw new InvalidArgumentException('Please provide at least one image');
+
+
+ if ((!empty($first_image) && !($first_image instanceof PiplApi_Image)) ||
+ (!empty($second_image) && !($second_image instanceof PiplApi_Image)))
+ {
+ throw new InvalidArgumentException('Please provide PiplApi_Image Object');
+ }
+
+ $images = array();
+
+ if (!empty($first_image->thumbnail_token))
+ $images[] = $first_image->thumbnail_token;
+
+ if (!empty($second_image->thumbnail_token))
+ $images[] = $second_image->thumbnail_token;
+
+ if (empty($images))
+ throw new InvalidArgumentException("You can only generate thumbnail URLs for image objects with a thumbnail token.");
+
+ if (sizeof($images) == 1)
+ $tokens = $images[0];
+ else {
+ foreach ($images as $key=>$token) {
+ $images[$key] = preg_replace("/&dsid=\d+/i","", $token);
+ }
+ $tokens = join(",", array_values($images));
+ }
+
+ $prefix = $use_https ? "https" : "http";
+ $params = array("width" => $width, "height" => $height, "zoom_face" => $zoom_face, "favicon" => $favicon);
+ $url = $prefix . "://thumb.pipl.com/image?tokens=" . $tokens . "&" . http_build_query($params);
+ return $url;
+ }
+ public function __toString(){
+ return $this->url;
+ }
+}
\ No newline at end of file
diff --git a/src/piplapis/models/fields/job.php b/src/piplapis/models/fields/job.php
new file mode 100644
index 0000000..c6fb841
--- /dev/null
+++ b/src/piplapis/models/fields/job.php
@@ -0,0 +1,43 @@
+title = $title;
+ }
+ if (!empty($organization))
+ {
+ $this->organization = $organization;
+ }
+ if (!empty($industry))
+ {
+ $this->industry = $industry;
+ }
+ if (!empty($display))
+ {
+ $this->display = $display;
+ }
+ if (!empty($date_range))
+ {
+ $this->date_range = $date_range;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/piplapis/models/fields/language.php b/src/piplapis/models/fields/language.php
new file mode 100644
index 0000000..3a41bb6
--- /dev/null
+++ b/src/piplapis/models/fields/language.php
@@ -0,0 +1,34 @@
+language = $language;
+ }
+ if (!empty($display))
+ {
+ $this->display = $display;
+ }
+ if (!empty($region))
+ {
+ $this->region = $region;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/piplapis/models/fields/name.php b/src/piplapis/models/fields/name.php
new file mode 100644
index 0000000..ef3b5d5
--- /dev/null
+++ b/src/piplapis/models/fields/name.php
@@ -0,0 +1,75 @@
+prefix = $prefix;
+ }
+ if (!empty($first))
+ {
+ $this->first = $first;
+ }
+ if (!empty($middle))
+ {
+ $this->middle = $middle;
+ }
+ if (!empty($last))
+ {
+ $this->last = $last;
+ }
+ if (!empty($suffix))
+ {
+ $this->suffix = $suffix;
+ }
+ if (!empty($raw))
+ {
+ $this->raw = $raw;
+ }
+ if (!empty($type))
+ {
+ $this->type = $type;
+ }
+ if (!empty($display))
+ {
+ $this->display = $display;
+ }
+ }
+
+ public function is_searchable()
+ {
+ // A bool value that indicates whether the name is a valid name to
+ // search by.
+ $first = PiplApi_Utils::piplapi_alpha_chars(!empty($this->first) ? $this->first : '');
+ $last = PiplApi_Utils::piplapi_alpha_chars(!empty($this->last) ? $this->last : '');
+ $raw = PiplApi_Utils::piplapi_alpha_chars(!empty($this->raw) ? $this->raw : '');
+
+ $func = function_exists("mb_strlen") ? "mb_strlen" : "strlen";
+ return ($func($first) >= 2 && $func($last) >= 2) || $func($raw) >= 4;
+ }
+}
+
diff --git a/src/piplapis/models/fields/origin_country.php b/src/piplapis/models/fields/origin_country.php
new file mode 100644
index 0000000..545685e
--- /dev/null
+++ b/src/piplapis/models/fields/origin_country.php
@@ -0,0 +1,33 @@
+country = $country;
+ }
+ }
+
+ public function __toString(){
+ if (!empty($this->country))
+ {
+ $uppedcoutnry = strtoupper($this->country);
+ return array_key_exists($uppedcoutnry, PiplApi_Utils::$piplapi_countries) ?
+ PiplApi_Utils::$piplapi_countries[$uppedcoutnry] : NULL;
+ }
+ return "";
+ }
+}
+
diff --git a/src/piplapis/models/fields/phone.php b/src/piplapis/models/fields/phone.php
new file mode 100644
index 0000000..de0ba48
--- /dev/null
+++ b/src/piplapis/models/fields/phone.php
@@ -0,0 +1,65 @@
+country_code = $country_code;
+ }
+ if (!empty($number))
+ {
+ $this->number = $number;
+ }
+ if (!empty($extension))
+ {
+ $this->extension = $extension;
+ }
+ if (!empty($raw))
+ {
+ $this->raw = $raw;
+ }
+ if (!empty($type))
+ {
+ $this->type = $type;
+ }
+ if (!empty($display))
+ {
+ $this->display = $display;
+ }
+ if (!empty($display_international))
+ {
+ $this->display_international = $display_international;
+ }
+ }
+
+ public function is_searchable()
+ {
+ // A bool value that indicates whether the phone is a valid phone
+ // to search by.
+ return (!empty($this->raw) || (!empty($this->number) && (empty($this->country_code) || $this->country_code == 1)));
+ }
+
+ public static function from_text($text)
+ {
+ return new PiplApi_Phone(array('raw' => $text));
+ }
+
+}
+
diff --git a/src/piplapis/models/fields/tag.php b/src/piplapis/models/fields/tag.php
new file mode 100644
index 0000000..a74df36
--- /dev/null
+++ b/src/piplapis/models/fields/tag.php
@@ -0,0 +1,39 @@
+content = $content;
+ }
+ if (!empty($classification))
+ {
+ $this->classification = $classification;
+ }
+ }
+
+ public function __toString()
+ {
+ return $this->content;
+ }
+}
\ No newline at end of file
diff --git a/src/piplapis/models/fields/url.php b/src/piplapis/models/fields/url.php
new file mode 100644
index 0000000..298a83f
--- /dev/null
+++ b/src/piplapis/models/fields/url.php
@@ -0,0 +1,73 @@
+url = $url;
+ }
+ if (!empty($category))
+ {
+ $this->category = $category;
+ }
+ if (!empty($source_id))
+ {
+ $this->source_id = $source_id;
+ }
+ if (!empty($name))
+ {
+ $this->name = $name;
+ }
+ if (!empty($domain))
+ {
+ $this->domain = $domain;
+ }
+ if (!empty($sponsored))
+ {
+ $this->sponsored = $sponsored;
+ }
+ }
+
+ public function is_valid_url()
+ {
+ // A bool value that indicates whether the URL is a valid URL.
+ return (!empty($this->url) && PiplApi_Utils::piplapi_is_valid_url($this->url));
+ }
+
+ public function is_searchable()
+ {
+ return (!empty($this->url));
+ }
+
+ public function __toString(){
+ return $this->url ? $this->url : $this->name;
+ }
+}
+
+
+
+
+
+
diff --git a/src/piplapis/models/fields/user_id.php b/src/piplapis/models/fields/user_id.php
new file mode 100644
index 0000000..d53104d
--- /dev/null
+++ b/src/piplapis/models/fields/user_id.php
@@ -0,0 +1,38 @@
+content = $content;
+ }
+ }
+
+ public function is_searchable()
+ {
+ return (!empty($this->content)) && preg_match('/(.)@(.)/', $this->content);
+ }
+
+ public function __toString(){
+ return $this->content;
+ }
+}
\ No newline at end of file
diff --git a/src/piplapis/models/fields/username.php b/src/piplapis/models/fields/username.php
new file mode 100644
index 0000000..d489ac7
--- /dev/null
+++ b/src/piplapis/models/fields/username.php
@@ -0,0 +1,42 @@
+content = $content;
+ }
+ }
+
+ public function is_searchable()
+ {
+ // A bool value that indicates whether the username is a valid username
+ // to search by.
+ $st = !empty($this->content) ? $this->content : '';
+ $clean = PiplApi_Utils::piplapi_alnum_chars($st);
+ $func = function_exists("mb_strlen") ? "mb_strlen" : "strlen";
+ return ($func($clean) >= 3);
+ }
+
+ public function __toString(){
+ return $this->content;
+ }
+}
\ No newline at end of file
diff --git a/src/piplapis/models/request.php b/src/piplapis/models/request.php
new file mode 100644
index 0000000..0d6918a
--- /dev/null
+++ b/src/piplapis/models/request.php
@@ -0,0 +1,372 @@
+ 'clark.kent@example.com'));
+ // $response = $request->send();
+ //
+ // Option 2 - using the data-model (useful for more complex queries; for
+ // example, when there are multiple parameters of the same type
+ // such as few phones or a few addresses or when you'd like to use
+ // information beyond the usual identifiers such as name or email,
+ // information like education, job, relationships etc):
+ //
+ // require_once dirname(__FILE__) . '/search.php';
+ // require_once dirname(__FILE__) . '/data/fields.php';
+ // $fields = array(new PiplApi_Name(array('first' => 'Clark', 'last' => 'Kent')),
+ // new PiplApi_Address(array('country' => 'US', 'state' => 'KS', 'city' => 'Metropolis')),
+ // new PiplApi_Address(array('country' => 'US', 'state' => 'KS')),
+ // new PiplApi_Job(array('title' => 'Field Reporter')));
+ // $request = new PiplApi_SearchAPIRequest(array('person' => new PiplApi_Person(array('fields' => $fields))));
+ // $response = $request->send();
+ //
+ // Sending the request and getting the response is very simple and can be done calling $request->send().
+
+ public static $default_configuration;
+ public $person;
+ public $configuration;
+
+ public static $base_url = 'api.pipl.com/search/?';
+
+ static function set_default_configuration($configuration)
+ {
+ self::$default_configuration = $configuration;
+ }
+
+ static function get_default_configuration()
+ {
+ if (!isset(self::$default_configuration)) {
+ self::$default_configuration = new PiplApi_SearchRequestConfiguration();
+ }
+ return self::$default_configuration;
+ }
+
+ public function __construct($search_params = array(), $configuration = NULL)
+ {
+ // Initiate a new request object with given query params.
+ //
+ // Each request must have at least one searchable parameter, meaning
+ // a name (at least first and last name), email, phone or username.
+ // Multiple query params are possible (for example querying by both email
+ // and phone of the person).
+ //
+ // Args:
+ //
+ // first_name -- string, minimum 2 chars.
+ // middle_name -- string.
+ // last_name -- string, minimum 2 chars.
+ // raw_name -- string, an unparsed name containing at least a first name
+ // and a last name.
+ // email -- string.
+ // phone -- string. A raw phone number.
+ // username -- string, minimum 4 chars.
+ // country -- string, a 2 letter country code from:
+ // http://en.wikipedia.org/wiki/ISO_3166-2
+ // state -- string, a state code from:
+ // http://en.wikipedia.org/wiki/ISO_3166-2%3AUS
+ // http://en.wikipedia.org/wiki/ISO_3166-2%3ACA
+ // city -- string.
+ // raw_address -- string, an unparsed address.
+ // from_age -- int.
+ // to_age -- int.
+ // person -- A PiplApi::Person object (available at containers.php).
+ // The person can contain every field allowed by the data-model
+ // (fields.php) and can hold multiple fields of
+ // the same type (for example: two emails, three addresses etc.)
+ // search_pointer -- a pointer from a possible person, received from an API response object.
+ //
+ // Each of the arguments that should have a string that accepts both
+ // strings.
+
+ # Set default configuration
+ if (is_null(self::$default_configuration)) {
+ self::$default_configuration = new PiplApi_SearchRequestConfiguration();
+ }
+
+ $person = !empty($search_params['person']) ? $search_params['person'] : new PiplApi_Person();
+
+ if (!empty($search_params['first_name']) || !empty($search_params['middle_name']) || !empty($search_params['last_name'])) {
+ $first = !empty($search_params['first_name']) ? $search_params['first_name'] : NULL;
+ $last = !empty($search_params['last_name']) ? $search_params['last_name'] : NULL;
+ $middle = !empty($search_params['middle_name']) ? $search_params['middle_name'] : NULL;
+ $name = new PiplApi_Name(array('first' => $first, 'middle' => $middle, 'last' => $last));
+ $person->add_fields(array($name));
+ }
+
+ if (!empty($search_params['raw_name'])) {
+ $person->add_fields(array(new PiplApi_Name(array('raw' => $search_params['raw_name']))));
+ }
+
+ if (!empty($search_params['email'])) {
+ $person->add_fields(array(new PiplApi_Email(array('address' => $search_params['email']))));
+ }
+
+ if (!empty($search_params['phone'])) {
+ $person->add_fields(array(PiplApi_Phone::from_text($search_params['phone'])));
+ }
+
+ if (!empty($search_params['username'])) {
+ $person->add_fields(array(new PiplApi_Username(array('content' => $search_params['username']))));
+ }
+
+ if (!empty($search_params['user_id'])) {
+ $person->add_fields(array(new PiplApi_UserID(array('content' => $search_params['user_id']))));
+ }
+
+ if (!empty($search_params['url'])) {
+ $person->add_fields(array(new PiplApi_URL(array('url' => $search_params['url']))));
+ }
+
+ if (!empty($search_params['country']) || !empty($search_params['state']) || !empty($search_params['city'])) {
+ $country = !empty($search_params['country']) ? $search_params['country'] : NULL;
+ $state = !empty($search_params['state']) ? $search_params['state'] : NULL;
+ $city = !empty($search_params['city']) ? $search_params['city'] : NULL;
+ $address = new PiplApi_Address(array('country' => $country, 'state' => $state, 'city' => $city));
+ $person->add_fields(array($address));
+ }
+
+ if (!empty($search_params['raw_address'])) {
+ $person->add_fields(array(new PiplApi_Address(array('raw' => $search_params['raw_address']))));
+ }
+
+ if (!empty($search_params['from_age']) || !empty($search_params['to_age'])) {
+ $dob = PiplApi_DOB::from_age_range(!empty($search_params['from_age']) ? $search_params['from_age'] : 0,
+ !empty($search_params['to_age']) ? $search_params['to_age'] : 1000);
+ $person->add_fields(array($dob));
+ }
+
+ if (!empty($search_params['search_pointer'])) {
+ $person->search_pointer = $search_params['search_pointer'];
+ }
+
+ $this->person = $person;
+ $this->configuration = $configuration;
+ }
+
+ public function validate_query_params($strict = true)
+ {
+ // Check if the request is valid and can be sent, raise InvalidArgumentException if
+ // not.
+ //
+ // `strict` is a boolean argument that defaults to true which means an
+ // exception is raised on every invalid query parameter, if set to false
+ // an exception is raised only when the search request cannot be performed
+ // because required query params are missing.
+
+ if (empty($this->get_effective_configuration()->api_key)) {
+ throw new InvalidArgumentException('API key is missing');
+ }
+
+ if ($strict && (isset($this->get_effective_configuration()->show_sources) &&
+ !in_array($this->get_effective_configuration()->show_sources, array("all", "matching", "true")))
+ ) {
+ throw new InvalidArgumentException('show_sources has a wrong value, should be "matching", "all" or "true"');
+ }
+
+ if ($strict && isset($this->get_effective_configuration()->minimum_probability) &&
+ (!(is_float($this->get_effective_configuration()->minimum_probability) ||
+ (0. < $this->get_effective_configuration()->minimum_probability ||
+ $this->get_effective_configuration()->minimum_probability > 1)))
+ ) {
+ throw new InvalidArgumentException('minimum_probability should be a float between 0 and 1');
+ }
+
+ if ($strict && isset($this->get_effective_configuration()->minimum_match) &&
+ (!(is_float($this->get_effective_configuration()->minimum_match) ||
+ (0. < $this->get_effective_configuration()->minimum_match ||
+ $this->get_effective_configuration()->minimum_match > 1)))
+ ) {
+ throw new InvalidArgumentException('minimum_match should be a float between 0 and 1');
+ }
+
+ if ($strict && isset($this->get_effective_configuration()->infer_persons) &&
+ (!(is_bool($this->get_effective_configuration()->infer_persons) ||
+ is_null($this->get_effective_configuration()->infer_persons)))
+ ) {
+ throw new InvalidArgumentException('infer_persons must be true, false or null');
+ }
+
+ if ($strict && isset($this->get_effective_configuration()->top_match) &&
+ (!(is_bool($this->get_effective_configuration()->top_match) ||
+ is_null($this->get_effective_configuration()->top_match)))
+ ) {
+ throw new InvalidArgumentException('top_match must be true, false or null');
+ }
+
+ if ($strict && $unsearchable = $this->person->unsearchable_fields()) {
+ $display_strings = array_map(function($field) {
+ return $field->get_representation();
+ }, $unsearchable);
+ throw new InvalidArgumentException(sprintf('Some fields are unsearchable: %s', implode(', ', $display_strings)));
+ }
+
+ if (!$this->person->is_searchable()) {
+ throw new InvalidArgumentException('No valid name/username/phone/email/address/user_id/url in request');
+ }
+ }
+
+ public function url()
+ {
+ // The URL of the request (string).
+ return $this->get_base_url() . http_build_query($this->get_query_params());
+ }
+
+ public function send($strict_validation = true)
+ {
+ // Send the request and return the response or raise PiplApi_SearchAPIError.
+ //
+ // Calling this method blocks the program until the response is returned,
+ //
+ // The response is returned as a PiplApi_SearchAPIResponse object
+ // Also raises an PiplApi_SearchAPIError object in case of an error
+ //
+ // `strict_validation` is a bool argument that's passed to the
+ // validate_query_params method.
+ //
+ // Example:
+ //
+ // require_once dirname(__FILE__) . '/search.php';
+ // $request = new PiplApi_SearchAPIRequest(array('api_key' => 'YOUR_KEY',
+ // 'email' => 'clark.kent@example.com'));
+ // try {
+ // $response = $request->send();
+ // // All good!
+ // } catch (PiplApi_SearchAPIError $e) {
+ // print $e->getMessage();
+ // }
+
+ $this->validate_query_params($strict_validation);
+
+ $curl = curl_init();
+ $params = $this->get_query_params();
+ $url = $this->get_base_url();
+ curl_setopt_array($curl, array(
+ CURLOPT_RETURNTRANSFER => 1,
+ CURLOPT_HEADER => 1,
+ CURLOPT_VERBOSE => 0,
+ CURLOPT_URL => $url,
+ CURLOPT_USERAGENT => PiplApi_Utils::PIPLAPI_USERAGENT,
+ CURLOPT_POST => count($params),
+ CURLOPT_POSTFIELDS => $params,
+ CURLOPT_HTTPHEADER => array('Expect:')
+ ));
+ $resp = curl_exec($curl);
+
+ #https://github.com/zendframework/zend-http/issues/24
+ #https://github.com/kriswallsmith/Buzz/issues/181
+ list($header_raw, $body) = explode("\r\n\r\n", $resp, 2);
+ $headers = $this->extract_headers_from_curl($header_raw);
+
+ $http_status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
+ if (in_array($http_status, range(200, 299))) {
+ // Trying to parse header_raw from curl request
+ $res = PiplApi_SearchAPIResponse::from_array(json_decode($body, true), $headers);
+ // save the raw json to response object
+ $res->raw_json = $body;
+ return $res;
+ } elseif ($resp) {
+ $err = PiplApi_SearchAPIError::from_array(json_decode($body, true), $headers);
+ throw $err;
+ } else {
+ $err = PiplApi_SearchAPIError::from_array(
+ array("error" => curl_error($curl),
+ "warnings" => null,
+ "@http_status_code" => $http_status),
+ $headers);
+ throw $err;
+ }
+ }
+
+ private function get_effective_configuration()
+ {
+ if (is_null($this->configuration)) {
+ return self::get_default_configuration();
+ }
+ return $this->configuration;
+ }
+
+ private function get_query_params()
+ {
+
+ $query = array('key' => $this->get_effective_configuration()->api_key);
+ if ($this->person->search_pointer) {
+ $query['search_pointer'] = $this->person->search_pointer;
+ } elseif ($this->person) {
+ $query['person'] = json_encode($this->person->to_array());
+ }
+ if ($this->get_effective_configuration()->show_sources) {
+ $query['show_sources'] = $this->get_effective_configuration()->show_sources;
+ }
+ if (isset($this->get_effective_configuration()->live_feeds)) {
+ $query['live_feeds'] = $this->get_effective_configuration()->live_feeds;
+ }
+ if (isset($this->get_effective_configuration()->hide_sponsored)) {
+ $query['hide_sponsored'] = $this->get_effective_configuration()->hide_sponsored;
+ }
+ if ($this->get_effective_configuration()->minimum_probability) {
+ $query['minimum_probability'] = $this->get_effective_configuration()->minimum_probability;
+ }
+ if ($this->get_effective_configuration()->minimum_match) {
+ $query['minimum_match'] = $this->get_effective_configuration()->minimum_match;
+ }
+ if ($this->get_effective_configuration()->match_requirements) {
+ $query['match_requirements'] = $this->get_effective_configuration()->match_requirements;
+ }
+ if ($this->get_effective_configuration()->source_category_requirements) {
+ $query['source_category_requirements'] = $this->get_effective_configuration()->source_category_requirements;
+ }
+ if ($this->get_effective_configuration()->infer_persons) {
+ $query['infer_persons'] = $this->get_effective_configuration()->infer_persons;
+ }
+ if ($this->get_effective_configuration()->top_match) {
+ $query['top_match'] = $this->get_effective_configuration()->top_match;
+ }
+
+ return $query;
+ }
+
+ private function get_base_url()
+ {
+ $prefix = $this->get_effective_configuration()->use_https ? "https://" : "http://";
+ return $prefix . self::$base_url;
+ }
+
+ private function extract_headers_from_curl($header_raw)
+ {
+ $headers = array();
+ foreach (explode("\r\n", $header_raw) as $i => $line) {
+ if ($i === 0)
+ $headers['http_code'] = $line;
+ else {
+ list ($key, $value) = explode(': ', $line);
+ $key = strtolower($key);
+ $headers[$key] = $value;
+ }
+ }
+ return $headers;
+ }
+}
diff --git a/src/piplapis/models/request_configuration.php b/src/piplapis/models/request_configuration.php
new file mode 100644
index 0000000..57e3c03
--- /dev/null
+++ b/src/piplapis/models/request_configuration.php
@@ -0,0 +1,39 @@
+api_key = $api_key;
+ $this->minimum_probability = $minimum_probability;
+ $this->minimum_match = $minimum_match;
+ $this->show_sources = $show_sources;
+ $this->live_feeds = $live_feeds;
+ $this->hide_sponsored = $hide_sponsored;
+ # We are using https only.
+ $this->use_https = true;
+ $this->match_requirements = $match_requirements;
+ $this->source_category_requirements = $source_category_requirements;
+ $this->infer_persons = $infer_persons;
+ $this->top_match = $top_match;
+ }
+
+}
+
+
diff --git a/src/piplapis/models/response.php b/src/piplapis/models/response.php
new file mode 100644
index 0000000..451572f
--- /dev/null
+++ b/src/piplapis/models/response.php
@@ -0,0 +1,422 @@
+http_status_code = $http_status_code;
+ $this->visible_sources = $visible_sources;
+ $this->available_sources = $available_sources;
+ $this->search_id = $search_id;
+ $this->query = $query;
+ $this->person = $person;
+ $this->match_requirements = $match_requirements;
+ $this->source_category_requirements = $source_category_requirements;
+ $this->possible_persons = !empty($possible_persons) ? $possible_persons : array();
+ $this->sources = !empty($sources) ? $sources : array();
+ $this->warnings = !empty($warnings) ? $warnings : array();
+ $this->available_data = !empty($available_data) ? $available_data : array();
+ $this->persons_count = !empty($persons_count) ? $persons_count : (!empty($person) ? 1 : count($this->possible_persons));
+
+ // Header Parsed Parameters http://pipl.com/dev/reference/#errors
+ // qps_allotted- int | The number of queries you are allowed to do per second.
+ // qps_current- int | The number of queries you have run this second.
+ // quota_allotted- int | Your quota limit.
+ // quota_current- int | Your used quota.
+ // quota_reset- DateTime Object | The time (in UTC) that your quota will be reset.
+ // qps_live_allotted - Your permitted queries per second
+ // qps_live_current - The number of queries that you've run in the same second as this one.
+ // qps_demo_allotted - Your permitted queries per second
+ // qps_demo_current - The number of queries that you've run in the same second as this one.
+ // demo_usage_allotted - Your permitted demo queries
+ // demo_usage_current - The number of demo queries that you've already run
+ // demo_usage_expiry - The expiry time of your demo usage
+
+ $this->qps_allotted = $qps_allotted;
+ $this->qps_current = $qps_current;
+ $this->qps_live_allotted = $qps_live_allotted;
+ $this->qps_live_current = $qps_live_current;
+ $this->qps_demo_allotted = $qps_demo_allotted;
+ $this->qps_demo_current = $qps_demo_current;
+ $this->quota_allotted = $quota_allotted;
+ $this->quota_current = $quota_current;
+ $this->quota_reset = $quota_reset;
+ $this->demo_usage_allotted = $demo_usage_allotted;
+ $this->demo_usage_current = $demo_usage_current;
+ $this->demo_usage_expiry = $demo_usage_expiry;
+
+ // raw json
+ $this->raw_json = NULL;
+ }
+
+ public function group_sources($key_function)
+ {
+ // Return an array with the sources grouped by the key returned by
+ // `key_function`.
+ //
+ // `key_function` takes a source and returns the value from the source to
+ // group by (see examples in the group_sources_by_* methods below).
+ //
+ // The return value is an array, a key in this array is a key returned by
+ // `key_function` and the value is a list of all the sources with this key.
+ $new_groups = array();
+ foreach ($this->sources as $rec) {
+ $grp = $key_function($rec);
+ $new_groups[$grp][] = $rec;
+ }
+ return $new_groups;
+ }
+
+ public function group_sources_by_domain()
+ {
+ // Return the sources grouped by the domain they came from.
+ //
+ // The return value is an array, a key in this array is a domain
+ // and the value is a list of all the sources with this domain.
+
+ $key_function = function($x) {
+ return $x->domain;
+ };
+ return $this->group_sources($key_function);
+ }
+
+ public function group_sources_by_category()
+ {
+ // Return the sources grouped by their category.
+ //
+ // The return value is an array, a key in this array is a category
+ // and the value is a list of all the sources with this category.
+
+ $key_function = function($x) {
+ return $x->category;
+ };
+ return $this->group_sources($key_function);
+ }
+
+ public function group_sources_by_match()
+ {
+ // Return the sources grouped by their query_person_match attribute.
+ //
+ // The return value is an array, a key in this array is a query_person_match
+ // float and the value is a list of all the sources with this
+ // query_person_match value.
+
+ $key_function = function($x) {
+ return $x->match;
+ };
+ return $this->group_sources($key_function);
+ }
+
+ public function to_array()
+ {
+ // Return a dict representation of the response.
+ $d = array();
+
+ if (!empty($this->http_status_code)) {
+ $d['@http_status_code'] = $this->http_status_code;
+ }
+ if (!empty($this->visible_sources)) {
+ $d['@visible_sources'] = $this->visible_sources;
+ }
+ if (!empty($this->available_sources)) {
+ $d['@available_sources'] = $this->available_sources;
+ }
+ if (!empty($this->search_id)) {
+ $d['@search_id'] = $this->search_id;
+ }
+ if (!empty($this->persons_count)) {
+ $d['@persons_count'] = $this->persons_count;
+ }
+
+ if (!empty($this->warnings)) {
+ $d['warnings'] = $this->warnings;
+ }
+ if (!empty($this->query)) {
+ $d['query'] = $this->query->to_array();
+ }
+ if (!empty($this->person)) {
+ $d['person'] = $this->person->to_array();
+ }
+ if (!empty($this->possible_persons)) {
+ $d['possible_persons'] = array();
+ foreach ($this->possible_persons as $possible_person) {
+ $d['possible_persons'][] = $possible_person->to_array();
+ }
+ }
+ if (!empty($this->sources)) {
+ $d['sources'] = array();
+ foreach ($this->sources as $source) {
+ $d['sources'][] = $source->to_array();
+ }
+ }
+
+ if (!empty($this->available_data)) {
+ $d['available_data'] = $this->available_data->to_array();
+ }
+
+ if (!empty($this->match_requirements)) {
+ $d['match_requirements'] = $this->match_requirements;
+ }
+
+ return $d;
+ }
+
+ public static function from_array($d, $headers = array())
+ {
+ // Transform the array to a response object and return the response.
+ $warnings = !empty($d['warnings']) ? $d['warnings'] : array();
+ $query = NULL;
+ if (!empty($d['query'])) {
+ $query = PiplApi_Person::from_array($d['query']);
+ }
+ $person = NULL;
+ if (!empty($d['person'])) {
+ $person = PiplApi_Person::from_array($d['person']);
+ }
+
+ $sources = array();
+ if (array_key_exists("sources", $d) && count($d['sources']) > 0) {
+ foreach ($d["sources"] as $source) {
+ $sources[] = PiplApi_Source::from_array($source);
+ }
+ }
+
+ $possible_persons = array();
+ if (array_key_exists("possible_persons", $d) && count($d['possible_persons']) > 0) {
+ foreach ($d["possible_persons"] as $possible_person) {
+ $possible_persons[] = PiplApi_Person::from_array($possible_person);
+ }
+ }
+
+ // Handle headers
+
+ $qps_allotted = !empty($headers['x-qps-allotted']) ? intval($headers['x-qps-allotted']) : null;
+ $qps_current = !empty($headers['x-qps-current']) ? intval($headers['x-qps-current']) : null;
+ $quota_allotted = !empty($headers['x-apikey-quota-allotted']) ? intval($headers['x-apikey-quota-allotted']) : null;
+ $quota_current = !empty($headers['x-apikey-quota-current']) ? intval($headers['x-apikey-quota-current']) : null;
+ $quota_reset = !empty($headers['x-quota-reset']) ?
+ DateTime::createFromFormat(PiplApi_Utils::PIPLAPI_DATE_QUOTA_RESET, $headers['x-quota-reset']) : null;
+ $qps_live_allotted = !empty($headers['x-qps-live-allotted']) ? intval($headers['x-qps-live-allotted']) : null;
+ $qps_live_current = !empty($headers['x-qps-live-current']) ? intval($headers['x-qps-live-current']) : null;
+ $qps_demo_allotted = !empty($headers['x-qps-demo-allotted']) ? intval($headers['x-qps-demo-allotted']) : null;
+ $qps_demo_current = !empty($headers['x-qps-demo-current']) ? intval($headers['x-qps-demo-current']) : null;
+ $demo_usage_allotted = !empty($headers['x-demo-usage-allotted']) ? intval($headers['x-demo-usage-allotted']) : null;
+ $demo_usage_current = !empty($headers['x-demo-usage-current']) ? intval($headers['x-demo-usage-current']) : null;
+ $demo_usage_expiry = !empty($headers['x-demo-usage-expiry']) ?
+ DateTime::createFromFormat(PiplApi_Utils::PIPLAPI_DATE_QUOTA_RESET, $headers['x-demo-usage-expiry']) : null;
+
+
+ // API V5 - New attributes
+
+ $available_data = NULL;
+ if (!empty($d['available_data'])) {
+ $available_data = PiplApi_AvailableData::from_array($d['available_data']);
+ }
+
+ $match_requirements = NULL;
+ if (!empty($d['match_requirements'])) {
+ $match_requirements = $d['match_requirements'];
+ }
+
+ $source_category_requirements = NULL;
+ if (!empty($d['source_category_requirements'])) {
+ $source_category_requirements = $d['source_category_requirements'];
+ }
+
+ $persons_count = NULL;
+ if (!empty($d['@persons_count'])) {
+ $persons_count = $d['@persons_count'];
+ }
+
+ $response = new PiplApi_SearchAPIResponse($d["@http_status_code"], $query, $d["@visible_sources"],
+ $d["@available_sources"], $d["@search_id"], $warnings, $person, $possible_persons, $sources,
+ $available_data, $match_requirements, $source_category_requirements, $persons_count,
+ $qps_allotted, $qps_current, $quota_allotted, $quota_current, $quota_reset, $qps_live_allotted,
+ $qps_live_current, $qps_demo_allotted, $qps_demo_current, $demo_usage_allotted,
+ $demo_usage_current, $demo_usage_expiry);
+ return $response;
+
+ }
+
+ public function name()
+ {
+ return ($this->person && count($this->person->names) > 0) ? $this->person->names[0] : NULL;
+ }
+
+ public function address()
+ {
+ return ($this->person && count($this->person->addresses) > 0) ? $this->person->addresses[0] : NULL;
+ }
+
+ public function phone()
+ {
+ return ($this->person && count($this->person->phones) > 0) ? $this->person->phones[0] : NULL;
+ }
+
+ public function email()
+ {
+ return ($this->person && count($this->person->emails) > 0) ? $this->person->emails[0] : NULL;
+ }
+
+ public function username()
+ {
+ return ($this->person && count($this->person->usernames) > 0) ? $this->person->usernames[0] : NULL;
+ }
+
+ public function user_id()
+ {
+ return ($this->person && count($this->person->user_ids) > 0) ? $this->person->user_ids[0] : NULL;
+ }
+
+ public function dob()
+ {
+ return ($this->person && $this->person->dob) ? $this->person->dob : NULL;
+ }
+
+ public function image()
+ {
+ return ($this->person && count($this->person->images) > 0) ? $this->person->images[0] : NULL;
+ }
+
+ public function job()
+ {
+ return ($this->person && count($this->person->jobs) > 0) ? $this->person->jobs[0] : NULL;
+ }
+
+ public function education()
+ {
+ return ($this->person && count($this->person->educations) > 0) ? $this->person->educations[0] : NULL;
+ }
+
+ public function gender()
+ {
+ return ($this->person && $this->person->gender) ? $this->person->gender : NULL;
+ }
+
+ public function ethnicity()
+ {
+ return ($this->person && count($this->person->ethnicities) > 0) ? $this->person->ethnicities[0] : NULL;
+ }
+
+ public function language()
+ {
+ return ($this->person && count($this->person->languages) > 0) ? $this->person->languages[0] : NULL;
+ }
+
+ public function origin_country()
+ {
+ return ($this->person && count($this->person->origin_countries) > 0) ? $this->person->origin_countries[0] : NULL;
+ }
+
+ public function relationship()
+ {
+ return ($this->person && count($this->person->relationships) > 0) ? $this->person->relationships[0] : NULL;
+ }
+
+ public function url()
+ {
+ return ($this->person && count($this->person->urls) > 0) ? $this->person->urls[0] : NULL;
+ }
+
+ /**
+ * Specify data which should be serialized to JSON
+ * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
+ * @return mixed data which can be serialized by json_encode,
+ * which is a value of any type other than a resource.
+ * @since 5.4.0
+ */
+ function jsonSerialize()
+ {
+ return $this->to_array();
+ }
+}
diff --git a/src/piplapis/models/search_api_error.php b/src/piplapis/models/search_api_error.php
new file mode 100644
index 0000000..ccb5453
--- /dev/null
+++ b/src/piplapis/models/search_api_error.php
@@ -0,0 +1,10 @@
+
+ array('WA'=> 'Washington', 'VA'=> 'Virginia', 'DE'=> 'Delaware', 'DC'=> 'District Of Columbia', 'WI'=> 'Wisconsin', 'WV'=> 'West Virginia', 'HI'=> 'Hawaii', 'FL'=> 'Florida', 'YT'=> 'Yukon', 'WY'=> 'Wyoming', 'PR'=> 'Puerto Rico', 'NJ'=> 'New Jersey', 'NM'=> 'New Mexico', 'TX'=> 'Texas', 'LA'=> 'Louisiana', 'NC'=> 'North Carolina', 'ND'=> 'North Dakota', 'NE'=> 'Nebraska', 'FM'=> 'Federated States Of Micronesia', 'TN'=> 'Tennessee', 'NY'=> 'New York', 'PA'=> 'Pennsylvania', 'CT'=> 'Connecticut', 'RI'=> 'Rhode Island', 'NV'=> 'Nevada', 'NH'=> 'New Hampshire', 'GU'=> 'Guam', 'CO'=> 'Colorado', 'VI'=> 'Virgin Islands', 'AK'=> 'Alaska', 'AL'=> 'Alabama', 'AS'=> 'American Samoa', 'AR'=> 'Arkansas', 'VT'=> 'Vermont', 'IL'=> 'Illinois', 'GA'=> 'Georgia', 'IN'=> 'Indiana', 'IA'=> 'Iowa', 'MA'=> 'Massachusetts', 'AZ'=> 'Arizona', 'CA'=> 'California', 'ID'=> 'Idaho', 'PW'=> 'Pala', 'ME'=> 'Maine', 'MD'=> 'Maryland', 'OK'=> 'Oklahoma', 'OH'=> 'Ohio', 'UT'=> 'Utah', 'MO'=> 'Missouri', 'MN'=> 'Minnesota', 'MI'=> 'Michigan', 'MH'=> 'Marshall Islands', 'KS'=> 'Kansas', 'MT'=> 'Montana', 'MP'=> 'Northern Mariana Islands', 'MS'=> 'Mississippi', 'SC'=> 'South Carolina', 'KY'=> 'Kentucky', 'OR'=> 'Oregon', 'SD'=> 'South Dakota'),
- 'CA'=> array('AB'=> 'Alberta', 'BC'=> 'British Columbia', 'MB'=> 'Manitoba', 'NB'=> 'New Brunswick', 'NT'=> 'Northwest Territories', 'NS'=> 'Nova Scotia', 'NU'=> 'Nunavut', 'ON'=> 'Ontario', 'PE'=> 'Prince Edward Island', 'QC'=> 'Quebec', 'SK'=> 'Saskatchewan', 'YU'=> 'Yukon', 'NL'=> 'Newfoundland and Labrador'),
- 'AU'=> array('WA'=> 'State of Western Australia', 'SA'=> 'State of South Australia', 'NT'=> 'Northern Territory', 'VIC'=> 'State of Victoria', 'TAS'=> 'State of Tasmania', 'QLD'=> 'State of Queensland', 'NSW'=> 'State of New South Wales', 'ACT'=> 'Australian Capital Territory'),
- 'GB'=> array('WLS'=> 'Wales', 'SCT'=> 'Scotland', 'NIR'=> 'Northern Ireland', 'ENG'=> 'England')
- );
-
- public static $piplapi_countries = array(
- 'BL'=> 'Saint Barthélemy', 'BQ'=> 'Caribbean Netherlands', 'MF'=> 'Saint Martin','SS'=> 'South Sudan', 'SX'=> 'Sint Maarten', 'XK'=> "Kosovo", 'CW'=> 'Curaçao', 'RS' => 'Serbia', 'BD'=> 'Bangladesh', 'WF'=> 'Wallis And Futuna Islands', 'BF'=> 'Burkina Faso', 'PY'=> 'Paraguay', 'BA'=> 'Bosnia And Herzegovina', 'BB'=> 'Barbados', 'BE'=> 'Belgium', 'BM'=> 'Bermuda', 'BN'=> 'Brunei Darussalam', 'BO'=> 'Bolivia', 'BH'=> 'Bahrain', 'BI'=> 'Burundi', 'BJ'=> 'Benin', 'BT'=> 'Bhutan', 'JM'=> 'Jamaica', 'BV'=> 'Bouvet Island', 'BW'=> 'Botswana', 'WS'=> 'Samoa', 'BR'=> 'Brazil', 'BS'=> 'Bahamas', 'JE'=> 'Jersey', 'BY'=> 'Belarus', 'BZ'=> 'Belize', 'RU'=> 'Russian Federation', 'RW'=> 'Rwanda', 'LT'=> 'Lithuania', 'RE'=> 'Reunion', 'TM'=> 'Turkmenistan', 'TJ'=> 'Tajikistan', 'RO'=> 'Romania', 'LS'=> 'Lesotho', 'GW'=> 'Guinea-bissa', 'GU'=> 'Guam', 'GT'=> 'Guatemala', 'GS'=> 'South Georgia And South Sandwich Islands', 'GR'=> 'Greece', 'GQ'=> 'Equatorial Guinea', 'GP'=> 'Guadeloupe', 'JP'=> 'Japan', 'GY'=> 'Guyana', 'GG'=> 'Guernsey', 'GF'=> 'French Guiana', 'GE'=> 'Georgia', 'GD'=> 'Grenada', 'GB'=> 'Great Britain', 'GA'=> 'Gabon', 'GN'=> 'Guinea', 'GM'=> 'Gambia', 'GL'=> 'Greenland', 'GI'=> 'Gibraltar', 'GH'=> 'Ghana', 'OM'=> 'Oman', 'TN'=> 'Tunisia', 'JO'=> 'Jordan', 'HR'=> 'Croatia', 'HT'=> 'Haiti', 'SV'=> 'El Salvador', 'HK'=> 'Hong Kong', 'HN'=> 'Honduras', 'HM'=> 'Heard And Mcdonald Islands', 'AD'=> 'Andorra', 'PR'=> 'Puerto Rico', 'PS'=> 'Palestine', 'PW'=> 'Pala', 'PT'=> 'Portugal', 'SJ'=> 'Svalbard And Jan Mayen Islands', 'VG'=> 'Virgin Islands, British', 'AI'=> 'Anguilla', 'KP'=> 'North Korea', 'PF'=> 'French Polynesia', 'PG'=> 'Papua New Guinea', 'PE'=> 'Per', 'PK'=> 'Pakistan', 'PH'=> 'Philippines', 'PN'=> 'Pitcairn', 'PL'=> 'Poland', 'PM'=> 'Saint Pierre And Miquelon', 'ZM'=> 'Zambia', 'EH'=> 'Western Sahara', 'EE'=> 'Estonia', 'EG'=> 'Egypt', 'ZA'=> 'South Africa', 'EC'=> 'Ecuador', 'IT'=> 'Italy', 'AO'=> 'Angola', 'KZ'=> 'Kazakhstan', 'ET'=> 'Ethiopia', 'ZW'=> 'Zimbabwe', 'SA'=> 'Saudi Arabia', 'ES'=> 'Spain', 'ER'=> 'Eritrea', 'ME'=> 'Montenegro', 'MD'=> 'Moldova', 'MG'=> 'Madagascar', 'MA'=> 'Morocco', 'MC'=> 'Monaco', 'UZ'=> 'Uzbekistan', 'MM'=> 'Myanmar', 'ML'=> 'Mali', 'MO'=> 'Maca', 'MN'=> 'Mongolia', 'MH'=> 'Marshall Islands', 'US'=> 'United States', 'UM'=> 'United States Minor Outlying Islands', 'MT'=> 'Malta', 'MW'=> 'Malawi', 'MV'=> 'Maldives', 'MQ'=> 'Martinique', 'MP'=> 'Northern Mariana Islands', 'MS'=> 'Montserrat', 'NA'=> 'Namibia', 'IM'=> 'Isle Of Man', 'UG'=> 'Uganda', 'MY'=> 'Malaysia', 'MX'=> 'Mexico', 'IL'=> 'Israel', 'BG'=> 'Bulgaria', 'FR'=> 'France', 'AW'=> 'Aruba', 'AX'=> '\xc3\x85land', 'FI'=> 'Finland', 'FJ'=> 'Fiji', 'FK'=> 'Falkland Islands', 'FM'=> 'Micronesia', 'FO'=> 'Faroe Islands', 'NI'=> 'Nicaragua', 'NL'=> 'Netherlands', 'NO'=> 'Norway', 'SO'=> 'Somalia', 'NC'=> 'New Caledonia', 'NE'=> 'Niger', 'NF'=> 'Norfolk Island', 'NG'=> 'Nigeria', 'NZ'=> 'New Zealand', 'NP'=> 'Nepal', 'NR'=> 'Naur', 'NU'=> 'Niue', 'MR'=> 'Mauritania', 'CK'=> 'Cook Islands', 'CI'=> "C\xc3\xb4te D'ivoire", 'CH'=> 'Switzerland', 'CO'=> 'Colombia', 'CN'=> 'China', 'CM'=> 'Cameroon', 'CL'=> 'Chile', 'CC'=> 'Cocos (keeling) Islands', 'CA'=> 'Canada', 'CG'=> 'Congo (brazzaville)', 'CF'=> 'Central African Republic', 'CD'=> 'Congo (kinshasa)', 'CZ'=> 'Czech Republic', 'CY'=> 'Cyprus', 'CX'=> 'Christmas Island', 'CS'=> 'Serbia', 'CR'=> 'Costa Rica', 'HU'=> 'Hungary', 'CV'=> 'Cape Verde', 'CU'=> 'Cuba', 'SZ'=> 'Swaziland', 'SY'=> 'Syria', 'KG'=> 'Kyrgyzstan', 'KE'=> 'Kenya', 'SR'=> 'Suriname', 'KI'=> 'Kiribati', 'KH'=> 'Cambodia', 'KN'=> 'Saint Kitts And Nevis', 'KM'=> 'Comoros', 'ST'=> 'Sao Tome And Principe', 'SK'=> 'Slovakia', 'KR'=> 'South Korea', 'SI'=> 'Slovenia', 'SH'=> 'Saint Helena', 'KW'=> 'Kuwait', 'SN'=> 'Senegal', 'SM'=> 'San Marino', 'SL'=> 'Sierra Leone', 'SC'=> 'Seychelles', 'SB'=> 'Solomon Islands', 'KY'=> 'Cayman Islands', 'SG'=> 'Singapore', 'SE'=> 'Sweden', 'SD'=> 'Sudan', 'DO'=> 'Dominican Republic', 'DM'=> 'Dominica', 'DJ'=> 'Djibouti', 'DK'=> 'Denmark', 'DE'=> 'Germany', 'YE'=> 'Yemen', 'AT'=> 'Austria', 'DZ'=> 'Algeria', 'MK'=> 'Macedonia', 'UY'=> 'Uruguay', 'YT'=> 'Mayotte', 'MU'=> 'Mauritius', 'TZ'=> 'Tanzania', 'LC'=> 'Saint Lucia', 'LA'=> 'Laos', 'TV'=> 'Tuval', 'TW'=> 'Taiwan', 'TT'=> 'Trinidad And Tobago', 'TR'=> 'Turkey', 'LK'=> 'Sri Lanka', 'LI'=> 'Liechtenstein', 'LV'=> 'Latvia', 'TO'=> 'Tonga', 'TL'=> 'Timor-leste', 'LU'=> 'Luxembourg', 'LR'=> 'Liberia', 'TK'=> 'Tokela', 'TH'=> 'Thailand', 'TF'=> 'French Southern Lands', 'TG'=> 'Togo', 'TD'=> 'Chad', 'TC'=> 'Turks And Caicos Islands', 'LY'=> 'Libya', 'VA'=> 'Vatican City', 'AC'=> 'Ascension Island', 'VC'=> 'Saint Vincent And The Grenadines', 'AE'=> 'United Arab Emirates', 'VE'=> 'Venezuela', 'AG'=> 'Antigua And Barbuda', 'AF'=> 'Afghanistan', 'IQ'=> 'Iraq', 'VI'=> 'Virgin Islands, U.s.', 'IS'=> 'Iceland', 'IR'=> 'Iran', 'AM'=> 'Armenia', 'AL'=> 'Albania', 'VN'=> 'Vietnam', 'AN'=> 'Netherlands Antilles', 'AQ'=> 'Antarctica', 'AS'=> 'American Samoa', 'AR'=> 'Argentina', 'AU'=> 'Australia', 'VU'=> 'Vanuat', 'IO'=> 'British Indian Ocean Territory', 'IN'=> 'India', 'LB'=> 'Lebanon', 'AZ'=> 'Azerbaijan', 'IE'=> 'Ireland', 'ID'=> 'Indonesia', 'PA'=> 'Panama', 'UA'=> 'Ukraine', 'QA'=> 'Qatar', 'MZ'=> 'Mozambique'
- );
-
- public static function piplapi_date_parse_from_format($format, $date)
- {
- $returnArray = array('hour' => 0, 'minute' => 0, 'second' => 0,
- 'month' => 0, 'day' => 0, 'year' => 0);
-
- $dateArray = array();
-
- // array of valid date codes with keys for the return array as the values
- $validDateTimeCode = array('Y' => 'year', 'y' => 'year',
- 'm' => 'month', 'n' => 'month',
- 'd' => 'day', 'j' => 'day',
- 'H' => 'hour', 'G' => 'hour',
- 'i' => 'minute', 's' => 'second');
-
- /* create an array of valid keys for the return array
- * in the order that they appear in $format
- */
- for ($i = 0 ; $i <= strlen($format) - 1 ; $i++) {
- $char = substr($format, $i, 1);
-
- if (array_key_exists($char, $validDateTimeCode)) {
- $dateArray[$validDateTimeCode[$char]] = '';
- }
- }
-
- // create array of reg ex things for each date part
- $regExArray = array('.' => '\.', // escape the period
-
- // parse d first so we dont mangle the reg ex
- // day
- 'd' => '(\d{2})',
-
- // year
- 'Y' => '(\d{4})',
- 'y' => '(\d{2})',
-
- // month
- 'm' => '(\d{2})',
- 'n' => '(\d{1,2})',
-
- // day
- 'j' => '(\d{1,2})',
-
- // hour
- 'H' => '(\d{2})',
- 'G' => '(\d{1,2})',
-
- // minutes
- 'i' => '(\d{2})',
-
- // seconds
- 's' => '(\d{2})');
-
- // create a full reg ex string to parse the date with
- $regEx = str_replace(array_keys($regExArray),
- array_values($regExArray),
- $format);
-
- // Parse the date
- preg_match("#$regEx#", $date, $matches);
-
- // some checks...
- if (!is_array($matches) ||
- (count($matches) > 0 && $matches[0] != $date) ||
- sizeof($dateArray) != (sizeof($matches) - 1)) {
- return $returnArray;
- }
-
- // an iterator for the $matches array
- $i = 1;
-
- foreach ($dateArray AS $key => $value) {
- $dateArray[$key] = $matches[$i++];
-
- if (array_key_exists($key, $returnArray)) {
- $returnArray[$key] = $dateArray[$key];
- }
- }
-
- return $returnArray;
- }
-
- public static function validate_datetime($parsed)
- {
- extract($parsed);
- if (!(checkdate($month, $day, $year)))
- {
- throw new InvalidArgumentException('Invalid date/time!');
- }
- }
-
- public static function piplapi_str_to_datetime($s)
- {
- // Transform a string to a DateTime object.
- $parsed = self::piplapi_date_parse_from_format(self::PIPLAPI_TIMESTAMP_FORMAT, $s);
- self::validate_datetime($parsed);
- return new DateTime(sprintf('%04d-%02d-%02d',
- $parsed['year'],
- $parsed['month'],
- $parsed['day']
- ), new DateTimeZone('GMT'));
- }
-
- public static function piplapi_datetime_to_str($dt)
- {
- // Transform a DateTime object to a string.
- return $dt->format(self::PIPLAPI_TIMESTAMP_FORMAT);
- }
-
- public static function piplapi_str_to_date($s)
- {
- // Transform an string to a DateTime object.
- $parsed = self::piplapi_date_parse_from_format(self::PIPLAPI_DATE_FORMAT, $s);
- self::validate_datetime($parsed);
- return new DateTime(sprintf('%04d-%02d-%02d %02d:%02d:%02d',
- $parsed['year'],
- $parsed['month'],
- $parsed['day'],
- $parsed['hour'],
- $parsed['minute'],
- $parsed['second']), new DateTimeZone('GMT'));
- }
-
- public static function piplapi_date_to_str($d)
- {
- // Transform a date object to a string.
- return $d->format(self::PIPLAPI_DATE_FORMAT);
- }
-
- public static function piplapi_is_valid_url($url)
- {
- // Return true if given url is valid
- return filter_var($url, FILTER_VALIDATE_URL) !== false;
- }
-
- public static function piplapi_alpha_chars($s)
- {
- // Strip all non alphabetic characters from string
- return preg_replace('/\PL+/u', '', $s);
- }
-
- public static function piplapi_alnum_chars($s)
- {
- // Strip all non alphanumeric characters from string
- return preg_replace('/[^(\pL|\pN)]/u', '', $s);
- }
-
- public static function piplapi_string_startswith($str1, $str2)
- {
- // returns true if str1 begins with str2.
- return (0 == strncmp($str1, $str2, strlen($str2)));
- }
-
-}
-
-if (!interface_exists('JsonSerializable')) {
- interface JsonSerializable
- {
- /**
- * Returns data that can be serialized by json_encode
- *
- */
- public function jsonSerialize();
- }
+ array('WA'=> 'Washington', 'VA'=> 'Virginia', 'DE'=> 'Delaware', 'DC'=> 'District Of Columbia', 'WI'=> 'Wisconsin', 'WV'=> 'West Virginia', 'HI'=> 'Hawaii', 'FL'=> 'Florida', 'YT'=> 'Yukon', 'WY'=> 'Wyoming', 'PR'=> 'Puerto Rico', 'NJ'=> 'New Jersey', 'NM'=> 'New Mexico', 'TX'=> 'Texas', 'LA'=> 'Louisiana', 'NC'=> 'North Carolina', 'ND'=> 'North Dakota', 'NE'=> 'Nebraska', 'FM'=> 'Federated States Of Micronesia', 'TN'=> 'Tennessee', 'NY'=> 'New York', 'PA'=> 'Pennsylvania', 'CT'=> 'Connecticut', 'RI'=> 'Rhode Island', 'NV'=> 'Nevada', 'NH'=> 'New Hampshire', 'GU'=> 'Guam', 'CO'=> 'Colorado', 'VI'=> 'Virgin Islands', 'AK'=> 'Alaska', 'AL'=> 'Alabama', 'AS'=> 'American Samoa', 'AR'=> 'Arkansas', 'VT'=> 'Vermont', 'IL'=> 'Illinois', 'GA'=> 'Georgia', 'IN'=> 'Indiana', 'IA'=> 'Iowa', 'MA'=> 'Massachusetts', 'AZ'=> 'Arizona', 'CA'=> 'California', 'ID'=> 'Idaho', 'PW'=> 'Pala', 'ME'=> 'Maine', 'MD'=> 'Maryland', 'OK'=> 'Oklahoma', 'OH'=> 'Ohio', 'UT'=> 'Utah', 'MO'=> 'Missouri', 'MN'=> 'Minnesota', 'MI'=> 'Michigan', 'MH'=> 'Marshall Islands', 'KS'=> 'Kansas', 'MT'=> 'Montana', 'MP'=> 'Northern Mariana Islands', 'MS'=> 'Mississippi', 'SC'=> 'South Carolina', 'KY'=> 'Kentucky', 'OR'=> 'Oregon', 'SD'=> 'South Dakota'),
+ 'CA'=> array('AB'=> 'Alberta', 'BC'=> 'British Columbia', 'MB'=> 'Manitoba', 'NB'=> 'New Brunswick', 'NT'=> 'Northwest Territories', 'NS'=> 'Nova Scotia', 'NU'=> 'Nunavut', 'ON'=> 'Ontario', 'PE'=> 'Prince Edward Island', 'QC'=> 'Quebec', 'SK'=> 'Saskatchewan', 'YU'=> 'Yukon', 'NL'=> 'Newfoundland and Labrador'),
+ 'AU'=> array('WA'=> 'State of Western Australia', 'SA'=> 'State of South Australia', 'NT'=> 'Northern Territory', 'VIC'=> 'State of Victoria', 'TAS'=> 'State of Tasmania', 'QLD'=> 'State of Queensland', 'NSW'=> 'State of New South Wales', 'ACT'=> 'Australian Capital Territory'),
+ 'GB'=> array('WLS'=> 'Wales', 'SCT'=> 'Scotland', 'NIR'=> 'Northern Ireland', 'ENG'=> 'England')
+ );
+
+ public static $piplapi_countries = array(
+ 'BL'=> 'Saint Barthélemy', 'BQ'=> 'Caribbean Netherlands', 'MF'=> 'Saint Martin','SS'=> 'South Sudan', 'SX'=> 'Sint Maarten', 'XK'=> "Kosovo", 'CW'=> 'Curaçao', 'RS' => 'Serbia', 'BD'=> 'Bangladesh', 'WF'=> 'Wallis And Futuna Islands', 'BF'=> 'Burkina Faso', 'PY'=> 'Paraguay', 'BA'=> 'Bosnia And Herzegovina', 'BB'=> 'Barbados', 'BE'=> 'Belgium', 'BM'=> 'Bermuda', 'BN'=> 'Brunei Darussalam', 'BO'=> 'Bolivia', 'BH'=> 'Bahrain', 'BI'=> 'Burundi', 'BJ'=> 'Benin', 'BT'=> 'Bhutan', 'JM'=> 'Jamaica', 'BV'=> 'Bouvet Island', 'BW'=> 'Botswana', 'WS'=> 'Samoa', 'BR'=> 'Brazil', 'BS'=> 'Bahamas', 'JE'=> 'Jersey', 'BY'=> 'Belarus', 'BZ'=> 'Belize', 'RU'=> 'Russian Federation', 'RW'=> 'Rwanda', 'LT'=> 'Lithuania', 'RE'=> 'Reunion', 'TM'=> 'Turkmenistan', 'TJ'=> 'Tajikistan', 'RO'=> 'Romania', 'LS'=> 'Lesotho', 'GW'=> 'Guinea-bissa', 'GU'=> 'Guam', 'GT'=> 'Guatemala', 'GS'=> 'South Georgia And South Sandwich Islands', 'GR'=> 'Greece', 'GQ'=> 'Equatorial Guinea', 'GP'=> 'Guadeloupe', 'JP'=> 'Japan', 'GY'=> 'Guyana', 'GG'=> 'Guernsey', 'GF'=> 'French Guiana', 'GE'=> 'Georgia', 'GD'=> 'Grenada', 'GB'=> 'Great Britain', 'GA'=> 'Gabon', 'GN'=> 'Guinea', 'GM'=> 'Gambia', 'GL'=> 'Greenland', 'GI'=> 'Gibraltar', 'GH'=> 'Ghana', 'OM'=> 'Oman', 'TN'=> 'Tunisia', 'JO'=> 'Jordan', 'HR'=> 'Croatia', 'HT'=> 'Haiti', 'SV'=> 'El Salvador', 'HK'=> 'Hong Kong', 'HN'=> 'Honduras', 'HM'=> 'Heard And Mcdonald Islands', 'AD'=> 'Andorra', 'PR'=> 'Puerto Rico', 'PS'=> 'Palestine', 'PW'=> 'Pala', 'PT'=> 'Portugal', 'SJ'=> 'Svalbard And Jan Mayen Islands', 'VG'=> 'Virgin Islands, British', 'AI'=> 'Anguilla', 'KP'=> 'North Korea', 'PF'=> 'French Polynesia', 'PG'=> 'Papua New Guinea', 'PE'=> 'Per', 'PK'=> 'Pakistan', 'PH'=> 'Philippines', 'PN'=> 'Pitcairn', 'PL'=> 'Poland', 'PM'=> 'Saint Pierre And Miquelon', 'ZM'=> 'Zambia', 'EH'=> 'Western Sahara', 'EE'=> 'Estonia', 'EG'=> 'Egypt', 'ZA'=> 'South Africa', 'EC'=> 'Ecuador', 'IT'=> 'Italy', 'AO'=> 'Angola', 'KZ'=> 'Kazakhstan', 'ET'=> 'Ethiopia', 'ZW'=> 'Zimbabwe', 'SA'=> 'Saudi Arabia', 'ES'=> 'Spain', 'ER'=> 'Eritrea', 'ME'=> 'Montenegro', 'MD'=> 'Moldova', 'MG'=> 'Madagascar', 'MA'=> 'Morocco', 'MC'=> 'Monaco', 'UZ'=> 'Uzbekistan', 'MM'=> 'Myanmar', 'ML'=> 'Mali', 'MO'=> 'Maca', 'MN'=> 'Mongolia', 'MH'=> 'Marshall Islands', 'US'=> 'United States', 'UM'=> 'United States Minor Outlying Islands', 'MT'=> 'Malta', 'MW'=> 'Malawi', 'MV'=> 'Maldives', 'MQ'=> 'Martinique', 'MP'=> 'Northern Mariana Islands', 'MS'=> 'Montserrat', 'NA'=> 'Namibia', 'IM'=> 'Isle Of Man', 'UG'=> 'Uganda', 'MY'=> 'Malaysia', 'MX'=> 'Mexico', 'IL'=> 'Israel', 'BG'=> 'Bulgaria', 'FR'=> 'France', 'AW'=> 'Aruba', 'AX'=> '\xc3\x85land', 'FI'=> 'Finland', 'FJ'=> 'Fiji', 'FK'=> 'Falkland Islands', 'FM'=> 'Micronesia', 'FO'=> 'Faroe Islands', 'NI'=> 'Nicaragua', 'NL'=> 'Netherlands', 'NO'=> 'Norway', 'SO'=> 'Somalia', 'NC'=> 'New Caledonia', 'NE'=> 'Niger', 'NF'=> 'Norfolk Island', 'NG'=> 'Nigeria', 'NZ'=> 'New Zealand', 'NP'=> 'Nepal', 'NR'=> 'Naur', 'NU'=> 'Niue', 'MR'=> 'Mauritania', 'CK'=> 'Cook Islands', 'CI'=> "C\xc3\xb4te D'ivoire", 'CH'=> 'Switzerland', 'CO'=> 'Colombia', 'CN'=> 'China', 'CM'=> 'Cameroon', 'CL'=> 'Chile', 'CC'=> 'Cocos (keeling) Islands', 'CA'=> 'Canada', 'CG'=> 'Congo (brazzaville)', 'CF'=> 'Central African Republic', 'CD'=> 'Congo (kinshasa)', 'CZ'=> 'Czech Republic', 'CY'=> 'Cyprus', 'CX'=> 'Christmas Island', 'CS'=> 'Serbia', 'CR'=> 'Costa Rica', 'HU'=> 'Hungary', 'CV'=> 'Cape Verde', 'CU'=> 'Cuba', 'SZ'=> 'Swaziland', 'SY'=> 'Syria', 'KG'=> 'Kyrgyzstan', 'KE'=> 'Kenya', 'SR'=> 'Suriname', 'KI'=> 'Kiribati', 'KH'=> 'Cambodia', 'KN'=> 'Saint Kitts And Nevis', 'KM'=> 'Comoros', 'ST'=> 'Sao Tome And Principe', 'SK'=> 'Slovakia', 'KR'=> 'South Korea', 'SI'=> 'Slovenia', 'SH'=> 'Saint Helena', 'KW'=> 'Kuwait', 'SN'=> 'Senegal', 'SM'=> 'San Marino', 'SL'=> 'Sierra Leone', 'SC'=> 'Seychelles', 'SB'=> 'Solomon Islands', 'KY'=> 'Cayman Islands', 'SG'=> 'Singapore', 'SE'=> 'Sweden', 'SD'=> 'Sudan', 'DO'=> 'Dominican Republic', 'DM'=> 'Dominica', 'DJ'=> 'Djibouti', 'DK'=> 'Denmark', 'DE'=> 'Germany', 'YE'=> 'Yemen', 'AT'=> 'Austria', 'DZ'=> 'Algeria', 'MK'=> 'Macedonia', 'UY'=> 'Uruguay', 'YT'=> 'Mayotte', 'MU'=> 'Mauritius', 'TZ'=> 'Tanzania', 'LC'=> 'Saint Lucia', 'LA'=> 'Laos', 'TV'=> 'Tuval', 'TW'=> 'Taiwan', 'TT'=> 'Trinidad And Tobago', 'TR'=> 'Turkey', 'LK'=> 'Sri Lanka', 'LI'=> 'Liechtenstein', 'LV'=> 'Latvia', 'TO'=> 'Tonga', 'TL'=> 'Timor-leste', 'LU'=> 'Luxembourg', 'LR'=> 'Liberia', 'TK'=> 'Tokela', 'TH'=> 'Thailand', 'TF'=> 'French Southern Lands', 'TG'=> 'Togo', 'TD'=> 'Chad', 'TC'=> 'Turks And Caicos Islands', 'LY'=> 'Libya', 'VA'=> 'Vatican City', 'AC'=> 'Ascension Island', 'VC'=> 'Saint Vincent And The Grenadines', 'AE'=> 'United Arab Emirates', 'VE'=> 'Venezuela', 'AG'=> 'Antigua And Barbuda', 'AF'=> 'Afghanistan', 'IQ'=> 'Iraq', 'VI'=> 'Virgin Islands, U.s.', 'IS'=> 'Iceland', 'IR'=> 'Iran', 'AM'=> 'Armenia', 'AL'=> 'Albania', 'VN'=> 'Vietnam', 'AN'=> 'Netherlands Antilles', 'AQ'=> 'Antarctica', 'AS'=> 'American Samoa', 'AR'=> 'Argentina', 'AU'=> 'Australia', 'VU'=> 'Vanuat', 'IO'=> 'British Indian Ocean Territory', 'IN'=> 'India', 'LB'=> 'Lebanon', 'AZ'=> 'Azerbaijan', 'IE'=> 'Ireland', 'ID'=> 'Indonesia', 'PA'=> 'Panama', 'UA'=> 'Ukraine', 'QA'=> 'Qatar', 'MZ'=> 'Mozambique'
+ );
+
+ public static function piplapi_date_parse_from_format($format, $date)
+ {
+ $returnArray = array('hour' => 0, 'minute' => 0, 'second' => 0,
+ 'month' => 0, 'day' => 0, 'year' => 0);
+
+ $dateArray = array();
+
+ // array of valid date codes with keys for the return array as the values
+ $validDateTimeCode = array('Y' => 'year', 'y' => 'year',
+ 'm' => 'month', 'n' => 'month',
+ 'd' => 'day', 'j' => 'day',
+ 'H' => 'hour', 'G' => 'hour',
+ 'i' => 'minute', 's' => 'second');
+
+ /* create an array of valid keys for the return array
+ * in the order that they appear in $format
+ */
+ for ($i = 0 ; $i <= strlen($format) - 1 ; $i++) {
+ $char = substr($format, $i, 1);
+
+ if (array_key_exists($char, $validDateTimeCode)) {
+ $dateArray[$validDateTimeCode[$char]] = '';
+ }
+ }
+
+ // create array of reg ex things for each date part
+ $regExArray = array('.' => '\.', // escape the period
+
+ // parse d first so we dont mangle the reg ex
+ // day
+ 'd' => '(\d{2})',
+
+ // year
+ 'Y' => '(\d{4})',
+ 'y' => '(\d{2})',
+
+ // month
+ 'm' => '(\d{2})',
+ 'n' => '(\d{1,2})',
+
+ // day
+ 'j' => '(\d{1,2})',
+
+ // hour
+ 'H' => '(\d{2})',
+ 'G' => '(\d{1,2})',
+
+ // minutes
+ 'i' => '(\d{2})',
+
+ // seconds
+ 's' => '(\d{2})');
+
+ // create a full reg ex string to parse the date with
+ $regEx = str_replace(array_keys($regExArray),
+ array_values($regExArray),
+ $format);
+
+ // Parse the date
+ preg_match("#$regEx#", $date, $matches);
+
+ // some checks...
+ if (!is_array($matches) ||
+ (count($matches) > 0 && $matches[0] != $date) ||
+ sizeof($dateArray) != (sizeof($matches) - 1)) {
+ return $returnArray;
+ }
+
+ // an iterator for the $matches array
+ $i = 1;
+
+ foreach ($dateArray AS $key => $value) {
+ $dateArray[$key] = $matches[$i++];
+
+ if (array_key_exists($key, $returnArray)) {
+ $returnArray[$key] = $dateArray[$key];
+ }
+ }
+
+ return $returnArray;
+ }
+
+ public static function validate_datetime($parsed)
+ {
+ extract($parsed);
+ if (!(checkdate($month, $day, $year)))
+ {
+ throw new InvalidArgumentException('Invalid date/time!');
+ }
+ }
+
+ public static function piplapi_str_to_datetime($s)
+ {
+ // Transform a string to a DateTime object.
+ $parsed = self::piplapi_date_parse_from_format(self::PIPLAPI_TIMESTAMP_FORMAT, $s);
+ self::validate_datetime($parsed);
+ return new DateTime(sprintf('%04d-%02d-%02d',
+ $parsed['year'],
+ $parsed['month'],
+ $parsed['day']
+ ), new DateTimeZone('GMT'));
+ }
+
+ public static function piplapi_datetime_to_str($dt)
+ {
+ // Transform a DateTime object to a string.
+ return $dt->format(self::PIPLAPI_TIMESTAMP_FORMAT);
+ }
+
+ public static function piplapi_str_to_date($s)
+ {
+ // Transform an string to a DateTime object.
+ $parsed = self::piplapi_date_parse_from_format(self::PIPLAPI_DATE_FORMAT, $s);
+ self::validate_datetime($parsed);
+ return new DateTime(sprintf('%04d-%02d-%02d %02d:%02d:%02d',
+ $parsed['year'],
+ $parsed['month'],
+ $parsed['day'],
+ $parsed['hour'],
+ $parsed['minute'],
+ $parsed['second']), new DateTimeZone('GMT'));
+ }
+
+ public static function piplapi_date_to_str($d)
+ {
+ // Transform a date object to a string.
+ return $d->format(self::PIPLAPI_DATE_FORMAT);
+ }
+
+ public static function piplapi_is_valid_url($url)
+ {
+ // Return true if given url is valid
+ return filter_var($url, FILTER_VALIDATE_URL) !== false;
+ }
+
+ public static function piplapi_alpha_chars($s)
+ {
+ // Strip all non alphabetic characters from string
+ return preg_replace('/\PL+/u', '', $s);
+ }
+
+ public static function piplapi_alnum_chars($s)
+ {
+ // Strip all non alphanumeric characters from string
+ return preg_replace('/[^(\pL|\pN)]/u', '', $s);
+ }
+
+ public static function piplapi_string_startswith($str1, $str2)
+ {
+ // returns true if str1 begins with str2.
+ return (0 == strncmp($str1, $str2, strlen($str2)));
+ }
+
+}
+
+if (!interface_exists('JsonSerializable')) {
+ interface JsonSerializable
+ {
+ /**
+ * Returns data that can be serialized by json_encode
+ *
+ */
+ public function jsonSerialize();
+ }
}
\ No newline at end of file
diff --git a/src/piplapis/search.php b/src/piplapis/search.php
index 2bb9173..a79c671 100644
--- a/src/piplapis/search.php
+++ b/src/piplapis/search.php
@@ -12,812 +12,10 @@
//
// The classes are based on the person data-model that's implemented here in containers.php
-require_once dirname(__FILE__) . '/error.php';
-require_once dirname(__FILE__) . '/data/containers.php';
+require_once dirname(__FILE__) . '/models/search_api_error.php';
+require_once dirname(__FILE__) . '/models/request_configuration.php';
+require_once dirname(__FILE__) . '/models/request.php';
+require_once dirname(__FILE__) . '/models/response.php';
-class PiplApi_SearchRequestConfiguration
-{
- public $api_key = NULL;
- public $minimum_probability = NULL;
- public $minimum_match = NULL;
- public $show_sources = NULL;
- public $live_feeds = NULL;
- public $use_https = true;
- public $hide_sponsored = NULL;
- public $match_requirements = NULL;
- public $source_category_requirements = NULL;
- public $infer_persons = NULL;
- public $top_match = NULL;
-
- function __construct($api_key = "YOUR_KEY", $minimum_probability = NULL, $minimum_match = NULL, $show_sources = NULL,
- $live_feeds = NULL, $hide_sponsored = NULL, $use_https = true, $match_requirements = NULL,
- $source_category_requirements = NULL, $infer_persons = NULL, $top_match = NULL)
- {
- $this->api_key = $api_key;
- $this->minimum_probability = $minimum_probability;
- $this->minimum_match = $minimum_match;
- $this->show_sources = $show_sources;
- $this->live_feeds = $live_feeds;
- $this->hide_sponsored = $hide_sponsored;
- # We are using https only.
- $this->use_https = true;
- $this->match_requirements = $match_requirements;
- $this->source_category_requirements = $source_category_requirements;
- $this->infer_persons = $infer_persons;
- $this->top_match = $top_match;
- }
-
-}
-
-class PiplApi_SearchAPIRequest
-{
- // A request to Pipl's Search API.
- //
- // Building the request from the query parameters can be done in two ways:
- //
- // Option 1 - directly and quickly (for simple requests with only few
- // parameters):
- //
- // require_once dirname(__FILE__) . '/search.php';
- // $request = new PiplApi_SearchAPIRequest(array('email' => 'clark.kent@example.com'));
- // $response = $request->send();
- //
- // Option 2 - using the data-model (useful for more complex queries; for
- // example, when there are multiple parameters of the same type
- // such as few phones or a few addresses or when you'd like to use
- // information beyond the usual identifiers such as name or email,
- // information like education, job, relationships etc):
- //
- // require_once dirname(__FILE__) . '/search.php';
- // require_once dirname(__FILE__) . '/data/fields.php';
- // $fields = array(new PiplApi_Name(array('first' => 'Clark', 'last' => 'Kent')),
- // new PiplApi_Address(array('country' => 'US', 'state' => 'KS', 'city' => 'Metropolis')),
- // new PiplApi_Address(array('country' => 'US', 'state' => 'KS')),
- // new PiplApi_Job(array('title' => 'Field Reporter')));
- // $request = new PiplApi_SearchAPIRequest(array('person' => new PiplApi_Person(array('fields' => $fields))));
- // $response = $request->send();
- //
- // Sending the request and getting the response is very simple and can be done calling $request->send().
-
- public static $default_configuration;
- public $person;
- public $configuration;
-
- public static $base_url = 'api.pipl.com/search/?';
-
- static function set_default_configuration($configuration)
- {
- self::$default_configuration = $configuration;
- }
-
- static function get_default_configuration()
- {
- if (!isset(self::$default_configuration)) {
- self::$default_configuration = new PiplApi_SearchRequestConfiguration();
- }
- return self::$default_configuration;
- }
-
- public function __construct($search_params = array(), $configuration = NULL)
- {
- // Initiate a new request object with given query params.
- //
- // Each request must have at least one searchable parameter, meaning
- // a name (at least first and last name), email, phone or username.
- // Multiple query params are possible (for example querying by both email
- // and phone of the person).
- //
- // Args:
- //
- // first_name -- string, minimum 2 chars.
- // middle_name -- string.
- // last_name -- string, minimum 2 chars.
- // raw_name -- string, an unparsed name containing at least a first name
- // and a last name.
- // email -- string.
- // phone -- string. A raw phone number.
- // username -- string, minimum 4 chars.
- // country -- string, a 2 letter country code from:
- // http://en.wikipedia.org/wiki/ISO_3166-2
- // state -- string, a state code from:
- // http://en.wikipedia.org/wiki/ISO_3166-2%3AUS
- // http://en.wikipedia.org/wiki/ISO_3166-2%3ACA
- // city -- string.
- // raw_address -- string, an unparsed address.
- // from_age -- int.
- // to_age -- int.
- // person -- A PiplApi::Person object (available at containers.php).
- // The person can contain every field allowed by the data-model
- // (fields.php) and can hold multiple fields of
- // the same type (for example: two emails, three addresses etc.)
- // search_pointer -- a pointer from a possible person, received from an API response object.
- //
- // Each of the arguments that should have a string that accepts both
- // strings.
-
- # Set default configuration
- if (is_null(self::$default_configuration)) {
- self::$default_configuration = new PiplApi_SearchRequestConfiguration();
- }
-
- $person = !empty($search_params['person']) ? $search_params['person'] : new PiplApi_Person();
-
- if (!empty($search_params['first_name']) || !empty($search_params['middle_name']) || !empty($search_params['last_name'])) {
- $first = !empty($search_params['first_name']) ? $search_params['first_name'] : NULL;
- $last = !empty($search_params['last_name']) ? $search_params['last_name'] : NULL;
- $middle = !empty($search_params['middle_name']) ? $search_params['middle_name'] : NULL;
- $name = new PiplApi_Name(array('first' => $first, 'middle' => $middle, 'last' => $last));
- $person->add_fields(array($name));
- }
-
- if (!empty($search_params['raw_name'])) {
- $person->add_fields(array(new PiplApi_Name(array('raw' => $search_params['raw_name']))));
- }
-
- if (!empty($search_params['email'])) {
- $person->add_fields(array(new PiplApi_Email(array('address' => $search_params['email']))));
- }
-
- if (!empty($search_params['phone'])) {
- $person->add_fields(array(PiplApi_Phone::from_text($search_params['phone'])));
- }
-
- if (!empty($search_params['username'])) {
- $person->add_fields(array(new PiplApi_Username(array('content' => $search_params['username']))));
- }
-
- if (!empty($search_params['user_id'])) {
- $person->add_fields(array(new PiplApi_UserID(array('content' => $search_params['user_id']))));
- }
-
- if (!empty($search_params['url'])) {
- $person->add_fields(array(new PiplApi_URL(array('url' => $search_params['url']))));
- }
-
- if (!empty($search_params['country']) || !empty($search_params['state']) || !empty($search_params['city'])) {
- $country = !empty($search_params['country']) ? $search_params['country'] : NULL;
- $state = !empty($search_params['state']) ? $search_params['state'] : NULL;
- $city = !empty($search_params['city']) ? $search_params['city'] : NULL;
- $address = new PiplApi_Address(array('country' => $country, 'state' => $state, 'city' => $city));
- $person->add_fields(array($address));
- }
-
- if (!empty($search_params['raw_address'])) {
- $person->add_fields(array(new PiplApi_Address(array('raw' => $search_params['raw_address']))));
- }
-
- if (!empty($search_params['from_age']) || !empty($search_params['to_age'])) {
- $dob = PiplApi_DOB::from_age_range(!empty($search_params['from_age']) ? $search_params['from_age'] : 0,
- !empty($search_params['to_age']) ? $search_params['to_age'] : 1000);
- $person->add_fields(array($dob));
- }
-
- if (!empty($search_params['search_pointer'])) {
- $person->search_pointer = $search_params['search_pointer'];
- }
-
- $this->person = $person;
- $this->configuration = $configuration;
- }
-
- public function validate_query_params($strict = true)
- {
- // Check if the request is valid and can be sent, raise InvalidArgumentException if
- // not.
- //
- // `strict` is a boolean argument that defaults to true which means an
- // exception is raised on every invalid query parameter, if set to false
- // an exception is raised only when the search request cannot be performed
- // because required query params are missing.
-
- if (empty($this->get_effective_configuration()->api_key)) {
- throw new InvalidArgumentException('API key is missing');
- }
-
- if ($strict && (isset($this->get_effective_configuration()->show_sources) &&
- !in_array($this->get_effective_configuration()->show_sources, array("all", "matching", "true")))
- ) {
- throw new InvalidArgumentException('show_sources has a wrong value, should be "matching", "all" or "true"');
- }
-
- if ($strict && isset($this->get_effective_configuration()->minimum_probability) &&
- (!(is_float($this->get_effective_configuration()->minimum_probability) ||
- (0. < $this->get_effective_configuration()->minimum_probability ||
- $this->get_effective_configuration()->minimum_probability > 1)))
- ) {
- throw new InvalidArgumentException('minimum_probability should be a float between 0 and 1');
- }
-
- if ($strict && isset($this->get_effective_configuration()->minimum_match) &&
- (!(is_float($this->get_effective_configuration()->minimum_match) ||
- (0. < $this->get_effective_configuration()->minimum_match ||
- $this->get_effective_configuration()->minimum_match > 1)))
- ) {
- throw new InvalidArgumentException('minimum_match should be a float between 0 and 1');
- }
-
- if ($strict && isset($this->get_effective_configuration()->infer_persons) &&
- (!(is_bool($this->get_effective_configuration()->infer_persons) ||
- is_null($this->get_effective_configuration()->infer_persons)))
- ) {
- throw new InvalidArgumentException('infer_persons must be true, false or null');
- }
-
- if ($strict && isset($this->get_effective_configuration()->top_match) &&
- (!(is_bool($this->get_effective_configuration()->top_match) ||
- is_null($this->get_effective_configuration()->top_match)))
- ) {
- throw new InvalidArgumentException('top_match must be true, false or null');
- }
-
- if ($strict && $unsearchable = $this->person->unsearchable_fields()) {
- $display_strings = array_map(function($field) {
- return $field->get_representation();
- }, $unsearchable);
- throw new InvalidArgumentException(sprintf('Some fields are unsearchable: %s', implode(', ', $display_strings)));
- }
-
- if (!$this->person->is_searchable()) {
- throw new InvalidArgumentException('No valid name/username/phone/email/address/user_id/url in request');
- }
- }
-
- public function url()
- {
- // The URL of the request (string).
- return $this->get_base_url() . http_build_query($this->get_query_params());
- }
-
- public function send($strict_validation = true)
- {
- // Send the request and return the response or raise PiplApi_SearchAPIError.
- //
- // Calling this method blocks the program until the response is returned,
- //
- // The response is returned as a PiplApi_SearchAPIResponse object
- // Also raises an PiplApi_SearchAPIError object in case of an error
- //
- // `strict_validation` is a bool argument that's passed to the
- // validate_query_params method.
- //
- // Example:
- //
- // require_once dirname(__FILE__) . '/search.php';
- // $request = new PiplApi_SearchAPIRequest(array('api_key' => 'YOUR_KEY',
- // 'email' => 'clark.kent@example.com'));
- // try {
- // $response = $request->send();
- // // All good!
- // } catch (PiplApi_SearchAPIError $e) {
- // print $e->getMessage();
- // }
-
- $this->validate_query_params($strict_validation);
-
- $curl = curl_init();
- $params = $this->get_query_params();
- $url = $this->get_base_url();
- curl_setopt_array($curl, array(
- CURLOPT_RETURNTRANSFER => 1,
- CURLOPT_HEADER => 1,
- CURLOPT_VERBOSE => 0,
- CURLOPT_URL => $url,
- CURLOPT_USERAGENT => PiplApi_Utils::PIPLAPI_USERAGENT,
- CURLOPT_POST => count($params),
- CURLOPT_POSTFIELDS => $params,
- CURLOPT_HTTPHEADER => array('Expect:')
- ));
- $resp = curl_exec($curl);
-
- #https://github.com/zendframework/zend-http/issues/24
- #https://github.com/kriswallsmith/Buzz/issues/181
- list($header_raw, $body) = explode("\r\n\r\n", $resp, 2);
- $headers = $this->extract_headers_from_curl($header_raw);
-
- $http_status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
- if (in_array($http_status, range(200, 299))) {
- // Trying to parse header_raw from curl request
- $res = PiplApi_SearchAPIResponse::from_array(json_decode($body, true), $headers);
- // save the raw json to response object
- $res->raw_json = $body;
- return $res;
- } elseif ($resp) {
- $err = PiplApi_SearchAPIError::from_array(json_decode($body, true), $headers);
- throw $err;
- } else {
- $err = PiplApi_SearchAPIError::from_array(
- array("error" => curl_error($curl),
- "warnings" => null,
- "@http_status_code" => $http_status),
- $headers);
- throw $err;
- }
- }
-
- private function get_effective_configuration()
- {
- if (is_null($this->configuration)) {
- return self::get_default_configuration();
- }
- return $this->configuration;
- }
-
- private function get_query_params()
- {
-
- $query = array('key' => $this->get_effective_configuration()->api_key);
- if ($this->person->search_pointer) {
- $query['search_pointer'] = $this->person->search_pointer;
- } elseif ($this->person) {
- $query['person'] = json_encode($this->person->to_array());
- }
- if ($this->get_effective_configuration()->show_sources) {
- $query['show_sources'] = $this->get_effective_configuration()->show_sources;
- }
- if (isset($this->get_effective_configuration()->live_feeds)) {
- $query['live_feeds'] = $this->get_effective_configuration()->live_feeds;
- }
- if (isset($this->get_effective_configuration()->hide_sponsored)) {
- $query['hide_sponsored'] = $this->get_effective_configuration()->hide_sponsored;
- }
- if ($this->get_effective_configuration()->minimum_probability) {
- $query['minimum_probability'] = $this->get_effective_configuration()->minimum_probability;
- }
- if ($this->get_effective_configuration()->minimum_match) {
- $query['minimum_match'] = $this->get_effective_configuration()->minimum_match;
- }
- if ($this->get_effective_configuration()->match_requirements) {
- $query['match_requirements'] = $this->get_effective_configuration()->match_requirements;
- }
- if ($this->get_effective_configuration()->source_category_requirements) {
- $query['source_category_requirements'] = $this->get_effective_configuration()->source_category_requirements;
- }
- if ($this->get_effective_configuration()->infer_persons) {
- $query['infer_persons'] = $this->get_effective_configuration()->infer_persons;
- }
- if ($this->get_effective_configuration()->top_match) {
- $query['top_match'] = $this->get_effective_configuration()->top_match;
- }
-
- return $query;
- }
-
- private function get_base_url()
- {
- $prefix = $this->get_effective_configuration()->use_https ? "https://" : "http://";
- return $prefix . self::$base_url;
- }
-
- private function extract_headers_from_curl($header_raw)
- {
- $headers = array();
- foreach (explode("\r\n", $header_raw) as $i => $line) {
- if ($i === 0)
- $headers['http_code'] = $line;
- else {
- list ($key, $value) = explode(': ', $line);
- $key = strtolower($key);
- $headers[$key] = $value;
- }
- }
- return $headers;
- }
-}
-
-class PiplApi_SearchAPIResponse implements JsonSerializable
-{
-
- // A response comprises the three things returned as a result to your query:
- //
- // - a person (PiplApi_Person) that is the data object
- // representing all the information available for the person you were
- // looking for.
- // this object will only be returned when our identity-resolution engine is
- // convinced that the information is of the person represented by your query.
- // obviously, if the query was for "John Smith" there's no way for our
- // identity-resolution engine to know which of the hundreds of thousands of
- // people named John Smith you were referring to, therefore you can expect
- // that the response will not contain a person object.
- // on the other hand, if you search by a unique identifier such as email or
- // a combination of identifiers that only lead to one person, such as
- // "Clark Kent from Smallville, KS, US", you can expect to get
- // a response containing a single person object.
- //
- // - a list of possible persons (PiplApi_Person). If our identity-resolution
- // engine did not find a definite match, you can use this list to further
- // drill down using the persons' search_pointer field.
- //
- // - a list of sources (PiplApi_Source) that fully/partially
- // match the person from your query, if the query was for "Clark Kent from
- // Kansas US" the response might also contain sources of "Clark Kent
- // from US" (without Kansas), if you need to differentiate between sources
- // with full match to the query and partial match or if you want to get a
- // score on how likely is that source to be related to the person you are
- // searching please refer to the source's "match" field.
- //
- // the response also contains the query as it was interpreted by Pipl. This
- // part is useful for verification and debugging, if some query parameters
- // were invalid you can see in response.query that they were ignored, you can
- // also see how the name/address from your query were parsed in case you
- // passed raw_name/raw_address in the query.
-
- public $query;
- public $person;
- public $sources;
- public $possible_persons;
- public $warnings;
- public $http_status_code;
- public $visible_sources;
- public $available_sources;
- public $available_data;
- public $search_id;
- public $match_requirements;
- public $source_category_requirements;
- public $persons_count;
- public $qps_allotted;
- public $qps_current;
- public $quota_allotted;
- public $quota_current;
- public $quota_reset;
- public $raw_json;
-
- public function __construct($http_status_code, $query, $visible_sources, $available_sources, $search_id, $warnings,
- $person, $possible_persons, $sources, $available_data = NULL,
- $match_requirements = NULL, $source_category_requirements = NULL, $persons_count = NULL,
- $qps_allotted = NULL, $qps_current = NULL, $quota_allotted = NULL, $quota_current = NULL,
- $quota_reset = NULL, $qps_live_allotted = NULL, $qps_live_current = NULL,
- $qps_demo_allotted = NULL, $qps_demo_current = NULL, $demo_usage_allotted = NULL,
- $demo_usage_current = NULL, $demo_usage_expiry = NULL)
- {
- // Args:
- // http_status_code -- The resposne code. 2xx if successful.
- // query -- A PiplApi_Person object with the query as interpreted by Pipl.
- // person -- A PiplApi_Person object with data about the person in the query.
- // sources -- A list of PiplApi_Source objects with full/partial match to the query.
- // possible_persons -- An array of PiplApi_Person objects, each of these is an
- // expansion of the original query, giving additional
- // query parameters to zoom in on the right person.
- // warnings -- An array of strings. A warning is returned when the query
- // contains a non-critical error and the search can still run.
- // visible_sources -- the number of sources in response
- // available_sources -- the total number of known sources for this search
- // search_id -- a unique ID which identifies this search. Useful for debugging.
- // available_data - showing the data available for your query.
- // match_requirements: string. Shows how Pipl interpreted your match_requirements criteria.
- // source_category_requirements: string. Shows how Pipl interpreted your source_category_requirements criteria.
- // persons_count : int. The number of persons in this response.
-
- $this->http_status_code = $http_status_code;
- $this->visible_sources = $visible_sources;
- $this->available_sources = $available_sources;
- $this->search_id = $search_id;
- $this->query = $query;
- $this->person = $person;
- $this->match_requirements = $match_requirements;
- $this->source_category_requirements = $source_category_requirements;
- $this->possible_persons = !empty($possible_persons) ? $possible_persons : array();
- $this->sources = !empty($sources) ? $sources : array();
- $this->warnings = !empty($warnings) ? $warnings : array();
- $this->available_data = !empty($available_data) ? $available_data : array();
- $this->persons_count = !empty($persons_count) ? $persons_count : (!empty($person) ? 1 : count($this->possible_persons));
-
- // Header Parsed Parameters http://pipl.com/dev/reference/#errors
- // qps_allotted- int | The number of queries you are allowed to do per second.
- // qps_current- int | The number of queries you have run this second.
- // quota_allotted- int | Your quota limit.
- // quota_current- int | Your used quota.
- // quota_reset- DateTime Object | The time (in UTC) that your quota will be reset.
- // qps_live_allotted - Your permitted queries per second
- // qps_live_current - The number of queries that you've run in the same second as this one.
- // qps_demo_allotted - Your permitted queries per second
- // qps_demo_current - The number of queries that you've run in the same second as this one.
- // demo_usage_allotted - Your permitted demo queries
- // demo_usage_current - The number of demo queries that you've already run
- // demo_usage_expiry - The expiry time of your demo usage
-
- $this->qps_allotted = $qps_allotted;
- $this->qps_current = $qps_current;
- $this->qps_live_allotted = $qps_live_allotted;
- $this->qps_live_current = $qps_live_current;
- $this->qps_demo_allotted = $qps_demo_allotted;
- $this->qps_demo_current = $qps_demo_current;
- $this->quota_allotted = $quota_allotted;
- $this->quota_current = $quota_current;
- $this->quota_reset = $quota_reset;
- $this->demo_usage_allotted = $demo_usage_allotted;
- $this->demo_usage_current = $demo_usage_current;
- $this->demo_usage_expiry = $demo_usage_expiry;
-
- // raw json
- $this->raw_json = NULL;
- }
-
- public function group_sources($key_function)
- {
- // Return an array with the sources grouped by the key returned by
- // `key_function`.
- //
- // `key_function` takes a source and returns the value from the source to
- // group by (see examples in the group_sources_by_* methods below).
- //
- // The return value is an array, a key in this array is a key returned by
- // `key_function` and the value is a list of all the sources with this key.
- $new_groups = array();
- foreach ($this->sources as $rec) {
- $grp = $key_function($rec);
- $new_groups[$grp][] = $rec;
- }
- return $new_groups;
- }
-
- public function group_sources_by_domain()
- {
- // Return the sources grouped by the domain they came from.
- //
- // The return value is an array, a key in this array is a domain
- // and the value is a list of all the sources with this domain.
-
- $key_function = function($x) {
- return $x->domain;
- };
- return $this->group_sources($key_function);
- }
-
- public function group_sources_by_category()
- {
- // Return the sources grouped by their category.
- //
- // The return value is an array, a key in this array is a category
- // and the value is a list of all the sources with this category.
-
- $key_function = function($x) {
- return $x->category;
- };
- return $this->group_sources($key_function);
- }
-
- public function group_sources_by_match()
- {
- // Return the sources grouped by their query_person_match attribute.
- //
- // The return value is an array, a key in this array is a query_person_match
- // float and the value is a list of all the sources with this
- // query_person_match value.
-
- $key_function = function($x) {
- return $x->match;
- };
- return $this->group_sources($key_function);
- }
-
- public function to_array()
- {
- // Return a dict representation of the response.
- $d = array();
-
- if (!empty($this->http_status_code)) {
- $d['@http_status_code'] = $this->http_status_code;
- }
- if (!empty($this->visible_sources)) {
- $d['@visible_sources'] = $this->visible_sources;
- }
- if (!empty($this->available_sources)) {
- $d['@available_sources'] = $this->available_sources;
- }
- if (!empty($this->search_id)) {
- $d['@search_id'] = $this->search_id;
- }
- if (!empty($this->persons_count)) {
- $d['@persons_count'] = $this->persons_count;
- }
-
- if (!empty($this->warnings)) {
- $d['warnings'] = $this->warnings;
- }
- if (!empty($this->query)) {
- $d['query'] = $this->query->to_array();
- }
- if (!empty($this->person)) {
- $d['person'] = $this->person->to_array();
- }
- if (!empty($this->possible_persons)) {
- $d['possible_persons'] = array();
- foreach ($this->possible_persons as $possible_person) {
- $d['possible_persons'][] = $possible_person->to_array();
- }
- }
- if (!empty($this->sources)) {
- $d['sources'] = array();
- foreach ($this->sources as $source) {
- $d['sources'][] = $source->to_array();
- }
- }
-
- if (!empty($this->available_data)) {
- $d['available_data'] = $this->available_data->to_array();
- }
-
- if (!empty($this->match_requirements)) {
- $d['match_requirements'] = $this->match_requirements;
- }
-
- return $d;
- }
-
- public static function from_array($d, $headers = array())
- {
- // Transform the array to a response object and return the response.
- $warnings = !empty($d['warnings']) ? $d['warnings'] : array();
- $query = NULL;
- if (!empty($d['query'])) {
- $query = PiplApi_Person::from_array($d['query']);
- }
- $person = NULL;
- if (!empty($d['person'])) {
- $person = PiplApi_Person::from_array($d['person']);
- }
-
- $sources = array();
- if (array_key_exists("sources", $d) && count($d['sources']) > 0) {
- foreach ($d["sources"] as $source) {
- $sources[] = PiplApi_Source::from_array($source);
- }
- }
-
- $possible_persons = array();
- if (array_key_exists("possible_persons", $d) && count($d['possible_persons']) > 0) {
- foreach ($d["possible_persons"] as $possible_person) {
- $possible_persons[] = PiplApi_Person::from_array($possible_person);
- }
- }
-
- // Handle headers
-
- $qps_allotted = !empty($headers['x-qps-allotted']) ? intval($headers['x-qps-allotted']) : null;
- $qps_current = !empty($headers['x-qps-current']) ? intval($headers['x-qps-current']) : null;
- $quota_allotted = !empty($headers['x-apikey-quota-allotted']) ? intval($headers['x-apikey-quota-allotted']) : null;
- $quota_current = !empty($headers['x-apikey-quota-current']) ? intval($headers['x-apikey-quota-current']) : null;
- $quota_reset = !empty($headers['x-quota-reset']) ?
- DateTime::createFromFormat(PiplApi_Utils::PIPLAPI_DATE_QUOTA_RESET, $headers['x-quota-reset']) : null;
- $qps_live_allotted = !empty($headers['x-qps-live-allotted']) ? intval($headers['x-qps-live-allotted']) : null;
- $qps_live_current = !empty($headers['x-qps-live-current']) ? intval($headers['x-qps-live-current']) : null;
- $qps_demo_allotted = !empty($headers['x-qps-demo-allotted']) ? intval($headers['x-qps-demo-allotted']) : null;
- $qps_demo_current = !empty($headers['x-qps-demo-current']) ? intval($headers['x-qps-demo-current']) : null;
- $demo_usage_allotted = !empty($headers['x-demo-usage-allotted']) ? intval($headers['x-demo-usage-allotted']) : null;
- $demo_usage_current = !empty($headers['x-demo-usage-current']) ? intval($headers['x-demo-usage-current']) : null;
- $demo_usage_expiry = !empty($headers['x-demo-usage-expiry']) ?
- DateTime::createFromFormat(PiplApi_Utils::PIPLAPI_DATE_QUOTA_RESET, $headers['x-demo-usage-expiry']) : null;
-
-
- // API V5 - New attributes
-
- $available_data = NULL;
- if (!empty($d['available_data'])) {
- $available_data = PiplApi_AvailableData::from_array($d['available_data']);
- }
-
- $match_requirements = NULL;
- if (!empty($d['match_requirements'])) {
- $match_requirements = $d['match_requirements'];
- }
-
- $source_category_requirements = NULL;
- if (!empty($d['source_category_requirements'])) {
- $source_category_requirements = $d['source_category_requirements'];
- }
-
- $persons_count = NULL;
- if (!empty($d['@persons_count'])) {
- $persons_count = $d['@persons_count'];
- }
-
- $response = new PiplApi_SearchAPIResponse($d["@http_status_code"], $query, $d["@visible_sources"],
- $d["@available_sources"], $d["@search_id"], $warnings, $person, $possible_persons, $sources,
- $available_data, $match_requirements, $source_category_requirements, $persons_count,
- $qps_allotted, $qps_current, $quota_allotted, $quota_current, $quota_reset, $qps_live_allotted,
- $qps_live_current, $qps_demo_allotted, $qps_demo_current, $demo_usage_allotted,
- $demo_usage_current, $demo_usage_expiry);
- return $response;
-
- }
-
- public function name()
- {
- return ($this->person && count($this->person->names) > 0) ? $this->person->names[0] : NULL;
- }
-
- public function address()
- {
- return ($this->person && count($this->person->addresses) > 0) ? $this->person->addresses[0] : NULL;
- }
-
- public function phone()
- {
- return ($this->person && count($this->person->phones) > 0) ? $this->person->phones[0] : NULL;
- }
-
- public function email()
- {
- return ($this->person && count($this->person->emails) > 0) ? $this->person->emails[0] : NULL;
- }
-
- public function username()
- {
- return ($this->person && count($this->person->usernames) > 0) ? $this->person->usernames[0] : NULL;
- }
-
- public function user_id()
- {
- return ($this->person && count($this->person->user_ids) > 0) ? $this->person->user_ids[0] : NULL;
- }
-
- public function dob()
- {
- return ($this->person && $this->person->dob) ? $this->person->dob : NULL;
- }
-
- public function image()
- {
- return ($this->person && count($this->person->images) > 0) ? $this->person->images[0] : NULL;
- }
-
- public function job()
- {
- return ($this->person && count($this->person->jobs) > 0) ? $this->person->jobs[0] : NULL;
- }
-
- public function education()
- {
- return ($this->person && count($this->person->educations) > 0) ? $this->person->educations[0] : NULL;
- }
-
- public function gender()
- {
- return ($this->person && $this->person->gender) ? $this->person->gender : NULL;
- }
-
- public function ethnicity()
- {
- return ($this->person && count($this->person->ethnicities) > 0) ? $this->person->ethnicities[0] : NULL;
- }
-
- public function language()
- {
- return ($this->person && count($this->person->languages) > 0) ? $this->person->languages[0] : NULL;
- }
-
- public function origin_country()
- {
- return ($this->person && count($this->person->origin_countries) > 0) ? $this->person->origin_countries[0] : NULL;
- }
-
- public function relationship()
- {
- return ($this->person && count($this->person->relationships) > 0) ? $this->person->relationships[0] : NULL;
- }
-
- public function url()
- {
- return ($this->person && count($this->person->urls) > 0) ? $this->person->urls[0] : NULL;
- }
-
- /**
- * Specify data which should be serialized to JSON
- * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
- * @return mixed data which can be serialized by json_encode,
- * which is a value of any type other than a resource.
- * @since 5.4.0
- */
- function jsonSerialize()
- {
- return $this->to_array();
- }
-}
-
-class PiplApi_SearchAPIError extends PiplApi_APIError
-{
- // An exception raised when the response from the search API contains an
- // error.
-}