diff --git a/assets/bg1.png b/assets/bg1.png new file mode 100644 index 0000000..f57c567 Binary files /dev/null and b/assets/bg1.png differ diff --git a/assets/bg2.png b/assets/bg2.png new file mode 100644 index 0000000..e5b81de Binary files /dev/null and b/assets/bg2.png differ diff --git a/assets/bg3.png b/assets/bg3.png new file mode 100644 index 0000000..6874c19 Binary files /dev/null and b/assets/bg3.png differ diff --git a/assets/fanstuffgarden.gif b/assets/fanstuffgarden.gif new file mode 100644 index 0000000..96b6c99 Binary files /dev/null and b/assets/fanstuffgarden.gif differ diff --git a/assets/pics.png b/assets/pics.png new file mode 100644 index 0000000..b231718 Binary files /dev/null and b/assets/pics.png differ diff --git a/assets/picsfooter.png b/assets/picsfooter.png new file mode 100644 index 0000000..23d4d42 Binary files /dev/null and b/assets/picsfooter.png differ diff --git a/favicon.png b/favicon.png new file mode 100644 index 0000000..da301ec Binary files /dev/null and b/favicon.png differ diff --git a/feed.php b/feed.php new file mode 100644 index 0000000..3a59c27 --- /dev/null +++ b/feed.php @@ -0,0 +1,273 @@ +channel) { + return self::fromRss($xml); + } else { + return self::fromAtom($xml); + } + } + + + /** + * Loads RSS feed. + * @param string RSS feed URL + * @param string optional user name + * @param string optional password + * @return Feed + * @throws FeedException + */ + public static function loadRss($url, $user = null, $pass = null) + { + return self::fromRss(self::loadXml($url, $user, $pass)); + } + + + /** + * Loads Atom feed. + * @param string Atom feed URL + * @param string optional user name + * @param string optional password + * @return Feed + * @throws FeedException + */ + public static function loadAtom($url, $user = null, $pass = null) + { + return self::fromAtom(self::loadXml($url, $user, $pass)); + } + + + private static function fromRss(SimpleXMLElement $xml) + { + if (!$xml->channel) { + throw new FeedException('Invalid feed.'); + } + + self::adjustNamespaces($xml); + + foreach ($xml->channel->item as $item) { + // converts namespaces to dotted tags + self::adjustNamespaces($item); + + // generate 'url' & 'timestamp' tags + $item->url = (string) $item->link; + if (isset($item->{'dc:date'})) { + $item->timestamp = strtotime($item->{'dc:date'}); + } elseif (isset($item->pubDate)) { + $item->timestamp = strtotime($item->pubDate); + } + } + $feed = new self; + $feed->xml = $xml->channel; + return $feed; + } + + + private static function fromAtom(SimpleXMLElement $xml) + { + if (!in_array('http://www.w3.org/2005/Atom', $xml->getDocNamespaces(), true) + && !in_array('http://purl.org/atom/ns#', $xml->getDocNamespaces(), true) + ) { + throw new FeedException('Invalid feed.'); + } + + // generate 'url' & 'timestamp' tags + foreach ($xml->entry as $entry) { + $entry->url = (string) $entry->link['href']; + $entry->timestamp = strtotime($entry->updated); + } + $feed = new self; + $feed->xml = $xml; + return $feed; + } + + + /** + * Returns property value. Do not call directly. + * @param string tag name + * @return SimpleXMLElement + */ + public function __get($name) + { + return $this->xml->{$name}; + } + + + /** + * Sets value of a property. Do not call directly. + * @param string property name + * @param mixed property value + * @return void + */ + public function __set($name, $value) + { + throw new Exception("Cannot assign to a read-only property '$name'."); + } + + + /** + * Converts a SimpleXMLElement into an array. + * @param SimpleXMLElement + * @return array + */ + public function toArray(SimpleXMLElement $xml = null) + { + if ($xml === null) { + $xml = $this->xml; + } + + if (!$xml->children()) { + return (string) $xml; + } + + $arr = []; + foreach ($xml->children() as $tag => $child) { + if (count($xml->$tag) === 1) { + $arr[$tag] = $this->toArray($child); + } else { + $arr[$tag][] = $this->toArray($child); + } + } + + return $arr; + } + + + /** + * Load XML from cache or HTTP. + * @param string + * @param string + * @param string + * @return SimpleXMLElement + * @throws FeedException + */ + private static function loadXml($url, $user, $pass) + { + $e = self::$cacheExpire; + $cacheFile = self::$cacheDir . '/feed.' . md5(serialize(func_get_args())) . '.xml'; + + if (self::$cacheDir + && (time() - @filemtime($cacheFile) <= (is_string($e) ? strtotime($e) - time() : $e)) + && $data = @file_get_contents($cacheFile) + ) { + // ok + } elseif ($data = trim(self::httpRequest($url, $user, $pass))) { + if (self::$cacheDir) { + file_put_contents($cacheFile, $data); + } + } elseif (self::$cacheDir && $data = @file_get_contents($cacheFile)) { + // ok + } else { + throw new FeedException('Cannot load feed.'); + } + + return new SimpleXMLElement($data, LIBXML_NOWARNING | LIBXML_NOERROR | LIBXML_NOCDATA); + } + + + /** + * Process HTTP request. + * @param string + * @param string + * @param string + * @return string|false + * @throws FeedException + */ + private static function httpRequest($url, $user, $pass) + { + if (extension_loaded('curl')) { + $curl = curl_init(); + curl_setopt($curl, CURLOPT_URL, $url); + if ($user !== null || $pass !== null) { + curl_setopt($curl, CURLOPT_USERPWD, "$user:$pass"); + } + curl_setopt($curl, CURLOPT_USERAGENT, self::$userAgent); // some feeds require a user agent + curl_setopt($curl, CURLOPT_HEADER, false); + curl_setopt($curl, CURLOPT_TIMEOUT, 20); + curl_setopt($curl, CURLOPT_ENCODING, ''); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); // no echo, just return result + curl_setopt($curl, CURLOPT_USERAGENT, ''); + if (!ini_get('open_basedir')) { + curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); // sometime is useful :) + } + $result = curl_exec($curl); + return curl_errno($curl) === 0 && curl_getinfo($curl, CURLINFO_HTTP_CODE) === 200 + ? $result + : false; + + } else { + $context = null; + if ($user !== null && $pass !== null) { + $options = [ + 'http' => [ + 'method' => 'GET', + 'header' => 'Authorization: Basic ' . base64_encode($user . ':' . $pass) . "\r\n", + ], + ]; + $context = stream_context_create($options); + } + + return file_get_contents($url, false, $context); + } + } + + + /** + * Generates better accessible namespaced tags. + * @param SimpleXMLElement + * @return void + */ + private static function adjustNamespaces($el) + { + foreach ($el->getNamespaces(true) as $prefix => $ns) { + if ($prefix === '') { + continue; + } + $children = $el->children($ns); + foreach ($children as $tag => $content) { + $el->{$prefix . ':' . $tag} = $content; + } + } + } +} + + + +/** + * An exception generated by Feed. + */ +class FeedException extends Exception +{ +} diff --git a/fonts/teko-bold-webfont.woff b/fonts/teko-bold-webfont.woff new file mode 100644 index 0000000..592f7cd Binary files /dev/null and b/fonts/teko-bold-webfont.woff differ diff --git a/fonts/teko-light-webfont.woff b/fonts/teko-light-webfont.woff new file mode 100644 index 0000000..3c7030c Binary files /dev/null and b/fonts/teko-light-webfont.woff differ diff --git a/fonts/teko-medium-webfont.woff b/fonts/teko-medium-webfont.woff new file mode 100644 index 0000000..2aa760d Binary files /dev/null and b/fonts/teko-medium-webfont.woff differ diff --git a/fonts/teko-regular-webfont.woff b/fonts/teko-regular-webfont.woff new file mode 100644 index 0000000..91a438d Binary files /dev/null and b/fonts/teko-regular-webfont.woff differ diff --git a/fonts/teko-semibold-webfont.woff b/fonts/teko-semibold-webfont.woff new file mode 100644 index 0000000..b87c0c6 Binary files /dev/null and b/fonts/teko-semibold-webfont.woff differ diff --git a/index.php b/index.php new file mode 100644 index 0000000..738cfb2 --- /dev/null +++ b/index.php @@ -0,0 +1,90 @@ + + + + + + + + + Press Garden Zone + + + + +
+ +
+
+

Press Garden Zone

+
+ + item as $item): ?> + +
+

title) ?> + timestamp) ?>

