Facebook auth stuff.
authorCameron Ball <cameron@getapproved.com.au>
Wed, 15 Oct 2014 07:36:37 +0000 (15:36 +0800)
committerCameron Ball <cameron@getapproved.com.au>
Wed, 15 Oct 2014 07:36:37 +0000 (15:36 +0800)
22 files changed:
.gitignore
Controllers/UserAuthController.php [new file with mode: 0644]
DataAccess/DataMapper/DataMapper.php
DataAccess/DataMapper/Helpers/AbstractPopulationHelper.php
DataAccess/IUserRepository.php [new file with mode: 0644]
DataAccess/Queries/QueryBuilder.php
DataAccess/UserRepository.php [new file with mode: 0644]
Domain/Entities/IUser.php
Domain/Entities/IUserBuilder.php
Domain/Entities/User.php
Domain/Entities/UserBuilder.php
Domain/Entities/UserFactory.php
Domain/Entities/UserStepByStepBuilder.php
Domain/Util.php [new file with mode: 0644]
Services/FacebookSessionFactory.php [new file with mode: 0644]
Services/IFacebookSessionFactory.php [new file with mode: 0644]
composer.json
config/DI.php
config/DataMaps.php
config/FacebookApp.php.example [new file with mode: 0644]
config/Routes.php
public_html/index.php

index f3cc513..008e5e6 100644 (file)
@@ -4,3 +4,4 @@ composer.lock
 vendor
 db.php
 files
+FacebookApp.php
diff --git a/Controllers/UserAuthController.php b/Controllers/UserAuthController.php
new file mode 100644 (file)
index 0000000..f261547
--- /dev/null
@@ -0,0 +1,125 @@
+<?php
+
+namespace Controllers;
+
+use Domain\Util;
+use Services\Http\IHttpResponse;
+use Services\Http\IHttpRequest;
+use Services\IFacebookSessionFactory;
+use Domain\Entities\IUserStepByStepBuilder;
+use Domain\Entities\IUser;
+use DataAccess\IUserRepository;
+use Facebook\FacebookSession;
+use Facebook\FacebookRequest;
+use Facebook\GraphUser;
+use Facebook\GraphLocation;
+use Facebook\FacebookRequestException;
+
+class UserAuthController implements IDivineController
+{
+    private $_response;
+    private $_request;
+    private $_facebookSessionFactory;
+    private $_facebookSession;
+    private $_facebookRequest;
+    private $_userRepository;
+    
+    /* @var $_userStepByStepBuilder Domain\Entities\UserStepByStepBuilder */
+    private $_userStepByStepBuilder;
+    
+    //override
+    public function __construct(
+        IHttpRequest $request,
+        IHttpResponse $response,
+        IFacebookSessionFactory $facebookSessionFactory,
+        IUserRepository $userRepository,
+        IUserStepByStepBuilder $userStepByStepBuilder
+    ) {
+        $this->_request = $request;
+        $this->_response = $response;
+        $this->_facebookSessionFactory = $facebookSessionFactory;
+        $this->_userRepository = $userRepository;
+        $this->_userStepByStepBuilder = $userStepByStepBuilder;
+    }
+        
+    public function indexAction() {
+        $token = $this->validateAuthRequest();
+        $facebookSession = $this->_facebookSessionFactory->createInstance($token);
+        
+        $this->_facebookSession = $this->isSessionLongLived($facebookSession) ? $facebookSession->getLongLivedSession() : $facebookSession;
+        $this->_facebookRequest = (new FacebookRequest($this->_facebookSession, 'GET', '/me?fields=hometown,first_name,last_name'))->execute();
+        
+        $id = $this->_facebookRequest->getGraphObject(GraphUser::className())->getId();
+        
+        // If the user is not in the DB, create them.
+        $user = $this->_userRepository->findByFacebookId($id) ?: $this->registerUser();
+        // Update stored auth token if needed.
+        $this->updateAuthToken($user);
+
+        $this->_response->setHeader('Content-Type', 'application/json')
+                        ->setBody(json_encode(array('token' => $this->_facebookSession->getToken(), 'expires' => $this->getSessionExpiryTimestamp($this->_facebookSession), 'displayName' => $user->getDisplayName())))
+                        ->sendResponse();
+    }
+    
+    private function validateAuthRequest()
+    {
+        $request = $this->_request->get();
+        $response = $this->_response->setHeader('Content-Type', 'application/json');
+
+        if(!isset($request['token']))
+        {
+            $response->setBody(json_encode(array('result' => 'error', 'message' => 'missing auth token')))
+                     ->sendResponse();            
+            die();            
+        }
+        
+        return $request['token'];
+    }
+    
+    private function registerUser()
+    {
+        $userProfile = $this->_facebookRequest->getGraphObject(GraphUser::className());    
+        
+        $homeTownPageId = $userProfile->getProperty('hometown')->getProperty('id');
+        $pageRequest = (new FacebookRequest($this->_facebookSession, 'GET', '/' . $homeTownPageId ))->execute();
+        $pageLocation = $pageRequest->getGraphObject(GraphLocation::className())->getProperty('location')->cast(GraphLocation::className());
+        
+        $country = Util::countryNameFromLatLong($pageLocation->getLatitude(), $pageLocation->getLongitude());
+        $firstName = $userProfile->getFirstName();
+        $lastName = $userProfile->getLastName();
+        $facebookId = $userProfile->getId();
+        
+        //TODO: Is insantiating the VO classes here a good idea?
+        $newUser = $this->_userStepByStepBuilder->With_Country(new \Domain\VOs\Country($country))
+                                                ->With_DisplayName($firstName)
+                                                ->With_Name(new \Domain\VOs\Name($firstName, $lastName))
+                                                ->With_Tags(array())
+                                                ->With_FacebookId($facebookId)
+                                                ->build();
+        
+        $newUser->setAuthToken($this->_facebookSession->getToken());
+        
+        $this->_userRepository->save($newUser);
+        
+        return $newUser;
+    }
+    
+    private function updateAuthToken(IUser $user)
+    {
+        if($user->getAuthToken() != $this->_facebookSession->getToken())
+        {
+            $user->setAuthToken($this->_facebookSession->getToken());
+            $this->_userRepository->save($user);
+        }
+    }
+    
+    private function isSessionLongLived(FacebookSession $session)
+    {
+        return $this->getSessionExpiryTimestamp($session) - time() >= 60;
+    }
+    
+    private function getSessionExpiryTimestamp(FacebookSession $session)
+    {
+        return $session->getSessionInfo()->getExpiresAt()->format('U');
+    }
+}
index 692763b..2a8c9e6 100644 (file)
@@ -49,7 +49,7 @@ class DataMapper implements IDataMapper
             $class->setId($row['id']);\r
             $entities[$row['id']] = $class;\r
         }\r
