Passed
Push — master ( 93dec2...ac6166 )
by Paweł
02:14
created

AccountQuery   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 94
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 12
dl 0
loc 94
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A findOne() 0 8 1
A findLastPosts() 0 15 3
A fetchContentAsArray() 0 8 1
B findPosts() 0 30 6
1
<?php
2
/**
3
 * Created for IG Client.
4
 * User: jakim <[email protected]>
5
 * Date: 14.03.2018
6
 */
7
8
namespace Jakim\Query;
9
10
11
use Jakim\Base\Query;
12
use Jakim\Helper\JsonHelper;
13
use jakim\ig\Endpoint;
14
use jakim\ig\Url;
15
use Jakim\Mapper\AccountDetails;
16
use Jakim\Mapper\AccountMedia;
17
use Jakim\Model\Account;
18
use Jakim\Model\Post;
19
20
class AccountQuery extends Query
21
{
22
    const MAX_POSTS_PER_PAGE = 100;
23
    public $postsPerPage = 100;
24
25
    protected $accountDetailsMapper;
26
    protected $accountMediaMapper;
27
28
    public function __construct($httpClient, AccountDetails $accountDetailsMapper = null, AccountMedia $accountMediaMapper = null)
29
    {
30
        parent::__construct($httpClient);
31
        $this->accountDetailsMapper = $accountDetailsMapper ?? new AccountDetails();
32
        $this->accountMediaMapper = $accountMediaMapper ?? new AccountMedia();
33
    }
34
35
    public function findOne(string $username): Account
36
    {
37
        $url = Url::account($username);
38
        $data = $this->fetchContentAsArray($url);
39
40
        $data = $this->accountDetailsMapper->normalizeData(Account::class, $data);
41
42
        return $this->accountDetailsMapper->populate(Account::class, $data);
43
    }
44
45
    /**
46
     * @param string $username
47
     * @param int $limit Max 12, for more see findPosts()
48
     * @return \Generator
49
     *
50
     * @see \Jakim\Query\AccountQuery::findPosts
51
     */
52
    public function findLastPosts(string $username, int $limit = 12)
53
    {
54
        $url = Url::account($username);
55
        $data = $this->fetchContentAsArray($url);
56
57
        $items = $this->accountDetailsMapper->normalizeData(Post::class, $data);
58
59
        $n = 0;
60
        foreach ($items as $item) {
61
            $model = $this->accountDetailsMapper->populate(Post::class, $item);
62
63
            yield $model;
64
65
            if (++$n >= $limit) {
66
                break;
67
            }
68
        }
69
    }
70
71
    public function findPosts(string $username, int $limit = 100)
72
    {
73
        if ($limit <= 12) {
74
            yield from $this->findLastPosts($username, $limit);
75
76
            return;
77
        }
78
79
        $account = $this->findOne($username);
80
81
        $n = 0;
82
        $nextPage = '';
83
        $this->postsPerPage = (int)$this->postsPerPage > self::MAX_POSTS_PER_PAGE ? self::MAX_POSTS_PER_PAGE : $this->postsPerPage;
84
85
        while ($nextPage !== null) {
86
            $url = Endpoint::accountMedia($account->id, $this->postsPerPage, [
87
                'variables' => ['after' => $nextPage],
88
            ]);
89
            $data = parent::fetchContentAsArray($url);
90
91
            $nextPage = $this->accountMediaMapper->nextPage($data);
92
93
            $items = $this->accountMediaMapper->normalizeData(Post::class, $data);
94
95
            foreach ($items as $item) {
96
97
                yield $this->accountMediaMapper->populate(Post::class, $item);
98
99
                if (++$n >= $limit) {
100
                    break 2;
101
                }
102
            }
103
        }
104
    }
105
106
    protected function fetchContentAsArray(string $url): ?array
107
    {
108
        $res = $this->httpClient->get($url);
109
        $content = $res->getBody()->getContents();
110
111
        preg_match('/\_sharedData \= (.*?)\;\<\/script\>/s', $content, $matches);
112
113
        return JsonHelper::decode($matches['1']);
114
    }
115
}