kopia lustrzana https://github.com/nextcloud/social
				
				
				
			left join cache, and returns data in timeline
Signed-off-by: Maxence Lange <maxence@artificial-owl.com>pull/25/head
							rodzic
							
								
									d7c2fc601f
								
							
						
					
					
						commit
						58093e65e5
					
				|  | @ -32,7 +32,7 @@ return [ | |||
| 
 | ||||
| 		['name' => 'Local#newPost', 'url' => '/api/v1/post', 'verb' => 'POST'], | ||||
| 		['name' => 'Local#timeline', 'url' => '/api/v1/timeline', 'verb' => 'GET'], | ||||
| 		['name' => 'Local#direct', 'url' => '/api/v1/direct', 'verb' => 'PUT'] | ||||
| 		['name' => 'Local#direct', 'url' => '/api/v1/direct', 'verb' => 'PUT'], | ||||
| 		['name' => 'Local#accountSearch', 'url' => '/api/v1/accounts/search', 'verb' => 'GET'], | ||||
| 		['name' => 'Local#actorInfo', 'url' => '/api/v1/actor/info', 'verb' => 'GET'] | ||||
| 
 | ||||
|  |  | |||
|  | @ -31,6 +31,8 @@ namespace OCA\Social\Db; | |||
| 
 | ||||
| 
 | ||||
| use Doctrine\DBAL\Query\QueryBuilder; | ||||
| use OCA\Social\Exceptions\InvalidResourceException; | ||||
| use OCA\Social\Model\ActivityPub\Person; | ||||
| use OCA\Social\Service\ConfigService; | ||||
| use OCA\Social\Service\MiscService; | ||||
| use OCP\DB\QueryBuilder\IQueryBuilder; | ||||
|  | @ -224,7 +226,8 @@ class CoreRequestBuilder { | |||
| 
 | ||||
| 	/** | ||||
| 	 * @param IQueryBuilder $qb | ||||
| 	 * @param string $recipient | ||||
| 	 * @param int $since | ||||
| 	 * @param int $limit | ||||
| 	 */ | ||||
| 	protected function limitPaginate(IQueryBuilder &$qb, int $since = 0, int $limit = 5) { | ||||
| 		if ($since > 0) { | ||||
|  | @ -232,7 +235,12 @@ class CoreRequestBuilder { | |||
| 			$dt = new \DateTime(); | ||||
| 			$dt->setTimestamp($since); | ||||
| 			// TODO: Pagination should use published date, once we can properly query the db for that
 | ||||
| 			$qb->andWhere($expr->lt('creation', $qb->createNamedParameter($dt, IQueryBuilder::PARAM_DATE), IQueryBuilder::PARAM_DATE)); | ||||
| 			$qb->andWhere( | ||||
| 				$expr->lt( | ||||
| 					'creation', $qb->createNamedParameter($dt, IQueryBuilder::PARAM_DATE), | ||||
| 					IQueryBuilder::PARAM_DATE | ||||
| 				) | ||||
| 			); | ||||
| 		} | ||||
| 		$qb->setMaxResults($limit); | ||||
| 		$qb->orderBy('creation', 'desc'); | ||||
|  | @ -273,30 +281,66 @@ class CoreRequestBuilder { | |||
| 		$qb->andWhere($expr->like($field, $qb->createNamedParameter($value))); | ||||
| 	} | ||||
| 
 | ||||
| //	/**
 | ||||
| //	 * Left Join service to get info about the serviceId
 | ||||
| //	 *
 | ||||
| //	 * @param IQueryBuilder $qb
 | ||||
| //	 */
 | ||||
| //	public function leftJoinService(IQueryBuilder &$qb) {
 | ||||
| //
 | ||||
| //		if ($qb->getType() !== QueryBuilder::SELECT) {
 | ||||
| //			return;
 | ||||
| //		}
 | ||||
| //
 | ||||
| //		$expr = $qb->expr();
 | ||||
| //		$pf = $this->defaultSelectAlias;
 | ||||
| //
 | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @param IQueryBuilder $qb | ||||
| 	 * @param string $fieldActorId | ||||
| 	 */ | ||||
| 	protected function leftJoinCacheActors(IQueryBuilder &$qb, string $fieldActorId) { | ||||
| 
 | ||||
| 		if ($qb->getType() !== QueryBuilder::SELECT) { | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		$expr = $qb->expr(); | ||||
| 		$pf = $this->defaultSelectAlias; | ||||
| 
 | ||||
| //		/** @noinspection PhpMethodParametersCountMismatchInspection */
 | ||||
| //		$qb->selectAlias('s.address', 'service_address')
 | ||||
| //		   ->selectAlias('s.status', 'service_status')
 | ||||
| //		   ->selectAlias('s.config', 'service_config')
 | ||||
| //		   ->selectAlias('s.type', 'service_type')
 | ||||
| //		   ->leftJoin(
 | ||||
| //			   $this->defaultSelectAlias, CoreRequestBuilder::TABLE_SERVICES, 's',
 | ||||
| //			   $expr->eq($pf . '.service_id', 's.id')
 | ||||
| //		   );
 | ||||
| //	}
 | ||||
| 		$qb->selectAlias('ca.id', 'cacheactor_id') | ||||
| 		   ->selectAlias('ca.account', 'cacheactor_account') | ||||
| 		   ->selectAlias('ca.following', 'cacheactor_following') | ||||
| 		   ->selectAlias('ca.followers', 'cacheactor_followers') | ||||
| 		   ->selectAlias('ca.inbox', 'cacheactor_inbox') | ||||
| 		   ->selectAlias('ca.shared_inbox', 'cacheactor_shared_inbox') | ||||
| 		   ->selectAlias('ca.outbox', 'cacheactor_outbox') | ||||
| 		   ->selectAlias('ca.featured', 'cacheactor_featured') | ||||
| 		   ->selectAlias('ca.url', 'cacheactor_url') | ||||
| 		   ->selectAlias('ca.preferred_username', 'cacheactor_preferred_username') | ||||
| 		   ->selectAlias('ca.name', 'cacheactor_name') | ||||
| 		   ->selectAlias('ca.summary', 'cacheactor_summary') | ||||
| 		   ->selectAlias('ca.public_key', 'cacheactor_public_key') | ||||
| 		   ->selectAlias('ca.creation', 'cacheactor_creation') | ||||
| 		   ->leftJoin( | ||||
| 			   $this->defaultSelectAlias, CoreRequestBuilder::TABLE_CACHE_ACTORS, 'ca', | ||||
| 			   $expr->eq($pf . '.' . $fieldActorId, 'ca.id') | ||||
| 		   ); | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @param array $data | ||||
| 	 * | ||||
| 	 * @return Person | ||||
| 	 * @throws InvalidResourceException | ||||
| 	 */ | ||||
| 	protected function parseCacheActorsLeftJoin(array $data): Person { | ||||
| 		$new = []; | ||||
| 
 | ||||
| 		foreach ($data as $k => $v) { | ||||
| 			if (substr($k, 0, 11) === 'cacheactor_') { | ||||
| 				$new[substr($k, 11)] = $v; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		$actor = new Person(); | ||||
| 		$actor->import($new); | ||||
| 
 | ||||
| 		if ($actor->getType() !== 'Person') { | ||||
| 			throw new InvalidResourceException(); | ||||
| 		} | ||||
| 
 | ||||
| 		return $actor; | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -99,14 +99,16 @@ class NotesRequest extends NotesRequestBuilder { | |||
| 
 | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @param string $actorId | ||||
| 	 * @param int $since | ||||
| 	 * @param int $limit | ||||
| 	 * | ||||
| 	 * @return array | ||||
| 	 */ | ||||
| 	public function getPublicNotes($since = 0, $limit = 5): array { | ||||
| 	public function getPublicNotes(int $since = 0, int $limit = 5): array { | ||||
| 		$qb = $this->getNotesSelectSql(); | ||||
| 		$this->limitToRecipient($qb, ActivityService::TO_PUBLIC); | ||||
| 		$this->limitPaginate($qb, $since, $limit); | ||||
| 		$this->leftJoinCacheActors($qb, 'attributed_to'); | ||||
| 
 | ||||
| 		$notes = []; | ||||
| 		$cursor = $qb->execute(); | ||||
|  | @ -126,6 +128,7 @@ class NotesRequest extends NotesRequestBuilder { | |||
| 	public function getNotesForActorId(string $actorId): array { | ||||
| 		$qb = $this->getNotesSelectSql(); | ||||
| 		$this->limitToRecipient($qb, $actorId); | ||||
| 		$this->leftJoinCacheActors($qb, 'attributed_to'); | ||||
| 
 | ||||
| 		$notes = []; | ||||
| 		$cursor = $qb->execute(); | ||||
|  |  | |||
|  | @ -31,8 +31,8 @@ namespace OCA\Social\Db; | |||
| 
 | ||||
| 
 | ||||
| use daita\MySmallPhpTools\Traits\TArrayTools; | ||||
| use OCA\Social\Exceptions\InvalidResourceException; | ||||
| use OCA\Social\Model\ActivityPub\Note; | ||||
| use OCA\Social\Model\Post; | ||||
| use OCP\DB\QueryBuilder\IQueryBuilder; | ||||
| 
 | ||||
| class NotesRequestBuilder extends CoreRequestBuilder { | ||||
|  | @ -118,32 +118,15 @@ class NotesRequestBuilder extends CoreRequestBuilder { | |||
| 			 ->setAttributedTo($data['attributed_to']) | ||||
| 			 ->setInReplyTo($data['in_reply_to']); | ||||
| 
 | ||||
| 		try { | ||||
| 			$actor = $this->parseCacheActorsLeftJoin($data); | ||||
| 			$note->setCompleteDetails(true); | ||||
| 			$note->setActor($actor); | ||||
| 		} catch (InvalidResourceException $e) { | ||||
| 		} | ||||
| 
 | ||||
| 		return $note; | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @param array $data | ||||
| 	 * | ||||
| 	 * @return Post | ||||
| 	 */ | ||||
| 	protected function parsePostsSelectSql($userId, $data): Note { | ||||
| 		$post = new Post($userId); | ||||
| 
 | ||||
| 		$post->setContent($data['content']); | ||||
| 
 | ||||
| //		$note->setId($data['id'])
 | ||||
| //			 ->setTo($data['to'])
 | ||||
| //			 ->setToArray(json_decode($data['to_array'], true))
 | ||||
| //			 ->setCc(json_decode($data['cc'], true))
 | ||||
| //			 ->setBcc(json_decode($data['bcc']));
 | ||||
| //		$note->setContent($data['content'])
 | ||||
| //			 ->setPublished($data['published'])
 | ||||
| //			 ->setAttributedTo($data['attributed_to'])
 | ||||
| //			 ->setInReplyTo($data['in_reply_to']);
 | ||||
| 
 | ||||
| 		return $post; | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -109,6 +109,8 @@ abstract class ACore implements JsonSerializable { | |||
| 	/** @var ICoreService */ | ||||
| 	private $saveAs; | ||||
| 
 | ||||
| 	/** @var bool */ | ||||
| 	private $completeDetails = false; | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Core constructor. | ||||
|  | @ -685,6 +687,25 @@ abstract class ACore implements JsonSerializable { | |||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @return bool | ||||
| 	 */ | ||||
| 	public function isCompleteDetails(): bool { | ||||
| 		return $this->completeDetails; | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @param bool $completeDetails | ||||
| 	 * | ||||
| 	 * @return ACore | ||||
| 	 */ | ||||
| 	public function setCompleteDetails(bool $completeDetails): ACore { | ||||
| 		$this->completeDetails = $completeDetails; | ||||
| 
 | ||||
| 		return $this; | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @param array $data | ||||
| 	 */ | ||||
|  | @ -727,6 +748,9 @@ abstract class ACore implements JsonSerializable { | |||
| 				'actor', $this->getActor() | ||||
| 							  ->getId() | ||||
| 			); | ||||
| 			if ($this->isCompleteDetails()) { | ||||
| 				$this->addEntryItem('actor_info', $this->getActor()); | ||||
| 			} | ||||
| 		} else { | ||||
| 			$this->addEntry('actor', $this->getActorId()); | ||||
| 		} | ||||
|  |  | |||
|  | @ -353,6 +353,10 @@ class Person extends ACore implements JsonSerializable { | |||
| 			 ->setSharedInbox($this->get('shared_inbox', $data, '')) | ||||
| 			 ->setFeatured($this->get('featured', $data, '')) | ||||
| 			 ->setCreation($this->getInt('creation', $data, 0)); | ||||
| 
 | ||||
| 		if ($this->getPreferredUsername() === '') { | ||||
| 			$this->setType('Invalid'); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
|  | @ -371,6 +375,7 @@ class Person extends ACore implements JsonSerializable { | |||
| 				'name'              => $this->getName(), | ||||
| 				'inbox'             => $this->getInbox(), | ||||
| 				'outbox'            => $this->getOutbox(), | ||||
| 				'account'           => $this->getAccount(), | ||||
| 				'following'         => $this->getFollowing(), | ||||
| 				'followers'         => $this->getFollowers(), | ||||
| 				'endpoints'         => | ||||
|  |  | |||
|  | @ -236,17 +236,9 @@ class NoteService implements ICoreService { | |||
| 	 * | ||||
| 	 * @return Note[] | ||||
| 	 */ | ||||
| 	public function getTimeline($since = 0, $limit = 5): array { | ||||
| 		$notes = $this->notesRequest->getPublicNotes($since, $limit); | ||||
| 		$result = []; | ||||
| 		/** @var Note $note */ | ||||
| 		foreach ($notes as $note) { | ||||
| 			$actor = $this->actorService->getActorById($note->getAttributedTo()); | ||||
| 			$noteEnhanced = $note->jsonSerialize(); | ||||
| 			$noteEnhanced['actor'] = $actor->jsonSerialize(); | ||||
| 			$result[] = $noteEnhanced; | ||||
| 		} | ||||
| 		return $result; | ||||
| 	public function getTimeline(int $since = 0, int $limit = 5): array { | ||||
| 		return $this->notesRequest->getPublicNotes($since, $limit); | ||||
| //		return $result;
 | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -175,6 +175,5 @@ class PersonService implements ICoreService { | |||
| 		$this->cacheActorsRequest->save($person); | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Ładowanie…
	
		Reference in New Issue
	
	 Maxence Lange
						Maxence Lange