-        \r
+\r
         return $entities;\r
     }\r
         \r
@@ -57,9 +57,53 @@ class DataMapper implements IDataMapper
     {\r
         $queries = AbstractPopulationHelper::generateUpdateSaveQuery($this->_maps, $entity, $entity->getId(), $this->_db);\r
         \r
+        $flattened = array();\r
+        $flattened_tables = array();\r
+        foreach($queries as $index => $query)\r
+        {\r
+            $this_table = $query['table'];\r
+            $this_columns = $query['columns'];\r
+            $add = false;\r
+            \r
+            for($i = $index+1; $i<count($queries); $i++)\r
+            {\r
+                if($queries[$i]['table'] == $this_table && !in_array($queries[$i]['table'], $flattened_tables) && isset($query['id'])) //only merge create queries, updates are fine to run multiple times\r
+                {\r
+                    $this_columns = array_merge($this_columns, $queries[$i]['columns']);\r
+                    $add = true;\r
+                }\r
+            }\r
+            \r
+            if(!in_array($this_table, $flattened_tables))\r
+            {\r
+                $flattened_tables[] = $this_table;\r
+                $prepared = isset($query['prepared']) ? $query['prepared'] : null;\r
+                $id = isset($query['id']) ? $query['id'] : null;\r
+                $flattened[] = array('columns' => $this_columns, 'table' => $this_table, 'prepared' => $prepared, 'id' => $id);\r
+            }\r
+        }\r
+        \r
+        $queries = array();\r
+        \r
+        foreach($flattened as $info)\r
+        {\r
+            if(isset($info['id']))\r
+            {\r
+                $query = $info['prepared'];\r
+                $query = substr($query, 0, -2);\r
+                $query .= sprintf(' WHERE id=%u', $info['id']);\r
+            } else {\r
+                $query = sprintf('INSERT INTO %s (%s) VALUES (%s)',\r
+                $info['table'],\r
+                implode(', ', array_keys($info['columns'])),\r
+                implode(', ', $info['columns']));\r
+            }\r
+            \r
+            $queries[] = $query;\r
+        }\r
+        \r
        // if($queries['TYPE'] == AbstractPopulationHelper::QUERY_TYPE_CREATE)\r
        // {\r
-            unset($queries['TYPE']);\r
             $idMap = [];\r
             foreach($queries as $index => $query)\r
             {                                \r
@@ -98,10 +142,6 @@ class DataMapper implements IDataMapper
                 $statement->execute();\r
             }\r
         //}\r
-        \r
-        echo '<pre>';\r
-        print_r($queries);\r
-        echo '</pre>';\r
     }\r
     \r
     //TODO: Implement\r
