Skip to content

Commit 362e1ea

Browse files
committed
Prepare to use
1 parent e055bbd commit 362e1ea

File tree

7 files changed

+802
-0
lines changed

7 files changed

+802
-0
lines changed

.gitignore

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# System
2+
.*
3+
!.gitignore
4+
5+
# Composer
6+
/vendor/*
7+
composer.lock
8+
9+
# Test
10+
phpunit.xml

composer.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"name": "asika/autolink",
3+
"description": "Auto convert url to link anchor.",
4+
"type": "library",
5+
"require": {
6+
"windwalker/dom": "~2.0@stable"
7+
},
8+
"require-dev": {
9+
"windwalker/test": "~2.0@stable"
10+
},
11+
"autoload": {
12+
"psr-4": {
13+
"Asika\\": "src/"
14+
}
15+
},
16+
"license": "LGPL-3.0+",
17+
"authors": [
18+
{
19+
"name": "Simon Asika",
20+
"email": "asika32764@gmail.com"
21+
}
22+
],
23+
"minimum-stability": "beta"
24+
}

phpunit.dist.xml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit bootstrap="vendor/autoload.php" colors="false"
3+
convertErrorsToExceptions="true"
4+
convertNoticesToExceptions="true"
5+
convertWarningsToExceptions="true"
6+
strict="true"
7+
syntaxCheck="true"
8+
>
9+
<php>
10+
<ini name="error_reporting" value="32767" />
11+
</php>
12+
<testsuites>
13+
<testsuite name="Unit">
14+
<directory>test</directory>
15+
</testsuite>
16+
</testsuites>
17+
</phpunit>

src/Autolink.php

Lines changed: 333 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,333 @@
1+
<?php
2+
/**
3+
* Part of php-autolink project.
4+
*
5+
* @copyright Copyright (C) 2015 {ORGANIZATION}. All rights reserved.
6+
* @license GNU General Public License version 2 or later;
7+
*/
8+
9+
namespace Asika;
10+
11+
use Windwalker\Dom\HtmlElement;
12+
13+
/**
14+
* The Autolink class.
15+
*
16+
* @since {DEPLOY_VERSION}
17+
*/
18+
class Autolink
19+
{
20+
/**
21+
* Property options.
22+
*
23+
* @var array
24+
*/
25+
public $options = array(
26+
'strip_scheme' => false,
27+
'text_limit' => false,
28+
'auto_title' => false
29+
);
30+
31+
/**
32+
* Property schemes.
33+
*
34+
* @var array
35+
*/
36+
protected $schemes = array(
37+
'http',
38+
'https',
39+
'ftp',
40+
'ftps'
41+
);
42+
43+
/**
44+
* Class init.
45+
*
46+
* @param array $options Basic options.
47+
* @param array $schemes
48+
*/
49+
public function __construct($options = array(), $schemes = array())
50+
{
51+
$this->options = array_merge($this->options, (array) $options);
52+
53+
$this->setSchemes(array_merge($this->schemes, $schemes));
54+
}
55+
56+
/**
57+
* render
58+
*
59+
* @param string $text
60+
* @param array $attribs
61+
*
62+
* @return string
63+
*/
64+
public function render($text, $attribs = array())
65+
{
66+
$self = $this;
67+
68+
$regex = "/(([a-zA-Z]*=\")*(" . $this->getSchemes(true) . ")\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?)/";
69+
70+
return preg_replace_callback(
71+
$regex,
72+
function($matches) use ($self, $attribs)
73+
{
74+
preg_match('/[a-zA-Z]*\=\"(.*)\"/', $matches[0], $inElements);
75+
76+
if (!$inElements)
77+
{
78+
return $self->convert($matches[0]);
79+
}
80+
81+
return $matches[0];
82+
},
83+
$text
84+
);
85+
}
86+
87+
/**
88+
* renderEmail
89+
*
90+
* @param string $text
91+
* @param array $attribs
92+
*
93+
* @return string
94+
*/
95+
public function renderEmail($text, $attribs = array())
96+
{
97+
$regex = "/(([a-zA-Z]*=\")*\S+@\S+\.\S+)/";
98+
99+
return preg_replace_callback(
100+
$regex,
101+
function($matches) use ($attribs)
102+
{
103+
preg_match('/[a-zA-Z]*\=\"(.*)\"/', $matches[0], $inElements);
104+
105+
if (!$inElements)
106+
{
107+
$attribs['href'] = 'mailto:' . htmlspecialchars($matches[0]);
108+
109+
return (string) new HtmlElement('a', htmlspecialchars($matches[0]), $attribs);
110+
}
111+
112+
return $matches[0];
113+
},
114+
$text
115+
);
116+
}
117+
118+
/**
119+
* convert
120+
*
121+
* @param string $url
122+
* @param array $attribs
123+
*
124+
* @return string
125+
*/
126+
public function convert($url, $attribs = array())
127+
{
128+
$content = $url;
129+
130+
if ($this->stripScheme())
131+
{
132+
if (preg_match('!^(' . $this->getSchemes(true) . ')://!i', $content, $m))
133+
{
134+
$content = substr($content, strlen($m[1]) + 3);
135+
}
136+
}
137+
138+
if ($limit = $this->textLimit())
139+
{
140+
if (is_callable($limit))
141+
{
142+
$content = call_user_func($limit, $content);
143+
}
144+
else
145+
{
146+
$content = $this->shorten($content, $limit);
147+
}
148+
}
149+
150+
$attribs['href'] = htmlspecialchars($url);
151+
152+
if ($this->autoTitle())
153+
{
154+
$attribs['title'] = htmlspecialchars($url);
155+
}
156+
157+
return (string) new HtmlElement('a', htmlspecialchars($content), $attribs);
158+
}
159+
160+
/**
161+
* autolinkLabel
162+
*
163+
* @param string $text
164+
* @param int $limit
165+
*
166+
* @return string
167+
*/
168+
public function shorten($text, $limit)
169+
{
170+
if (!$limit)
171+
{
172+
return $text;
173+
}
174+
175+
if (strlen($text) > $limit)
176+
{
177+
return substr($text, 0, $limit - 3) . '...';
178+
}
179+
180+
return $text;
181+
}
182+
183+
/**
184+
* stripScheme
185+
*
186+
* @param mixed $value
187+
*
188+
* @return mixed|static
189+
*/
190+
public function stripScheme($value = null)
191+
{
192+
return $this->optionAccess('strip_scheme', $value);
193+
}
194+
195+
/**
196+
* textLimit
197+
*
198+
* @param int|callable $value
199+
*
200+
* @return int|callable|static
201+
*/
202+
public function textLimit($value = null)
203+
{
204+
return $this->optionAccess('text_limit', $value);
205+
}
206+
207+
/**
208+
* autoTitle
209+
*
210+
* @param mixed $value
211+
*
212+
* @return mixed|static
213+
*/
214+
public function autoTitle($value = null)
215+
{
216+
return $this->optionAccess('auto_title', $value);
217+
}
218+
219+
/**
220+
* optionAccess
221+
*
222+
* @param string $name
223+
* @param mixed $value
224+
*
225+
* @return mixed|static
226+
*/
227+
protected function optionAccess($name, $value = null)
228+
{
229+
if ($value === null)
230+
{
231+
return isset($this->options[$name]) ? $this->options[$name] : null;
232+
}
233+
234+
$this->options[$name] = $value;
235+
236+
return $this;
237+
}
238+
239+
/**
240+
* addScheme
241+
*
242+
* @param string $scheme
243+
*
244+
* @return static
245+
*/
246+
public function addScheme($scheme)
247+
{
248+
$scheme = strtolower($scheme);
249+
250+
if (!in_array($scheme, $this->schemes))
251+
{
252+
$this->schemes[] = $scheme;
253+
}
254+
255+
return $this;
256+
}
257+
258+
/**
259+
* removeScheme
260+
*
261+
* @param string $scheme
262+
*
263+
* @return static
264+
*/
265+
public function removeScheme($scheme)
266+
{
267+
$index = array_search($scheme, $this->schemes);
268+
269+
if ($index !== false)
270+
{
271+
unset($this->schemes[$index]);
272+
}
273+
274+
return $this;
275+
}
276+
277+
/**
278+
* Method to get property Options
279+
*
280+
* @return array
281+
*/
282+
public function getOptions()
283+
{
284+
return $this->options;
285+
}
286+
287+
/**
288+
* Method to set property options
289+
*
290+
* @param array $options
291+
*
292+
* @return static Return self to support chaining.
293+
*/
294+
public function setOptions($options)
295+
{
296+
$this->options = $options;
297+
298+
return $this;
299+
}
300+
301+
/**
302+
* Method to get property Schemes
303+
*
304+
* @param bool $regex
305+
*
306+
* @return array|string
307+
*/
308+
public function getSchemes($regex = false)
309+
{
310+
if ($regex)
311+
{
312+
return implode('|', $this->schemes);
313+
}
314+
315+
return $this->schemes;
316+
}
317+
318+
/**
319+
* Method to set property schemes
320+
*
321+
* @param array $schemes
322+
*
323+
* @return static Return self to support chaining.
324+
*/
325+
public function setSchemes($schemes)
326+
{
327+
$schemes = array_unique(array_map('strtolower', (array) $schemes));
328+
329+
$this->schemes = $schemes;
330+
331+
return $this;
332+
}
333+
}

0 commit comments

Comments
 (0)