diff --git a/application/bundles.php b/application/bundles.php index a408a244..e8b8f266 100644 --- a/application/bundles.php +++ b/application/bundles.php @@ -35,8 +35,6 @@ return array( - // route the official docs - 'docs' => array( - 'handles' => 'docs' - ), + 'docs' => array('handles' => 'docs'), + ); \ No newline at end of file diff --git a/application/config/application.php b/application/config/application.php old mode 100644 new mode 100755 index c5f5a3ba..8cbf104a --- a/application/config/application.php +++ b/application/config/application.php @@ -38,14 +38,24 @@ | remain secret and should not be shared with anyone. Make it about 32 | characters of random gibberish. | - | The "auto_key" option tells Laravel to automatically set this key value - | if one has not already been set. This is generally done on the first - | request to the Laravel splash screen. - | */ 'key' => 'YourSecretKeyGoesHere!', + /* + |-------------------------------------------------------------------------- + | Profiler Toolbar + |-------------------------------------------------------------------------- + | + | Laravel includes a beautiful profiler toolbar that gives you a heads + | up display of the queries and logs performed by your application. + | This is wonderful for development, but, of course, you should + | disable the toolbar for production applications.. + | + */ + + 'profiler' => true, + /* |-------------------------------------------------------------------------- | Application Character Encoding @@ -140,6 +150,7 @@ 'Log' => 'Laravel\\Log', 'Memcached' => 'Laravel\\Memcached', 'Paginator' => 'Laravel\\Paginator', + 'Profiler' => 'Laravel\\Profiling\\Profiler', 'URL' => 'Laravel\\URL', 'Redirect' => 'Laravel\\Redirect', 'Redis' => 'Laravel\\Redis', @@ -157,4 +168,4 @@ 'View' => 'Laravel\\View', ), -); \ No newline at end of file +); diff --git a/application/start.php b/application/start.php old mode 100644 new mode 100755 index 085dd090..06649bf6 --- a/application/start.php +++ b/application/start.php @@ -112,6 +112,22 @@ return Lang::file($bundle, $language, $file); }); +/* +|-------------------------------------------------------------------------- +| Attach The Laravel Profiler +|-------------------------------------------------------------------------- +| +| If the profiler is enabled, we will attach it to the Laravel events +| for both queries and logs. This allows the profiler to intercept +| any of the queries or logs performed by the application. +| +*/ + +if (Config::get('application.profiler')) +{ + Profiler::attach(); +} + /* |-------------------------------------------------------------------------- | Enable The Blade View Engine @@ -154,4 +170,4 @@ if ( ! Request::cli() and Config::get('session.driver') !== '') { Session::load(); -} \ No newline at end of file +} diff --git a/application/views/home/index.blade.php b/application/views/home/index.blade.php new file mode 100644 index 00000000..0a4c8332 --- /dev/null +++ b/application/views/home/index.blade.php @@ -0,0 +1,57 @@ + + + + + + Laravel: A Framework For Web Artisans + + {{ HTML::style('laravel/css/style.css') }} + + +
+
+

Laravel

+

A Framework For Web Artisans

+ +

+

+
+
+
+

Learn the terrain.

+ +

+ You've landed yourself on our default home page. The route that + is generating this page lives at: +

+ +
{{ path('app') }}routes.php
+ +

And the view sitting before you can be found at:

+ +
{{ path('app') }}views/home/index.php
+ +

Grow in knowledge.

+ +

+ Leaning to use Laravel is amazingly simple thanks to + its {{ HTML::link('docs', 'wonderful documentation') }}. +

+ +

Create something beautiful.

+ +

+ Now that you're up and running, it's time to start creating! + Here are some links to help you get started: +

+ + +
+
+
+ + diff --git a/application/views/home/index.php b/application/views/home/index.php deleted file mode 100644 index 156c36ab..00000000 --- a/application/views/home/index.php +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - Laravel - A Framework For Web Artisans - - - - -
-

Welcome To Laravel

- -

A Framework For Web Artisans

- -

- You have successfully installed the Laravel framework. Laravel is a simple framework - that helps web artisans create beautiful, creative applications using elegant, expressive - syntax. You'll love using it. -

- -

Learn the terrain.

- -

- You've landed yourself on our default home page. The route that - is generating this page lives at: -

- -
APP_PATH/routes.php
- -

And the view sitting before you can be found at:

- -
APP_PATH/views/home/index.php
- -

Create something beautiful.

- -

- Now that you're up and running, it's time to start creating! - Here are some links to help you get started: -

- - -
- - \ No newline at end of file diff --git a/artisan b/artisan index 66a0cc09..8f7bfe4e 100644 --- a/artisan +++ b/artisan @@ -3,7 +3,7 @@ * Laravel - A PHP Framework For Web Artisans * * @package Laravel - * @version 3.1.4 + * @version 3.1.5 * @author Taylor Otwell * @link http://laravel.com */ diff --git a/bundles/docs/libraries/markdown.php b/bundles/docs/libraries/markdown.php index 95dfd221..b0a31a3f 100755 --- a/bundles/docs/libraries/markdown.php +++ b/bundles/docs/libraries/markdown.php @@ -1,8 +1,8 @@ # @@ -13,6 +13,7 @@ define( 'MARKDOWN_VERSION', "1.0.1o" ); # Sun 8 Jan 2012 +define( 'MARKDOWNEXTRA_VERSION', "1.2.5" ); # Sun 8 Jan 2012 # @@ -25,6 +26,14 @@ # Define the width of a tab for code blocks. @define( 'MARKDOWN_TAB_WIDTH', 4 ); +# Optional title attribute for footnote links and backlinks. +@define( 'MARKDOWN_FN_LINK_TITLE', "" ); +@define( 'MARKDOWN_FN_BACKLINK_TITLE', "" ); + +# Optional class attribute for footnote links and backlinks. +@define( 'MARKDOWN_FN_LINK_CLASS', "" ); +@define( 'MARKDOWN_FN_BACKLINK_CLASS', "" ); + # # WordPress settings: @@ -38,7 +47,7 @@ ### Standard Function Interface ### -@define( 'MARKDOWN_PARSER_CLASS', 'Markdown_Parser' ); +@define( 'MARKDOWN_PARSER_CLASS', 'MarkdownExtra_Parser' ); function Markdown($text) { # @@ -59,10 +68,10 @@ function Markdown($text) { ### WordPress Plugin Interface ### /* -Plugin Name: Markdown +Plugin Name: Markdown Extra Plugin URI: http://michelf.com/projects/php-markdown/ Description: Markdown syntax allows you to write using an easy-to-read, easy-to-write plain text format. Based on the original Perl version by John Gruber. More... -Version: 1.0.1o +Version: 1.2.5 Author: Michel Fortin Author URI: http://michelf.com/ */ @@ -79,9 +88,9 @@ function Markdown($text) { remove_filter('the_content', 'wpautop'); remove_filter('the_content_rss', 'wpautop'); remove_filter('the_excerpt', 'wpautop'); - add_filter('the_content', 'Markdown', 6); - add_filter('the_content_rss', 'Markdown', 6); - add_filter('get_the_excerpt', 'Markdown', 6); + add_filter('the_content', 'mdwp_MarkdownPost', 6); + add_filter('the_content_rss', 'mdwp_MarkdownPost', 6); + add_filter('get_the_excerpt', 'mdwp_MarkdownPost', 6); add_filter('get_the_excerpt', 'trim', 7); add_filter('the_excerpt', 'mdwp_add_p'); add_filter('the_excerpt_rss', 'mdwp_strip_p'); @@ -92,6 +101,21 @@ function Markdown($text) { add_filter('get_the_excerpt', 'balanceTags', 9); } + # Add a footnote id prefix to posts when inside a loop. + function mdwp_MarkdownPost($text) { + static $parser; + if (!$parser) { + $parser_class = MARKDOWN_PARSER_CLASS; + $parser = new $parser_class; + } + if (is_single() || is_page() || is_feed()) { + $parser->fn_id_prefix = ""; + } else { + $parser->fn_id_prefix = get_the_ID() . "."; + } + return $parser->transform($text); + } + # Comments # - Remove WordPress paragraph generator. # - Remove WordPress auto-link generator. @@ -140,15 +164,15 @@ function mdwp_show_tags($text) { function identify_modifier_markdown() { return array( - 'name' => 'markdown', - 'type' => 'modifier', - 'nicename' => 'Markdown', - 'description' => 'A text-to-HTML conversion tool for web writers', - 'authors' => 'Michel Fortin and John Gruber', - 'licence' => 'BSD-like', - 'version' => MARKDOWN_VERSION, - 'help' => 'Markdown syntax allows you to write using an easy-to-read, easy-to-write plain text format. Based on the original Perl version by John Gruber. More...' - ); + 'name' => 'markdown', + 'type' => 'modifier', + 'nicename' => 'PHP Markdown Extra', + 'description' => 'A text-to-HTML conversion tool for web writers', + 'authors' => 'Michel Fortin and John Gruber', + 'licence' => 'GPL', + 'version' => MARKDOWNEXTRA_VERSION, + 'help' => 'Markdown syntax allows you to write using an easy-to-read, easy-to-write plain text format. Based on the original Perl version by John Gruber. More...', + ); } @@ -731,9 +755,9 @@ function _doAnchors_reference_callback($matches) { if (isset($this->urls[$link_id])) { $url = $this->urls[$link_id]; - // dayle convert - $url = URL::to($url); + $url = URL::to($url); $url = $this->encodeAttribute($url); + $result = "titles[$link_id] ) ) { $title = $this->titles[$link_id]; @@ -755,8 +779,8 @@ function _doAnchors_inline_callback($matches) { $link_text = $this->runSpanGamut($matches[2]); $url = $matches[3] == '' ? $matches[4] : $matches[3]; $title =& $matches[7]; - // dayle convert - $url = URL::to($url); + + $url = URL::to($url); $url = $this->encodeAttribute($url); $result = "$codeblock\n"; + $codeblock = "
$codeblock\n
"; return "\n\n".$this->hashBlock($codeblock)."\n\n"; } @@ -1447,7 +1471,6 @@ function doAutoLinks($text) { } function _doAutoLinks_url_callback($matches) { $url = $this->encodeAttribute($matches[1]); - $url = Laravel\URL::to($url); $link = "
$url"; return $this->hashPart($link); } @@ -1648,16 +1671,1192 @@ function _unhash_callback($matches) { } + +# +# Markdown Extra Parser Class +# + +class MarkdownExtra_Parser extends Markdown_Parser { + + # Prefix for footnote ids. + var $fn_id_prefix = ""; + + # Optional title attribute for footnote links and backlinks. + var $fn_link_title = MARKDOWN_FN_LINK_TITLE; + var $fn_backlink_title = MARKDOWN_FN_BACKLINK_TITLE; + + # Optional class attribute for footnote links and backlinks. + var $fn_link_class = MARKDOWN_FN_LINK_CLASS; + var $fn_backlink_class = MARKDOWN_FN_BACKLINK_CLASS; + + # Predefined abbreviations. + var $predef_abbr = array(); + + + function MarkdownExtra_Parser() { + # + # Constructor function. Initialize the parser object. + # + # Add extra escapable characters before parent constructor + # initialize the table. + $this->escape_chars .= ':|'; + + # Insert extra document, block, and span transformations. + # Parent constructor will do the sorting. + $this->document_gamut += array( + "doFencedCodeBlocks" => 5, + "stripFootnotes" => 15, + "stripAbbreviations" => 25, + "appendFootnotes" => 50, + ); + $this->block_gamut += array( + "doFencedCodeBlocks" => 5, + "doTables" => 15, + "doDefLists" => 45, + ); + $this->span_gamut += array( + "doFootnotes" => 5, + "doAbbreviations" => 70, + ); + + parent::Markdown_Parser(); + } + + + # Extra variables used during extra transformations. + var $footnotes = array(); + var $footnotes_ordered = array(); + var $abbr_desciptions = array(); + var $abbr_word_re = ''; + + # Give the current footnote number. + var $footnote_counter = 1; + + + function setup() { + # + # Setting up Extra-specific variables. + # + parent::setup(); + + $this->footnotes = array(); + $this->footnotes_ordered = array(); + $this->abbr_desciptions = array(); + $this->abbr_word_re = ''; + $this->footnote_counter = 1; + + foreach ($this->predef_abbr as $abbr_word => $abbr_desc) { + if ($this->abbr_word_re) + $this->abbr_word_re .= '|'; + $this->abbr_word_re .= preg_quote($abbr_word); + $this->abbr_desciptions[$abbr_word] = trim($abbr_desc); + } + } + + function teardown() { + # + # Clearing Extra-specific variables. + # + $this->footnotes = array(); + $this->footnotes_ordered = array(); + $this->abbr_desciptions = array(); + $this->abbr_word_re = ''; + + parent::teardown(); + } + + + ### HTML Block Parser ### + + # Tags that are always treated as block tags: + var $block_tags_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|form|fieldset|iframe|hr|legend'; + + # Tags treated as block tags only if the opening tag is alone on it's line: + var $context_block_tags_re = 'script|noscript|math|ins|del'; + + # Tags where markdown="1" default to span mode: + var $contain_span_tags_re = 'p|h[1-6]|li|dd|dt|td|th|legend|address'; + + # Tags which must not have their contents modified, no matter where + # they appear: + var $clean_tags_re = 'script|math'; + + # Tags that do not need to be closed. + var $auto_close_tags_re = 'hr|img'; + + + function hashHTMLBlocks($text) { + # + # Hashify HTML Blocks and "clean tags". + # + # We only want to do this for block-level HTML tags, such as headers, + # lists, and tables. That's because we still want to wrap

s around + # "paragraphs" that are wrapped in non-block-level tags, such as anchors, + # phrase emphasis, and spans. The list of tags we're looking for is + # hard-coded. + # + # This works by calling _HashHTMLBlocks_InMarkdown, which then calls + # _HashHTMLBlocks_InHTML when it encounter block tags. When the markdown="1" + # attribute is found whitin a tag, _HashHTMLBlocks_InHTML calls back + # _HashHTMLBlocks_InMarkdown to handle the Markdown syntax within the tag. + # These two functions are calling each other. It's recursive! + # + # + # Call the HTML-in-Markdown hasher. + # + list($text, ) = $this->_hashHTMLBlocks_inMarkdown($text); + + return $text; + } + function _hashHTMLBlocks_inMarkdown($text, $indent = 0, + $enclosing_tag_re = '', $span = false) + { + # + # Parse markdown text, calling _HashHTMLBlocks_InHTML for block tags. + # + # * $indent is the number of space to be ignored when checking for code + # blocks. This is important because if we don't take the indent into + # account, something like this (which looks right) won't work as expected: + # + #

+ #
+ # Hello World. <-- Is this a Markdown code block or text? + #
<-- Is this a Markdown code block or a real tag? + #
+ # + # If you don't like this, just don't indent the tag on which + # you apply the markdown="1" attribute. + # + # * If $enclosing_tag_re is not empty, stops at the first unmatched closing + # tag with that name. Nested tags supported. + # + # * If $span is true, text inside must treated as span. So any double + # newline will be replaced by a single newline so that it does not create + # paragraphs. + # + # Returns an array of that form: ( processed text , remaining text ) + # + if ($text === '') return array('', ''); + + # Regex to check for the presense of newlines around a block tag. + $newline_before_re = '/(?:^\n?|\n\n)*$/'; + $newline_after_re = + '{ + ^ # Start of text following the tag. + (?>[ ]*)? # Optional comment. + [ ]*\n # Must be followed by newline. + }xs'; + + # Regex to match any tag. + $block_tag_re = + '{ + ( # $2: Capture hole tag. + # Tag name. + '.$this->block_tags_re.' | + '.$this->context_block_tags_re.' | + '.$this->clean_tags_re.' | + (?!\s)'.$enclosing_tag_re.' + ) + (?: + (?=[\s"\'/a-zA-Z0-9]) # Allowed characters after tag name. + (?> + ".*?" | # Double quotes (can contain `>`) + \'.*?\' | # Single quotes (can contain `>`) + .+? # Anything but quotes and `>`. + )*? + )? + > # End of tag. + | + # HTML Comment + | + <\?.*?\?> | <%.*?%> # Processing instruction + | + # CData Block + | + # Code span marker + `+ + '. ( !$span ? ' # If not in span. + | + # Indented code block + (?: ^[ ]*\n | ^ | \n[ ]*\n ) + [ ]{'.($indent+4).'}[^\n]* \n + (?> + (?: [ ]{'.($indent+4).'}[^\n]* | [ ]* ) \n + )* + | + # Fenced code block marker + (?> ^ | \n ) + [ ]{0,'.($indent).'}~~~+[ ]*\n + ' : '' ). ' # End (if not is span). + ) + }xs'; + + + $depth = 0; # Current depth inside the tag tree. + $parsed = ""; # Parsed text that will be returned. + + # + # Loop through every tag until we find the closing tag of the parent + # or loop until reaching the end of text if no parent tag specified. + # + do { + # + # Split the text using the first $tag_match pattern found. + # Text before pattern will be first in the array, text after + # pattern will be at the end, and between will be any catches made + # by the pattern. + # + $parts = preg_split($block_tag_re, $text, 2, + PREG_SPLIT_DELIM_CAPTURE); + + # If in Markdown span mode, add a empty-string span-level hash + # after each newline to prevent triggering any block element. + if ($span) { + $void = $this->hashPart("", ':'); + $newline = "$void\n"; + $parts[0] = $void . str_replace("\n", $newline, $parts[0]) . $void; + } + + $parsed .= $parts[0]; # Text before current tag. + + # If end of $text has been reached. Stop loop. + if (count($parts) < 3) { + $text = ""; + break; + } + + $tag = $parts[1]; # Tag to handle. + $text = $parts[2]; # Remaining text after current tag. + $tag_re = preg_quote($tag); # For use in a regular expression. + + # + # Check for: Code span marker + # + if ($tag{0} == "`") { + # Find corresponding end marker. + $tag_re = preg_quote($tag); + if (preg_match('{^(?>.+?|\n(?!\n))*?(?.*\n)+?[ ]{0,'.($indent).'}'.$tag_re.'[ ]*\n}', $text, + $matches)) + { + # End marker found: pass text unchanged until marker. + $parsed .= $tag . $matches[0]; + $text = substr($text, strlen($matches[0])); + } + else { + # No end marker: just skip it. + $parsed .= $tag; + } + } + # + # Check for: Indented code block. + # + else if ($tag{0} == "\n" || $tag{0} == " ") { + # Indented code block: pass it unchanged, will be handled + # later. + $parsed .= $tag; + } + # + # Check for: Opening Block level tag or + # Opening Context Block tag (like ins and del) + # used as a block tag (tag is alone on it's line). + # + else if (preg_match('{^<(?:'.$this->block_tags_re.')\b}', $tag) || + ( preg_match('{^<(?:'.$this->context_block_tags_re.')\b}', $tag) && + preg_match($newline_before_re, $parsed) && + preg_match($newline_after_re, $text) ) + ) + { + # Need to parse tag and following text using the HTML parser. + list($block_text, $text) = + $this->_hashHTMLBlocks_inHTML($tag . $text, "hashBlock", true); + + # Make sure it stays outside of any paragraph by adding newlines. + $parsed .= "\n\n$block_text\n\n"; + } + # + # Check for: Clean tag (like script, math) + # HTML Comments, processing instructions. + # + else if (preg_match('{^<(?:'.$this->clean_tags_re.')\b}', $tag) || + $tag{1} == '!' || $tag{1} == '?') + { + # Need to parse tag and following text using the HTML parser. + # (don't check for markdown attribute) + list($block_text, $text) = + $this->_hashHTMLBlocks_inHTML($tag . $text, "hashClean", false); + + $parsed .= $block_text; + } + # + # Check for: Tag with same name as enclosing tag. + # + else if ($enclosing_tag_re !== '' && + # Same name as enclosing tag. + preg_match('{^= 0); + + return array($parsed, $text); + } + function _hashHTMLBlocks_inHTML($text, $hash_method, $md_attr) { + # + # Parse HTML, calling _HashHTMLBlocks_InMarkdown for block tags. + # + # * Calls $hash_method to convert any blocks. + # * Stops when the first opening tag closes. + # * $md_attr indicate if the use of the `markdown="1"` attribute is allowed. + # (it is not inside clean tags) + # + # Returns an array of that form: ( processed text , remaining text ) + # + if ($text === '') return array('', ''); + + # Regex to match `markdown` attribute inside of a tag. + $markdown_attr_re = ' + { + \s* # Eat whitespace before the `markdown` attribute + markdown + \s*=\s* + (?> + (["\']) # $1: quote delimiter + (.*?) # $2: attribute value + \1 # matching delimiter + | + ([^\s>]*) # $3: unquoted attribute value + ) + () # $4: make $3 always defined (avoid warnings) + }xs'; + + # Regex to match any tag. + $tag_re = '{ + ( # $2: Capture hole tag. + + ".*?" | # Double quotes (can contain `>`) + \'.*?\' | # Single quotes (can contain `>`) + .+? # Anything but quotes and `>`. + )*? + )? + > # End of tag. + | + # HTML Comment + | + <\?.*?\?> | <%.*?%> # Processing instruction + | + # CData Block + ) + }xs'; + + $original_text = $text; # Save original text in case of faliure. + + $depth = 0; # Current depth inside the tag tree. + $block_text = ""; # Temporary text holder for current text. + $parsed = ""; # Parsed text that will be returned. + + # + # Get the name of the starting tag. + # (This pattern makes $base_tag_name_re safe without quoting.) + # + if (preg_match('/^<([\w:$]*)\b/', $text, $matches)) + $base_tag_name_re = $matches[1]; + + # + # Loop through every tag until we find the corresponding closing tag. + # + do { + # + # Split the text using the first $tag_match pattern found. + # Text before pattern will be first in the array, text after + # pattern will be at the end, and between will be any catches made + # by the pattern. + # + $parts = preg_split($tag_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE); + + if (count($parts) < 3) { + # + # End of $text reached with unbalenced tag(s). + # In that case, we return original text unchanged and pass the + # first character as filtered to prevent an infinite loop in the + # parent function. + # + return array($original_text{0}, substr($original_text, 1)); + } + + $block_text .= $parts[0]; # Text before current tag. + $tag = $parts[1]; # Tag to handle. + $text = $parts[2]; # Remaining text after current tag. + + # + # Check for: Auto-close tag (like
) + # Comments and Processing Instructions. + # + if (preg_match('{^auto_close_tags_re.')\b}', $tag) || + $tag{1} == '!' || $tag{1} == '?') + { + # Just add the tag to the block as if it was text. + $block_text .= $tag; + } + else { + # + # Increase/decrease nested tag count. Only do so if + # the tag's name match base tag's. + # + if (preg_match('{^mode = $attr_m[2] . $attr_m[3]; + $span_mode = $this->mode == 'span' || $this->mode != 'block' && + preg_match('{^<(?:'.$this->contain_span_tags_re.')\b}', $tag); + + # Calculate indent before tag. + if (preg_match('/(?:^|\n)( *?)(?! ).*?$/', $block_text, $matches)) { + $strlen = $this->utf8_strlen; + $indent = $strlen($matches[1], 'UTF-8'); + } else { + $indent = 0; + } + + # End preceding block with this tag. + $block_text .= $tag; + $parsed .= $this->$hash_method($block_text); + + # Get enclosing tag name for the ParseMarkdown function. + # (This pattern makes $tag_name_re safe without quoting.) + preg_match('/^<([\w:$]*)\b/', $tag, $matches); + $tag_name_re = $matches[1]; + + # Parse the content using the HTML-in-Markdown parser. + list ($block_text, $text) + = $this->_hashHTMLBlocks_inMarkdown($text, $indent, + $tag_name_re, $span_mode); + + # Outdent markdown text. + if ($indent > 0) { + $block_text = preg_replace("/^[ ]{1,$indent}/m", "", + $block_text); + } + + # Append tag content to parsed text. + if (!$span_mode) $parsed .= "\n\n$block_text\n\n"; + else $parsed .= "$block_text"; + + # Start over a new block. + $block_text = ""; + } + else $block_text .= $tag; + } + + } while ($depth > 0); + + # + # Hash last block text that wasn't processed inside the loop. + # + $parsed .= $this->$hash_method($block_text); + + return array($parsed, $text); + } + + + function hashClean($text) { + # + # Called whenever a tag must be hashed when a function insert a "clean" tag + # in $text, it pass through this function and is automaticaly escaped, + # blocking invalid nested overlap. + # + return $this->hashPart($text, 'C'); + } + + + function doHeaders($text) { + # + # Redefined to add id attribute support. + # + # Setext-style headers: + # Header 1 {#header1} + # ======== + # + # Header 2 {#header2} + # -------- + # + $text = preg_replace_callback( + '{ + (^.+?) # $1: Header text + (?:[ ]+\{\#([-_:a-zA-Z0-9]+)\})? # $2: Id attribute + [ ]*\n(=+|-+)[ ]*\n+ # $3: Header footer + }mx', + array(&$this, '_doHeaders_callback_setext'), $text); + + # atx-style headers: + # # Header 1 {#header1} + # ## Header 2 {#header2} + # ## Header 2 with closing hashes ## {#header3} + # ... + # ###### Header 6 {#header2} + # + $text = preg_replace_callback('{ + ^(\#{1,6}) # $1 = string of #\'s + [ ]* + (.+?) # $2 = Header text + [ ]* + \#* # optional closing #\'s (not counted) + (?:[ ]+\{\#([-_:a-zA-Z0-9]+)\})? # id attribute + [ ]* + \n+ + }xm', + array(&$this, '_doHeaders_callback_atx'), $text); + + return $text; + } + function _doHeaders_attr($attr) { + if (empty($attr)) return ""; + return " id=\"$attr\""; + } + function _doHeaders_callback_setext($matches) { + if ($matches[3] == '-' && preg_match('{^- }', $matches[1])) + return $matches[0]; + $level = $matches[3]{0} == '=' ? 1 : 2; + $attr = $this->_doHeaders_attr($id =& $matches[2]); + $block = "".$this->runSpanGamut($matches[1]).""; + return "\n" . $this->hashBlock($block) . "\n\n"; + } + function _doHeaders_callback_atx($matches) { + $level = strlen($matches[1]); + $attr = $this->_doHeaders_attr($id =& $matches[3]); + $block = "".$this->runSpanGamut($matches[2]).""; + return "\n" . $this->hashBlock($block) . "\n\n"; + } + + + function doTables($text) { + # + # Form HTML tables. + # + $less_than_tab = $this->tab_width - 1; + # + # Find tables with leading pipe. + # + # | Header 1 | Header 2 + # | -------- | -------- + # | Cell 1 | Cell 2 + # | Cell 3 | Cell 4 + # + $text = preg_replace_callback(' + { + ^ # Start of a line + [ ]{0,'.$less_than_tab.'} # Allowed whitespace. + [|] # Optional leading pipe (present) + (.+) \n # $1: Header row (at least one pipe) + + [ ]{0,'.$less_than_tab.'} # Allowed whitespace. + [|] ([ ]*[-:]+[-| :]*) \n # $2: Header underline + + ( # $3: Cells + (?> + [ ]* # Allowed whitespace. + [|] .* \n # Row content. + )* + ) + (?=\n|\Z) # Stop at final double newline. + }xm', + array(&$this, '_doTable_leadingPipe_callback'), $text); + + # + # Find tables without leading pipe. + # + # Header 1 | Header 2 + # -------- | -------- + # Cell 1 | Cell 2 + # Cell 3 | Cell 4 + # + $text = preg_replace_callback(' + { + ^ # Start of a line + [ ]{0,'.$less_than_tab.'} # Allowed whitespace. + (\S.*[|].*) \n # $1: Header row (at least one pipe) + + [ ]{0,'.$less_than_tab.'} # Allowed whitespace. + ([-:]+[ ]*[|][-| :]*) \n # $2: Header underline + + ( # $3: Cells + (?> + .* [|] .* \n # Row content + )* + ) + (?=\n|\Z) # Stop at final double newline. + }xm', + array(&$this, '_DoTable_callback'), $text); + + return $text; + } + function _doTable_leadingPipe_callback($matches) { + $head = $matches[1]; + $underline = $matches[2]; + $content = $matches[3]; + + # Remove leading pipe for each row. + $content = preg_replace('/^ *[|]/m', '', $content); + + return $this->_doTable_callback(array($matches[0], $head, $underline, $content)); + } + function _doTable_callback($matches) { + $head = $matches[1]; + $underline = $matches[2]; + $content = $matches[3]; + + # Remove any tailing pipes for each line. + $head = preg_replace('/[|] *$/m', '', $head); + $underline = preg_replace('/[|] *$/m', '', $underline); + $content = preg_replace('/[|] *$/m', '', $content); + + # Reading alignement from header underline. + $separators = preg_split('/ *[|] */', $underline); + foreach ($separators as $n => $s) { + if (preg_match('/^ *-+: *$/', $s)) $attr[$n] = ' align="right"'; + else if (preg_match('/^ *:-+: *$/', $s))$attr[$n] = ' align="center"'; + else if (preg_match('/^ *:-+ *$/', $s)) $attr[$n] = ' align="left"'; + else $attr[$n] = ''; + } + + # Parsing span elements, including code spans, character escapes, + # and inline HTML tags, so that pipes inside those gets ignored. + $head = $this->parseSpan($head); + $headers = preg_split('/ *[|] */', $head); + $col_count = count($headers); + + # Write column headers. + $text = "\n"; + $text .= "\n"; + $text .= "\n"; + foreach ($headers as $n => $header) + $text .= " ".$this->runSpanGamut(trim($header))."\n"; + $text .= "\n"; + $text .= "\n"; + + # Split content by row. + $rows = explode("\n", trim($content, "\n")); + + $text .= "\n"; + foreach ($rows as $row) { + # Parsing span elements, including code spans, character escapes, + # and inline HTML tags, so that pipes inside those gets ignored. + $row = $this->parseSpan($row); + + # Split row by cell. + $row_cells = preg_split('/ *[|] */', $row, $col_count); + $row_cells = array_pad($row_cells, $col_count, ''); + + $text .= "\n"; + foreach ($row_cells as $n => $cell) + $text .= " ".$this->runSpanGamut(trim($cell))."\n"; + $text .= "\n"; + } + $text .= "\n"; + $text .= "
"; + + return $this->hashBlock($text) . "\n"; + } + + + function doDefLists($text) { + # + # Form HTML definition lists. + # + $less_than_tab = $this->tab_width - 1; + + # Re-usable pattern to match any entire dl list: + $whole_list_re = '(?> + ( # $1 = whole list + ( # $2 + [ ]{0,'.$less_than_tab.'} + ((?>.*\S.*\n)+) # $3 = defined term + \n? + [ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition + ) + (?s:.+?) + ( # $4 + \z + | + \n{2,} + (?=\S) + (?! # Negative lookahead for another term + [ ]{0,'.$less_than_tab.'} + (?: \S.*\n )+? # defined term + \n? + [ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition + ) + (?! # Negative lookahead for another definition + [ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition + ) + ) + ) + )'; // mx + + $text = preg_replace_callback('{ + (?>\A\n?|(?<=\n\n)) + '.$whole_list_re.' + }mx', + array(&$this, '_doDefLists_callback'), $text); + + return $text; + } + function _doDefLists_callback($matches) { + # Re-usable patterns to match list item bullets and number markers: + $list = $matches[1]; + + # Turn double returns into triple returns, so that we can make a + # paragraph for the last item in a list, if necessary: + $result = trim($this->processDefListItems($list)); + $result = "
\n" . $result . "\n
"; + return $this->hashBlock($result) . "\n\n"; + } + + + function processDefListItems($list_str) { + # + # Process the contents of a single definition list, splitting it + # into individual term and definition list items. + # + $less_than_tab = $this->tab_width - 1; + + # trim trailing blank lines: + $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str); + + # Process definition terms. + $list_str = preg_replace_callback('{ + (?>\A\n?|\n\n+) # leading line + ( # definition terms = $1 + [ ]{0,'.$less_than_tab.'} # leading whitespace + (?![:][ ]|[ ]) # negative lookahead for a definition + # mark (colon) or more whitespace. + (?> \S.* \n)+? # actual term (not whitespace). + ) + (?=\n?[ ]{0,3}:[ ]) # lookahead for following line feed + # with a definition mark. + }xm', + array(&$this, '_processDefListItems_callback_dt'), $list_str); + + # Process actual definitions. + $list_str = preg_replace_callback('{ + \n(\n+)? # leading line = $1 + ( # marker space = $2 + [ ]{0,'.$less_than_tab.'} # whitespace before colon + [:][ ]+ # definition mark (colon) + ) + ((?s:.+?)) # definition text = $3 + (?= \n+ # stop at next definition mark, + (?: # next term or end of text + [ ]{0,'.$less_than_tab.'} [:][ ] | +
| \z + ) + ) + }xm', + array(&$this, '_processDefListItems_callback_dd'), $list_str); + + return $list_str; + } + function _processDefListItems_callback_dt($matches) { + $terms = explode("\n", trim($matches[1])); + $text = ''; + foreach ($terms as $term) { + $term = $this->runSpanGamut(trim($term)); + $text .= "\n
" . $term . "
"; + } + return $text . "\n"; + } + function _processDefListItems_callback_dd($matches) { + $leading_line = $matches[1]; + $marker_space = $matches[2]; + $def = $matches[3]; + + if ($leading_line || preg_match('/\n{2,}/', $def)) { + # Replace marker with the appropriate whitespace indentation + $def = str_repeat(' ', strlen($marker_space)) . $def; + $def = $this->runBlockGamut($this->outdent($def . "\n\n")); + $def = "\n". $def ."\n"; + } + else { + $def = rtrim($def); + $def = $this->runSpanGamut($this->outdent($def)); + } + + return "\n
" . $def . "
\n"; + } + + + function doFencedCodeBlocks($text) { + # + # Adding the fenced code block syntax to regular Markdown: + # + # ~~~ + # Code block + # ~~~ + # + $less_than_tab = $this->tab_width; + + $text = preg_replace_callback('{ + (?:\n|\A) + # 1: Opening marker + ( + ~{3,} # Marker: three tilde or more. + ) + [ ]* \n # Whitespace and newline following marker. + + # 2: Content + ( + (?> + (?!\1 [ ]* \n) # Not a closing marker. + .*\n+ + )+ + ) + + # Closing marker. + \1 [ ]* \n + }xm', + array(&$this, '_doFencedCodeBlocks_callback'), $text); + + return $text; + } + function _doFencedCodeBlocks_callback($matches) { + $codeblock = $matches[2]; + $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES); + $codeblock = preg_replace_callback('/^\n+/', + array(&$this, '_doFencedCodeBlocks_newlines'), $codeblock); + $codeblock = "
$codeblock
"; + return "\n\n".$this->hashBlock($codeblock)."\n\n"; + } + function _doFencedCodeBlocks_newlines($matches) { + return str_repeat("empty_element_suffix", + strlen($matches[0])); + } + + + # + # Redefining emphasis markers so that emphasis by underscore does not + # work in the middle of a word. + # + var $em_relist = array( + '' => '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? tags + # + # Strip leading and trailing lines: + $text = preg_replace('/\A\n+|\n+\z/', '', $text); + + $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY); + + # + # Wrap

