/** * Starts a recurring subscription * @param {Streams_Stream} $plan The subscription plan stream * @param {string} [$payments=null] The type of payments processor, could be "authnet" or "stripe". If omitted, the subscription proceeds without any payments. * @param {array} [$options=array()] Options for the subscription * @param {date} [$options.startDate=today] The start date of the subscription * @param {date} [$options.endDate=today+year] The end date of the subscription * @param {Users_User} [$options.user=Users::loggedInUser()] Allows us to set the user to subscribe * @param {Users_User} [$options.publisherId=Users::communityId()] Allows us to override the publisher to subscribe to * @param {string} [$options.description=null] description of the charge, to be sent to customer * @param {string} [$options.metadata=null] any additional metadata to store with the charge * @param {string} [$options.subscription=null] if this charge is related to a subscription stream * @param {string} [$options.subscription.publisherId] * @param {string} [$options.subscription.streamName] * @throws Assets_Exception_DuplicateTransaction * @throws Assets_Exception_HeldForReview * @throws Assets_Exception_ChargeFailed * @return {Streams_Stream} A stream of type 'Assets/subscription' representing this subscription */ static function startSubscription($plan, $payments = null, $options = array()) { if (!isset($options['user'])) { $options['user'] = Users::loggedInUser(true); } $app = Q_Config::expect('Q', 'app'); $user = Q::ifset($options, 'user', Users::loggedInUser(true)); $currency = 'USD'; // TODO: may want to implement support for currency conversion $startDate = Q::ifset($options, 'startDate', date("Y-m-d")); $startDate = date('Y-m-d', strtotime($startDate)); $months = $plan->getAttribute('months', 12); $amount = $plan->getAttribute('amount'); $endDate = date("Y-m-d", strtotime("-1 day", strtotime("+{$months} month", strtotime($startDate)))); $endDate = date('Y-m-d', strtotime($endDate)); $publisherId = Q::ifset($options, 'publisherId', Users::communityId()); $publisher = Users_User::fetch($publisherId); $streamName = "Assets/subscription/{$user->id}/{$plan->name}"; if ($subscription = Streams::fetchOne($publisherId, $publisherId, $streamName)) { return $subscription; // it already started } $attributes = Q::json_encode(array('payments' => $payments, 'planPublisherId' => $plan->publisherId, 'planStreamName' => $plan->name, 'startDate' => $startDate, 'endDate' => $endDate, 'months' => $months, 'amount' => $amount, 'currency' => $currency)); $stream = Streams::create($publisherId, $publisherId, "Assets/subscription", array('name' => $streamName, 'title' => $plan->title, 'readLevel' => Streams::$READ_LEVEL['none'], 'writeLevel' => Streams::$WRITE_LEVEL['none'], 'adminLevel' => Streams::$ADMIN_LEVEL['none'], 'attributes' => $attributes)); $access = new Streams_Access(array('publisherId' => $publisherId, 'streamName' => $streamName, 'ofUserId' => $user->id, 'grantedByUserId' => $app, 'readLevel' => Streams::$READ_LEVEL['max'], 'writeLevel' => -1, 'adminLevel' => -1)); $access->save(); $amount = $plan->getAttribute('amount', null); if (!is_numeric($amount)) { throw new Q_Exception_WrongValue(array('field' => 'amount', 'range' => 'an integer')); } $options['stream'] = $stream; if ($payments) { Assets::charge($payments, $amount, $currency, $options); } /** * @event Assets/startSubscription {before} * @param {Streams_Stream} plan * @param {Streams_Stream} subscription * @param {string} startDate * @param {string} endDate * @return {Users_User} */ Q::event('Assets/startSubscription', compact('plan', 'user', 'publisher', 'stream', 'startDate', 'endDate', 'months', 'currency'), 'after'); return $stream; }
/** * Adds a stream to represent an area within a location. * Also may add streams to represent the floor and column. * @method addArea * @static * @param {Streams_Stream} $location The location stream * @param {string} $title The title of the area * @param {string} [$floor] The number of the floor on which the area is located * @param {string} [$column] The name of the column on which the area is located * @param {array} [$options=array()] Any options to pass to Streams::create. Also can include: * @param {array} [$options.asUserId=null] Override the first parameter to Streams::create * @return {array} An array of ($area, $floor, $column) */ static function addArea($location, $title, $floor = null, $column = null, $options = array()) { $locationName = $location->name; $parts = explode('/', $locationName); $placeId = $parts[2]; $asUserId = Q::ifset($options, 'asUserId', null); $publisherId = $location->publisherId; $skipAccess = Q::ifset($options, 'skipAccess', true); $floorName = isset($floor) ? "Places/floor/{$placeId}/" . Q_Utils::normalize($floor) : null; $columnName = isset($column) ? "Places/column/{$placeId}/" . Q_Utils::normalize($column) : null; $name = "Places/area/{$placeId}/" . Q_Utils::normalize($title); $area = Streams::fetchOne($asUserId, $publisherId, $name, $options); if (!$area) { $attributes = array('locationName' => $locationName, 'locationTitle' => $location->title, 'locationAddress' => $location->getAttribute('address'), 'floorName' => $floorName, 'columnName' => $columnName); $area = Streams::create($asUserId, $publisherId, 'Places/area', compact('name', 'title', 'skipAccess', 'attributes')); $area->relateTo($location, 'location', $asUserId, $options); if ($floorName) { $name = $floorName; $title = $location->title . " floor {$floor}"; if (!($floor = Streams::fetchOne($asUserId, $publisherId, $name))) { $floor = Streams::create($asUserId, $publisherId, 'Places/floor', compact('name', 'title', 'skipAccess')); } $area->relateTo($floor, 'floor', $asUserId, $options); } if ($columnName) { $name = $columnName; $title = $location->title . " column {$column}"; if (!($column = Streams::fetchOne($asUserId, $publisherId, $name))) { $column = Streams::create($asUserId, $publisherId, 'Places/column', compact('name', 'title', 'skipAccess')); } $area->relateTo($column, 'column', $asUserId, $options); } } else { $column = $columnName ? Streams::fetchOne($asUserId, $publisherId, $columnName) : null; $floor = $floorName ? Streams::fetchOne($asUserId, $publisherId, $floorName) : null; } return array($area, $floor, $column); }