index 6f17458..034a8d6 100644 (file)
@@ -41,7 +41,7 @@ class AbstractPopulationHelper
     static function generateUpdateSaveQuery($maps, $entity, $id, $db, &$queries = array(), $extraColumns = array())\r
     {\r
         $entityMapsIndex = self::getMapsNameFromEntityObject($entity, $maps);\r
-        \r
+\r
         if($id)\r
         {\r
             $query = sprintf('update %s set ', $maps[$entityMapsIndex]['table']);    \r
@@ -113,8 +113,6 @@ class AbstractPopulationHelper
 \r
                             break;\r
                         case self::REFERENCE_BACK:\r
-                            echo 'bleh';\r
-\r
                             $voId = self::findVOInDB($maps,\r
                                 $property,\r
                                 $db,\r
@@ -221,10 +219,11 @@ class AbstractPopulationHelper
                 // in the case of setting up a new entity, the VOs should never\r
                 // exist in the first place, so we just make them.\r
                 case 'DataAccess\DataMapper\Helpers\VOArrayMapsHelper':\r
-                    if($id)\r
+                    if($id && isset($property[0]))\r
                     {\r
                         // If we assume that all elements in the array are the same then\r
                         // we can just use the first one to figure out which maps entry to use\r
+                        \r
                         $subEntityMapsIndex = self::getMapsNameFromEntityObject($property[0], $maps);\r
                         $voIds = self::mapVOArrayToIds($maps[$subEntityMapsIndex]['table'],\r
                             array(strtolower($entityMapsIndex . '_id'), $id),\r
@@ -254,22 +253,32 @@ class AbstractPopulationHelper
                     }\r
             }\r
         }\r
+//        \r
+//        if($id)\r
+//        {\r
+//            $query = substr($query, 0, -2);\r
+//            $query .= sprintf(' WHERE id=%u', $id);\r
+//            $queries['TYPE'] = self::QUERY_TYPE_UPDATE;\r
+//        } else {\r
+//            $queryColumnNamesAndValues = array_merge($queryColumnNamesAndValues, $extraColumns);\r
+//            $query = sprintf('INSERT INTO %s (%s) VALUES (%s)',\r
+//                $maps[$entityMapsIndex]['table'],\r
+//                implode(', ', array_keys($queryColumnNamesAndValues)),\r
+//                implode(', ', $queryColumnNamesAndValues));\r
+//            $queries['TYPE'] = self::QUERY_TYPE_CREATE;\r
+//        }\r
+//        print_r($queryColumnNamesAndValues);\r
+//        echo '<br />';\r
         \r
         if($id)\r
         {\r
-            $query = substr($query, 0, -2);\r
-            $query .= sprintf(' WHERE id=%u', $id);\r
-            $queries['TYPE'] = self::QUERY_TYPE_UPDATE;\r
+            $queryColumnNamesAndValues = @$queryColumnNamesAndValues ?: array();\r
+            $queries[] = array('id' => $id, 'prepared' => $query, 'table' => $maps[$entityMapsIndex]['table'], 'columns' => $queryColumnNamesAndValues);\r
         } else {\r
             $queryColumnNamesAndValues = array_merge($queryColumnNamesAndValues, $extraColumns);\r
-            $query = sprintf('INSERT INTO %s (%s) VALUES (%s)',\r
-                $maps[$entityMapsIndex]['table'],\r
-                implode(', ', array_keys($queryColumnNamesAndValues)),\r
-                implode(', ', $queryColumnNamesAndValues));\r
-            $queries['TYPE'] = self::QUERY_TYPE_CREATE;\r
+            $queries[] = array('table' => $maps[$entityMapsIndex]['table'], 'columns' => $queryColumnNamesAndValues);\r
         }\r
-        \r
-        $queries[] = $query;\r
+            \r
         return $queries;\r
     }\r
     \r
diff --git a/DataAccess/IUserRepository.php b/DataAccess/IUserRepository.php
new file mode 100644 (file)
index 0000000..f34efc5
--- /dev/null
@@ -0,0 +1,17 @@
+<?php
+
+namespace DataAccess;
+
+use DataAccess\IRepository;
+use Domain\Entities\IUser;
+
+interface IUserRepository extends IRepository
+{
+    public function findById($id);
+    public function findByAuthToken($token);
+    public function findByFacebookId($id);
+    public function save(IUser $entity);
+    public function remove(IUser $entity);
+}
+
+    
index da9bcbc..5e95a8c 100644 (file)
@@ -17,7 +17,7 @@ class QueryBuilder implements IQueryBuilder
         $this->applyJoinClauses()
              ->applyWhereClauses()
              ->applyLimitClause();
-        
+
         return $this->_queryString;
     }
     