tags and unhashify HTML blocks + # + foreach ($grafs as $key => $value) { + $value = trim($this->runSpanGamut($value)); + + # Check if this should be enclosed in a paragraph. + # Clean tag hashes & block tag hashes are left alone. + $is_p = !preg_match('/^B\x1A[0-9]+B|^C\x1A[0-9]+C$/', $value); + + if ($is_p) { + $value = "

$value

"; + } + $grafs[$key] = $value; + } + + # Join grafs in one text, then unhash HTML tags. + $text = implode("\n\n", $grafs); + + # Finish by removing any tag hashes still present in $text. + $text = $this->unhash($text); + + return $text; + } + + + ### Footnotes + + function stripFootnotes($text) { + # + # Strips link definitions from text, stores the URLs and titles in + # hash references. + # + $less_than_tab = $this->tab_width - 1; + + # Link defs are in the form: [^id]: url "optional title" + $text = preg_replace_callback('{ + ^[ ]{0,'.$less_than_tab.'}\[\^(.+?)\][ ]?: # note_id = $1 + [ ]* + \n? # maybe *one* newline + ( # text = $2 (no blank lines allowed) + (?: + .+ # actual text + | + \n # newlines but + (?!\[\^.+?\]:\s)# negative lookahead for footnote marker. + (?!\n+[ ]{0,3}\S)# ensure line is not blank and followed + # by non-indented content + )* + ) + }xm', + array(&$this, '_stripFootnotes_callback'), + $text); + return $text; + } + function _stripFootnotes_callback($matches) { + $note_id = $this->fn_id_prefix . $matches[1]; + $this->footnotes[$note_id] = $this->outdent($matches[2]); + return ''; # String that will replace the block + } + + + function doFootnotes($text) { + # + # Replace footnote references in $text [^id] with a special text-token + # which will be replaced by the actual footnote marker in appendFootnotes. + # + if (!$this->in_anchor) { + $text = preg_replace('{\[\^(.+?)\]}', "F\x1Afn:\\1\x1A:", $text); + } + return $text; + } + + + function appendFootnotes($text) { + # + # Append footnote list to text. + # + $text = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}', + array(&$this, '_appendFootnotes_callback'), $text); + + if (!empty($this->footnotes_ordered)) { + $text .= "\n\n"; + $text .= "
\n"; + $text .= "empty_element_suffix ."\n"; + $text .= "
    \n\n"; + + $attr = " rev=\"footnote\""; + if ($this->fn_backlink_class != "") { + $class = $this->fn_backlink_class; + $class = $this->encodeAttribute($class); + $attr .= " class=\"$class\""; + } + if ($this->fn_backlink_title != "") { + $title = $this->fn_backlink_title; + $title = $this->encodeAttribute($title); + $attr .= " title=\"$title\""; + } + $num = 0; + + while (!empty($this->footnotes_ordered)) { + $footnote = reset($this->footnotes_ordered); + $note_id = key($this->footnotes_ordered); + unset($this->footnotes_ordered[$note_id]); + + $footnote .= "\n"; # Need to append newline before parsing. + $footnote = $this->runBlockGamut("$footnote\n"); + $footnote = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}', + array(&$this, '_appendFootnotes_callback'), $footnote); + + $attr = str_replace("%%", ++$num, $attr); + $note_id = $this->encodeAttribute($note_id); + + # Add backlink to last paragraph; create new paragraph if needed. + $backlink = ""; + if (preg_match('{

    $}', $footnote)) { + $footnote = substr($footnote, 0, -4) . " $backlink

    "; + } else { + $footnote .= "\n\n

    $backlink

    "; + } + + $text .= "
  1. \n"; + $text .= $footnote . "\n"; + $text .= "
  2. \n\n"; + } + + $text .= "