+
description ?>
+
+ + + +
+
+ item as $item): ?> +
+

title) ?> + timestamp) ?>

+
description ?>
+
+ + +
+
+ + + + diff --git a/style.css b/style.css new file mode 100644 index 0000000..044f668 --- /dev/null +++ b/style.css @@ -0,0 +1,162 @@ +@font-face { + font-family: 'Teko'; + src: url('fonts/teko-light-webfont.woff'); + font-weight: 300; +} + +@font-face { + font-family: 'Teko'; + src: url('fonts/teko-regular-webfont.woff'); + font-weight: 400; +} + +@font-face { + font-family: 'Teko'; + src: url('fonts/teko-medium-webfont.woff'); + font-weight: 500; +} + +@font-face { + font-family: 'Teko'; + src: url('fonts/teko-semibold-webfont.woff'); + font-weight: 600; +} + +@font-face { + font-family: 'Teko'; + src: url('fonts/teko-bold-webfont.woff'); + font-weight: 700; +} + +body { + background-image: url("assets/bg3.png"), url("assets/bg2.png"), url("assets/bg1.png"); + background-attachment: fixed, fixed, fixed; + font-family: Inter,Cantarell,-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,'Fira Sans','Droid Sans','Helvetica Neue',sans-serif; +} + +body, html { + margin: 0; + padding: 0; +} + +article { + background-color: white; + border-radius: 8px; + padding: 0.5rem 1rem 1rem 1rem; + margin-bottom: 1rem; + box-shadow: 0px 1px 1px 1px rgba(0, 0, 0, 0.3); + border-left: 8px solid #e67700; +} + +article:last-child { + margin-bottom: 0rem; +} + +header nav { + background-color: #1971c2; + padding: 0.4rem!important; +} + +main { + background-image: url("assets/pics.png"), url("assets/picsfooter.png"); + background-repeat: repeat-x, repeat-x; + background-position: top center, bottom center; + padding-bottom: 1.5rem; + padding-left: 1rem; + padding-right: 1rem; +} + +h1 { + margin: 0; + padding-top: 1.5rem; + padding-bottom: 1rem; + color:white; + text-align: center; + font-family: 'Teko', sans-serif; + font-size: 3.5rem; + text-shadow: -2px -2px 0 #000, + 0 -2px 0 #000, + 2px -2px 0 #000, + 2px 0 0 #000, + 2px 2px 0 #000, + 0 2px 0 #000, + -2px 2px 0 #000, + -2px 0 0 #000, + .05em .1em 0 #000; +} + +section { + max-width: 960px; + margin: auto; +} + +section:not(.shown) { + display: none; +} + +nav ul { + display:flex; + justify-content:center; + margin:0; + padding:0; + list-style-type: none; +} + +a:not(:hover) { + text-decoration: none; +} + +nav a { + color: white!important; + padding: 0.8rem 1.2rem; + display: block; + border-radius: 8px; + text-decoration: none; + margin-left: 0.2rem; + margin-right: 0.2rem; +} + +nav a:hover { + background-color:rgba(255,255,255,0.4); +} + +nav a.active { + background-color:rgba(255,255,255,0.2); +} + +footer { + color: white; + background-color: #343a40; + padding-top: 0.5rem; + padding-left: 1rem; + padding-right: 1rem; +} + +footer p { + max-width: 960px; + margin: auto; + padding-bottom: 0.5rem; +} + +footer a { + color:#a5d8ff!important; +} + +.btn-area { + padding: 1rem; + text-align: center; +} + +.btn { + background-color: #e67700; + padding: 0.8rem 1.2rem; + color: white; + font-weight: bold; + text-decoration: none!important; + border-radius: 9999px; + box-shadow: 0px 1px 1px 1px rgba(0, 0, 0, 0.3); +} + +.btn:hover { + background-color: #f08c00; +}