Issues (45)

src/helpers/TwitterHelper.php (3 issues)

1
<?php
2
/**
3
 * @link      https://dukt.net/twitter/
4
 * @copyright Copyright (c) Dukt
5
 * @license   https://github.com/dukt/twitter/blob/master/LICENSE.md
6
 */
7
8
namespace dukt\twitter\helpers;
9
10
use Craft;
11
use craft\helpers\FileHelper;
12
use DateInterval;
13
use DateTime;
14
use dukt\twitter\Plugin;
15
use GuzzleHttp\Exception\GuzzleException;
16
17
/**
18
 * Twitter Helper
19
 *
20
 * @author Dukt <[email protected]>
21
 * @since  3.0
22
 */
23
class TwitterHelper
24
{
25
    // Public Methods
26
    // =========================================================================
27
28
    /**
29
     * Returns a user image from a Twitter user ID for given size. Default size is 48.
30
     *
31
     * @param int $remoteUserId
32
     * @param int $size
33
     *
34
     * @return string|null
35
     * @throws GuzzleException
36
     * @throws \craft\errors\ImageException
37
     * @throws \yii\base\Exception
38
     */
39
    public static function getUserProfileImageResourceUrl($remoteUserId, $size = 48)
40
    {
41
        $baseDir = Craft::$app->getPath()->getRuntimePath().DIRECTORY_SEPARATOR.'twitter'.DIRECTORY_SEPARATOR.'userimages'.DIRECTORY_SEPARATOR.$remoteUserId;
42
        $originalDir = $baseDir.DIRECTORY_SEPARATOR.'original';
43
        $dir = $baseDir.DIRECTORY_SEPARATOR.$size;
44
        $file = null;
45
46
        if (is_dir($dir)) {
47
            $files = FileHelper::findFiles($dir);
48
49
            if (count($files) > 0) {
50
                $file = $files[0];
51
            }
52
        }
53
54
        if (!$file) {
55
            // Retrieve original image
56
            $originalPath = null;
57
58
            if (is_dir($originalDir)) {
59
                $originalFiles = FileHelper::findFiles($originalDir);
60
61
                if (count($originalFiles) > 0) {
62
                    $originalPath = $originalFiles[0];
63
                }
64
            }
65
            if (!$originalPath) {
66
                $user = Plugin::getInstance()->getApi()->getUserById($remoteUserId);
67
68
                $url = str_replace('_normal', '', $user['profile_image_url_https']);
69
                $name = pathinfo($url, PATHINFO_BASENAME);
70
                $originalPath = $originalDir.DIRECTORY_SEPARATOR.$name;
0 ignored issues
show
Are you sure $name of type array|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

70
                $originalPath = $originalDir.DIRECTORY_SEPARATOR./** @scrutinizer ignore-type */ $name;
Loading history...
71
72
                FileHelper::createDirectory($originalDir);
73
                $client = new \GuzzleHttp\Client();
74
                $response = $client->request('GET', $url, [
75
                    'sink' => $originalPath,
76
                ]);
77
78
                if ($response->getStatusCode() != 200) {
79
                    return null;
80
                }
81
            } else {
82
                $name = pathinfo($originalPath, PATHINFO_BASENAME);
83
            }
84
85
            // Generate the thumb
86
            $path = $dir.DIRECTORY_SEPARATOR.$name;
87
            FileHelper::createDirectory($dir);
88
            Craft::$app->getImages()->loadImage($originalPath, false, $size)
89
                ->scaleToFit($size, $size)
90
                ->saveAs($path);
91
        } else {
92
            $name = pathinfo($file, PATHINFO_BASENAME);
93
        }
94
95
        return Craft::$app->getAssetManager()->getPublishedUrl($dir, true)."/{$name}";
0 ignored issues
show
The call to yii\web\AssetManager::getPublishedUrl() has too many arguments starting with true. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

95
        return Craft::$app->getAssetManager()->/** @scrutinizer ignore-call */ getPublishedUrl($dir, true)."/{$name}";

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
Are you sure Craft::app->getAssetMana...ublishedUrl($dir, true) of type false|mixed|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

95
        return /** @scrutinizer ignore-type */ Craft::$app->getAssetManager()->getPublishedUrl($dir, true)."/{$name}";
Loading history...
96
    }
97
98
    /**
99
     * Extract the tweet ID from a tweet URL, or simply returns the ID.
100
     *
101
     * @param $urlOrId
102
     *
103
     * @return int|null
104
     */
105
    public static function extractTweetId($urlOrId)
106
    {
107
        if (preg_match('/^\d+$/', $urlOrId)) {
108
            // If the string is a number, return it right away
109
            return (int)$urlOrId;
110
        }
111
112
        if (preg_match('/\/status(es)?\/(\d+)\/?$/', $urlOrId, $matches)) {
113
            // Extract the tweet ID from the URL
114
            return (int)$matches[2];
115
        }
116
117
        return null;
118
    }
119
120
    /**
121
     * Formats a duration to seconds.
122
     *
123
     * @param string $duration
124
     *
125
     * @return int
126
     * @throws \Exception
127
     */
128
    public static function durationToSeconds($duration): int
129
    {
130
        $date = new DateTime;
131
        $current = $date->getTimestamp();
132
        $date->add(new DateInterval($duration));
133
134
        return $date->getTimestamp() - $current;
135
    }
136
137
    /**
138
     * Formats a date to a time ago string like “3 days ago”.
139
     *
140
     * @param DateTime|string $date
141
     *
142
     * @return string
143
     */
144
    public static function timeAgo($date): string
145
    {
146
        if (is_string($date)) {
147
            $date = new DateTime($date);
148
        }
149
150
        $now = new DateTime();
151
152
        $difference = $now->getTimestamp() - $date->getTimestamp();
153
154
        $duration = self::secondsToHumanTimeDuration($difference);
155
156
        return Craft::t('twitter', '{duration} ago', ['duration' => $duration]);
157
    }
158
159
    /**
160
     * Seconds to human duration.
161
     *
162
     * @param int $seconds The number of seconds.
163
     * @return string The duration.
164
     */
165
    public static function secondsToHumanTimeDuration($seconds): string
166
    {
167
        $periods = ['second', 'minute', 'hour', 'day', 'week', 'month', 'year', 'decade'];
168
        $lengths = ['60', '60', '24', '7', '4.35', '12', '10'];
169
170
        $difference = $seconds;
171
172
        for ($j = 0; $difference >= $lengths[$j] && $j < count($lengths) - 1; $j++) {
173
            $difference /= $lengths[$j];
174
        }
175
176
        $difference = round($difference);
177
178
        if ($difference != 1) {
179
            $periods[$j] .= 's';
180
        }
181
182
        return Craft::t('twitter', '{difference} {period}', ['difference' => $difference, 'period' => $periods[$j]]);
183
    }
184
}
185