\n"; + $text .= "
"; + } + return $text; + } + function _appendFootnotes_callback($matches) { + $node_id = $this->fn_id_prefix . $matches[1]; + + # Create footnote marker only if it has a corresponding footnote *and* + # the footnote hasn't been used by another marker. + if (isset($this->footnotes[$node_id])) { + # Transfert footnote content to the ordered list. + $this->footnotes_ordered[$node_id] = $this->footnotes[$node_id]; + unset($this->footnotes[$node_id]); + + $num = $this->footnote_counter++; + $attr = " rel=\"footnote\""; + if ($this->fn_link_class != "") { + $class = $this->fn_link_class; + $class = $this->encodeAttribute($class); + $attr .= " class=\"$class\""; + } + if ($this->fn_link_title != "") { + $title = $this->fn_link_title; + $title = $this->encodeAttribute($title); + $attr .= " title=\"$title\""; + } + + $attr = str_replace("%%", $num, $attr); + $node_id = $this->encodeAttribute($node_id); + + return + "". + "$num". + ""; + } + + return "[^".$matches[1]."]"; + } + + + ### Abbreviations ### + + function stripAbbreviations($text) { + # + # Strips abbreviations from text, stores titles in hash references. + # + $less_than_tab = $this->tab_width - 1; + + # Link defs are in the form: [id]*: url "optional title" + $text = preg_replace_callback('{ + ^[ ]{0,'.$less_than_tab.'}\*\[(.+?)\][ ]?: # abbr_id = $1 + (.*) # text = $2 (no blank lines allowed) + }xm', + array(&$this, '_stripAbbreviations_callback'), + $text); + return $text; + } + function _stripAbbreviations_callback($matches) { + $abbr_word = $matches[1]; + $abbr_desc = $matches[2]; + if ($this->abbr_word_re) + $this->abbr_word_re .= '|'; + $this->abbr_word_re .= preg_quote($abbr_word); + $this->abbr_desciptions[$abbr_word] = trim($abbr_desc); + return ''; # String that will replace the block + } + + + function doAbbreviations($text) { + # + # Find defined abbreviations in text and wrap them in elements. + # + if ($this->abbr_word_re) { + // cannot use the /x modifier because abbr_word_re may + // contain significant spaces: + $text = preg_replace_callback('{'. + '(?abbr_word_re.')'. + '(?![\w\x1A])'. + '}', + array(&$this, '_doAbbreviations_callback'), $text); + } + return $text; + } + function _doAbbreviations_callback($matches) { + $abbr = $matches[0]; + if (isset($this->abbr_desciptions[$abbr])) { + $desc = $this->abbr_desciptions[$abbr]; + if (empty($desc)) { + return $this->hashPart("$abbr"); + } else { + $desc = $this->encodeAttribute($desc); + return $this->hashPart("$abbr"); + } + } else { + return $matches[0]; + } + } + +} + + /* -PHP Markdown -============ +PHP Markdown Extra +================== Description ----------- -This is a PHP translation of the original Markdown formatter written in -Perl by John Gruber. +This is a PHP port of the original Markdown formatter written in Perl +by John Gruber. This special "Extra" version of PHP Markdown features +further enhancements to the syntax for making additional constructs +such as tables and definition list. Markdown is a text-to-HTML filter; it translates an easy-to-read / easy-to-write structured text format into HTML. Markdown's text format @@ -1694,12 +2893,12 @@ function _unhash_callback($matches) { Copyright and License --------------------- -PHP Markdown +PHP Markdown & Extra Copyright (c) 2004-2009 Michel Fortin All rights reserved. -Based on Markdown +Based on Markdown Copyright (c) 2003-2006 John Gruber All rights reserved. diff --git a/bundles/docs/routes.php b/bundles/docs/routes.php index 43641286..334c652d 100644 --- a/bundles/docs/routes.php +++ b/bundles/docs/routes.php @@ -1,38 +1,85 @@ add('prettify', 'laravel/js/prettify.js'); - $view->with('sidebar', Markdown(file_get_contents(path('storage').'documentation/contents.md'))); + $view->with('sidebar', document('contents')); }); +/** + * Handle the documentation homepage. + * + * This page contains the "introduction" to Laravel. + */ Route::get('(:bundle)', function() { - return View::make('docs::home'); + return View::make('docs::page')->with('content', document('home')); }); -Route::get('docs/(:any)/(:any?)', function($section, $page = null) +/** + * Handle documentation routes for sections and pages. + * + * @param string $section + * @param string $page + * @return mixed + */ +Route::get('(:bundle)/(:any)/(:any?)', function($section, $page = null) { - $root = path('storage').'documentation/'; + $file = rtrim(implode('/', func_get_args()), '/'); - $file = rtrim(implode('/', array($section, $page)), '/').'.md'; - - if (file_exists($path = $root.$file)) + // If no page was specified, but a "home" page exists for the section, + // we'll set the file to the home page so that the proper page is + // display back out to the client for the requested doc page. + if (is_null($page) and document_exists($file.'/home')) { - $content = Markdown(file_get_contents($path)); + $file .= '/home'; } - elseif (file_exists($path = $root.$section.'/home.md')) + + if (document_exists($file)) { - $content = Markdown(file_get_contents($path)); + return View::make('docs::page')->with('content', document($file)); } else { return Response::error('404'); } - - return View::make('docs::page')->with('content', $content); }); \ No newline at end of file diff --git a/bundles/docs/views/home.blade.php b/bundles/docs/views/home.blade.php deleted file mode 100644 index 86670159..00000000 --- a/bundles/docs/views/home.blade.php +++ /dev/null @@ -1,37 +0,0 @@ -@layout('docs::template') - -@section('content') -