diff --git a/DataAccess/UserRepository.php b/DataAccess/UserRepository.php
new file mode 100644 (file)
index 0000000..70fe069
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+
+namespace DataAccess;
+
+use DataAccess\IUserRepository;
+use DataAccess\DataMapper\IDataMapper;
+use Domain\Entities\IUser;
+use DataAccess\Queries\IQueryBuilderFactory;
+
+//TODO: Implement some sort of caching. Probably OK for now not to worry.
+class UserRepository implements IUserRepository
+{
+    private $_dataMapper;
+    private $_queryBuilderFactory;
+    
+    public function __construct(IDataMapper $dataMapper, IQueryBuilderFactory $queryBuilderFactory) {
+        $this->_dataMapper = $dataMapper;
+        $this->_queryBuilderFactory = $queryBuilderFactory;
+    }
+    
+    public function findById($id) {
+        $queryBuilder = $this->_queryBuilderFactory->createInstance();
+        $queryBuilder->where('id', '=', "$id");
+        
+        return $this->_dataMapper->map(
+            'User',
+            $queryBuilder
+        );
+    }
+    
+    public function findRange($id, $limit)
+    {
+        return $this->_dataMapper->findRange(
+            'User',
+            'SELECT * FROM %s WHERE id>=' . $id . ' LIMIT ' . $limit
+        );
+    }
+    
+    public function findByFacebookId($id) {
+        $queryBuilder = $this->_queryBuilderFactory->createInstance();
+        $queryBuilder->where('facebook_id', '=', "$id");
+        
+        $results = $this->_dataMapper->map(
+                    'User',
+                    $queryBuilder
+                   );
+                
+        return reset($results);
+    }
+    
+    public function findByAuthToken($token) {
+        return $this->_dataMapper->map(
+            'User',
+            'SELECT * FROM %s WHERE auth_token=' . $token
+        );
+    }
+    
+    public function save(IUser $entity) {
+        $this->_dataMapper->save($entity);
+    }
+    
+    //TODO: Implement
+    public function remove(IUser $entity) {
+        ;
+    }
+    
+}
index 3bbc462..143afc8 100644 (file)
@@ -11,4 +11,8 @@ interface IUser
     public function getCountry();\r
     public function getDisplayName();\r
     public function getYearsStepArtist();\r
+    public function getFacebookId();\r
+    public function setFacebookId($id);\r
+    public function getAuthToken();\r
+    public function setAuthToken($token);\r
 }\r
index 552e00c..a938f0e 100644 (file)
@@ -11,6 +11,7 @@ interface IUserBuilder
     public function With_DisplayName($name);\r
     public function With_Name(IName $name);\r
     public function With_Tags(array $tags);\r
+    public function With_FacebookId($id);\r
     public function With_YearsStepArtist($years);\r
     public function build();\r
 }\r
index 1628017..3b65ef1 100644 (file)
@@ -15,17 +15,23 @@ class User extends AbstractEntity implements IUser
     private $_name;\r
     private $_tags;\r
     private $_yearsStepArtist;\r
+    private $_facebookId;\r
+    private $_authToken;\r
     \r
     public function __construct(\r
         ICountry $country,\r
         $displayName,\r
         IName $name,\r
-        array $tags\r
+        array $tags,\r
+        $facebookId,\r
+        $authToken = null\r
     ) {\r
         $this->_country = $country;\r
         $this->_displayName = $displayName;\r
         $this->_name = $name;\r
         $this->_tags = $tags;\r
+        $this->_facebookId = $facebookId;\r
+        $this->_authToken = $authToken;\r
     }\r
         \r
     public function getCountry() {\r
@@ -44,6 +50,26 @@ class User extends AbstractEntity implements IUser
         return $this->_tags;\r
     }\r
     \r
+    public function getFacebookId()\r
+    {\r
+        return $this->_facebookId;\r
+    }\r
+    \r
+    public function setFacebookId($id)\r
+    {\r
+        $this->_facebookId = $id;\r
+    }\r
+    \r
+    public function getAuthToken()\r
+    {\r
+        return $this->_authToken;\r
+    }\r
+    \r
+    public function setAuthToken($token)\r
+    {\r
+        $this->_authToken = $token;\r
+    }\r
+    \r
     public function getYearsStepArtist() {\r
         return $this->_yearsStepArtist;\r
     }\r
index 44608f3..8957a3d 100644 (file)
@@ -14,6 +14,7 @@ class UserBuilder implements IUserBuilder
     private $_displayName;\r
     private $_name;\r
     private $_tags;\r
+    private $_facebookId;\r
     private $_yearsStepArtist;\r
     \r
     public function __construct(IUserFactory $userFactory)\r
@@ -41,6 +42,11 @@ class UserBuilder implements IUserBuilder
         return $this;\r
     }\r
     \r
+    public function With_FacebookId($id) {\r
+        $this->_facebookId = $id;\r
+        return $this;\r
+    }\r
+    \r
     public function With_YearsStepArtist($years) {\r
         $this->_yearsStepArtist = $years;\r
         return $this;\r
@@ -52,6 +58,6 @@ class UserBuilder implements IUserBuilder
                                      $this->_displayName,\r
                                      $this->_name,\r
                                      $this->_tags,\r
-                                     $this->_yearsStepArtist);\r
+                                     $this->_facebookId);\r
     }\r
 }
