diff --git a/.gitignore b/.gitignore
index 81b46483f..762924975 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,9 +1,8 @@
lib/form/doctrine/op*Plugin
-web/cache/*
log/*
plugins/op*
+!plugins/opAuthMailAddressPlugin
!plugins/opSkinBasicPlugin
-!plugins/opSkinClassicPlugin
plugins/.*
lib/filter/doctrine/*
cache/*
diff --git a/NOTICE b/NOTICE
index ca1d27b0e..ca058dad4 100644
--- a/NOTICE
+++ b/NOTICE
@@ -20,18 +20,26 @@ This product includes also softwares developed by :
- Apache License 2.0
- Andy Smith (http://term.ie/)
- MIT License
+ - Ryan Parman, Geoffrey Sneddon
+ - BSD 3-clause License (SimplePie)
- Fabien Potencier (http://fabien.potencier.org/)
- MIT License
- Kousuke Ebihara (http://co3k.org/)
- Apache License 2.0
+ - Stig Bakken, Gregory Beaver, Helgi Þormar Þorbjörnsson, Tomas V.V.Cox, Martin Jansen
+ - BSD 2-clause License (PEAR)
+ - Greg Beaver
+ - BSD 2-clause License (PEAR_PackageFileManager2)
- Vincent Oostindie, Alan Knowles, Peter Bowyer, Philippe Jausions
- - PHP License 3.0 (PEAR::Image_Transform)
+ - PHP License 3.0 (Image_Transform)
+ - Harry Fuecks, Lorenzo Alberton
+ - BSD 3-clause License (Calendar)
This product needs the third-party softwares listed blow to run.
- PHP: Hypertext Preprocessor (5.2.4 +)
This product includes dependent libraries listed blow:
- - symfony 1.4.1
+ - LExpress/symfony1 1.5.9 (fork of symfony 1.4)
- Zend Framework 1.10.8 (partly)
- Zend_Acl
- Zend_Exception
@@ -47,6 +55,10 @@ This product includes dependent libraries listed blow:
- Zend_Version
- Auth OpenID 2.1.2
- PHP OAuth library
+ - SimplePie 1.4.3
- sfFormExtraPlugin 1.0.12
- sfImageHandlerPlugin 1.0.0
- - PEAR::Image_Transform 0.9.3
+ - PEAR 1.10.3
+ - PEAR_PackageFileManager2 1.0.4
+ - Image_Transform 0.9.5
+ - Calendar 0.5.5
diff --git a/apps/api/config/factories.yml b/apps/api/config/factories.yml
index 9a46337b2..aea47a0be 100644
--- a/apps/api/config/factories.yml
+++ b/apps/api/config/factories.yml
@@ -52,23 +52,10 @@ all:
#all:
# controller:
# class: sfFrontWebController
-#
-# request:
-# class: sfWebRequest
-# param:
-# logging: %SF_LOGGING_ENABLED%
-# path_info_array: SERVER
-# path_info_key: PATH_INFO
-# relative_url_root: ~
-# formats:
-# txt: text/plain
-# js: [application/javascript, application/x-javascript, text/javascript]
-# css: text/css
-# json: [application/json, application/x-json]
-# xml: [text/xml, application/xml, application/x-xml]
-# rdf: application/rdf+xml
-# atom: application/atom+xml
-#
+
+ request:
+ class: opWebRequest
+
# response:
# class: sfWebResponse
# param:
@@ -83,12 +70,10 @@ all:
# logging: %SF_LOGGING_ENABLED%
# use_flash: true
# default_culture: %SF_DEFAULT_CULTURE%
-#
-# storage:
-# class: sfSessionStorage
-# param:
-# session_name: symfony
-#
+
+ storage:
+ class: sfNoStorage
+
# view_cache:
# class: sfFileCache
# param:
diff --git a/apps/api/config/routing.yml b/apps/api/config/routing.yml
index 366d4cb83..a53bdbca0 100644
--- a/apps/api/config/routing.yml
+++ b/apps/api/config/routing.yml
@@ -13,3 +13,118 @@ no_default:
default:
url: /:module/:action/*
+
+activity_search:
+ url: /activity/search.json
+ param: { module: activity, action: search, sf_format: json }
+ requirements: { sf_method: [get] }
+
+activity_list:
+ url: /activity/list.json
+ param: { module: activity, action: search, sf_format: json }
+ requirements: { sf_method: [get] }
+
+activity_member:
+ url: /activity/member.json
+ param: { module: activity, action: member, sf_format: json }
+ requirements: { sf_method: [get] }
+
+activity_friends:
+ url: /activity/friends.json
+ param: { module: activity, action: friends, sf_format: json }
+ requirements: { sf_method: [get] }
+
+activity_community:
+ url: /activity/community.json
+ param: { module: activity, action: community, sf_format: json }
+ requirements: { sf_method: [get] }
+
+activity_mentions:
+ url: /activity/mentions.json
+ param: { module: activity, action: mentions, sf_format: json }
+ requirements: { sf_method: [get] }
+
+activity_post:
+ url: /activity/post.json
+ param: { module: activity, action: post, sf_format: json }
+ requirements: { sf_method: [post, get] }
+
+activity_delete:
+ url: /activity/delete.json
+ param: { module: activity, action: delete, sf_format: json }
+ requirements: { sf_method: [get] }
+
+member_search:
+ url: /member/search.json
+ param: { module: member, action: search, sf_format: json }
+ requirements: { sf_method: [get] }
+
+member_list:
+ url: /member/list.json
+ param: { module: member, action: search, sf_format: json }
+ requirements: { sf_method: [get] }
+
+member_community:
+ url: /member/community.json
+ param: { module: member, action: community, sf_format: json }
+ requirements: { sf_method: [get] }
+
+member_friend_accept:
+ url: /member/friend_accept.json
+ param: { module: member, action: friendAccept, sf_format: json }
+ requirements: { sf_method: [get] }
+
+member_friend_reject:
+ url: /member/friend_reject.json
+ param: { module: member, action: friendAccept, sf_format: json, reject: 1 }
+ requirements: { sf_method: [get] }
+
+member_friend_request:
+ url: /member/friend_request.json
+ param: { module: member, action: friendRequest, sf_format: json, }
+ requirements: { sf_method: [get] }
+
+member_friend_unlink:
+ url: /member/friend_unlink.json
+ param: { module: member, action: friendRequest, sf_format: json, unlink: 1 }
+ requirements: { sf_method: [get] }
+
+community_search:
+ url: /community/search.json
+ param: { module: community, action: search, sf_format: json }
+ requirements: { sf_method: [get] }
+
+community_list:
+ url: /community/list.json
+ param: { module: community, action: search, sf_format: json }
+ requirements: { sf_method: [get] }
+
+community_member:
+ url: /community/member.json
+ param: { module: community, action: member, sf_format: json }
+ requirements: { sf_method: [get] }
+
+community_join:
+ url: /community/join.json
+ param: { module: community, action: join, sf_format: json }
+ requirements: { sf_method: [get] }
+
+push_search:
+ url: /push/search.json
+ param: { module: push, action: search, sf_format: json }
+ requirements: { sf_method: [get] }
+
+push_list:
+ url: /push/list.json
+ param: { module: push, action: search, sf_format: json }
+ requirements: { sf_method: [get] }
+
+push_count:
+ url: /push/count.json
+ param: { module: push, action: count, sf_format: json }
+ requirements: { sf_method: [get] }
+
+push_read:
+ url: /push/read.json
+ param: { module: push, action: read, sf_format: json }
+ requirements: { sf_method: [get] }
diff --git a/apps/api/config/settings.yml b/apps/api/config/settings.yml
index a5f6a520c..0d4848319 100644
--- a/apps/api/config/settings.yml
+++ b/apps/api/config/settings.yml
@@ -13,7 +13,7 @@ dev:
test:
.settings:
- error_reporting:
+ error_reporting:
cache: false
web_debug: false
no_script_name: false
@@ -30,8 +30,17 @@ all:
#all:
# .actions:
-# error_404_module: default # To be called when a 404 error is raised
-# error_404_action: error404 # Or when the requested URL doesn't match any route
+ error_404_module: default # To be called when a 404 error is raised
+ error_404_action: error404 # Or when the requested URL doesn't match any route
+
+ error_400_module: default
+ error_400_action: error400
+
+ error_401_module: default
+ error_401_action: error401
+
+ error_403_module: default
+ error_403_action: error403
#
# login_module: default # To be called when a non-authenticated user
# login_action: login # Tries to access a secure page
@@ -42,7 +51,7 @@ all:
# module_disabled_module: default # To be called when a user requests
# module_disabled_action: disabled # A module disabled in the module.yml
#
- .settings:
+# .settings:
# # Optional features. Deactivating unused features boots performance a bit.
# use_database: on # Enable database manager. Set to off if you don't use a database.
i18n: on # Enable interface translation. Set to off if your application should not be translated.
@@ -74,7 +83,7 @@ all:
# calendar_web_dir: /sf/calendar
#
# # Helpers included in all templates by default
-# standard_helpers: [Partial, Cache, Form]
+ standard_helpers: [Partial, Cache, sfImage, opUtil, opJsonApi]
#
# # Activated modules from plugins or from the symfony core
# enabled_modules: [default]
@@ -90,4 +99,4 @@ all:
# logging_enabled: true
#
# # i18n
- default_culture: ja # Default user culture
+ default_culture: ja_JP # Default user culture
diff --git a/apps/api/lib/helper/opJsonApiHelper.php b/apps/api/lib/helper/opJsonApiHelper.php
new file mode 100644
index 000000000..073cfb2de
--- /dev/null
+++ b/apps/api/lib/helper/opJsonApiHelper.php
@@ -0,0 +1,206 @@
+
+ */
+function op_api_member($member)
+{
+ $viewMemberId = sfContext::getInstance()->getUser()->getMemberId();
+
+ $memberImageFileName = $member->getImageFileName();
+ if (!$memberImageFileName)
+ {
+ $memberImage = op_image_path('no_image.gif', true);
+ }
+ else
+ {
+ $memberImage = sf_image_path($memberImageFileName, array('size' => '48x48'), true);
+ }
+
+ $relation = null;
+ if ((string)$viewMemberId !== (string)$member->getId())
+ {
+ $relation = Doctrine::getTable('MemberRelationship')->retrieveByFromAndTo($viewMemberId, $member->getId());
+ }
+
+ $selfIntroduction = $member->getProfile('op_preset_self_introduction', true);
+
+ return array(
+ 'id' => $member->getId(),
+ 'profile_image' => $memberImage,
+ 'screen_name' => $member->getConfig('op_screen_name', $member->getName()),
+ 'name' => $member->getName(),
+ 'profile_url' => op_api_member_profile_url($member->getId()),
+ 'friend' => $relation ? $relation->isFriend() : false,
+ 'blocking' => $relation ? $relation->isAccessBlocked() : false,
+ 'self' => $viewMemberId === $member->getId(),
+ 'friends_count' => $member->countFriends(),
+ 'self_introduction' => $selfIntroduction ? (string)$selfIntroduction : null,
+ );
+}
+
+function op_api_member_profile_url($memberId)
+{
+ return app_url_for('pc_frontend', array('sf_route' => 'obj_member_profile', 'id' => $memberId), true);
+}
+
+function op_api_activity($activity)
+{
+ use_helper('opActivity');
+
+ $viewMemberId = sfContext::getInstance()->getUser()->getMemberId();
+ $member = $activity->getMember();
+
+ $images = array();
+ foreach ($activity->getImages() as $activityImage)
+ {
+ $images[] = array(
+ 'small_size' => op_activity_image_uri($activityImage, array('size' => '48x48'), true),
+ 'full_size' => op_activity_image_uri($activityImage, array(), true),
+ );
+ }
+
+ return array(
+ 'id' => $activity->getId(),
+ 'member' => op_api_member($member),
+ 'body' => $activity->getBody(),
+ 'body_html' => op_activity_linkification(nl2br(op_api_force_escape($activity->getBody()))),
+ 'uri' => $activity->getUri(),
+ 'source' => $activity->getSource(),
+ 'source_uri' => $activity->getSourceUri(),
+ 'image_uris' => $images,
+ 'created_at' => date('r', strtotime($activity->getCreatedAt())),
+ );
+}
+
+function op_activity_linkification($body, $options = array())
+{
+ $body = op_auto_link_text($body);
+
+ return preg_replace_callback('/(@+)([-._0-9A-Za-z]+)/', 'op_activity_linkification_callback', $body);
+}
+
+function op_activity_linkification_callback($matches)
+{
+ $at = $matches[1];
+ $screenName = $matches[2];
+ $screenNameConfig = Doctrine::getTable('MemberConfig')->createQuery()
+ ->select('member_id')
+ ->addWhere('name = "op_screen_name"')
+ ->addWhere('value = ?', $screenName)
+ ->fetchOne(array(), Doctrine::HYDRATE_NONE);
+
+ if ($screenNameConfig)
+ {
+ $memberId = $screenNameConfig[0];
+ return link_to($at.$screenName, op_api_member_profile_url($memberId), array('target' => '_blank'));
+ }
+
+ return $matches[0];
+}
+
+function op_api_force_escape($text)
+{
+ if (!sfConfig::get('sf_escaping_strategy'))
+ {
+ // escape body even if escaping method is disabled.
+ $text = sfOutputEscaper::escape(sfConfig::get('sf_escaping_method'), $text);
+ }
+
+ return $text;
+}
+
+function op_api_community($community)
+{
+ $viewMemberId = sfContext::getInstance()->getUser()->getMemberId();
+
+ $communityUrl = app_url_for('pc_frontend', array('sf_route' => 'community_home', 'id' => $community->getId()), true);
+
+ $communityImageFileName = $community->getImageFileName();
+ if (!$communityImageFileName)
+ {
+ $communityImage = op_image_path('no_image.gif', true);
+ }
+ else
+ {
+ $communityImage = sf_image_path($communityImageFileName, array('size' => '48x48'), true);
+ }
+
+ $communityMember = Doctrine::getTable('CommunityMember')
+ ->retrieveByMemberIdAndCommunityId($viewMemberId, $community->getId());
+
+ return array(
+ 'id' => $community->getId(),
+ 'name' => $community->getName(),
+ 'category' => $community->getCommunityCategory() ? $community->getCommunityCategory()->getName() : null,
+ 'community_url' => $communityUrl,
+ 'community_image_url' => $communityImage,
+ 'joining' => $communityMember ? !$communityMember->getIsPre() : false,
+ 'admin' => $communityMember ? $communityMember->hasPosition('admin') : false,
+ 'sub_admin' => $communityMember ? $communityMember->hasPosition('sub_admin') : false,
+ 'created_at' => op_api_date($community->getCreatedAt()),
+ 'admin_member' => op_api_member($community->getAdminMember()),
+ 'member_count' => $community->countCommunityMembers(),
+ 'public_flag' => $community->getConfig('public_flag'),
+ 'register_policy' => $community->getConfig('register_policy'),
+ 'description' => $community->getConfig('description'),
+ );
+}
+
+function op_api_date($date)
+{
+ return gmdate('r', strtotime($date));
+}
+
+function op_api_notification($notification)
+{
+ if ($notification['icon_url'])
+ {
+ $iconUrl = $notification['icon_url'];
+ }
+ else
+ {
+ if ('link' === $notification['category'])
+ {
+ $fromMember = Doctrine::getTable('Member')->find($notification['member_id_from']);
+ $fromMemberImageFileName = $fromMember ? $fromMember->getImageFileName() : null;
+
+ if ($fromMemberImageFileName)
+ {
+ $iconUrl = sf_image_path($fromMemberImageFileName, array('size' => '48x48'), true);
+ }
+ }
+ }
+
+ if (!$iconUrl)
+ {
+ $iconUrl = op_image_path('no_image.gif', true);
+ }
+ elseif (false !== strpos('http://', $iconUrl))
+ {
+ $iconUrl = sf_image_path($iconUrl, array('size' => '48x48'), true);
+ }
+
+ return array(
+ 'id' => $notification['id'],
+ 'body' => sfContext::getInstance()->getI18N()->__($notification['body']),
+ 'category' => $notification['category'],
+ 'unread' => $notification['unread'],
+ 'created_at' => date('r', strtotime($notification['created_at'])),
+ 'icon_url' => $iconUrl,
+ 'url' => $notification['url'] ? url_for($notification['url'], array('abstract' => true)) : null,
+ 'member_id_from' => $notification['member_id_from'],
+ );
+}
diff --git a/apps/api/lib/myUser.class.php b/apps/api/lib/myUser.class.php
index 4c793028e..1b1af5c7a 100644
--- a/apps/api/lib/myUser.class.php
+++ b/apps/api/lib/myUser.class.php
@@ -1,5 +1,76 @@
+ */
class myUser extends sfBasicSecurityUser
{
+ protected
+ $member = null;
+
+ public function getMemberByApiKey($apiKey)
+ {
+ if (!$apiKey)
+ {
+ return null;
+ }
+
+ $config = Doctrine::getTable('MemberConfig')->createQuery('c')
+ ->leftJoin('c.Member')
+ ->where('c.name = \'api_key\'')
+ ->where('c.value = ?', $apiKey)
+ ->fetchOne();
+
+ if (!$config)
+ {
+ return null;
+ }
+
+ return $config->getMember();
+ }
+
+ public function getMember()
+ {
+ if (!is_null($this->member))
+ {
+ return $this->member;
+ }
+
+ $request = sfContext::getInstance()->getRequest();
+
+ $apiKey = $request['apiKey'];
+ if (false === $apiKey)
+ {
+ $exception = new opErrorHttpException('apiKey parameter not specified.');
+ throw $exception->setHttpStatusCode(401);
+ }
+
+ $member = $this->getMemberByApiKey($apiKey);
+ if (is_null($member) || $member->isOnBlackList() || $member->getIsLoginRejected())
+ {
+ $exception = new opErrorHttpException('Invalid API key.');
+ throw $exception->setHttpStatusCode(401);
+ }
+
+ $this->member = $member;
+
+ return $member;
+ }
+
+ public function getMemberId()
+ {
+ return $this->getMember()->getId();
+ }
}
diff --git a/apps/api/modules/activity/actions/actions.class.php b/apps/api/modules/activity/actions/actions.class.php
new file mode 100644
index 000000000..15f6804e9
--- /dev/null
+++ b/apps/api/modules/activity/actions/actions.class.php
@@ -0,0 +1,283 @@
+
+ */
+class activityActions extends opJsonApiActions
+{
+ public function executeSearch(sfWebRequest $request)
+ {
+ $builder = opActivityQueryBuilder::create()
+ ->setViewerId($this->getUser()->getMemberId());
+
+ if (isset($request['target']))
+ {
+ if ('friend' === $request['target'])
+ {
+ $builder->includeFriends($request['target_id'] ? $request['target_id'] : null);
+ }
+ elseif ('community' === $request['target'])
+ {
+ $this->forward400Unless($request['target_id'], 'target_id parameter not specified.');
+ $builder
+ ->includeSelf()
+ ->includeFriends()
+ ->includeSns()
+ ->setCommunityId($request['target_id']);
+ }
+ else
+ {
+ $this->forward400('target parameter is invalid.');
+ }
+ }
+ else
+ {
+ if (isset($request['member_id']))
+ {
+ $builder->includeMember($request['member_id']);
+ }
+ else
+ {
+ $builder
+ ->includeSns()
+ ->includeFriends()
+ ->includeSelf();
+ }
+ }
+
+ $query = $builder->buildQuery();
+
+ if (isset($request['keyword']))
+ {
+ $query->andWhereLike('body', $request['keyword']);
+ }
+
+ $globalAPILimit = sfConfig::get('op_json_api_limit', 20);
+ if (isset($request['count']) && (int)$request['count'] < $globalAPILimit)
+ {
+ $query->limit($request['count']);
+ }
+ else
+ {
+ $query->limit($globalAPILimit);
+ }
+
+ if (isset($request['max_id']))
+ {
+ $query->addWhere('id <= ?', $request['max_id']);
+ }
+
+ if (isset($request['since_id']))
+ {
+ $query->addWhere('id > ?', $request['since_id']);
+ }
+
+ if (isset($request['activity_id']))
+ {
+ $query->addWhere('id = ?', $request['activity_id']);
+ }
+
+ $this->activityData = $query
+ ->andWhere('in_reply_to_activity_id IS NULL')
+ ->execute();
+
+ $this->setTemplate('array');
+ }
+
+ public function executeMember(sfWebRequest $request)
+ {
+ if ($request['id'])
+ {
+ $request['member_id'] = $request['id'];
+ }
+
+ if (isset($request['target']))
+ {
+ unset($request['target']);
+ }
+
+ $this->forward('activity', 'search');
+ }
+
+ public function executeFriends(sfWebRequest $request)
+ {
+ $request['target'] = 'friend';
+
+ if (isset($request['member_id']))
+ {
+ $request['target_id'] = $request['member_id'];
+ unset($request['member_id']);
+ }
+ elseif (isset($request['id']))
+ {
+ $request['target_id'] = $request['id'];
+ unset($request['id']);
+ }
+
+ $this->forward('activity', 'search');
+ }
+
+ public function executeCommunity(sfWebRequest $request)
+ {
+ $request['target'] = 'community';
+
+ if (isset($request['community_id']))
+ {
+ $request['target_id'] = $request['community_id'];
+ unset($request['community_id']);
+ }
+ elseif (isset($request['id']))
+ {
+ $request['target_id'] = $request['id'];
+ unset($request['id']);
+ }
+ else
+ {
+ $this->forward400('community_id parameter not specified.');
+ }
+
+ $this->forward('activity', 'search');
+ }
+
+ public function executePost(sfWebRequest $request)
+ {
+ if (!opConfig::get('is_allow_post_activity'))
+ {
+ return $this->renderJSON(array('status' => 'error', 'message' => "you are not allowed this action."));
+ }
+
+ $body = (string)$request['body'];
+ $this->forward400If('' === $body, 'body parameter not specified.');
+ $this->forward400If(mb_strlen($body) > 140, 'The body text is too long.');
+
+ $memberId = $this->getUser()->getMemberId();
+ $options = array();
+
+ if (isset($request['public_flag']))
+ {
+ $options['public_flag'] = $request['public_flag'];
+ }
+
+ if (isset($request['in_reply_to_activity_id']))
+ {
+ $options['in_reply_to_activity_id'] = $request['in_reply_to_activity_id'];
+ }
+
+ if (isset($request['uri']))
+ {
+ $options['uri'] = $request['uri'];
+ }
+ elseif (isset($request['url']))
+ {
+ $options['uri'] = $request['url'];
+ }
+
+ if (isset($request['target']) && 'community' === $request['target'])
+ {
+ if (!isset($request['target_id']))
+ {
+ $this->forward400('target_id parameter not specified.');
+ }
+
+ $this->checkCommunityMember($request['target_id']);
+
+ $options['foreign_table'] = 'community';
+ $options['foreign_id'] = $request['target_id'];
+ }
+
+ $options['source'] = 'API';
+
+ $imageFiles = $request->getFiles('images');
+ if (!empty($imageFiles))
+ {
+ foreach ((array)$imageFiles as $imageFile)
+ {
+ $validator = new opValidatorImageFile(array('required' => false));
+ try
+ {
+ $obj = $validator->clean($imageFile);
+ }
+ catch (sfValidatorError $e)
+ {
+ $this->forward400('This image file is invalid.');
+ }
+ if (is_null($obj))
+ {
+ continue; // empty value
+ }
+ $file = new File();
+ $file->setFromValidatedFile($obj);
+ $file->setName('ac_'.$this->getUser()->getMemberId().'_'.$file->getName());
+ $file->save();
+ $options['images'][]['file_id'] = $file->getId();
+ }
+ }
+
+ $this->activity = Doctrine::getTable('ActivityData')->updateActivity($memberId, $body, $options);
+
+ $this->setTemplate('object');
+ }
+
+ public function executeDelete(sfWebRequest $request)
+ {
+ if (isset($request['activity_id']))
+ {
+ $activityId = $request['activity_id'];
+ }
+ elseif (isset($request['id']))
+ {
+ $activityId = $request['id'];
+ }
+ else
+ {
+ $this->forward400('activity_id parameter not specified.');
+ }
+
+ $activity = Doctrine::getTable('ActivityData')->find($activityId);
+
+ $this->forward404Unless($activity, 'Invalid activity id.');
+
+ $this->forward403Unless($activity->getMemberId() === $this->getUser()->getMemberId());
+
+ $activity->delete();
+
+ return $this->renderJSON(array('status' => 'success'));
+ }
+
+ public function executeMentions(sfWebRequest $request)
+ {
+ $builder = opActivityQueryBuilder::create()
+ ->setViewerId($this->getUser()->getMemberId())
+ ->includeMentions();
+
+ $query = $builder->buildQuery()
+ ->andWhere('in_reply_to_activity_id IS NULL')
+ ->andWhere('foreign_table IS NULL')
+ ->andWhere('foreign_id IS NULL')
+ ->limit(20);
+
+ $this->activityData = $query->execute();
+
+ $this->setTemplate('array');
+ }
+
+ protected function checkCommunityMember($communityId)
+ {
+ $memberId = $this->getUser()->getMemberId();
+ $isCommunityMember = Doctrine_Core::getTable('CommunityMember')->isMember($memberId, $communityId);
+
+ $this->forward403Unless($isCommunityMember, 'You don\'t participate in this community.');
+ }
+}
diff --git a/apps/api/modules/activity/templates/arraySuccess.php b/apps/api/modules/activity/templates/arraySuccess.php
new file mode 100644
index 000000000..4eb150457
--- /dev/null
+++ b/apps/api/modules/activity/templates/arraySuccess.php
@@ -0,0 +1,26 @@
+getReplies();
+ if (0 !== count($replies))
+ {
+ $acEntity['replies'] = array();
+
+ foreach ($replies as $reply)
+ {
+ $acEntity['replies'][] = op_api_activity($reply);
+ }
+ }
+
+ $ac[] = $acEntity;
+}
+
+return array(
+ 'status' => 'success',
+ 'data' => $ac,
+);
diff --git a/apps/api/modules/activity/templates/objectSuccess.php b/apps/api/modules/activity/templates/objectSuccess.php
new file mode 100644
index 000000000..c6fb31e48
--- /dev/null
+++ b/apps/api/modules/activity/templates/objectSuccess.php
@@ -0,0 +1,19 @@
+getReplies();
+if (0 !== count($replies))
+{
+ $acEntity['replies'] = array();
+
+ foreach ($replies as $reply)
+ {
+ $acEntity['replies'][] = op_api_activity($reply);
+ }
+}
+
+return array(
+ 'status' => 'success',
+ 'data' => $acEntity,
+);
diff --git a/apps/api/modules/community/actions/actions.class.php b/apps/api/modules/community/actions/actions.class.php
new file mode 100644
index 000000000..a4cea8bfa
--- /dev/null
+++ b/apps/api/modules/community/actions/actions.class.php
@@ -0,0 +1,115 @@
+
+ */
+class communityActions extends opJsonApiActions
+{
+ public function executeSearch(sfWebRequest $request)
+ {
+ $query = Doctrine::getTable('Community')->createQuery();
+
+ if (isset($request['keyword']))
+ {
+ $query->andWhereLike('name', $request['keyword']);
+ }
+
+ $this->communities = $query
+ ->limit(sfConfig::get('op_json_api_limit', 20))
+ ->execute();
+
+ $this->setTemplate('array');
+ }
+
+ public function executeMember(sfWebRequest $request)
+ {
+ if (isset($request['community_id']))
+ {
+ $communityId = $request['community_id'];
+ }
+ elseif (isset($request['id']))
+ {
+ $communityId = $request['id'];
+ }
+ else
+ {
+ $this->forward400('community_id parameter not specified.');
+ }
+
+ $this->members = Doctrine::getTable('Member')->createQuery('m')
+ ->addWhere('EXISTS (FROM CommunityMember cm WHERE m.id = cm.member_id AND cm.is_pre = false AND cm.community_id = ?)', $communityId)
+ ->limit(sfConfig::get('op_json_api_limit', 20))
+ ->execute();
+
+ $this->setTemplate('array', 'member');
+ }
+
+ public function executeJoin(sfWebRequest $request)
+ {
+ $memberId = $this->getUser()->getMemberId();
+
+ if (isset($request['community_id']))
+ {
+ $communityId = $request['community_id'];
+ }
+ elseif (isset($request['id']))
+ {
+ $communityId = $request['id'];
+ }
+ else
+ {
+ $this->forward400('community_id parameter not specified.');
+ }
+
+ $community = Doctrine::getTable('Community')->find($communityId);
+ if (!$community)
+ {
+ $this->forward404('This community does not exist.');
+ }
+
+ $communityJoinPolicy = $community->getConfig('register_policy');
+
+ $communityMember = Doctrine::getTable('CommunityMember')
+ ->retrieveByMemberIdAndCommunityId($memberId, $community->getId());
+
+ if ($request['leave'])
+ {
+ if (!$communityMember || $communityMember->hasPosition('admin'))
+ {
+ $this->forward400('You can\'t leave this community.');
+ }
+
+ Doctrine::getTable('CommunityMember')->quit($memberId, $communityId);
+ }
+ else
+ {
+ if ($communityMember)
+ {
+ if ($communityMember->getIsPre())
+ {
+ $this->forward400('You are already sent request to join this community.');
+ }
+ else
+ {
+ $this->forward400('You are already this community\'s member.');
+ }
+ }
+
+ Doctrine::getTable('CommunityMember')->join($memberId, $communityId, $communityJoinPolicy);
+ }
+
+ return $this->renderJSON(array('status' => 'success'));
+ }
+}
diff --git a/apps/api/modules/community/templates/arraySuccess.php b/apps/api/modules/community/templates/arraySuccess.php
new file mode 100644
index 000000000..2574ab914
--- /dev/null
+++ b/apps/api/modules/community/templates/arraySuccess.php
@@ -0,0 +1,13 @@
+ 'success',
+ 'data' => $data,
+);
diff --git a/apps/api/modules/default/actions/actions.class.php b/apps/api/modules/default/actions/actions.class.php
new file mode 100644
index 000000000..cd3ea6c68
--- /dev/null
+++ b/apps/api/modules/default/actions/actions.class.php
@@ -0,0 +1,62 @@
+
+ */
+class defaultActions extends sfActions
+{
+ public function executeError400(sfWebRequest $request)
+ {
+ $this->getResponse()->setStatusCode(400);
+
+ return $this->renderError($request['error_message']);
+ }
+
+ public function executeError401(sfWebRequest $request)
+ {
+ $this->getResponse()->setStatusCode(401);
+
+ return $this->renderError($request['error_message']);
+ }
+
+ public function executeError403(sfWebRequest $request)
+ {
+ $this->getResponse()->setStatusCode(403);
+
+ return $this->renderError($request['error_message']);
+ }
+
+ public function executeError404(sfWebRequest $request)
+ {
+ $this->getResponse()->setStatusCode(404);
+
+ return $this->renderError($request['error_message']);
+ }
+
+ protected function renderError($message = null)
+ {
+ $response = $this->getResponse();
+ $response->setContentType('text/plain');
+
+ $errorText = $response->getStatusCode().' '.$response->getStatusText();
+
+ if ($message)
+ {
+ $errorText .= ': '.$message;
+ }
+
+ return $this->renderText($errorText);
+ }
+}
diff --git a/apps/api/modules/member/actions/actions.class.php b/apps/api/modules/member/actions/actions.class.php
new file mode 100644
index 000000000..8f8df37b4
--- /dev/null
+++ b/apps/api/modules/member/actions/actions.class.php
@@ -0,0 +1,187 @@
+
+ */
+class memberActions extends opJsonApiActions
+{
+ public function executeCommunity(sfWebRequest $request)
+ {
+ if (isset($request['member_id']))
+ {
+ $memberId = $request['member_id'];
+ }
+ elseif (isset($request['id']))
+ {
+ $memberId = $request['id'];
+ }
+ else
+ {
+ $memberId = $this->getUser()->getMemberId();
+ }
+
+ $query = Doctrine::getTable('Community')->createQuery('c')
+ ->innerJoin('c.CommunityMember cm WITH cm.is_pre = false AND cm.member_id = ?', $memberId)
+ ->limit(sfConfig::get('op_json_api_limit', 20));
+
+ if (isset($request['keyword']))
+ {
+ $query->whereLike('c.name', $request['keyword']);
+ }
+
+ $this->communities = $query->execute();
+
+ $this->setTemplate('array', 'community');
+ }
+
+ public function executeSearch(sfWebRequest $request)
+ {
+ $query = Doctrine::getTable('Member')->createQuery('m')
+ ->andWhere('m.is_active = true');
+
+ if (isset($request['target']))
+ {
+ if (!isset($request['target_id']))
+ {
+ $this->forward400('target_id parameter not specified.');
+ }
+ $targetId = $request['target_id'];
+
+ if ('friend' === $request['target'])
+ {
+ $query->andWhere('EXISTS (FROM MemberRelationship mr WHERE m.id = mr.member_id_to AND mr.member_id_from = ? AND mr.is_friend = true)', $targetId);
+ }
+ if ('community' === $request['target'])
+ {
+ $query->andWhere('EXISTS (FROM CommunityMember cm WHERE m.id = cm.member_id AND cm.community_id = ?)', $targetId);
+ }
+ }
+
+ if (isset($request['keyword']))
+ {
+ $query->andWhereLike('m.name', $request['keyword']);
+ }
+
+ $this->members = $query
+ ->limit(sfConfig::get('op_json_api_limit', 20))
+ ->execute();
+
+ $this->setTemplate('array');
+ }
+
+ public function executeFriendAccept(sfWebRequest $request)
+ {
+ if (isset($request['member_id']))
+ {
+ $targetMemberId = $request['member_id'];
+ }
+ elseif (isset($request['id']))
+ {
+ $targetMemberId = $request['id'];
+ }
+ else
+ {
+ $this->forward400('member_id parameter not specified.');
+ }
+
+ $memberId = $this->getUser()->getMemberId();
+
+ $preRequest = Doctrine::getTable('MemberRelationship')->createQuery()
+ ->addWhere('member_id_from = ?', $targetMemberId)
+ ->addWhere('member_id_to = ?', $memberId)
+ ->addWhere('is_friend_pre = true')
+ ->fetchOne();
+
+ if (!$preRequest)
+ {
+ $this->forward404('Invalid member_id.');
+ }
+
+ if (!isset($request['reject']))
+ {
+ $preRequest->setFriend();
+ }
+ else
+ {
+ $preRequest->removeFriendPre();
+ }
+
+ $preRequest->free(true);
+
+ return $this->renderJSON(array('status' => 'success'));
+ }
+
+ public function executeFriendRequest(sfWebRequest $request)
+ {
+ $memberId = $this->getUser()->getMemberId();
+
+ if (isset($request['member_id']))
+ {
+ $targetMemberId = $request['member_id'];
+ }
+ elseif (isset($request['id']))
+ {
+ $targetMemberId = $request['id'];
+ }
+ else
+ {
+ $this->forward400('member_id parameter not specified.');
+ }
+
+ if ($memberId === $targetMemberId)
+ {
+ $this->forward400('Friend request to myself is not allowed.');
+ }
+
+ $relation = Doctrine::getTable('MemberRelationship')->retrieveByFromAndTo($memberId, $targetMemberId);
+ if (!$relation)
+ {
+ $relation = new MemberRelationship();
+ $relation->setMemberIdFrom($memberId);
+ $relation->setMemberIdTo($targetMemberId);
+ }
+
+ if (isset($request['unlink']))
+ {
+ if (!$relation->isFriend())
+ {
+ $this->forward400('This member is not your friend.');
+ }
+
+ $relation->removeFriend();
+ }
+ else
+ {
+ if ($relation->isAccessBlocked())
+ {
+ $this->forward403('Friend request is blocked.');
+ }
+ if ($relation->isFriend())
+ {
+ $this->forward400('This member already belongs to your friend.');
+ }
+ if ($relation->isFriendPreFrom())
+ {
+ $this->forward400('Friend request is already sent.');
+ }
+
+ $relation->setFriendPre();
+ }
+
+ $relation->free(true);
+
+ return $this->renderJSON(array('status' => 'success'));
+ }
+}
diff --git a/apps/api/modules/member/templates/arraySuccess.php b/apps/api/modules/member/templates/arraySuccess.php
new file mode 100644
index 000000000..acc241bfe
--- /dev/null
+++ b/apps/api/modules/member/templates/arraySuccess.php
@@ -0,0 +1,13 @@
+ 'success',
+ 'data' => $data,
+);
diff --git a/apps/api/modules/push/actions/actions.class.php b/apps/api/modules/push/actions/actions.class.php
new file mode 100644
index 000000000..896eb5fb6
--- /dev/null
+++ b/apps/api/modules/push/actions/actions.class.php
@@ -0,0 +1,76 @@
+
+ */
+class pushActions extends opJsonApiActions
+{
+ public function executeSearch(sfWebRequest $request)
+ {
+ $member = $this->getUser()->getMember();
+ $this->notifications = opNotificationCenter::getNotifications($member);
+
+ $this->setTemplate('array');
+ }
+
+ public function executeCount(sfWebRequest $request)
+ {
+ $member = $this->getUser()->getMember();
+ $notifications = opNotificationCenter::getNotifications($member);
+
+ $this->count = array(
+ 'link' => 0,
+ 'message' => 0,
+ 'other' => 0,
+ );
+
+ foreach ($notifications as $notification)
+ {
+ if (array_key_exists($notification['category'], $this->count))
+ {
+ $category = $notification['category'];
+ }
+ else
+ {
+ $category = 'other';
+ }
+
+ if ($notification['unread'])
+ {
+ $this->count[$category]++;
+ }
+ }
+
+ $this->setTemplate('count');
+ }
+
+ public function executeRead(sfWebRequest $request)
+ {
+ $this->forward400Unless($request['id'], 'id parameter not specified.');
+
+ $member = $this->getUser()->getMember();
+
+ $ret = opNotificationCenter::setRead($member, $request['id']);
+
+ if ($ret)
+ {
+ return $this->renderJSON(array('status' => 'success'));
+ }
+ else
+ {
+ $this->forward404('Request parameter id does not exist.');
+ }
+ }
+}
diff --git a/apps/api/modules/push/templates/arraySuccess.php b/apps/api/modules/push/templates/arraySuccess.php
new file mode 100644
index 000000000..afcf70c91
--- /dev/null
+++ b/apps/api/modules/push/templates/arraySuccess.php
@@ -0,0 +1,13 @@
+ 'success',
+ 'data' => $data
+);
diff --git a/apps/api/modules/push/templates/countSuccess.php b/apps/api/modules/push/templates/countSuccess.php
new file mode 100644
index 000000000..c9ad93471
--- /dev/null
+++ b/apps/api/modules/push/templates/countSuccess.php
@@ -0,0 +1,6 @@
+ 'success',
+ 'data' => $count->getRawValue(),
+);
diff --git a/apps/mobile_frontend/config/factories.yml b/apps/mobile_frontend/config/factories.yml
index bc25a5b4b..5742d6620 100644
--- a/apps/mobile_frontend/config/factories.yml
+++ b/apps/mobile_frontend/config/factories.yml
@@ -93,13 +93,7 @@ all:
debug: false
untranslated_prefix: "[T]"
untranslated_suffix: "[/T]"
- cache:
- class: sfFileCache
- param:
- automatic_cleaning_factor: 0
- cache_dir: %SF_I18N_CACHE_DIR%
- lifetime: 86400
- prefix: %SF_APP_DIR%
+ cache: ~
routing:
class: sfPatternRouting
diff --git a/apps/mobile_frontend/i18n/messages.ja.xml b/apps/mobile_frontend/i18n/messages.ja.xml
index 363d0a99b..7f3d48ef7 100644
--- a/apps/mobile_frontend/i18n/messages.ja.xml
+++ b/apps/mobile_frontend/i18n/messages.ja.xml
@@ -106,26 +106,6 @@
Public Flag for Profile Page
プロフィールページの公開範囲
-
- All Users on the Web
- Web全体に公開
-
-
- All Members
- 全員に公開
-
-
- %my_friend%
- %my_friend%まで公開
-
-
- Only Open to %my_friend%
- %my_friend%まで公開
-
-
- Private
- 公開しない
-
Register mobile
携帯電話を登録する
@@ -162,14 +142,6 @@
%Community% Members
%Community%メンバー
-
- Everyone can see
- Web全体に公開
-
-
- Only SNS members can see
- SNS参加者のみ公開
-
Everyone can join
誰でも参加できる
@@ -234,6 +206,10 @@
Please select the item from the menu.
メニューから設定したい項目を選択してください。
+
+ There is no available settings.
+ 利用可能な設定はありません。
+
Successful in invite.
送信が完了しました。
@@ -307,7 +283,7 @@
携帯電話を登録します。
- Prease input your password, press "%1%" button.
+ Please input your password, and press "%1%" button.
パスワードを入力して、「%1%」ボタンを押してください。
@@ -511,16 +487,20 @@
%community%作成
- Search Communities
- コミュニティ検索
+ Search %Community%
+ %Community%検索
+
+
+ %Community% Top
+ %Community% トップ
Categories
カテゴリ
- Your search queries did not match any communities.
- 該当するコミュニティはありませんでした。
+ Your search queries did not match any %community%.
+ 該当する%community%はありませんでした。
All categories
@@ -629,7 +609,7 @@
The form submission cannot be processed. It probably means that you have uploaded a file that is too big.
- 送信に失敗しました。
+ フォームの送信に失敗しました。アップロードしたファイルが大きすぎる可能性があります。
"%value%" is not an integer.
@@ -1235,6 +1215,18 @@
Block access from the selected member with input MemberID.<br /> MemberID is written at the end of member top page URL.<br /> ex. The MemberID is 1 when the URL "http://sns.example.com/member/1"
メンバーIDを入力して特定のメンバーからのアクセスをブロックします。<br />メンバーIDは相手トップページのURL末尾に表示されています。<br />例:"http://sns.example.com/member/1" というURLである場合にはメンバーIDは1になります。
+
+ A mobile UID was already registered.
+ その携帯電話の個体識別番号はすでに登録されています。
+
+
+ A mobile UID is required. Please check settings of your mobile phone and retry.
+ 携帯電話の個体識別番号は必須です。携帯電話の個体識別番号設定を確認してもう一度お試しください。
+
+
+ A mobile UID is invalid.
+ その携帯電話の個体識別番号は無効です。
+