Learn the terrain.

- -

- You've landed yourself on our default home page. The route that - is generating this page lives in the main routes file. You can - find it here: -

- -
APP_PATH/routes.php
- - -

And the view sitting before you can be found at:

- -
APP_PATH/views/home/index.php
- -

Create something beautiful.

- -

- Now that you're up and running, it's time to start creating! - Here are some links to help you get started: -

- - -@endsection diff --git a/bundles/docs/views/menu.blade.php b/bundles/docs/views/menu.blade.php deleted file mode 100644 index 164556da..00000000 --- a/bundles/docs/views/menu.blade.php +++ /dev/null @@ -1,27 +0,0 @@ -

Documentation

- \ No newline at end of file diff --git a/bundles/docs/views/page.blade.php b/bundles/docs/views/page.blade.php index 9f6da707..1309e905 100644 --- a/bundles/docs/views/page.blade.php +++ b/bundles/docs/views/page.blade.php @@ -2,4 +2,4 @@ @section('content') {{ $content }} -@endsection +@endsection \ No newline at end of file diff --git a/bundles/docs/views/template.blade.php b/bundles/docs/views/template.blade.php index 44c6ff87..02e24bd9 100644 --- a/bundles/docs/views/template.blade.php +++ b/bundles/docs/views/template.blade.php @@ -5,8 +5,9 @@ Laravel: A Framework For Web Artisans - {{ Asset::styles(); }} - {{ Asset::scripts(); }} + + {{ HTML::style('laravel/css/style.css') }} + {{ HTML::style('laravel/js/modernizr-2.5.3.min.js') }}
@@ -14,10 +15,7 @@

