Created
April 29, 2016 20:04
-
-
Save sameg14/e23238bba8f34ac1144086f8567fa697 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Tib\CoreBundle\Service; | |
use Tib\CoreBundle\Db\DBCommon; | |
use Tib\CoreBundle\Model\Mix; | |
use Tib\CoreBundle\Model\User; | |
use Tib\CoreBundle\Model\MixComment; | |
use Tib\CoreBundle\Util\Inflect; | |
use Tib\CoreBundle\Util\FilterOutput; | |
use Tib\CoreBundle\Util\RemoteAddress; | |
use Tib\CoreBundle\Exception\SpamException; | |
use Tib\CoreBundle\Exception\MissingDataException; | |
use Tib\CoreBundle\Exception\InvalidDataException; | |
use Tib\CoreBundle\Exception\MissingPropertyException; | |
use Symfony\Component\HttpFoundation\Session\Session; | |
use \Swift_Mailer; | |
use \stdClass; | |
use Aws\S3\Exception\S3Exception; | |
/** | |
* Class MixHydrate deals with the business of creating Mix objects | |
* @package Tib\CoreBundle\Service | |
*/ | |
class MixService extends AbstractService | |
{ | |
/** | |
* @var Mix[] | |
*/ | |
protected $popularMixes; | |
/** | |
* Handles processing mix images and such | |
* | |
* @var MixImageService | |
*/ | |
protected $mixImageService; | |
/** | |
* @var Mix | |
*/ | |
protected $mixModel; | |
/** | |
* MixService constructor. | |
* @param DBCommon $db | |
* @param Session $session | |
* @param Swift_Mailer $mailer | |
* @param MixImageService $mixImage | |
* @param S3Service $s3 | |
* @param UserService $user | |
* @param RemoteAddress $remoteAddress | |
* @param Mix $mixModel | |
*/ | |
public function __construct(DBCommon $db, Session $session, Swift_Mailer $mailer, MixImageService $mixImage, S3Service $s3, UserService $user, RemoteAddress $remoteAddress, Mix $mixModel) | |
{ | |
$this->setDb($db); | |
$this->setSession($session); | |
$this->setMailer($mailer); | |
$this->setMixImageService($mixImage); | |
$this->setS3Service($s3); | |
$this->setUserService($user); | |
$this->setRemoteAddress($remoteAddress); | |
$this->setMixModel($mixModel); | |
} | |
/** | |
* Get a bunch of Mix objects back from these Ids | |
* @param array $mixIds Array of mixIds from the DB | |
* @return Mix[] | null | |
*/ | |
public function getMixes($mixIds) | |
{ | |
$mixRows = $this->getMixModel()->getMixes($mixIds); | |
$mixObjects = $this->createMixObjects($mixRows); | |
return array_reverse($mixObjects); | |
} | |
/** | |
* Get all the latest mixes that have been uploaded | |
* @param int $limit The number of latest mixes to get | |
* @return Mix[] | |
*/ | |
public function getLatestMixes($limit = 20) | |
{ | |
$mixRows = $this->mixModel->getLatestMixes($limit); | |
return $this->createMixObjects($mixRows); | |
} | |
/** | |
* Get popular mixes | |
* @param int $limit The number of top mixes to get | |
* @return Mix[]|null | |
*/ | |
public function getPopularMixes($limit = 10) | |
{ | |
if (isset($this->popularMixes)) { | |
return $this->popularMixes; | |
} | |
$popularMixRows = $this->mixModel->getPopularMixes($limit); | |
if (empty($popularMixRows)) { | |
return $this->getPopularMixes(); | |
} | |
return $this->popularMixes = $this->createMixObjects($popularMixRows); | |
} | |
/** | |
* Get an array of mixIds from the genre and subGenre | |
* @param string $genre Genre SEF name | |
* @param string $subGenre Sub-Genre SEF name | |
* @return array | |
*/ | |
public function getMixesByGenreAndSubGenreSlug($genre, $subGenre) | |
{ | |
$mixRows = $this->mixModel->getMixesByGenreAndSubGenreSlug($genre, $subGenre); | |
return $this->createMixObjects($mixRows); | |
} | |
/** | |
* Get a mix by its SEF slug | |
* @param string $slug mix slug | |
* @return Mix | |
*/ | |
public function getBySlug($slug) | |
{ | |
$mixRows = $this->mixModel->getBySlug($slug); | |
if (empty($mixRows)) { | |
return null; | |
} | |
$mixArray = $this->createMixObjects($mixRows); | |
if (empty($mixArray)) { | |
return null; | |
} | |
return array_pop($mixArray); | |
} | |
/** | |
* Get all mixes for this user | |
* @param string $userSlug SEF Slug for this user | |
* @return Mix[]|null | |
*/ | |
public function getMixesByUserSlug($userSlug) | |
{ | |
$rows = $this->mixModel->getMixesByUserSlug($userSlug); | |
return $this->createMixObjects($rows); | |
} | |
/** | |
* Get an array of mix names and slugs | |
* @return stdClass[] | |
*/ | |
public function getMixNamesForUser() | |
{ | |
$userId = $this->session->get('userId'); | |
return $this->mixModel->getMixNamesForUser($userId); | |
} | |
/** | |
* @param MixImageService $mixImageService | |
*/ | |
public function setMixImageService($mixImageService) | |
{ | |
$this->mixImageService = $mixImageService; | |
} | |
/** | |
* Add a comment to this mix | |
* @param string $mixSlug SEF Slug for this mix | |
* @param string $name Name of the person writing the comment | |
* @param string $location Where the person is located | |
* @param string $comment The comment itself | |
* @throws MissingDataException | |
* @throws SpamException | |
* @return array|null | |
* @todo: refactor this out to the model | |
*/ | |
public function processComment($mixSlug, $name, $location, $comment) | |
{ | |
if (empty($mixSlug)) { | |
throw new MissingDataException('Mix not found!'); | |
} | |
if (empty($name)) { | |
throw new MissingDataException('Please enter your name'); | |
} | |
if (empty($location)) { | |
throw new MissingDataException('Please enter a location'); | |
} | |
if (empty($comment)) { | |
throw new MissingDataException('Your comment cannot be empty'); | |
} | |
if ($location == 'New York') { | |
throw new SpamException(); | |
} | |
// If this user is determined to be a known spammer, throw a SpamException | |
$this->userService->blacklistCheck(); | |
$name = $this->db->quote(FilterOutput::cleanText($name)); | |
$location = $this->db->quote(FilterOutput::cleanText($location)); | |
$comment = $this->db->quote(FilterOutput::cleanText($comment)); | |
$ip = $this->db->quote($this->remoteAddress->getIpAddress()); | |
$query | |
= ' | |
select | |
m.mixid, | |
m.name as mix_name, | |
u.email | |
from | |
' . Mix::TABLE_NAME . ' m | |
inner join ' . User::TABLE_NAME . ' u on (u.id = m.userid) | |
where | |
m.slug="' . $this->db->quote($mixSlug) . '"'; | |
$this->db->setQuery($query); | |
$obj = $this->db->loadObject(); | |
if (empty($obj)) { | |
throw new MissingDataException('mixId cannot be determined!'); | |
} | |
$mixId = $obj->mixid; | |
$email = $obj->email; | |
$mixName = $obj->mix_name; | |
if (empty($mixId)) { | |
throw new MissingDataException('mixId cannot be determined!'); | |
} | |
if (empty($email)) { | |
throw new MissingDataException('Email cannot be determined from this mix'); | |
} | |
$hash = sha1($mixId . $email . $mixName . strtotime('now')); | |
$query = 'replace into ' | |
. MixComment::TABLE_NAME | |
. ' set name="' . $name | |
. '", location ="' . $location | |
. '", comment = "' . $comment | |
. '", mixId = "' . $mixId | |
. '", hash = "' . $hash | |
. '", source_ip = "' . $ip . '"'; | |
$this->db->setQuery($query); | |
if (!$this->db->query()) { | |
return false; | |
} | |
return array( | |
'mixName' => $mixName, | |
'email' => $email, | |
'hash' => $hash | |
); | |
} | |
/** | |
* Delete a mix | |
* @param int $userId The user who owns this mix | |
* @param int $mixId PK for this mix to get nixed | |
* @throws MissingDataException | |
* @throws S3Exception | |
* @throws InvalidDataException | |
* @return bool | |
* @todo: fire off a job for this API call | |
*/ | |
public function deleteMix($userId, $mixId) | |
{ | |
if (empty($userId)) { | |
throw new MissingDataException('Invalid user operation'); | |
} | |
if (empty($mixId)) { | |
throw new MissingDataException('Invalid mix'); | |
} | |
$user = $this->userService->getUserById($userId); | |
if (empty($user)) { | |
throw new InvalidDataException('Invalid user'); | |
} | |
$mixes = $this->getMixes(array($mixId)); | |
if (empty($mixes)) { | |
throw new InvalidDataException('Invalid Mix cannot be retrieved'); | |
} | |
/** @var Mix $mix */ | |
$mix = array_pop($mixes); | |
$s3MixStatus = $this->s3Service->deleteMix($user->getSlug(), $mix->getFileName()); | |
if (!$s3MixStatus) { | |
throw new S3Exception('Cannot delete mix from S3'); | |
} | |
$s3ImageStatus = $this->s3Service->deleteMixImages( | |
$user->getSlug(), $mix->getS3ImageFilename(), $mix->getS3ThumbFilename() | |
); | |
if (!$s3ImageStatus) { | |
throw new S3Exception('Cannot delete images from S3'); | |
} | |
return $mix->delete(); | |
} | |
/** | |
* Get the current play position, if possible | |
* @param int $mixId PK from ill_mixes | |
* @param int $userId If the user is logged in, get their Id | |
* @param string $sessionId Current string sessionId | |
* @return float | |
*/ | |
public function getPlayPosition($mixId, $userId, $sessionId) | |
{ | |
$positionId = $this->discoverPositionId($mixId, $userId, $sessionId); | |
if (!empty($positionId)) { | |
$query = 'select position from ill_position where id = "' . $this->db->quote($positionId) . '"'; | |
$this->db->setQuery($query); | |
return (float) $this->db->loadResult(); | |
} | |
return 0.00; | |
} | |
/** | |
* Update the currently playing position of this mix | |
* @param int $mixId PK from ill_mixes | |
* @param int $userId If the user is logged in, get their Id | |
* @param float $position Currently playing track position in seconds | |
* @param string $sessionId Current string sessionId | |
* @return bool | |
*/ | |
public function updatePosition($mixId, $userId, $position, $sessionId) | |
{ | |
$mixId = $this->db->quote($mixId); | |
$userId = $this->db->quote($userId); | |
$position = $this->db->quote($position); | |
$sessionId = $this->db->quote($sessionId); | |
// Try to get one with a user record first | |
$id = $this->discoverPositionId($mixId, $userId, $sessionId); | |
// Create one | |
if (empty($id)) { | |
$query = ' | |
insert into ill_position | |
(sessid, userid, mixid, position) | |
values | |
("' . $sessionId . '", "' . $userId . '", "' . $mixId . '", "' . $position . '")'; | |
$this->db->setQuery($query); | |
return $this->db->query(); | |
} | |
$query = 'update ill_position set position = "' . $position . '" where id = "' . $id . '"'; | |
$this->db->setQuery($query); | |
return $this->db->query(); | |
} | |
/** | |
* Process a moderated mix comment | |
* @param string $hash Hash to identify unique mix_comment | |
* @param string $shouldApprove Will be either [approve, deny] | |
* @throws InvalidDataException | |
* @return stdClass | |
*/ | |
public function processCommentModeration($hash, $shouldApprove) | |
{ | |
if (empty($hash) || empty($shouldApprove)) { | |
throw new InvalidDataException('Invalid request'); | |
} | |
$query = ' | |
select | |
m.name as mix_name, | |
u.email, | |
mc.name as comment_name, | |
mc.location as comment_location, | |
mc.comment as comment_text, | |
mc.source_ip as source_ip | |
from | |
mix_comments mc | |
inner join ill_mixes m on (m.mixid = mc.mixId) | |
inner join jos_users u on (u.id = m.userid) | |
where | |
mc.hash = "' . $hash . '"'; | |
$this->db->setQuery($query); | |
$data = $this->db->loadObject(); | |
if (empty($data)) { | |
throw new InvalidDataException('Invalid hash'); | |
} | |
// Spam, don't even bother sending an email | |
if ($shouldApprove == 'deny') { | |
// Nix the comment | |
$query = 'delete from mix_comments where hash = "' . $hash . '"'; | |
$this->db->setQuery($query); | |
$this->db->query(); | |
// Blacklist the IP | |
$this->userService->blacklistSpammer($data->source_ip); | |
} | |
return $data; | |
} | |
/** | |
* Create mix objects from raw mix rows from the DB | |
* @param stdClass[] $mixRows from query | |
* @throws MissingPropertyException | |
* @return Mix[] | |
*/ | |
protected function createMixObjects($mixRows) | |
{ | |
/** @var Mix[] $mixes */ | |
$mixes = []; | |
if (empty($mixRows)) { | |
return null; | |
} | |
foreach ($mixRows as $mixRow) { | |
$mix = clone($this->getMixModel()); | |
foreach ($mixRow as $k => $v) { | |
$setter = 'set' . Inflect::underscoreToProper($k); | |
// If we don't have a slug, set one explicitly | |
if ($k == 'slug' && empty($v)) { | |
$v = Inflect::titleToSef($mix->getName()); | |
} | |
if (method_exists($mix, $setter)) { | |
$mix->$setter($v); | |
} else { | |
throw new MissingPropertyException(get_class($mix) . ' is missing a setter "' . $setter . '"'); | |
} | |
} | |
array_push($mixes, $mix); | |
} | |
return $mixes; | |
} | |
/** | |
* Attempt to discover a positionId for a given mix | |
* @param int $mixId PK from ill_mixes | |
* @param int $userId If the user is logged in, get their Id | |
* @param string $sessionId Current string sessionId | |
* @return mixed | |
*/ | |
protected function discoverPositionId($mixId, $userId, $sessionId) | |
{ | |
// Try to get one with a user record first | |
$query = 'select id from ill_position where userid = "' . $userId . '" and mixid = "' . $mixId . '"'; | |
$this->db->setQuery($query); | |
$id = $this->db->loadResult(); | |
// Try to get it via session | |
if (empty($id)) { | |
$query = 'select id from ill_position where sessid = "' . $sessionId . '" and mixid = "' . $mixId . '"'; | |
$this->db->setQuery($query); | |
$id = $this->db->loadResult(); | |
} | |
return $id; | |
} | |
/** | |
* @return Mix | |
*/ | |
public function getMixModel() | |
{ | |
return $this->mixModel; | |
} | |
/** | |
* @param Mix $mixModel | |
*/ | |
public function setMixModel($mixModel) | |
{ | |
$this->mixModel = $mixModel; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment