Completed
Pull Request — master (#7)
by
unknown
13:44
created

FacebookFeed_Item::SmartLink()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 0
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace SunnySideUp\ShareThis;
4
5
use HtmlEditorField;
6
use SunnySideUp\ShareThis\FacebookFeed_Page;
7
use SilverStripe\Security\Permission;
8
use SilverStripe\Control\Director;
9
use SilverStripe\Forms\LiteralField;
10
use SilverStripe\Forms\TextField;
11
use SilverStripe\Core\Injector\Injector;
12
use SunnySideUp\ShareThis\RemoveFacebookItemController;
13
use SilverStripe\ORM\DataObject;
14
15
/**
16
 * FROM: http://www.acornartwork.com/blog/2010/04/19/tutorial-facebook-rss-feed-parser-in-pure-php/
17
 * EXAMPLE:
18
 *		//Run the function with the url and a number as arguments
19
 *		$fb = new TheFaceBook_communicator();
20
 *		$dos = $fb->fetchFBFeed('http://facebook.com/feeds/status.php?id=xxxxxx&viewer=xxxxxx&key=xxxxx&format=rss20', 3);
21
 *		//Print Facebook status updates
22
 *		echo '<ul class="fb-updates">';
23
 *			 foreach ($dos as $do) {
24
 *					echo '<li>';
25
 *					echo '<span class="update">' .$do->Description. '</span>';
26
 *					echo '<span class="date">' .$do->Date. '</span>';
27
 *					echo '<span class="link"><a href="' .$do->Link. '">more</a></span>';
28
 *					echo '</li>';
29
 *			 }
30
 *		echo '</ul>';
31
 *
32
 *  SEE README on getting facebook URL for RSS Feed.
33
 *
34
 *
35
 **/
36
37
class FacebookFeed_Item extends DataObject
38
{
39
    private static $db = array(
40
        "Title" => "varchar(255)",
41
        "KeepOnTop" => "Boolean",
42
        "Hide" => "Boolean",
43
        "UID" => "varchar(32)",
44
        "Author" => "Varchar(244)",
45
        "Description" => "HTMLText",
46
        "DescriptionWithShortLink" => "HTMLText",
47
        "Link" => "Varchar(244)",
48
        "PictureLink" => "Text"
49
    );
50
51
52
    private static $summary_fields = array(
53
        "Created.Nice" => "Created",
54
        "FacebookFeed_Page.Title" => "Feed",
55
        "Title" => "Title",
56
        "KeepOnTopNice" => "Keep on top",
57
        "HideNice" => "Hide",
58
    );
59
60
61
    private static $has_one = array(
62
        "FacebookFeed_Page" => FacebookFeed_Page::class
63
    );
64
65
    private static $indexes = array(
66
        "UID" => true
67
    );
68
69
    private static $casting = array(
70
        'KeepOnTopNice' => 'Varchar',
71
        'HideNice' => 'Varchar',
72
        'FacebookPostLink' => 'Varchar'
73
    );
74
75
    private static $searchable_fields = array(
76
        'Title' => 'PartialMatchFilter',
77
        'Author' => 'PartialMatchFilter',
78
        'Description' => 'PartialMatchFilter',
79
        'Hide' => true,
80
        'KeepOnTop' => true
81
    );
82
83
    private static $default_sort = "\"Created\" DESC";
84
85
    public function canCreate($member = null, $context = [])
86
    {
87
        return false;
88
    }
89
90
    public function canView($member = null)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
91
    {
92
        return Permission::checkMember($member, 'SOCIAL_MEDIA');
93
    }
94
95
    public function canEdit($member = null)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
96
    {
97
        return Permission::checkMember($member, 'SOCIAL_MEDIA');
98
    }
99
100
    public function canDelete($member = null)
101
    {
102
        return false;
103
    }
104
105
    private static $singular_name = "Facebook Item";
106
    public function i18n_singular_name()
107
    {
108
        return "Facebook Item";
109
    }
110
111
    private static $plural_name = "Facebook Items";
112
    public function i18n_plural_name()
113
    {
114
        return "Facebook Items";
115
    }
116
117
    public function onBeforeWrite()
118
    {
119
        parent::onBeforeWrite();
120
        $this->DescriptionWithShortLink = $this->Description;
121
        //$this->DescriptionWithShortLink = $this->createDescriptionWithShortLinks();
122
    }
123
124
    protected function createDescriptionWithShortLinks()
125
    {
126
        require_once(Director::baseFolder()."/".SS_SHARETHIS_DIR.'/code/api/thirdparty/simple_html_dom.php');
127
        $html = str_get_html($this->Description);
128
        if ($html) {
129
            foreach ($html->find('text') as $element) {
130
                //what exactly does it do?
131
                if (! in_array($element->parent()->tag, array('a', 'img'))) {
132
                    $element->innertext = $this->replaceLinksWithProperOnes($element->innertext);
133
                }
134
            }
135
        } else {
136
            $this->Hide = true;
137
            $this->write();
138
        }
139
    }
140
141
    protected function replaceLinksWithProperOnes($text)
142
    {
143
        $rexProtocol = '(https?://)?';
144
        $rexDomain   = '((?:[-a-zA-Z0-9]{1,63}\.)+[-a-zA-Z0-9]{2,63}|(?:[0-9]{1,3}\.){3}[0-9]{1,3})';
145
        $rexPort     = '(:[0-9]{1,5})?';
146
        $rexPath     = '(/[!$-/0-9:;=@_\':;!a-zA-Z\x7f-\xff]*?)?';
147
        $rexQuery    = '(\?[!$-/0-9:;=@_\':;!a-zA-Z\x7f-\xff]+?)?';
148
        $rexFragment = '(#[!$-/0-9:;=@_\':;!a-zA-Z\x7f-\xff]+?)?';
149
        $outcome  = "";
150
        $validTlds = array_fill_keys(explode(" ", ".aero .asia .biz .cat .com .coop .edu .gov .info .int .jobs .mil .mobi .museum .name .net .org .pro .tel .travel .ac .ad .ae .af .ag .ai .al .am .an .ao .aq .ar .as .at .au .aw .ax .az .ba .bb .bd .be .bf .bg .bh .bi .bj .bm .bn .bo .br .bs .bt .bv .bw .by .bz .ca .cc .cd .cf .cg .ch .ci .ck .cl .cm .cn .co .cr .cu .cv .cx .cy .cz .de .dj .dk .dm .do .dz .ec .ee .eg .er .es .et .eu .fi .fj .fk .fm .fo .fr .ga .gb .gd .ge .gf .gg .gh .gi .gl .gm .gn .gp .gq .gr .gs .gt .gu .gw .gy .hk .hm .hn .hr .ht .hu .id .ie .il .im .in .io .iq .ir .is .it .je .jm .jo .jp .ke .kg .kh .ki .km .kn .kp .kr .kw .ky .kz .la .lb .lc .li .lk .lr .ls .lt .lu .lv .ly .ma .mc .md .me .mg .mh .mk .ml .mm .mn .mo .mp .mq .mr .ms .mt .mu .mv .mw .mx .my .mz .na .nc .ne .nf .ng .ni .nl .no .np .nr .nu .nz .om .pa .pe .pf .pg .ph .pk .pl .pm .pn .pr .ps .pt .pw .py .qa .re .ro .rs .ru .rw .sa .sb .sc .sd .se .sg .sh .si .sj .sk .sl .sm .sn .so .sr .st .su .sv .sy .sz .tc .td .tf .tg .th .tj .tk .tl .tm .tn .to .tp .tr .tt .tv .tw .tz .ua .ug .uk .us .uy .uz .va .vc .ve .vg .vi .vn .vu .wf .ws .ye .yt .yu .za .zm .zw .xn--0zwm56d .xn--11b5bs3a9aj6g .xn--80akhbyknj4f .xn--9t4b11yi5a .xn--deba0ad .xn--g6w251d .xn--hgbk6aj7f53bba .xn--hlcj6aya9esc7a .xn--jxalpdlp .xn--kgbechtv .xn--zckzah .arpa"), true);
151
152
        $position = 0;
153
        while (preg_match("{\\b$rexProtocol$rexDomain$rexPort$rexPath$rexQuery$rexFragment(?=[?.!,;:\"]?(\s|$))}", $text, $match, PREG_OFFSET_CAPTURE, $position)) {
154
            list($url, $urlPosition) = $match[0];
155
156
            // Print the text leading up to the URL.
157
            $outcome .= (htmlspecialchars(substr($text, $position, $urlPosition - $position)));
158
159
            $domain = $match[2][0];
160
            $port   = $match[3][0];
161
            $path   = $match[4][0];
162
163
            // Check if the TLD is valid - or that $domain is an IP address.
164
            $tld = strtolower(strrchr($domain, '.'));
165
            if (preg_match('{\.[0-9]{1,3}}', $tld) || isset($validTlds[$tld])) {
166
                // Prepend http:// if no protocol specified
167
                $completeUrl = $match[1][0] ? $url : "http://$url";
168
169
                // Print the hyperlink.
170
                $outcome .= sprintf('<a href="%s">%s</a>', htmlspecialchars($completeUrl), htmlspecialchars("$domain$port$path"));
171
            } else {
172
                // Not a valid URL.
173
                $outcome .= (htmlspecialchars($url));
174
            }
175
176
            // Continue text parsing from after the URL.
177
            $position = $urlPosition + strlen($url);
178
        }
179
180
        // Print the remainder of the text.
181
        $outcome .= ((substr($text, $position)));
182
        return $outcome;
183
    }
184
185
    public function getCMSFields()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
186
    {
187
        $fields = parent::getCMSFields();
188
        $fields->removeByName("UID");
189
        $fields->removeByName("PictureLink");
190
        if ($this->PictureLink) {
191
            $fields->addFieldToTab("Root.Main", new LiteralField("PictureLinkIMG", "<img src=\"".$this->PictureLink."\" alt=\"\" />"), "Author");
192
        }
193
        if ($this->Link) {
194
            $fields->addFieldToTab("Root.Main", new LiteralField("LinkLink", "<h2><a href=\"".$this->Link."\" >go to link final link: ".substr($this->Link, 0, 45)."...</a></h2>"), "Author");
195
            $fields->addFieldToTab("Root.Main", new LiteralField("LinkLink", "<h2><a href=\"".$this->getFacebookPostLink()."\" >go to face book post: ".substr($this->getFacebookPostLink(), 0, 45)."...</a></h2>"), "Author");
196
            $fields->addFieldToTab("Root.RawData", new TextField("Link", "Link"));
197
        }
198
        if ($this->Description) {
199
            $fields->addFieldToTab("Root.RawData", new HtmlEditorField("Description"));
200
            $fields->addFieldToTab("Root.Main", new HtmlEditorField("DescriptionWithShortLink", "Edited Description"));
201
        }
202
        return $fields;
203
    }
204
205
    public function KeepOnTopNice()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
206
    {
207
        return $this->dbObject('KeepOnTop')->Nice();
208
    }
209
210
    public function HideNice()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
211
    {
212
        return $this->dbObject('Hide')->Nice();
213
    }
214
215
    /**
216
     * @return string
217
     */
218
    public function getFacebookPostLink()
219
    {
220
        return "https://facebook.com/" . $this->UID;
221
    }
222
223
    /**
224
     * is the link attached to the FB post a link back to this site?
225
     *
226
     * @return bool
227
     */
228
    public function IsLinkBackToSite()
229
    {
230
        $currentURL = Director::absoluteBaseURL();
231
        if (strpos($this->Link, $currentURL) === false) {
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return !(strpos($this->L...currentURL) === false);.
Loading history...
232
            return false;
233
        }
234
        return true;
235
    }
236
237
    /**
238
     * returns a link back to the same site if that is what the FB post links to
239
     * or a link to FB if it ultimately links to third-party site.
240
     *
241
     * @return strring
242
     */
243
    public function SmartLink()
244
    {
245
        if ($this->IsLinkBackToSite()) {
246
            return $this->Link;
247
        } else {
248
            return $this->getFacebookPostLink();
249
        }
250
    }
251
252
    public function fbpostExists()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
253
    {
254
        $exists = true;
255
        $handle = curl_init($this->getFacebookPostLink());
256
        curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
257
258
        /* Get the HTML or whatever is linked in $url. */
259
        $response = curl_exec($handle);
0 ignored issues
show
Unused Code introduced by
$response is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
260
261
        /* Check for 404 (file not found). */
262
        $httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
263
        if ($httpCode !== 200 && $httpCode !== 301) {
264
            $exists = false;
265
        }
266
267
        curl_close($handle);
268
269
        return $exists();
270
    }
271
272
    public function canRemove()
273
    {
274
        return Permission::check('CMS_ACCESS_CMSMain') ? true : false;
275
    }
276
277
    public function RemoveLink()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
278
    {
279
        $obj = Injector::inst()->get(RemoveFacebookItemController::class);
280
281
        return $obj->Link('remove/'.$this->UID.'/');
282
    }
283
}
284