Laravel

A Framework For Web Artisans

-

- You have successfully installed the Laravel framework. Laravel is a simple framework - that helps web artisans create beautiful, creative applications using elegant, expressive - syntax. You'll love using it. +

@@ -29,6 +27,8 @@
- {{ Asset::container('footer')->scripts(); }} + {{ HTML::script('http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js') }} + {{ HTML::script('laravel/js/prettify.js') }} + {{ HTML::script('laravel/js/scroll.js') }} - + \ No newline at end of file diff --git a/laravel/blade.php b/laravel/blade.php index 7e6d33c9..e3111d09 100644 --- a/laravel/blade.php +++ b/laravel/blade.php @@ -264,7 +264,7 @@ protected static function compile_includes($value) { $pattern = static::matcher('include'); - return preg_replace($pattern, '$1with(get_defined_vars()); ?>', $value); + return preg_replace($pattern, '$1with(get_defined_vars())->render(); ?>', $value); } /** diff --git a/laravel/database/eloquent/relationships/has_many.php b/laravel/database/eloquent/relationships/has_many.php index b80d3844..cbf216e7 100644 --- a/laravel/database/eloquent/relationships/has_many.php +++ b/laravel/database/eloquent/relationships/has_many.php @@ -12,6 +12,54 @@ public function results() return parent::get(); } + /** + * Sync the association table with an array of models. + * + * @param mixed $models + * @return bool + */ + public function save($models) + { + // If the given "models" are not an array, we'll force them into an array so + // we can conveniently loop through them and insert all of them into the + // related database table assigned to the associated model instance. + if ( ! is_array($models)) $models = array($models); + + $current = $this->table->lists($this->model->key()); + + foreach ($models as $attributes) + { + $attributes[$this->foreign_key()] = $this->base->get_key(); + + $class = get_class($this->model); + + // If the "attributes" are actually an array of the related model we'll + // just use the existing instance instead of creating a fresh model + // instance for the attributes. This allows for validation. + if ($attributes instanceof $class) + { + $model = $attributes; + } + else + { + $model = $this->fresh_model($attributes); + } + + $id = $model->get_key(); + + $model->exists = ( ! is_null($id) and in_array($id, $current)); + + // Before saving we'll force the entire model to be "dirty" so all of + // the attributes are saved. It shouldn't affect the updates as + // saving all the attributes shouldn't hurt anything. + $model->original = array(); + + $model->save(); + } + + return true; + } + /** * Initialize a relationship on an array of parent models. * diff --git a/storage/documentation/artisan/commands.md b/laravel/documentation/artisan/commands.md similarity index 100% rename from storage/documentation/artisan/commands.md rename to laravel/documentation/artisan/commands.md diff --git a/storage/documentation/artisan/tasks.md b/laravel/documentation/artisan/tasks.md similarity index 100% rename from storage/documentation/artisan/tasks.md rename to laravel/documentation/artisan/tasks.md diff --git a/storage/documentation/auth/config.md b/laravel/documentation/auth/config.md similarity index 100% rename from storage/documentation/auth/config.md rename to laravel/documentation/auth/config.md diff --git a/storage/documentation/auth/usage.md b/laravel/documentation/auth/usage.md similarity index 100% rename from storage/documentation/auth/usage.md rename to laravel/documentation/auth/usage.md diff --git a/storage/documentation/bundles.md b/laravel/documentation/bundles.md similarity index 100% rename from storage/documentation/bundles.md rename to laravel/documentation/bundles.md diff --git a/storage/documentation/cache/config.md b/laravel/documentation/cache/config.md similarity index 100% rename from storage/documentation/cache/config.md rename to laravel/documentation/cache/config.md diff --git a/storage/documentation/cache/usage.md b/laravel/documentation/cache/usage.md similarity index 100% rename from storage/documentation/cache/usage.md rename to laravel/documentation/cache/usage.md diff --git a/changes.md b/laravel/documentation/changes.md similarity index 89% rename from changes.md rename to laravel/documentation/changes.md index ae1d2cd2..0047ff83 100644 --- a/changes.md +++ b/laravel/documentation/changes.md @@ -1,9 +1,11 @@ -## Laravel Change Log +# Laravel Change Log ## Contents - [Laravel 3.2](#3.2) - [Upgrading From 3.1](#upgrade-3.2) +- [Laravel 3.1.5](#3.1.5) +- [Upgrading From 3.1.4](#upgrade-3.1.5) - [Laravel 3.1.4](#3.1.4) - [Upgrading From 3.1.3](#upgrade-3.1.4) - [Laravel 3.1.3](#3.1.3) @@ -18,11 +20,12 @@ ## Contents ## Laravel 3.2 +- [Added `to_array` method to the base Eloquent model](/docs/database/eloquent#to-array). +- [Added `$hidden` static variable to the base Eloquent model](/docs/database/eloquent#to-array). +- [Added `sync` method to has\_many\_and\_belongs\_to Eloquent relationship](/docs/database/eloquent#sync-method). +- [Added `save` method to has\_many Eloquent relationship](/docs/database/eloquent#has-many-save). - Fixed the passing of strings into the Input::except method. - Fixed replacement of optional parameters in URL::transpose method. -- Added "to_array" method to the base Eloquent model. -- Added "$hidden" static variable to the base Eloquent model. -- Added "sync" method to has_many_and_belongs_to Eloquent relationship. - Improved View performance by only loading contents from file once. - Fix handling of URLs beginning with has in URL::to. @@ -32,6 +35,16 @@ ## Upgrading From 3.1 - Replace the **laravel** folder. - Add new **vendors** folder. + +## Laravel 3.1.5 + +- Fixes bug that could allow secure cookies to be sent over HTTP. + + +## Upgrading From 3.1.4 + +- Replace the **laravel** folder. + ## Laravel 3.1.4 diff --git a/storage/documentation/config.md b/laravel/documentation/config.md similarity index 100% rename from storage/documentation/config.md rename to laravel/documentation/config.md diff --git a/storage/documentation/contents.md b/laravel/documentation/contents.md similarity index 99% rename from storage/documentation/contents.md rename to laravel/documentation/contents.md index 25d78c8a..ab0a9f1f 100644 --- a/storage/documentation/contents.md +++ b/laravel/documentation/contents.md @@ -1,5 +1,6 @@ ### General - [Laravel Overview](/docs/home) +- [Change Log](/docs/changes) - [Installation & Setup](/docs/install) - [Requirements](/docs/install#requirements) - [Installation](/docs/install#installation) diff --git a/storage/documentation/controllers.md b/laravel/documentation/controllers.md similarity index 100% rename from storage/documentation/controllers.md rename to laravel/documentation/controllers.md diff --git a/storage/documentation/database/config.md b/laravel/documentation/database/config.md similarity index 100% rename from storage/documentation/database/config.md rename to laravel/documentation/database/config.md diff --git a/storage/documentation/database/eloquent.md b/laravel/documentation/database/eloquent.md similarity index 92% rename from storage/documentation/database/eloquent.md rename to laravel/documentation/database/eloquent.md index 8624b8a7..0706b7d9 100644 --- a/storage/documentation/database/eloquent.md +++ b/laravel/documentation/database/eloquent.md @@ -14,6 +14,7 @@ ## Contents - [Constraining Eager Loads](#constraining-eager-loads) - [Setter & Getter Methods](#getter-and-setter-methods) - [Mass-Assignment](#mass-assignment) +- [Converting Models To Arrays](#to-array) ## The Basics @@ -289,6 +290,20 @@ ## Inserting Related Models When inserting related models through their parent model, the foreign key will automatically be set. So, in this case, the "post_id" was automatically set to "1" on the newly inserted comment. + +When working with `has_many` relationships, you may use the `save` method to insert / update related models: + + $comments = array( + array('message' => 'A new comment.'), + array('message' => 'A second comment.'), + ); + + $post = Post::find(1); + + $post->comments()->save($comments); + +### Inserting Related Models (Many-To-Many) + This is even more helpful when working with many-to-many relationships. For example, consider a **User** model that has many roles. Likewise, the **Role** model may have many users. So, the intermediate table for this relationship has "user_id" and "role_id" columns. Now, let's insert a new Role for a User: $role = new Role(array('title' => 'Admin')); @@ -303,6 +318,11 @@ ## Inserting Related Models $user->roles()->attach($role_id); + +Alternatively, you can use the `sync` method, which accepts an array of IDs to "sync" with the intermediate table. After this operation is complete, only the IDs in the array will be on the intermediate table. + + $user->roles()->sync(array(1, 2, 3)); + ## Working With Intermediate Tables @@ -457,4 +477,25 @@ ## Mass-Assignment User::accessible(array('email', 'password', 'name')); -> **Note:** Utmost caution should be taken when mass-assigning using user-input. Technical oversights could cause serious security vulnerabilities. \ No newline at end of file +> **Note:** Utmost caution should be taken when mass-assigning using user-input. Technical oversights could cause serious security vulnerabilities. + + +## Converting Models To Arrays + +When building JSON APIs, you will often need to convert your models to array so they can be easily serialized. It's really simple. + +#### Convert a model to an array: + + return json_encode($user->to_array()); + +The `to_array` method will automatically grab all of the attributes on your model, as well as any loaded relationships. + +Sometimes you may wish to limit the attributes that are included in your model's array, such as passwords. To do this, add a `hidden` attribute definition to your model: + +#### Excluding attributes from the array: + + class User extends Eloquent { + + public static $hidden = array('password'); + + } \ No newline at end of file diff --git a/storage/documentation/database/fluent.md b/laravel/documentation/database/fluent.md similarity index 100% rename from storage/documentation/database/fluent.md rename to laravel/documentation/database/fluent.md diff --git a/storage/documentation/database/migrations.md b/laravel/documentation/database/migrations.md similarity index 100% rename from storage/documentation/database/migrations.md rename to laravel/documentation/database/migrations.md diff --git a/storage/documentation/database/raw.md b/laravel/documentation/database/raw.md similarity index 100% rename from storage/documentation/database/raw.md rename to laravel/documentation/database/raw.md diff --git a/storage/documentation/database/redis.md b/laravel/documentation/database/redis.md similarity index 100% rename from storage/documentation/database/redis.md rename to laravel/documentation/database/redis.md diff --git a/storage/documentation/database/schema.md b/laravel/documentation/database/schema.md similarity index 100% rename from storage/documentation/database/schema.md rename to laravel/documentation/database/schema.md diff --git a/storage/documentation/encryption.md b/laravel/documentation/encryption.md similarity index 100% rename from storage/documentation/encryption.md rename to laravel/documentation/encryption.md diff --git a/storage/documentation/events.md b/laravel/documentation/events.md similarity index 100% rename from storage/documentation/events.md rename to laravel/documentation/events.md diff --git a/storage/documentation/files.md b/laravel/documentation/files.md similarity index 100% rename from storage/documentation/files.md rename to laravel/documentation/files.md diff --git a/storage/documentation/home.md b/laravel/documentation/home.md similarity index 100% rename from storage/documentation/home.md rename to laravel/documentation/home.md diff --git a/storage/documentation/input.md b/laravel/documentation/input.md similarity index 100% rename from storage/documentation/input.md rename to laravel/documentation/input.md diff --git a/storage/documentation/install.md b/laravel/documentation/install.md similarity index 100% rename from storage/documentation/install.md rename to laravel/documentation/install.md diff --git a/storage/documentation/ioc.md b/laravel/documentation/ioc.md similarity index 100% rename from storage/documentation/ioc.md rename to laravel/documentation/ioc.md diff --git a/storage/documentation/loading.md b/laravel/documentation/loading.md similarity index 100% rename from storage/documentation/loading.md rename to laravel/documentation/loading.md diff --git a/storage/documentation/localization.md b/laravel/documentation/localization.md similarity index 100% rename from storage/documentation/localization.md rename to laravel/documentation/localization.md diff --git a/storage/documentation/logging.md b/laravel/documentation/logging.md similarity index 100% rename from storage/documentation/logging.md rename to laravel/documentation/logging.md diff --git a/storage/documentation/models.md b/laravel/documentation/models.md similarity index 100% rename from storage/documentation/models.md rename to laravel/documentation/models.md diff --git a/storage/documentation/requests.md b/laravel/documentation/requests.md similarity index 100% rename from storage/documentation/requests.md rename to laravel/documentation/requests.md diff --git a/storage/documentation/routing.md b/laravel/documentation/routing.md similarity index 100% rename from storage/documentation/routing.md rename to laravel/documentation/routing.md diff --git a/storage/documentation/session/config.md b/laravel/documentation/session/config.md similarity index 100% rename from storage/documentation/session/config.md rename to laravel/documentation/session/config.md diff --git a/storage/documentation/session/usage.md b/laravel/documentation/session/usage.md similarity index 100% rename from storage/documentation/session/usage.md rename to laravel/documentation/session/usage.md diff --git a/storage/documentation/strings.md b/laravel/documentation/strings.md similarity index 100% rename from storage/documentation/strings.md rename to laravel/documentation/strings.md diff --git a/storage/documentation/testing.md b/laravel/documentation/testing.md similarity index 100% rename from storage/documentation/testing.md rename to laravel/documentation/testing.md diff --git a/storage/documentation/urls.md b/laravel/documentation/urls.md similarity index 100% rename from storage/documentation/urls.md rename to laravel/documentation/urls.md diff --git a/storage/documentation/validation.md b/laravel/documentation/validation.md similarity index 100% rename from storage/documentation/validation.md rename to laravel/documentation/validation.md diff --git a/storage/documentation/views/assets.md b/laravel/documentation/views/assets.md similarity index 100% rename from storage/documentation/views/assets.md rename to laravel/documentation/views/assets.md diff --git a/storage/documentation/views/forms.md b/laravel/documentation/views/forms.md similarity index 100% rename from storage/documentation/views/forms.md rename to laravel/documentation/views/forms.md diff --git a/storage/documentation/views/home.md b/laravel/documentation/views/home.md similarity index 100% rename from storage/documentation/views/home.md rename to laravel/documentation/views/home.md diff --git a/storage/documentation/views/html.md b/laravel/documentation/views/html.md similarity index 100% rename from storage/documentation/views/html.md rename to laravel/documentation/views/html.md diff --git a/storage/documentation/views/pagination.md b/laravel/documentation/views/pagination.md similarity index 100% rename from storage/documentation/views/pagination.md rename to laravel/documentation/views/pagination.md diff --git a/storage/documentation/views/templating.md b/laravel/documentation/views/templating.md similarity index 100% rename from storage/documentation/views/templating.md rename to laravel/documentation/views/templating.md diff --git a/laravel/laravel.php b/laravel/laravel.php index 9d0ec57a..665b8538 100644 --- a/laravel/laravel.php +++ b/laravel/laravel.php @@ -195,4 +195,4 @@ | */ -Event::fire('laravel.done'); \ No newline at end of file +Event::fire('laravel.done', array($response)); diff --git a/laravel/profiling/profiler.css b/laravel/profiling/profiler.css new file mode 100755 index 00000000..1fb4e52f --- /dev/null +++ b/laravel/profiling/profiler.css @@ -0,0 +1,200 @@ +.anbu +{ + font-family:Helvetica, "Helvetica Neue", Arial, sans-serif !important; + font-size:14px !important; + background-color:#222 !important; + position:fixed !important; + bottom:0 !important; + right:0 !important; + width:100%; + z-index: 9999 !important; +} + +.anbu-tabs +{ + margin:0 !important; + padding:0 !important; + overflow:hidden !important; +} + +.anbu-tabs li +{ + display:inline; +} + +.anbu-tabs a, .anbu-tabs a:visited +{ + color:#aaa !important; + text-transform:uppercase !important; + font-weight:bold !important; + display:inline-block; + text-decoration:none !important; + font-size:0.8em !important; + padding: 0.8em 2em 0.7em 2em !important; + -webkit-transition-property:color, background-color; + -webkit-transition-duration: 0.7s, 0.2s; + -webkit-transition-timing-function: ease-in, ease-in; + -moz-transition-property:color, background-color; + -moz-transition-duration: 0.7s, 0.2s; + -moz-transition-timing-function: ease-in, ease-in; + -ms-transition-property:color, background-color; + -ms-transition-duration: 0.7s, 0.2s; + -ms-transition-timing-function: ease-in, ease-in; + -o-transition-property:color, background-color; + -o-transition-duration: 0.7s, 0.2s; + -o-transition-timing-function: ease-in, ease-in; + transition-property:color, background-color; + transition-duration: 0.7s, 0.2s; + transition-timing-function: ease-in, ease-in; +} + +#anbu-closed-tabs a, #anbu-closed-tabs a:visited +{ + padding: 0.85em 1.2em 0.85em 1.2em !important; +} + +.anbu-tabs a:hover +{ + background-color:#333 !important; + color:#fff !important; +} + +.anbu-tabs a.anbu-active-tab +{ + color:#fff !important; + background-color:#333 !important; +} + +.anbu a:focus +{ + outline:none !important; +} + +.anbu-tabs a:active +{ + background-color:#111 !important; +} + +.anbu-tabs li.anbu-tab-right +{ + float:right !important; +} + +.anbu-tabs li.anbu-tab-right a, .anbu-tabs li.anbu-tab-right a:visited +{ + padding: 0.86em 2em 0.7em 2em !important; +} + +#anbu-closed-tabs +{ + display:none; +} + + +.anbu-window +{ + display:none; +} + +.anbu-content-area +{ + background-color: #fff !important; + background-image: -webkit-gradient(linear, left top, left bottom, from(#eeeeee), to(#ffffff)); + background-image: -webkit-linear-gradient(top, #eeeeee, #ffffff); + background-image: -moz-linear-gradient(top, #eeeeee, #ffffff); + background-image: -ms-linear-gradient(top, #eeeeee, #ffffff); + background-image: -o-linear-gradient(top, #eeeeee, #ffffff); + background-image: linear-gradient(to bottom, #eeeeee, #ffffff); + height:14em; + margin-top:6px !important; + overflow-x:hidden !important; + overflow-y:auto !important; +} + +.anbu-table table +{ + margin:0 !important; + padding:0 !important; + font-size:0.9em !important; + border:0 !important; + border-collapse:collapse !important; + width:100% !important; + background-color:#fff !important; +} + +.anbu-table pre +{ + margin:0 !important; +} + +.anbu-table tr +{ + border-bottom:1px solid #ccc !important; +} + +.anbu-table tr:first-child +{ + border:0 !important; +} + +.anbu-table th +{ + background-color:#555 !important; + color:#fff !important; + text-transform:uppercase !important; +} + +.anbu-table th, .anbu-table td +{ + text-align:left !important; + padding:0.4em 1em !important; + margin:0 !important; +} + +.anbu-table td +{ + vertical-align:top !important; +} + +.anbu-table-first +{ + background-color:#eee !important; + border-right:1px solid #ccc !important; + width:10% !important; +} + +span.anbu-count +{ + margin-left:0.5em !important; + background-color:#555 !important; + display:inline-block !important; + padding:0.1em 0.5em 0.2em 0.5em !important; + color:#eee !important; + text-shadow:0 0 4px #000 !important; + -webkit-border-radius: 1px; + -moz-border-radius: 1px; + border-radius: 1px; + -moz-background-clip: padding; -webkit-background-clip: padding-box; background-clip: padding-box; + +} + +.anbu-empty +{ + display:block !important; + padding:1em !important; + text-align:center !important; + font-style:italic !important; + color:#ccc !important; + margin:1em !important; + text-shadow:0 1px 0px #fff !important; +} + +.anbu pre +{ + overflow-x: auto; + white-space: pre-wrap; + white-space: -moz-pre-wrap !important; + white-space: -pre-wrap; + white-space: -o-pre-wrap; + word-wrap: break-word; +} diff --git a/laravel/profiling/profiler.js b/laravel/profiling/profiler.js new file mode 100755 index 00000000..f91ad18f --- /dev/null +++ b/laravel/profiling/profiler.js @@ -0,0 +1,165 @@ +var anbu = { + + // BOUND ELEMENTS + // ------------------------------------------------------------- + // Binding these elements early, stops jQuery from "querying" + // the DOM every time they are used. + + el : { + main : $('.anbu'), + close : $('#anbu-close'), + zoom : $('#anbu-zoom'), + hide : $('#anbu-hide'), + show : $('#anbu-show'), + tab_pane : $('.anbu-tab-pane'), + hidden_tab_pane : $('.anbu-tab-pane:visible'), + tab : $('.anbu-tab'), + tabs : $('.anbu-tabs'), + tab_links : $('.anbu-tabs a'), + window : $('.anbu-window'), + closed_tabs : $('#anbu-closed-tabs'), + open_tabs : $('#anbu-open-tabs'), + content_area : $('.anbu-content-area') + }, + + // CLASS ATTRIBUTES + // ------------------------------------------------------------- + // Useful variable for Anbu. + + isZoomed : false, // is anbu in full screen mode + small_height : $('.anbu-content-area').height(), // initial height of content area + active_tab : 'anbu-active-tab', // the name of the active tab css + tab_data : 'data-anbu-tab', // the data attribute of the tab link + mini_button_width : '2.6em', // size of anbu when compact + window_open : false, // is the top window open? + active_pane : '', // current active pane + + // START() + // ------------------------------------------------------------- + // Sets up all the binds for Anbu! + + start : function () + { + // hide initial elements + + anbu.el.close.hide(); + anbu.el.zoom.hide(); + anbu.el.tab_pane.hide(); + + // bind all click events + anbu.el.close.click( function () { anbu.close_window(); }); + anbu.el.hide.click( function () { anbu.hide(); }); + anbu.el.show.click( function () { anbu.show(); }); + anbu.el.zoom.click( function () { anbu.zoom(); }); + anbu.el.tab.click( function () { anbu.clicked_tab($(this)); }); + }, + + // CLICKED_TAB() + // ------------------------------------------------------------- + // A tab has been clicked, decide what to do. + + clicked_tab : function (tab) + { + // if the tab is closed + if(anbu.window_open && anbu.active_pane == tab.attr(anbu.tab_data)) + { + anbu.close_window(); + } + else + { + anbu.open_window(tab); + } + }, + + // OPEN_WINDOW() + // ------------------------------------------------------------- + // Animate open the top window to the appropriate tab. + + open_window : function (tab) + { + // can't directly assign this line, but it works + $('.anbu-tab-pane:visible').fadeOut(200); + $('.' + tab.attr(anbu.tab_data)).delay(220).fadeIn(300); + anbu.el.tab_links.removeClass(anbu.active_tab); + tab.addClass(anbu.active_tab); + anbu.el.window.slideDown(300); + anbu.el.close.fadeIn(300); + anbu.el.zoom.fadeIn(300); + anbu.active_pane = tab.attr(anbu.tab_data); + anbu.window_open = true; + }, + + + // CLOSE_WINDOW() + // ------------------------------------------------------------- + // Animate closed the top window hiding all tabs. + + close_window : function() + { + anbu.el.tab_pane.fadeOut(100); + anbu.el.window.slideUp(300); + anbu.el.close.fadeOut(300); + anbu.el.zoom.fadeOut(300); + anbu.el.tab_links.removeClass(anbu.active_tab); + anbu.active_pane = ''; + anbu.window_open = false; + }, + + + // SHOW() + // ------------------------------------------------------------- + // Show the Anbu toolbar when it has been compacted. + + show : function () + { + anbu.el.closed_tabs.fadeOut(600, function () { + anbu.el.open_tabs.fadeIn(200); + }) + anbu.el.main.animate({width: '100%'}, 700); + }, + + // HIDE() + // ------------------------------------------------------------- + // Hide the anbu toolbar, show a tiny re-open button. + + hide : function () + { + anbu.close_window(); + anbu.el.window.slideUp(400, function () { + anbu.close_window(); + anbu.el.open_tabs.fadeOut(200, function () { + anbu.el.closed_tabs.fadeIn(200); + }) + anbu.el.main.animate({width: anbu.mini_button_width}, 700); + }); + + }, + + // TOGGLEZOOM() + // ------------------------------------------------------------- + // Toggle the zoomed mode of the top window. + + zoom : function () + { + if(anbu.isZoomed) + { + height = anbu.small_height; + anbu.isZoomed = false; + } + else + { + // the 6px is padding on the top of the window + height = ($(window).height() - anbu.el.tabs.height() - 6) + 'px'; + anbu.isZoomed = true; + } + + anbu.el.content_area.animate({height: height}, 700); + } + +} + + +jQuery(document).ready(function () { + // launch anbu + anbu.start(); +}); \ No newline at end of file diff --git a/laravel/profiling/profiler.php b/laravel/profiling/profiler.php new file mode 100644 index 00000000..bb1ed496 --- /dev/null +++ b/laravel/profiling/profiler.php @@ -0,0 +1,105 @@ + array(), 'logs' => array()); + + /** + * Get the rendered contents of the Profiler. + * + * @param Response $response + * @return string + */ + public static function render($response) + { + // We only want to send the profiler toolbar if the request is not an AJAX + // request, as sending it on AJAX requests could mess up JSON driven API + // type applications, so we will not send anything in those scenarios. + if ( ! Request::ajax()) + { + return render('path: '.__DIR__.'/template'.BLADE_EXT, static::$data); + } + } + + /** + * Add a log entry to the log entries array. + * + * @return void + */ + public static function log($type, $message) + { + static::$data['logs'][] = array($type, $message); + } + + /** + * Add a performed SQL query to the Profiler. + * + * @param string $sql + * @param array $bindings + * @param float $time + * @return void + */ + public static function query($sql, $bindings, $time) + { + foreach ($bindings as $binding) + { + $sql = preg_replace('/\?/', $binding, $sql, 1); + } + + static::$data['queries'][] = array($sql, $time); + } + + /** + * Determine if the given response includes jQuery. + * + * @param Response $response + * @return bool + */ + protected static function has_jquery($response) + { + $pattern = '/\(.*)\\<\/script\>(.*)\<\/head\>/'; + + return preg_match($pattern, $response->content); + } + + /** + * Attach the Profiler's event listeners. + * + * @return void + */ + public static function attach() + { + // First we'll attach to the query and log events. These allow us to catch + // all of the SQL queries and log messages that come through Laravel, + // and we will pass them onto the Profiler for simple storage. + Event::listen('laravel.log', function($type, $message) + { + Profiler::log($type, $message); + }); + + Event::listen('laravel.query', function($sql, $bindings, $time) + { + Profiler::query($sql, $bindings, $time); + }); + + // We'll attach the profiler to the "done" event so that we can easily + // attach the profiler output to the end of the output sent to the + // browser. This will display the profiler's nice toolbar. + Event::listen('laravel.done', function($response) + { + echo Profiler::render($response); + }); + } + +} diff --git a/laravel/profiling/template.blade.php b/laravel/profiling/template.blade.php new file mode 100755 index 00000000..9c6e4d24 --- /dev/null +++ b/laravel/profiling/template.blade.php @@ -0,0 +1,69 @@ + + +
+
+
+
+ @if (count($logs) > 0) + + + + + + @foreach ($logs as $log) + + + + @endforeach + +
TypeMessage
+ {{ $log[0] }} + + {{ $log[1] }} +
+ @else + There are no log entries. + @endif +
+ +
+ @if (count($queries) > 0) + + + + + + @foreach ($queries as $query) + + + + + @endforeach +
TimeQuery
+ {{ $query[1] }}ms + +
{{ $query[0] }}
+
+ @else + There have been no SQL queries executed. + @endif +
+
+
+ + + + +
+ + + + \ No newline at end of file diff --git a/paths.php b/paths.php index 152a4f79..0f44dd30 100644 --- a/paths.php +++ b/paths.php @@ -3,7 +3,7 @@ * Laravel - A PHP Framework For Web Artisans * * @package Laravel - * @version 3.1.4 + * @version 3.1.5 * @author Taylor Otwell * @link http://laravel.com */ @@ -13,6 +13,14 @@ // -------------------------------------------------------------- if ( ! isset($web)) $web = false; +// -------------------------------------------------------------- +// Change to the current directory if not from the web. +// -------------------------------------------------------------- +if ( ! $web) +{ + chdir(__DIR__); +} + // -------------------------------------------------------------- // Define the directory separator for the environment. // -------------------------------------------------------------- diff --git a/public/index.php b/public/index.php index 561d13a3..56896d97 100644 --- a/public/index.php +++ b/public/index.php @@ -3,7 +3,7 @@ * Laravel - A PHP Framework For Web Artisans * * @package Laravel - * @version 3.1.4 + * @version 3.1.5 * @author Taylor Otwell * @link http://laravel.com */ diff --git a/public/laravel/css/style.css b/public/laravel/css/style.css index b98816df..5d10cc70 100755 --- a/public/laravel/css/style.css +++ b/public/laravel/css/style.css @@ -141,6 +141,14 @@ .content>h2 { margin-top:2.2em; } +div.home>h2:not(:first-child) { + margin-top:2.2em; +} + +div.home>h2 { + font-size: 14pt; +} + .content>h3 { font-size: 12pt; } @@ -153,6 +161,33 @@ .content>h1:not(:first-child) { margin-top: 30px; } +.content table +{ + border-collapse:collapse + border:1px solid #eee; + width:100%; + line-height:1.5em; +} + +.content table code +{ + background-color:transparent; + font-size:0.9em; +} + +.content table td, .content table th +{ + border:1px solid #eee; + padding:0.5em 0.7em; + vertical-align:middle; + text-align:left; +} + +.content table th +{ + background-color:#f5f5f5; +} + .content li { line-height:1.5em; @@ -218,7 +253,12 @@ pre font-size:0.8em; background-color:#f5f5f5; text-shadow:1px 1px 0 #fff; - line-height:1.7em; + line-height:1.5em; +} + +.content pre li +{ + margin:0.2em 0; } code @@ -230,6 +270,45 @@ code text-shadow:1px 1px 0 #fff; } +.out-links +{ + margin:0; + padding:0; +} + +.out-links li +{ + display:inline-block; +} + +.out-links li:not(:first-child):before +{ + content:"/"; + padding:0 1em; + color:#888; +} + +#toTop +{ + display:none; + padding:0.2em 1em 0.05em 1em; + position:fixed; + top:1.2em; + right:1.2em; + background-color:#777; + text-align:center; + color:#fff; + text-decoration:none; + text-transform:uppercase; + font-size:0.9em; + border-radius:3px; +} + +#toTop:hover +{ + background-color:#E3591E; +} + /* Prettify Styles -------------- */ diff --git a/public/laravel/js/scroll.js b/public/laravel/js/scroll.js new file mode 100644 index 00000000..1a4e9f05 --- /dev/null +++ b/public/laravel/js/scroll.js @@ -0,0 +1,236 @@ + +/* + * jQuery EasIng v1.1.2 - http://gsgd.co.uk/sandbox/jquery.easIng.php + * + * Uses the built In easIng capabilities added In jQuery 1.1 + * to offer multiple easIng options + * + * Copyright (c) 2007 George Smith + * Licensed under the MIT License: + * http://www.opensource.org/licenses/mit-license.php + */ + +// t: current time, b: begInnIng value, c: change In value, d: duration + +jQuery.extend( jQuery.easing, +{ + easeInQuad: function (x, t, b, c, d) { + return c*(t/=d)*t + b; + }, + easeOutQuad: function (x, t, b, c, d) { + return -c *(t/=d)*(t-2) + b; + }, + easeInOutQuad: function (x, t, b, c, d) { + if ((t/=d/2) < 1) return c/2*t*t + b; + return -c/2 * ((--t)*(t-2) - 1) + b; + }, + easeInCubic: function (x, t, b, c, d) { + return c*(t/=d)*t*t + b; + }, + easeOutCubic: function (x, t, b, c, d) { + return c*((t=t/d-1)*t*t + 1) + b; + }, + easeInOutCubic: function (x, t, b, c, d) { + if ((t/=d/2) < 1) return c/2*t*t*t + b; + return c/2*((t-=2)*t*t + 2) + b; + }, + easeInQuart: function (x, t, b, c, d) { + return c*(t/=d)*t*t*t + b; + }, + easeOutQuart: function (x, t, b, c, d) { + return -c * ((t=t/d-1)*t*t*t - 1) + b; + }, + easeInOutQuart: function (x, t, b, c, d) { + if ((t/=d/2) < 1) return c/2*t*t*t*t + b; + return -c/2 * ((t-=2)*t*t*t - 2) + b; + }, + easeInQuint: function (x, t, b, c, d) { + return c*(t/=d)*t*t*t*t + b; + }, + easeOutQuint: function (x, t, b, c, d) { + return c*((t=t/d-1)*t*t*t*t + 1) + b; + }, + easeInOutQuint: function (x, t, b, c, d) { + if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b; + return c/2*((t-=2)*t*t*t*t + 2) + b; + }, + easeInSine: function (x, t, b, c, d) { + return -c * Math.cos(t/d * (Math.PI/2)) + c + b; + }, + easeOutSine: function (x, t, b, c, d) { + return c * Math.sin(t/d * (Math.PI/2)) + b; + }, + easeInOutSine: function (x, t, b, c, d) { + return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; + }, + easeInExpo: function (x, t, b, c, d) { + return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b; + }, + easeOutExpo: function (x, t, b, c, d) { + return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b; + }, + easeInOutExpo: function (x, t, b, c, d) { + if (t==0) return b; + if (t==d) return b+c; + if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b; + return c/2 * (-Math.pow(2, -10 * --t) + 2) + b; + }, + easeInCirc: function (x, t, b, c, d) { + return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b; + }, + easeOutCirc: function (x, t, b, c, d) { + return c * Math.sqrt(1 - (t=t/d-1)*t) + b; + }, + easeInOutCirc: function (x, t, b, c, d) { + if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b; + return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b; + }, + easeInElastic: function (x, t, b, c, d) { + var s=1.70158;var p=0;var a=c; + if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; + if (a < Math.abs(c)) { a=c; var s=p/4; } + else var s = p/(2*Math.PI) * Math.asin (c/a); + return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; + }, + easeOutElastic: function (x, t, b, c, d) { + var s=1.70158;var p=0;var a=c; + if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; + if (a < Math.abs(c)) { a=c; var s=p/4; } + else var s = p/(2*Math.PI) * Math.asin (c/a); + return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; + }, + easeInOutElastic: function (x, t, b, c, d) { + var s=1.70158;var p=0;var a=c; + if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5); + if (a < Math.abs(c)) { a=c; var s=p/4; } + else var s = p/(2*Math.PI) * Math.asin (c/a); + if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; + return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b; + }, + easeInBack: function (x, t, b, c, d, s) { + if (s == undefined) s = 1.70158; + return c*(t/=d)*t*((s+1)*t - s) + b; + }, + easeOutBack: function (x, t, b, c, d, s) { + if (s == undefined) s = 1.70158; + return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; + }, + easeInOutBack: function (x, t, b, c, d, s) { + if (s == undefined) s = 1.70158; + if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; + return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; + }, + easeInBounce: function (x, t, b, c, d) { + return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b; + }, + easeOutBounce: function (x, t, b, c, d) { + if ((t/=d) < (1/2.75)) { + return c*(7.5625*t*t) + b; + } else if (t < (2/2.75)) { + return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; + } else if (t < (2.5/2.75)) { + return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; + } else { + return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; + } + }, + easeInOutBounce: function (x, t, b, c, d) { + if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b; + return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b; + } +}); + +/* +|-------------------------------------------------------------------------- +| UItoTop jQuery Plugin 1.1 +| http://www.mattvarone.com/web-design/uitotop-jquery-plugin/ +|-------------------------------------------------------------------------- +*/ + +(function($){ + $.fn.UItoTop = function(options) { + + var defaults = { + text: 'To Top', + min: 200, + inDelay:600, + outDelay:400, + containerID: 'toTop', + containerHoverID: 'toTopHover', + scrollSpeed: 1200, + easingType: 'linear' + }; + + var settings = $.extend(defaults, options); + var containerIDhash = '#' + settings.containerID; + var containerHoverIDHash = '#'+settings.containerHoverID; + + $('body').append(''+settings.text+''); + $(containerIDhash).hide().click(function(){ + $('html, body').animate({scrollTop:0}, settings.scrollSpeed, settings.easingType); + $('#'+settings.containerHoverID, this).stop().animate({'opacity': 0 }, settings.inDelay, settings.easingType); + return false; + }) + .prepend('') + .hover(function() { + $(containerHoverIDHash, this).stop().animate({ + 'opacity': 1 + }, 600, 'linear'); + }, function() { + $(containerHoverIDHash, this).stop().animate({ + 'opacity': 0 + }, 700, 'linear'); + }); + + $(window).scroll(function() { + var sd = $(window).scrollTop(); + if(typeof document.body.style.maxHeight === "undefined") { + $(containerIDhash).css({ + 'position': 'absolute', + 'top': $(window).scrollTop() + $(window).height() - 50 + }); + } + if ( sd > settings.min ) + $(containerIDhash).fadeIn(settings.inDelay); + else + $(containerIDhash).fadeOut(settings.Outdelay); + }); + +}; +})(jQuery); + + +$(document).ready(function() { + $().UItoTop({ easingType: 'easeOutQuart' }); + if ($('#docs-sidebar').length ) { + $.get('/docs/sidebar', function(data) { + $('.sidebar ul.toc').before(data); + $('.sidebar ul.toc').hide(); + var url = document.location.href; + // console.log(url); + var parent_folder = url.substr(0, url.lastIndexOf('/')); + var active = url.substr(0, url.length-document.location.hash.length); + + $('.docs.sidebar ul ul').hide(); + $('.docs.sidebar ul ul').each(function() { + $(this).parent('li').addClass('nav-close'); + var anchor = $(this).prev('a').attr('href'); + if (anchor == active.replace('http://laravel.com', '')) { + $(this).prev('a').addClass('active'); + $(this).parent('li').addClass('nav-open').removeClass('nav-close'); + $(this).show(); + } else if (anchor == parent_folder.replace('http://laravel.com', '')) { + $(this).prev('a').addClass('active'); + $(this).parent('li').addClass('nav-open').removeClass('nav-close'); + $(this).show(); + } + //console.log(anchor+' == '+parent_folder); + $(this).prev('a').bind('click', function(e) { + $(this).parent('li').toggleClass('nav-open').toggleClass('nav-close'); + $(this).next('ul').animate({opacity: 'toggle', height: 'toggle'}, "slow"); + return false; + }); + }); + }); + } // end if +}); \ No newline at end of file