\ No newline at end of file
index a9a5402..94235be 100644 (file)
@@ -13,7 +13,7 @@ interface IUserFactory
         $displayName,\r
         IName $name,\r
         array $tags,\r
-        $yearsStepArtist\r
+        $facebookId\r
     );\r
 }\r
 \r
@@ -24,14 +24,14 @@ class UserFactory implements IUserFactory
         $displayName,\r
         IName $name,\r
         array $tags,\r
-        $yearsStepArtist\r
+        $facebookId\r
     ) {\r
         return new User(\r
             $country,\r
             $displayName,\r
             $name,\r
             $tags,\r
-            $yearsStepArtist\r
+            $facebookId\r
         );\r
     }\r
 }
\ No newline at end of file
index 068c191..e586e64 100644 (file)
@@ -3,8 +3,7 @@
 namespace Domain\Entities;\r
 \r
 use Domain\VOs\ICountry;\r
-use Domain\Vos\IName;\r
-use Domain\Entities\IUser;\r
+use Domain\VOs\IName;\r
 \r
 interface IUserStepByStepBuilder\r
 {\r
@@ -28,6 +27,11 @@ interface IUserStepByStepBuilder_With_Name
 \r
 interface IUserStepByStepBuilder_With_Tags\r
 {\r
+    public function With_FacebookId($id);\r
+}\r
+\r
+interface IUserStepByStepBuilder_With_FacebookId\r
+{\r
     public function With_YearsStepArtist($years); //not going to make this mandatory as it is kind of a joke\r
     public function build();\r
 }\r
@@ -76,6 +80,14 @@ class UserStepByStepBuilder_With_Name extends AbstractUserStepByStepBuilder impl
 \r
 class UserStepByStepBuilder_With_Tags extends AbstractUserStepByStepBuilder implements IUserStepByStepBuilder_With_Tags\r
 {\r
+    public function With_FacebookId($id) {\r
+        $this->_userBuilder->With_FacebookId($id);\r
+        return new UserStepByStepBuilder_With_FacebookId($this->_userBuilder);\r
+    }\r
+}\r
+\r
+class UserStepByStepBuilder_With_FacebookId extends AbstractUserStepByStepBuilder implements IUserStepByStepBuilder_With_FacebookId\r
+{\r
     public function With_YearsStepArtist($years) {\r
         $this->_userBuilder->With_YearsStepArtist($years);\r
         return $this;\r
diff --git a/Domain/Util.php b/Domain/Util.php
new file mode 100644 (file)
index 0000000..1b0d555
--- /dev/null
@@ -0,0 +1,276 @@
+<?php
+
+namespace Domain;
+
+class Util
+{
+    private static $_countryCodes =
+        array (
+            'AF' => 'Afghanistan',
+            'AX' => 'Åland Islands',
+            'AL' => 'Albania',
+            'DZ' => 'Algeria',
+            'AS' => 'American Samoa',
+            'AD' => 'Andorra',
+            'AO' => 'Angola',
+            'AI' => 'Anguilla',
+            'AQ' => 'Antarctica',
+            'AG' => 'Antigua and Barbuda',
+            'AR' => 'Argentina',
+            'AU' => 'Australia',
+            'AT' => 'Austria',
+            'AZ' => 'Azerbaijan',
+            'BS' => 'Bahamas',
+            'BH' => 'Bahrain',
+            'BD' => 'Bangladesh',
+            'BB' => 'Barbados',
+            'BY' => 'Belarus',
+            'BE' => 'Belgium',
+            'BZ' => 'Belize',
+            'BJ' => 'Benin',
+            'BM' => 'Bermuda',
+            'BT' => 'Bhutan',
+            'BO' => 'Bolivia',
+            'BA' => 'Bosnia and Herzegovina',
+            'BW' => 'Botswana',
+            'BV' => 'Bouvet Island',
+            'BR' => 'Brazil',
+            'IO' => 'British Indian Ocean Territory',
+            'BN' => 'Brunei Darussalam',
+            'BG' => 'Bulgaria',
+            'BF' => 'Burkina Faso',
+            'BI' => 'Burundi',
+            'KH' => 'Cambodia',
+            'CM' => 'Cameroon',
+            'CA' => 'Canada',
+            'CV' => 'Cape Verde',
+            'KY' => 'Cayman Islands',
+            'CF' => 'Central African Republic',
+            'TD' => 'Chad',
+            'CL' => 'Chile',
+            'CN' => 'China',
+            'CX' => 'Christmas Island',
+            'CC' => 'Cocos (Keeling) Islands',
+            'CO' => 'Colombia',
+            'KM' => 'Comoros',
+            'CG' => 'Congo',
+            'CD' => 'Zaire',
+            'CK' => 'Cook Islands',
+            'CR' => 'Costa Rica',
+            'CI' => 'Côte D\'Ivoire',
+            'HR' => 'Croatia',
+            'CU' => 'Cuba',
+            'CY' => 'Cyprus',
+            'CZ' => 'Czech Republic',
+            'DK' => 'Denmark',
+            'DJ' => 'Djibouti',
+            'DM' => 'Dominica',
+            'DO' => 'Dominican Republic',
+            'EC' => 'Ecuador',
+            'EG' => 'Egypt',
+            'SV' => 'El Salvador',
+            'GQ' => 'Equatorial Guinea',
+            'ER' => 'Eritrea',
+            'EE' => 'Estonia',
+            'ET' => 'Ethiopia',
+            'FK' => 'Falkland Islands (Malvinas)',
+            'FO' => 'Faroe Islands',
+            'FJ' => 'Fiji',
+            'FI' => 'Finland',
+            'FR' => 'France',
+            'GF' => 'French Guiana',
+            'PF' => 'French Polynesia',
+            'TF' => 'French Southern Territories',
+            'GA' => 'Gabon',
+            'GM' => 'Gambia',
+            'GE' => 'Georgia',
+            'DE' => 'Germany',
+            'GH' => 'Ghana',
+            'GI' => 'Gibraltar',
+            'GR' => 'Greece',
+            'GL' => 'Greenland',
+            'GD' => 'Grenada',
+            'GP' => 'Guadeloupe',
+            'GU' => 'Guam',
+            'GT' => 'Guatemala',
+            'GG' => 'Guernsey',
+            'GN' => 'Guinea',
+            'GW' => 'Guinea-Bissau',
+            'GY' => 'Guyana',
+            'HT' => 'Haiti',
+            'HM' => 'Heard Island and Mcdonald Islands',
+            'VA' => 'Vatican City State',
+            'HN' => 'Honduras',
+            'HK' => 'Hong Kong',
+            'HU' => 'Hungary',
+            'IS' => 'Iceland',
+            'IN' => 'India',
+            'ID' => 'Indonesia',
+            'IR' => 'Iran, Islamic Republic of',
+            'IQ' => 'Iraq',
+            'IE' => 'Ireland',
+            'IM' => 'Isle of Man',
+            'IL' => 'Israel',
+            'IT' => 'Italy',
+            'JM' => 'Jamaica',
+            'JP' => 'Japan',
+            'JE' => 'Jersey',
+            'JO' => 'Jordan',
+            'KZ' => 'Kazakhstan',
+            'KE' => 'KENYA',
+            'KI' => 'Kiribati',
+            'KP' => 'Korea, Democratic People\'s Republic of',
+            'KR' => 'Korea, Republic of',
+            'KW' => 'Kuwait',
+            'KG' => 'Kyrgyzstan',
+            'LA' => 'Lao People\'s Democratic Republic',
+            'LV' => 'Latvia',
+            'LB' => 'Lebanon',
+            'LS' => 'Lesotho',
+            'LR' => 'Liberia',
+            'LY' => 'Libyan Arab Jamahiriya',
+            'LI' => 'Liechtenstein',
+            'LT' => 'Lithuania',
+            'LU' => 'Luxembourg',
+            'MO' => 'Macao',
+            'MK' => 'Macedonia, the Former Yugoslav Republic of',
+            'MG' => 'Madagascar',
+            'MW' => 'Malawi',
+            'MY' => 'Malaysia',
+            'MV' => 'Maldives',
+            'ML' => 'Mali',
+            'MT' => 'Malta',
+            'MH' => 'Marshall Islands',
+            'MQ' => 'Martinique',
+            'MR' => 'Mauritania',
+            'MU' => 'Mauritius',
+            'YT' => 'Mayotte',
+            'MX' => 'Mexico',
+            'FM' => 'Micronesia, Federated States of',
+            'MD' => 'Moldova, Republic of',
+            'MC' => 'Monaco',
+            'MN' => 'Mongolia',
+            'ME' => 'Montenegro',
+            'MS' => 'Montserrat',
+            'MA' => 'Morocco',
+            'MZ' => 'Mozambique',
+            'MM' => 'Myanmar',
+            'NA' => 'Namibia',
+            'NR' => 'Nauru',
+            'NP' => 'Nepal',
+            'NL' => 'Netherlands',
+            'AN' => 'Netherlands Antilles',
+            'NC' => 'New Caledonia',
+            'NZ' => 'New Zealand',
+            'NI' => 'Nicaragua',
+            'NE' => 'Niger',
+            'NG' => 'Nigeria',
+            'NU' => 'Niue',
+            'NF' => 'Norfolk Island',
+            'MP' => 'Northern Mariana Islands',
+            'NO' => 'Norway',
+            'OM' => 'Oman',
+            'PK' => 'Pakistan',
+            'PW' => 'Palau',
+            'PS' => 'Palestinian Territory, Occupied',
+            'PA' => 'Panama',
+            'PG' => 'Papua New Guinea',
+            'PY' => 'Paraguay',
+            'PE' => 'Peru',
+            'PH' => 'Philippines',
+            'PN' => 'Pitcairn',
+            'PL' => 'Poland',
+            'PT' => 'Portugal',
+            'PR' => 'Puerto Rico',
+            'QA' => 'Qatar',
+            'RE' => 'Réunion',
+            'RO' => 'Romania',
+            'RU' => 'Russian Federation',
+            'RW' => 'Rwanda',
+            'SH' => 'Saint Helena',
+            'KN' => 'Saint Kitts and Nevis',
+            'LC' => 'Saint Lucia',
+            'PM' => 'Saint Pierre and Miquelon',
+            'VC' => 'Saint Vincent and the Grenadines',
+            'WS' => 'Samoa',
+            'SM' => 'San Marino',
+            'ST' => 'Sao Tome and Principe',
+            'SA' => 'Saudi Arabia',
+            'SN' => 'Senegal',
+            'RS' => 'Serbia',
+            'SC' => 'Seychelles',
+            'SL' => 'Sierra Leone',
+            'SG' => 'Singapore',
+            'SK' => 'Slovakia',
+            'SI' => 'Slovenia',
+            'SB' => 'Solomon Islands',
+            'SO' => 'Somalia',
+            'ZA' => 'South Africa',
+            'GS' => 'South Georgia and the South Sandwich Islands',
+            'ES' => 'Spain',
+            'LK' => 'Sri Lanka',
+            'SD' => 'Sudan',
+            'SR' => 'Suriname',
+            'SJ' => 'Svalbard and Jan Mayen',
+            'SZ' => 'Swaziland',
+            'SE' => 'Sweden',
+            'CH' => 'Switzerland',
+            'SY' => 'Syrian Arab Republic',
+            'TW' => 'Taiwan, Province of China',
+            'TJ' => 'Tajikistan',
+            'TZ' => 'Tanzania, United Republic of',
+            'TH' => 'Thailand',
+            'TL' => 'Timor-Leste',
+            'TG' => 'Togo',
+            'TK' => 'Tokelau',
+            'TO' => 'Tonga',
+            'TT' => 'Trinidad and Tobago',
+            'TN' => 'Tunisia',
+            'TR' => 'Turkey',
+            'TM' => 'Turkmenistan',
+            'TC' => 'Turks and Caicos Islands',
+            'TV' => 'Tuvalu',
+            'UG' => 'Uganda',
+            'UA' => 'Ukraine',
+            'AE' => 'United Arab Emirates',
+            'GB' => 'United Kingdom',
+            'US' => 'United States',
+            'UM' => 'United States Minor Outlying Islands',
+            'UY' => 'Uruguay',
+            'UZ' => 'Uzbekistan',
+            'VU' => 'Vanuatu',
+            'VE' => 'Venezuela',
+            'VN' => 'Viet Nam',
+            'VG' => 'Virgin Islands, British',
+            'VI' => 'Virgin Islands, U.S.',
+            'WF' => 'Wallis and Futuna',
+            'EH' => 'Western Sahara',
+            'YE' => 'Yemen',
+            'ZM' => 'Zambia',
+            'ZW' => 'Zimbabwe',
+        );
+    
+    public static function countryNameToCode($name)
+    {
+        return array_search($name, self::$_countryCodes);
+    }
+    
+    public static function countryNameFromLatLong($lat, $long)
+    {
+        $url = 'http://maps.google.com/maps/api/geocode/json?address=' . $lat .',' . $long .'&sensor=false'; 
+        $get     = file_get_contents($url);
+        $geoData = json_decode($get);
+        if (json_last_error() !== JSON_ERROR_NONE) {
+            throw new \InvalidArgumentException('Invalid geocoding results');
+        }
+
+        if(isset($geoData->results[0])) {
+            foreach($geoData->results[0]->address_components as $addressComponent) {
+                if(in_array('country', $addressComponent->types)) {
+                    return $addressComponent->long_name; 
+                }
+            }
+        }
+        return null; 
+    }
+}
\ No newline at end of file
diff --git a/Services/FacebookSessionFactory.php b/Services/FacebookSessionFactory.php
new file mode 100644 (file)
index 0000000..cfac400
--- /dev/null
@@ -0,0 +1,24 @@
+<?php
+
+namespace Services;
+
+use Services\IFacebookSessionFactory;
+use Facebook\FacebookSession;
+
+class FacebookSessionFactory implements IFacebookSessionFactory {
+    private $_appId;
+    private $_appSecret;
+    
+    public function __construct($appConfig) {
+        $config = include $appConfig;
+
+        $this->_appId = $config['appId'];
+        $this->_appSecret = $config['appSecret'];
+    }
+    
+    public function createInstance($token)
+    {
+        FacebookSession::setDefaultApplication($this->_appId, $this->_appSecret);
+        return new FacebookSession($token);
+    }
+}
diff --git a/Services/IFacebookSessionFactory.php b/Services/IFacebookSessionFactory.php
new file mode 100644 (file)
index 0000000..7bd1c02
--- /dev/null
@@ -0,0 +1,7 @@
+<?php
+
+namespace Services;
+
+interface IFacebookSessionFactory {
+    public function createInstance($token);
+}
\ No newline at end of file
index 8f82601..0ef6017 100644 (file)
@@ -1,6 +1,7 @@
 {\r
     "require": {\r
-        "mnapoli/php-di": "~4.0"\r
+        "mnapoli/php-di" : "~4.0",\r
+        "facebook/php-sdk-v4" : "4.0.*"\r
     },    \r
     "autoload": {\r
         "psr-0": {\r
@@ -9,6 +10,7 @@
             "Controllers" : "./",\r
             "Services" : "./"\r
         },\r
+        "classmap":["Domain/"],\r
         "files" : ["./DataAccess/functions.php"]\r
     }\r
 }
\ No newline at end of file
index 992b015..49627d5 100644 (file)
@@ -5,9 +5,13 @@ return [
     'datamapper.maps' => '../config/DataMaps.php',\r
     'router.maps' => '../config/Routes.php',\r
     'db.credentials' => '../config/db.php',\r
+    'facebook.app' => '../config/FacebookApp.php',\r
     \r
     //entites\r
     'Domain\Entities\StepMania\ISimfile' => DI\object('Domain\Entities\StepMania\Simfile'),\r
+    'Domain\Entities\IUserStepByStepBuilder' => DI\object('Domain\Entities\UserStepByStepBuilder'),\r
+    'Domain\Entities\IUserBuilder' => DI\object('Domain\Entities\UserBuilder'),\r
+    'Domain\Entities\IUserFactory' => DI\object('Domain\Entities\UserFactory'),\r
     \r
     //services\r
     'Services\Http\IHttpResponse' => DI\object('Services\Http\HttpResponse'),\r
@@ -16,12 +20,16 @@ return [
         ->constructor(DI\link('router.maps')),\r
     'Services\Uploads\IUploadManager' => DI\object('Services\Uploads\UploadManager'),\r
     'Services\Uploads\IFileFactory' => DI\object('Services\Uploads\FileFactory'),\r
+    'Services\IFacebookSessionFactory' => DI\object('Services\FacebookSessionFactory')\r
+        ->constructor(DI\link('facebook.app')),\r
     \r
     //DA\r
     'DataAccess\StepMania\ISimfileRepository' => DI\object('DataAccess\StepMania\SimfileRepository'),\r
+    'DataAccess\IUserRepository' => DI\object('DataAccess\UserRepository'),\r
     'DataAccess\IDatabaseFactory' => DI\object('DataAccess\DatabaseFactory')\r
         ->constructor(DI\link('db.credentials')),\r
     'DataAccess\DataMapper\IDataMapper' => DI\object('DataAccess\DataMapper\DataMapper')\r
         ->constructor(DI\link('datamapper.maps')),\r
-    'DataAccess\Queries\IQueryBuilderFactory' => DI\object('DataAccess\Queries\QueryBuilderFactory')\r
+    'DataAccess\Queries\IQueryBuilderFactory' => DI\object('DataAccess\Queries\QueryBuilderFactory'),\r
+    \r
 ];\r
index 6de6c02..dbe5157 100644 (file)
@@ -40,7 +40,9 @@ return [
             'country' => DataAccess\VO('Country'),\r
             'displayName' => DataAccess\Varchar('display_name'),\r
             'name' => DataAccess\VO('Name'),\r
-            'tags' => DataAccess\VOArray('Tag', 'getTags') // TODO: Make VarcharArray class\r
+            'tags' => DataAccess\VOArray('Tag', 'getTags'), // TODO: Make VarcharArray class\r
+            'facebookId' => DataAccess\Varchar('facebook_id'),\r
+            'authToken' => DataAccess\Varchar('auth_token')\r
         ]\r
     ],\r
     \r
diff --git a/config/FacebookApp.php.example b/config/FacebookApp.php.example
new file mode 100644 (file)
index 0000000..8a4ae41
--- /dev/null
@@ -0,0 +1,7 @@
+<?php
+
+return [
+    'appId' => 'id',
+    'appSecret' => 'secret'
+];
+
index 32a4255..e3188f6 100644 (file)
@@ -17,5 +17,10 @@ return [
         'methods' => ['GET'],\r
         'controller' => 'Simfile',\r
         'action' => 'test'\r
+    ],\r
+    \r
+    '/user/auth' => [\r
+        'method' => ['GET'],\r
+        'controller' => 'UserAuth'\r
     ]\r
 ];\r
index d892c87..8ed4f0b 100644 (file)
@@ -2,6 +2,7 @@
 \r
 //TODO: Config this\r
 header("Access-Control-Allow-Origin: http://172.17.12.110:8000");\r
+header("Access-Control-Allow-Origin: http://roll.divinelegy.meeples:8000");\r
 \r
 require_once('../vendor/autoload.php');\r
 \r