| 542 | | <div title="Choosing a Custom Theme" modifier="miklb" modified="200710132257" created="200803130446" wikiformat="mediawiki" server.host="wiki.habariproject.org/w" server.page.revision="694"> |
| 543 | | <pre>#REDIRECT [[Creating a Custom Theme]]</pre> |
| | 542 | <div title="Available Plugins" modifier="laserlight" modified="200806260907" created="200807250028" wikiformat="mediawiki" server.host="wiki.habariproject.org/w" server.page.revision="undefined"> |
| | 543 | <pre>''Add your plugins to the list!'' |
| | 544 | |
| | 545 | The Habari community also maintains the [http://trac.habariproject.org/habari-extras Habari-Extras repository] to house community developed plugins and themes, many of which are not listed here. Plugins can be [http://www.habariproject.org/dist/plugins/ downloaded from the distribution directory]. Currently this repository does not separate stable builds from development builds, so compatibility with various builds of Habari is not guaranteed. Eventually this will be resolved. |
| | 546 | |
| | 547 | == [http://www.awhitebox.com Ali B. (a.k.a. dmondark)] == |
| | 548 | [http://www.awhitebox.com/audio-player-plugin-quick-update Audio Player Plugin 0.2] |
| | 549 | ''lets you insert a flash-based, mp3 audio player anywhere within your posts or pages.'' |
| | 550 | |
| | 551 | [http://www.awhitebox.com/woopra-plugin-for-habari Woopra Plugin 0.3] |
| | 552 | ''Add Woopra's tracking code to the footer of your site.'' |
| | 553 | |
| | 554 | The plugins below can now be found in the [http://trac.habariproject.org/habari-extras Habari-Extras] repository, and can be [http://www.habariproject.org/dist/plugins/ downloaded from the distribution directory] |
| | 555 | |
| | 556 | '''Recent Comments''' |
| | 557 | ''Display the most recent comments in your blog and customize how they are displayed'' |
| | 558 | |
| | 559 | '''Blogroll''' |
| | 560 | ''Displays a blogroll on your blog'' |
| | 561 | |
| | 562 | == [http://myfla.ws Arthus Erea] == |
| | 563 | The plugins below can now be found in the [http://trac.habariproject.org/habari-extras Habari-Extras] repository, and can be [http://www.habariproject.org/dist/plugins/ downloaded from the distribution directory]. |
| | 564 | |
| | 565 | * '''[http://trac.habariproject.org/habari-extras/browser/plugins/aliencontact AlienContact]''' generates and manages an extensible contact form for insertion into pages. |
| | 566 | * '''[http://trac.habariproject.org/habari-extras/browser/plugins/partytime partyTime]''' creates an event content-type for managing events on your Habari blog |
| | 567 | |
| | 568 | == [http://www.andrewdasilva.com/plugins Andrew da Silva] == |
| | 569 | |
| | 570 | ''These plugins can now be found in the [http://trac.habariproject.org/habari-extras Habari-Extras] repository, and can be [http://www.habariproject.org/dist/plugins/ downloaded from the distribution directory]'' |
| | 571 | |
| | 572 | '''Feedburner 0.5''' |
| | 573 | ''Redirects your Habari feeds through Feedburner.'' |
| | 574 | |
| | 575 | '''Google Sitemaps 0.6''' |
| | 576 | ''Generates a sitemap.xml when requested.'' |
| | 577 | |
| | 578 | '''Gravatar 0.5''' |
| | 579 | ''Simple yet effective Gravatar plugin for Habari.'' |
| | 580 | |
| | 581 | '''MetaWeblog 0.8.2''' |
| | 582 | ''Adds support for the metaWeblog XMLRPC protocol! |
| | 583 | |
| | 584 | '''Route 301 0.5''' |
| | 585 | ''Ease your move to Habari, route your old URLs to your new format.'' |
| | 586 | |
| | 587 | '''Thickbox 0.1''' |
| | 588 | ''Add Thickbox, a lightweight clone of Lightbox using the jQuery library.'' |
| | 589 | |
| | 590 | '''OpenSearch 0.1''' |
| | 591 | ''Add OpenSearch functionality to Habari'' |
| | 592 | |
| | 593 | '''OpenID 0.1''' |
| | 594 | ''Add OpenID support to Habari'' |
| | 595 | |
| | 596 | == [http://www.nbrightside.com/blog/ Andy C] == |
| | 597 | [http://www.nbrightside.com/blog/user/files/plugins/quote-0.2.tar.gz Quote] |
| | 598 | ''Display a random one-line quote from a user defined list'' |
| | 599 | |
| | 600 | == [http://caius.name/ Caius Durling] == |
| | 601 | [http://qwert.us/habari-markdown Habari Markdown (Updated)] |
| | 602 | ''An updated version of drunkenmonkeys markdown plugin. Applies markdown to the atom feed as well as the http:// content'' |
| | 603 | |
| | 604 | == [http://www.chrisjdavis.org/plugins/ Chris J. Davis] == |
| | 605 | [http://www.chrisjdavis.org/akismet-for-habari Akismet for Habari] |
| | 606 | ''Uhhh, yeah Akismet for Habari, like it says.'' |
| | 607 | |
| | 608 | [http://www.chrisjdavis.org/cjd-lifestream-1-0 CJD Lifestream 1.0] |
| | 609 | ''Lifestream for Habari'' |
| | 610 | |
| | 611 | [http://www.chrisjdavis.org/cjd-quick-posts-1-0 CJD Quick Post] |
| | 612 | ''Quickly post asides without loading the admin interface with this plugin.'' |
| | 613 | |
| | 614 | == [http://drunkenmonkey.org/ Drunken Monkey Labs] == |
| | 615 | [http://drunkenmonkey.org/projects/habari-markdown Habari Markdown] ''Enables [http://daringfireball.net John Gruber's] [http://daringfireball.net/projects/markdown/ Markdown syntax] for Habari'' |
| | 616 | |
| | 617 | [http://drunkenmonkey.org/user/files/habminbar-0.2.tar.gz Habminbar v.0.2] ''Habmin Bar is a small plugin for Habari that adds an admin bar to top of every page for easy access to the admin section. And in the latest version the styling makes it all look beautiful.'' |
| | 618 | |
| | 619 | [http://drunkenmonkey.org/projects/jambo Jambo Development Preview] ''Jambo plugin for Habari that will insert a contact form into any post you wish. Just insert <nowiki><!-- Jambo --></nowiki> wherever you want the contact form to be displayed.'' |
| | 620 | |
| | 621 | [http://drunkenmonkey.org/user/files/tabasamu.dev.tar.gz Tabasamu Development Preview] ''Tabasamu is a plugin for Habari that allows for the selection of different smilies packages. Smilies packages are a set of text/image smiley replacements which filter the post content and replace all text smilies with their image counterpart.'' |
| | 622 | |
| | 623 | == [http://blog.trifolddesigns.com/ Dylan Wreggelsworth] == |
| | 624 | [http://blog.trifolddesigns.com/textile-2-0-0-plugin-for-habari Habari Textile] |
| | 625 | ''Allows Textile 2.0.0 Parsing for articles and pages.'' |
| | 626 | |
| | 627 | [http://blog.trifolddesigns.com/pownce-plugin-for-habari Habari Pownce] |
| | 628 | ''Show your latest public posts from Pownce.'' |
| | 629 | |
| | 630 | == [http://iamgraham.net/ Graham Christensen 'itrebal' ] == |
| | 631 | [http://iamgraham.net/plugins#adsense Google AdSense] |
| | 632 | ''Displays Google AdSense in the sidebar.'' |
| | 633 | |
| | 634 | [http://iamgraham.net/plugins#analytics Google Analytics] |
| | 635 | ''Adds Google Analytics JS code to track your site using their services.'' |
| | 636 | |
| | 637 | [http://iamgraham.net/plugins#commenthttp Comment HTTP Filter] |
| | 638 | ''Filters out http:// from comments who's URL is '''only''' http://, leaves "http://" for all other URLs.'' |
| | 639 | |
| | 640 | == [http://josedasilva.net/blog/ Jose da Silva ] == |
| | 641 | [http://josedasilva.net/blog/habari-linkedin-plugin LinkedIn Habari Plugin] ''LinkedIn Plugin for Habari allows you to have the plugin badge in you template on a simple way!'' |
| | 642 | * Current Version: 0.1 |
| | 643 | * Tested on Habari Versions: DR 0.4 |
| | 644 | |
| | 645 | == [http://massimiliano.farinetti.eu Massimiliano Farinetti ] == |
| | 646 | [http://massimiliano.farinetti.eu/scartari/comment-notifier-for-habari Comment Notifier] |
| | 647 | ''Enables comment notification to a selected e-mail address.'' |
| | 648 | * Current Version: 0.4 |
| | 649 | * Tested on Habari 0.4 and 0.5-alpha (r1382) |
| | 650 | |
| | 651 | == [http://www.twofishcreative.com/michael/blog Michael C. Harris ] == |
| | 652 | [http://www.twofishcreative.com/michael/blog/publish-quote Publish Quote] |
| | 653 | ''Easily quote web sites on your blog using a bookmarklet.'' |
| | 654 | |
| | 655 | [http://www.twofishcreative.com/michael/blog/tinymce TinyMCE] |
| | 656 | ''Publish posts using the TinyMCE WYSIWYG HTML editor.'' |
| | 657 | |
| | 658 | (The following plugins are available on [http://habariproject.org/dist/plugins/ Habari-Extras]) |
| | 659 | |
| | 660 | [http://www.habariproject.org/dist/plugins/jwysiwyg.zip jWYSIWYG] |
| | 661 | ''Publish posts using the lightweight JQuery-based jWYSIWYG HTML editor.'' |
| | 662 | |
| | 663 | [http://www.habariproject.org/dist/plugins/youtubesilo.zip YouTube Media Silo] |
| | 664 | ''Access your YouTube videos from within Habari's publish page, for easy embedding.'' |
| | 665 | |
| | 666 | [http://www.habariproject.org/dist/plugins/livehelp.zip Live Help] |
| | 667 | ''Get live help from Habari developers and users from your Habari admin.'' |
| | 668 | |
| | 669 | == [http://blog.tinyau.net/ Raman Ng (a.k.a. tinyau)] == |
| | 670 | [http://blog.tinyau.net/archives/2007/06/25/habari-rn-code-escape-plugin/ RN Code Escape] |
| | 671 | ''Escape &, <, > inside &lt;code&gt;...&lt;/code&gt; block into HTML entities automatically'' |
| | 672 | |
| | 673 | [http://blog.tinyau.net/archives/2007/07/02/habari-rn-related-posts-plugin/ RN Related Posts] |
| | 674 | ''Show related posts of a post based on tag intersection of tags'' |
| | 675 | |
| | 676 | [http://blog.tinyau.net/archives/2007/07/17/habari-rn-related-tags-plugin/ RN Related Tags] |
| | 677 | ''Show related tags of a post'' |
| | 678 | |
| | 679 | [http://blog.tinyau.net/archives/2007/07/29/habari-rn-flickrrss-plugin/ RN FlickrRSS] |
| | 680 | ''Show recent images of Flickr through RSS feed'' |
| | 681 | |
| | 682 | [http://blog.tinyau.net/archives/2007/07/29/habari-rn-zooomrrss-plugin/ RN ZooomrRSS] |
| | 683 | ''Show recent images of Zooomr through RSS feed'' |
| | 684 | |
| | 685 | [http://blog.tinyau.net/archives/2007/08/30/habari-rn-tag-cloud-plugin/ RN Tag Cloud] |
| | 686 | ''Show tag cloud of your blog'' |
| | 687 | |
| | 688 | [http://blog.tinyau.net/archives/2007/09/22/habari-rn-monthly-archives-plugin/ RN Monthly Archives] |
| | 689 | ''Show monthly archives'' |
| | 690 | |
| | 691 | [http://blog.tinyau.net/archives/2008/03/12/habari-rn-custom-permalink-plugin/ RN Custom Permalink] |
| | 692 | ''Customize permalink structure of every content type and its corresponding comments feed'' |
| | 693 | |
| | 694 | == [http://robinadr.com Robin Adrianse ] == |
| | 695 | [http://robinadr.com/projects/footnotes Footnotes] |
| | 696 | ''Adds footnotes to your posts!'' |
| | 697 | |
| | 698 | [http://robinadr.com/projects/headcode Headcode] |
| | 699 | ''Enables you to Inject your own code into the section of your template, and before the closing tag in your template.'' |
| | 700 | |
| | 701 | [http://robinadr.com/projects/underscore_permalinks Underscore Permalinks] |
| | 702 | ''changes Habari’s slug creation to use underscores (_) instead of dashes (-).'' |
| | 703 | |
| | 704 | == [http://www.morydd.net/ Sean T Evans (a.k.a. Morydd)] == |
| | 705 | [http://www.morydd.net/habari-magic-tags-0-1 Morydd's Magic Tags] |
| | 706 | ''Hide tags begining with "@" from display Tested on DR 0.2)'' |
| | 707 | * Current Version: 0.3 |
| | 708 | * Tested on Habari Versions: DR 0.2 |
| | 709 | (Now avilable on [http://habariproject.org/dist/plugins/ Habari-Extras]) |
| | 710 | |
| | 711 | == [http://www.shihui.org/sheng/ Mike Shi] == |
| | 712 | [http://www.shihui.org/sheng/chinese-plugin-for-habari Chinese Plugin For Habari] |
| | 713 | |
| | 714 | 让Habari更好支持中文的插件,主要功能是把中文标题转换成拼音形式,比如标题为“测试”,则生成的URL地址为“ce-shi”,对于标签做同样的操作。 |
| | 715 | |
| | 716 | If you can NOT understand the text above, I guess you will not be interested in this plugin, because it is useful (or meaningful) only for people who write blogs in Chinese. You, however, still can get the English introduction from [http://www.shihui.org/sheng/chinese-plugin-for-habari here] |
| | 717 | |
| | 718 | [http://www.shihui.org/sheng/fanfou-plugin-for-habari Fanfou Plugin For Habari] |
| | 719 | |
| | 720 | Fanfou(饭否) is one of twitter's mimics in China. It supplies a badge for showing the lastest messages of you in the sidebar of your blog. I wrote this plugin to make it easy to use it. Maybe it's useless for the people who do not use Fanfou, but I think it's useful for some Chinese people since Fanfou is very popular in China. You can download it at [http://code.google.com/p/habari-chinese-plugin/downloads/list here] |
| | 721 | |
| | 722 | [http://www.shihui.org/sheng/timezone-plugin-for-habari Timezone Plugin For Habari] '''OMG, there is still a serious bug in it, I will fix it asap. Sorry.''' |
| | 723 | |
| | 724 | Timezone plugin can make your blog's time be shown correctly for your timezone. Active it, and select your timezone in configuration field, and, that's all. The date saved in database is still the server's timezone, so it will not damage your data. You can download from [http://habari-chinese-plugin.googlecode.com/files/timezone_0.8.zip here] |
| | 725 | |
| | 726 | == [http://numberbox.net Elijah Snyder] == |
| | 727 | [http://numberbox.net/blogs/files/barcampdev.zip barcamp Orlando Developer Day Badge] |
| | 728 | |
| | 729 | [http://numberbox.net/blogs/files/barcampmedia.zip barcamp Orlando Media Day Badge] |
| | 730 | |
| | 731 | Simple plugins to add barcamp badges to your sidebar for [http://barcamporlando.com barcamp Orlando] |
| | 732 | |
| | 733 | These plugins are designed to work "out of the box" with the K2 and other older themes that use act('theme_sidebar_top'), or invoked with $theme->sidebar_top() |
| | 734 | |
| | 735 | [http://numberbox.net/blogs/files/diggplugin.zip Digg Tags on your posts] |
| | 736 | Simple plugin for a configurable Digg tag on your post content. Very old, not very useful... |
| | 737 | Invoked with $theme->digg("link to article"), for example: $theme->digg($post->permalink) |
| | 738 | |
| | 739 | [http://numberbox.net/blogs/files/geshiplugin.zip GeSHi plugin for Habari.] |
| | 740 | GeSHi in Habari!<br/> |
| | 741 | This plugin requires that you download GeSHi yourself.<br/> |
| | 742 | [http://geshi.org Get GeSHi] |
| | 743 | |
| | 744 | [http://numberbox.net/blogs/habaritup-testing Content editor for Habari featuring markItUp! and simpleModal -- IN TESTING!] |
| | 745 | Adds a light weight, extensible jQuery based editor to Habari. |
| | 746 | |
| | 747 | == [http://mikelietz.org/code/habari Mike Lietz] == |
| | 748 | [http://mikelietz.org/code/habari/geotags.php GeoTags] ''Adds [http://wikipedia.org/wiki/Geotagging Geotag] meta tags to the header, for 0.4.1 and later.'' |
| | 749 | |
| | 750 | [http://mikelietz.org/code/habari/counters.php Post Word Count] ''Counts words in a given post, for 0.4.1 and later.'' |
| | 751 | |
| | 752 | [http://mikelietz.org/code/habari/counters.php Word Count by Tag] ''Totals word counts for all published posts in with one or more specified tags, for 0.4.1 and later.'' |
| | 753 | |
| | 754 | == [http://gopherwood.info wayne] == |
| | 755 | [http://gopherwood.info/2008/05/19/habari-plugin-post-mailer Post Mailer] ''Be used to mail a copy of post new published to indicated email addresses.'' |
| | 756 | |
| | 757 | [http://gopherwood.info/2008/05/21/fckeditor-plugin-for-habari Fckeditor] ''FckEditor plugin for Habari'' |
| | 758 | |
| | 759 | [http://gopherwood.info/2008/05/21/syntaxhighlighter-for-habari SyntaxHighlighter for Habari] ''SyntaxHighlighter for Habari is used to highlight source code in your post'' |
| | 760 | |
| | 761 | == [http://www.aranel.net Eugene Wee] == |
| | 762 | [https://launchpad.net/habari-captcha CAPTCHA] ''Provides a CAPTCHA for comment submission.'' |
| | 763 | |
| | 764 | Comments are allowed to bypass moderation if the submitter passes the CAPTCHA provided by reCAPTCHA. By default, comment submitters may choose to ignore the CAPTCHA, but this behaviour may be configured through the Habari admin panel. |
| | 765 | * Current version: 1.0b2 |
| | 766 | * Compatible with Habari 0.5 (tested on revision 2104) |
| | 767 | * Version 1.0b1 compatible with Habari 0.4.1</pre> |
| 545 | | <div title="Code Submisson" modifier="habari" modified="200710161723" created="200710132030" tags="MediaWikiFormat" changecount="2"> |
| 546 | | <pre>== Editing the Code == |
| | 769 | <div title="CSS Coding Standards" modifier="rickc" modified="200807241310" created="200807242317" tags="Category:Manual" wikiformat="mediawiki" server.host="wiki.habariproject.org/w" server.page.revision="undefined"> |
| | 770 | <pre>===Shorthand=== |
| | 771 | |
| | 772 | It is not only legal to use shorthand CSS, it is in fact recommended to save space. Thus, instead of: |
| | 773 | <pre> |
| | 774 | font-family: Helvetica, Sans-Serif; |
| | 775 | font-size: 1em; |
| | 776 | </pre> |
| | 777 | You should use: |
| | 778 | <pre> |
| | 779 | font: 1em Helvetica, Sans-Serif; |
| | 780 | </pre> |
| | 781 | This isn't applicable however if using shorthand means overwriting cascading CSS with similar CSS simply for the sake of using shorthand. The following example for instance, is wrong: |
| | 782 | <pre> |
| | 783 | ul li { |
| | 784 | margin: 0 5px; |
| | 785 | } |
| | 786 | |
| | 787 | ul li.last-child { |
| | 788 | margin: 0 5px 0 10px; |
| | 789 | } |
| | 790 | </pre> |
| | 791 | This would be the correct way of changing the left margin: |
| | 792 | <pre> |
| | 793 | ul li.last-child { |
| | 794 | margin-left: 10px; |
| | 795 | } |
| | 796 | </pre> |
| | 797 | In this way, you retain any changes higher up in the hierarchy. |
| | 798 | |
| | 799 | ===Colors Shorthand=== |
| | 800 | |
| | 801 | Using shorthand colors is entirely legal, like so: |
| | 802 | <pre> |
| | 803 | body { |
| | 804 | color: #222; |
| | 805 | } |
| | 806 | </pre> |
| | 807 | Color names (white, black, cyan) should not be used, because implementation on all browsers is not the same. Additionally, they provide no added benefit beyond convenience. |
| | 808 | |
| | 809 | ===Proprietary Styling=== |
| | 810 | |
| | 811 | It is fully legal to use proprietary styling rules, like for instance -webkit-box-shadow, as long as it doesn't degrade the user experience in any significant way on browsers where it isn't supported. |
| | 812 | |
| | 813 | Also, when doing so, e.g. with -webkit-border-radius, it is recommended that any other similar implementations be supported as well; in this case -moz-border-radius. |
| | 814 | |
| | 815 | ===Remember the Cascade=== |
| | 816 | |
| | 817 | It is easy to forget the cascading part of CSS in the heat of battle. However, in order to make future editing of admin.css as effortless as possible, remembering to contain the cascading of styling is paramount. |
| | 818 | |
| | 819 | Because of this, it is also suggested that the !important rule not be used, as it most often means that the cascading isn't being handled properly elsewhere in the CSS. |
| | 820 | |
| | 821 | ===Sections=== |
| | 822 | |
| | 823 | Some files, like /system/admin/css/admin.css, can grow quite large, and require some measure of organization to remain usable. For this, 'sections' are employed, which loosely group definitions by the elements they affect. admin.css for instance has sections like The Basics, The Menubar, The Menu, Dropbuttons and so on and so forth. |
| | 824 | |
| | 825 | A section is a commented capitalized section title with a dash to the extreme left in the comment: |
| | 826 | <pre> |
| | 827 | /*- FORMS */ |
| | 828 | </pre> |
| | 829 | And is always preceeded by two line breaks and followed by a single line space. |
| | 830 | |
| | 831 | Sub-sections can be helpful for dividing large sections. The sub-section title should be descriptive, so browsing the CSS file is swift. They looks like this: |
| | 832 | <pre> |
| | 833 | /*-- FORM BUTTONS */ |
| | 834 | </pre> |
| | 835 | The use of the dash to the left of the inside of the comment, makes it easy to step-search through the CSS file for a section, sub-section or simple comment, but searching for '/*- ' (sections) or '/*-- ' (sub-sections) or simply '/* ' (comments). |
| | 836 | |
| | 837 | ===CSS Code Layout=== |
| | 838 | |
| | 839 | All style definitions should have one line of space before and after. All CSS rules should be indented with a single tab space, and have a single space between the colon and the value of the rule. Finally, a semi-colon should follow all values, regardless of whether the value is the last in the style definition. |
| | 840 | |
| | 841 | Like so: |
| | 842 | <pre> |
| | 843 | body { |
| | 844 | background: #eee; |
| | 845 | font: 1em Helvetica, 'Trebuchet MS', Sans-Serif; |
| | 846 | color: #222; |
| | 847 | } |
| | 848 | </pre> |
| | 849 | As with any well-formed CSS, notice the apostrophe's around 'Trebuchet MS' and the defaulting to Sans-Serif. |
| | 850 | |
| | 851 | For readability and consistency's sake, it is generally recommended that even single-line style definitions be set up in the above manner, and not on a single line, like so: |
| | 852 | <pre> |
| | 853 | body { color: #222; } |
| | 854 | </pre> |
| | 855 | ===Inline Comments=== |
| | 856 | |
| | 857 | When a piece of CSS is inserted for non-obvious reasons, it can be a good idea to leave a small comment for others so as to not have it removed later because it didn't seem to make any immediate sense. |
| | 858 | |
| | 859 | Comments are inserted on the right-hand side of the element they are meant for. If they cover an entire block of code, it would look like this: |
| | 860 | <pre> |
| | 861 | body { /* Something insightful goes here */ |
| | 862 | background: #eee; |
| | 863 | font: 1em Helvetica, 'Trebuchet MS', Sans-Serif; |
| | 864 | color: #222; |
| | 865 | } |
| | 866 | </pre> |
| | 867 | If they cover only a single element, it would look like this: |
| | 868 | <pre> |
| | 869 | body { |
| | 870 | background: #eee; |
| | 871 | font: 1em Helvetica, 'Trebuchet MS', Sans-Serif; /* Trebuchet MS doesn't match Helvetica well */ |
| | 872 | color: #222; |
| | 873 | } |
| | 874 | </pre> |
| | 875 | |
| | 876 | ===Complete Example=== |
| | 877 | |
| | 878 | This is how the end of one section and the beginning of a new, complete with inline comments, might look: |
| | 879 | |
| | 880 | <pre> |
| | 881 | body { |
| | 882 | background: #eee; |
| | 883 | font: 1em Helvetica, 'Trebuchet MS', Sans-Serif; |
| | 884 | color: #222; |
| | 885 | } |
| | 886 | |
| | 887 | |
| | 888 | /*- HEADERS */ |
| | 889 | |
| | 890 | h1, h2 { |
| | 891 | color: #111; /* Redundant comment */ |
| | 892 | font-size: 2em; |
| | 893 | } |
| | 894 | |
| | 895 | h2 { |
| | 896 | font-size: 1.5em; |
| | 897 | } |
| | 898 | </pre> |
| | 899 | |
| | 900 | [[Category:Manual]]</pre> |
| | 901 | </div> |
| | 902 | <div title="Classes/QueryRecord" modifier="dmondark" modified="200803031924" created="200807242317" tags="Category:Manual" wikiformat="mediawiki" server.host="wiki.habariproject.org/w" server.page.revision="undefined"> |
| | 903 | <pre>A single instance of QueryRecord represents a single query result row. QueryRecord also serves as the base class for derivative classes that provide row-level data access. QueryRecord is, in many ways, the fundamental building block of Habari. |
| | 904 | |
| | 905 | ==Using QueryRecord== |
| | 906 | |
| | 907 | QueryRecord provides basic functions that allow Habari to interact with the single row of data. The properties of a QueryRecord object represent the field values of the row. |
| | 908 | |
| | 909 | To obtain an instance of QueryRecord with data, call one of these static methods on the DB class: |
| | 910 | ;get_row():Returns a single QueryRecord instance for the single row retrieved |
| | 911 | ;get_results():Returns an array of QueryRecord instances, one per row returned in the query |
| | 912 | |
| | 913 | For example: |
| | 914 | <code> |
| | 915 | $record = DB::get_row('SELECT id, bar FROM foo WHERE id = 1'); |
| | 916 | echo $record->bar; |
| | 917 | </code> |
| | 918 | |
| | 919 | The code above firsts queries the database for a record containing the fields <tt>id</tt> and <tt>bar</tt> from the table 'foo' where the 'id' field is equal to 1. The single record (only one is returned by <tt>DB::get_row()</tt>) is stored in <tt>$record</tt> as an instance of the QueryRecord class. The property <tt>bar</tt> referenced as <tt>$record->bar</tt> contains the value of the 'bar' field returned by the query. Similarly, although this is not shown, the 'id' field is assigned to <tt>$record->id</tt>. |
| | 920 | |
| | 921 | By echoing the value of <tt>$record->bar</tt>, the value of that field is output. |
| | 922 | |
| | 923 | ==Updating a Record== |
| | 924 | |
| | 925 | By changing the values of these properties and calling the update() method on the object, the QueryRow can commit that data back to the database. For example: |
| | 926 | |
| | 927 | <code> |
| | 928 | $record = DB::get_row('SELECT id, bar FROM foo WHERE id = 1'); |
| | 929 | $record->bar = 'hello'; |
| | 930 | $record->update('foo', array('id')); |
| | 931 | </code> |
| | 932 | |
| | 933 | As with the prior example, the values of the fields 'id' and 'bar' have been queried into an instance of QueryRecord. |
| | 934 | |
| | 935 | The <tt>$record->bar</tt> is then assigned the value 'hello'. This prepares the new data for update in the database. The value of <tt>$record->bar</tt> will contain 'hello' after this assignment. |
| | 936 | |
| | 937 | To update the record in the database, the <tt>update()</tt> method is called. In QueryRecord, update() accepts two parameters. The first is the table to which the data will be written and the second is an array of fields that will be used to match the data in the object to the correct row in the database. |
| | 938 | |
| | 939 | In this case, the table updated is 'foo', and the value of <tt>$record->id</tt> will be matched against the field 'id' in the database. Any record in the database with a matching id value will have its fields updated to the other property values of <tt>$record</tt> |
| | 940 | |
| | 941 | ==Inserting a Record== |
| | 942 | |
| | 943 | QueryRecord can also be used to insert new records into a table. For example: |
| | 944 | |
| | 945 | <code> |
| | 946 | $record = new QueryRecord( |
| | 947 | array('bar'=>'hello') |
| | 948 | ); |
| | 949 | $record->insert('foo'); |
| | 950 | </code> |
| | 951 | |
| | 952 | In the above example, a new instance of QueryRecord is created and asigned to <tt>$record</tt>. The values of the properties in the new QueryRecord are built from the associative array that is passed to the QueryRecord constructor. The keys of the array become the object's properties, and the values of the array become those properties' values. After creating <tt>$record</tt> as above, the value of <tt>$record->bar</tt> would be set to 'hello'. |
| | 953 | |
| | 954 | Calling <tt>$record->insert()</tt> inserts the property values into the specified table, in this case, 'foo'. |
| | 955 | |
| | 956 | In order for this to work correctly, all of the values required to insert a row into a table must have been set as properties of the QueryRecord object. Note that in this example, the 'id' field is omitted with the assumption that it is an auto_increment primary key in the 'foo' table. |
| | 957 | |
| | 958 | After the row is inserted, the value of 'id' *will not* be set in <tt>$record->id</tt>. This must be done manually using <tt>DB::last_insert_id()</tt>, which is often handled from a subclass, as described in the Extending QueryRecord section below. |
| | 959 | |
| | 960 | ==Deleting a Record== |
| | 961 | |
| | 962 | This is fundamentally the same as updating a row, except it deletes the row from the table that has fields with the matching values. |
| | 963 | |
| | 964 | <code> |
| | 965 | $record->delete('foo', array('id')); |
| | 966 | </code> |
| | 967 | |
| | 968 | ==Extending QueryRecord== |
| | 969 | |
| | 970 | As part of Habari's Object-Oriented approach, other classes can extend the QueryRecord class to provide additional methods that interact with QueryRecords that contain a specific type of data. For example, the Post class extends QueryRecord to provide additional methods that are post-specific. The class that extends QueryRecord [http://en.wikipedia.org/wiki/Inheritance_%28computer_science%29 inherits] all of the methods of QueryRecord in addition to any that it provides on its own. |
| | 971 | |
| | 972 | In most cases, a QueryRecord is not the class of a row. A row is usually requested as one of QueryRecord's descendant classes. |
| | 973 | |
| | 974 | Many classes extend the QueryRecord class. The following classes all inherit from QueryRecord: |
| | 975 | ;Post: Represents a single post |
| | 976 | ;Comment: Represents a single comment |
| | 977 | ;LogEntry: Represents a single entry in the event log |
| | 978 | ;CronJob: Represents a single periodically executed task |
| | 979 | ;RewriteRule: Represents a single rewrite rule |
| | 980 | ;User: Represents a single user |
| | 981 | |
| | 982 | The classes above represent wildly different functionality and and data representations; yet they each extend the base QueryRecord class. By providing this core functionality for descendant classes, extended classes don't need to duplicate code. |
| | 983 | |
| | 984 | QueryRecord descendants map to database tables of the same name, and most of the properties of the descendants map the columns of that table. For example, the Post table is used to store Post object data. The Post object has fields 'id', 'title', and 'content', among others. These fields are also columns in the 'posts' table in the database. |
| | 985 | |
| | 986 | The Post class also provides special functionality that is associated only to posts. For example, every post has a status value. In the database, this status value is stored as an integer. Because it's often easier to work with the names of these status, the Post class provides the ability to accept either the integer or the string as the value of the poperty, but always stores the value in the database as an integer. This is just one example of what additional functionality a subclass of QueryRecord can provide. |
| | 987 | |
| | 988 | One of the more significant additions a subclass can make is to override the <tt>update()</tt> and <tt>insert()</tt> methods of QueryRecord. By creating having its own <tt>update()</tt> method, a class can identify the correct table and key fields that are used to update that row in the database. This allows a subclass instance to omit the table and keyfields parameters in the call to update. So when updating a post, instead of this: |
| | 989 | |
| | 990 | <code>$record->update('foo', array('id'));</code> |
| | 991 | |
| | 992 | You would simply call this: |
| | 993 | |
| | 994 | <code>$post->update();</code> |
| | 995 | |
| | 996 | Using a subclass, you can transparently assign the value of DB::last_insert_id() to the keyfield property of the object. This will allow you to update the object after it is inserted without having to manually retrieve the key values each time. So when inserting a post, instead of this, where the <tt>id</tt> property must be set manually: |
| | 997 | |
| | 998 | <code> |
| | 999 | $record = new QueryRecord(/* post field data */); |
| | 1000 | $record->insert('posts'); |
| | 1001 | $record->id = DB::last_insert_id(); |
| | 1002 | $record->title = 'new title'; |
| | 1003 | $record->update('post', array('id')); |
| | 1004 | </code> |
| | 1005 | |
| | 1006 | You would simply call this: |
| | 1007 | |
| | 1008 | <code> |
| | 1009 | $post = new Post(/* post field data*/); |
| | 1010 | $post->insert(); |
| | 1011 | $post->title = 'new title'; |
| | 1012 | $post->update(); |
| | 1013 | </code> |
| | 1014 | |
| | 1015 | It's not that the assignment doesn't need to be made at all, but that it takes place in the Post class (which extends QueryRecord) so that you need not repeat it whenever you insert a new post. |
| | 1016 | |
| | 1017 | Please review the documentation for the classes that extend QueryRecord for the details of functionality that they provide beyond QueryRecord itself. |
| | 1018 | |
| | 1019 | |
| | 1020 | QueryRecord provides the following: |
| | 1021 | * [http://us.php.net/manual/en/language.oop5.overloading.php overloaded] __get(), __set() and __isset() |
| | 1022 | * exclude_fields() and list_excluded_fields(), for identifying properties handled exclusively by the database |
| | 1023 | * insert(), for adding data to the database |
| | 1024 | * to_array(), to permit array operations on the object (like <code>foreach</code>) |
| | 1025 | * get_url_args(), which returns an array of the values represented by the object |
| | 1026 | * update(), for recording modified values to the database |
| | 1027 | * delete(), for deleting an item from the database |
| | 1028 | |
| | 1029 | {{developer}} |
| | 1030 | |
| | 1031 | [[Category:Manual]]</pre> |
| | 1032 | </div> |
| | 1033 | <div title="Code Submisson" modifier="michaeltwofish" modified="200805241224" created="200807242317" tags="Category:Manual" wikiformat="mediawiki" server.host="wiki.habariproject.org/w" server.page.revision="undefined"> |
| | 1034 | <pre>Contributions to the Habari codebase made by the wider community are incredibly important. This page describes the process that developers should follow to submit code to Habari. |
| | 1035 | |
| | 1036 | == Editing the Code == |
| 575 | | <div title="Creating A Plugin" modifier="Massimiliano" modified="200802022118" created="200803130446" tags="Category:Manual" wikiformat="mediawiki" server.host="wiki.habariproject.org/w" server.page.revision="1199"> |
| 576 | | <pre>Habari's functionality can be modified or extended using plugins, which are written in PHP. Writing a plugin for Habari is extremely simple. |
| 577 | | |
| 578 | | The steps below describe in detail how to create a plugin for Habari, and provide some examples of the sorts of things that can be done with a plugin. |
| 579 | | |
| 580 | | == Step 1: Create The Plugin Class File == |
| 581 | | |
| 582 | | Create a new directory in your <tt>/user/plugins</tt> directory that uses the name of your plugin. As an example, you could create: <tt>/user/plugins/mysample</tt> |
| 583 | | |
| 584 | | In that directory, create a php file that contains the name of your plugin (the same as the directory) plus <tt>.plugin.php</tt> added to the end. For our example, we would create: <tt>/user/plugins/mysample/mysample.plugin.php</tt> |
| 585 | | |
| 586 | | == Step 2: Create the Base Plugin Class == |
| 587 | | |
| 588 | | All plugins in Habari must extend the core <tt>Plugin</tt> class. This allows the system to easily find and register your plugin. The following code creates a plugin called <tt>MyPlugin</tt>. |
| 589 | | |
| 590 | | <code> |
| 591 | | class MyPlugin extends Plugin |
| 592 | | { |
| 593 | | function info() |
| 594 | | { |
| 595 | | return array( |
| 596 | | 'name' => 'My Plugin', |
| 597 | | 'version' => '1.0', |
| 598 | | 'url' => 'http://habariproject.org/', |
| 599 | | 'author' => 'Habari Community', |
| 600 | | 'authorurl' => 'http://habariproject.org/', |
| 601 | | 'license' => 'Apache License 2.0', |
| 602 | | 'description' => 'Description', |
| 603 | | ); |
| 604 | | } |
| 605 | | } |
| 606 | | </code> |
| 607 | | |
| 608 | | The <tt>info()</tt> member of the plugin is _required_. It indicates the basic plugin information. If you want your plugin to appear properly in Habari's list of plugins in the admin, then you need to provide these fields at a minimum: |
| 609 | | |
| 610 | | ;name: The name of the plugin as it will appear in the admin console. |
| 611 | | ;version: The version of your plugin. It is important that this version number be compatible with PHP's [http://php.net/version_compare version_compare()] function if you want your plugin to be compatible with the habariproject.org update beacon. |
| 612 | | ;url: The URL location of your plugin. This will be used to create a link to your plugin from the admin console. |
| 613 | | ;author: The name of the author of your plugin. (Your name!) |
| 614 | | ;authorurl: The URL location of your blog/web site if any. |
| 615 | | ;license: The distribution license of your plugin. |
| 616 | | ;description: Description of your plugin. |
| 617 | | |
| 618 | | You should not create an instance of your plugin (<tt>$foo = new MyPlugin()</tt>) within your plugin class file. Habari will find your plugin and create an instance of it for you when your plugin is activated. It is able to do this because your plugin extends the core <tt>Plugin</tt> class. (If your plugin requires a separate class, Habari won't create an instance of it, because it wouldn't extend <tt>Plugin</tt>.) |
| 619 | | |
| 620 | | == Step 3: Add Actions and Filters == |
| 621 | | |
| 622 | | The plugin system in Habari is based on Actions and Filters. |
| 623 | | |
| 624 | | An Action occurs when a certain event in the software takes place. For example, when a post is saved or displayed an Action is triggered. An Action notifies your plugin that the event has taken place, allowing your plugin to perform some function. Values that are passed to an action cannot be changed. |
| 625 | | |
| 626 | | A Filter is similar to an Action but allows your plugin to change data that will be used by the system when an event occurs. Filters are passed the value of a parameter to filter, and return that parameter, possibly having altered it in some way. Some Filters also pass additional parameters to give plugins extra information. An example is a Filter that responds to a comment submission and returns the "spamminess" of the comment. The value that is returned from a Filter is passed to subsequent Filters as the first parameter, and is eventually used as the value for the filtered item. |
| 627 | | |
| 628 | | Each Action or Filter has a name called a "hook name" that represents an event. A plugin "hook" is the place in the code where Habari checks to see if any plugins need to be informed of an event. A hook is either an Action or a Filter. See [[Plugin Hooks]] for more information on plugin hooks, including a list of available Actions and Filters. A plugin "sink" is one of the actual functions that is executed when the plugin hook code is run. Creating sinks that are activated for specific hooks is as simple as adding a method to your class with the appropriate name, either <tt>filter_hook_name</tt> or <tt>action_hook_name</tt>. |
| 629 | | |
| 630 | | === Action Example === |
| 631 | | |
| 632 | | Assume that you want your plugin to perform a task whenever the system has finished loading all plugins. The hook name of this hook is <tt>plugins_loaded</tt>. <tt>plugins_loaded</tt> is an Action. |
| 633 | | |
| 634 | | To sink this action, create a new method in your plugin like so: |
| 635 | | |
| 636 | | <code> |
| 637 | | function action_plugins_loaded() |
| 638 | | { |
| 639 | | Utils::debug('Hello!'); |
| 640 | | } |
| 641 | | </code> |
| 642 | | |
| 643 | | The prefix of <tt>action_</tt> in your function name tells Habari that you are creating a sink for an Action. The <tt>plugins_loaded</tt> part of the function name tells Habari what hook you want to sink. |
| 644 | | |
| 645 | | When you activate the plugin with this function in it, the "Hello!" message will be displayed inside the pink debug box immediately after all active plugins are loaded. |
| 646 | | |
| 647 | | Some Actions will pass values to the sink methods. These values can be checked and acted upon. |
| 648 | | |
| 649 | | === Filter Example === |
| 650 | | |
| 651 | | Assume that you want your plugin to check the spamminess of a comment. The hook name of a hook that will do this is <tt>spam_filter</tt>. <tt>spam_filter</tt> is a Filter. |
| 652 | | |
| 653 | | To sink this Filter, create a new method in your plugin like so: |
| 654 | | |
| 655 | | <code> |
| 656 | | function filter_spam_filter($rating, $comment, $handler_vars) |
| 657 | | { |
| 658 | | if ( strpos( $comment->content, 'viagra' ) ) { |
| 659 | | $rating++; |
| 660 | | } |
| 661 | | return $rating; |
| 662 | | } |
| 663 | | </code> |
| 664 | | |
| 665 | | The prefix of <tt>filter_</tt> in your function name tells Habari that you are creating a sink for a Filter. The <tt>spam_filter</tt> part of the function name tells Habari what hook you want to sink. |
| 666 | | |
| 667 | | When you activate the plugin with this method, Habari will pass every submitted comment through it. The function looks for the word "viagra" in the content of the comment, and upon finding it, increases the spam rating of the comment. |
| 668 | | |
| 669 | | Finally, the rating is returned for use by the next plugin, and by the system. Note that even when no adjustment is made to the value of <tt>$rating</tt> it *must* be returned, otherwise the system will not have a value to process. |
| 670 | | |
| 671 | | In this sink method, the <tt>$handler_vars</tt> parameter is provided to the method by the system, but it is not used by the method. This parameter could have been omitted in the method declaration, but it might be useful to leave it there for future use. |
| 672 | | |
| 673 | | === XMLRPC Example === |
| 674 | | |
| 675 | | Implementing XMLRPC via plugins is very easy by use of a special prefix for a plugin function. |
| 676 | | |
| 677 | | <code> |
| 678 | | function xmlrpc_namespace__function($param1, $param2, ...); |
| 679 | | </code> |
| 680 | | |
| 681 | | A hook implemented in this way uses the "namespace" part of the hook name as the XMLRPC namespace, and the "function" part as the XMLRPC function. The two are separated by two underscore characters. |
| 682 | | |
| 683 | | Values passed from to this hook function are those interpreted by processing the incoming values posted to Habari's XMLRPC endpoint. |
| 684 | | |
| 685 | | To return a properly formatted XMLRPC value, simply return a standard PHP data type. This will be converted into a proper XMLRPC response by the plugin system. |
| 686 | | |
| 687 | | == Step 4: Common Plugin Tasks == |
| 688 | | |
| 689 | | The previous steps provide instructions for constructing the basic structure of a Habari plugin. With that knowledge, leveraging the many plugin hooks is a simple task. |
| 690 | | |
| 691 | | What follows are a few things that are common tasks when creating a plugin. |
| 692 | | |
| 693 | | === Add Output to a Theme === |
| 694 | | |
| 695 | | So, you have created your killer plugin and want to provide theme developers a chance to show off your work. Based on the action example above, you can do something like this: |
| 696 | | |
| 697 | | <code> |
| 698 | | function action_add_template_vars( $theme ) { |
| 699 | | { |
| 700 | | $theme->yourvariable= 'Sweet Plugin Output'; |
| 701 | | } |
| 702 | | </code> |
| 703 | | |
| 704 | | This makes <tt>$yourvariable</tt> available in the theme, where you can do something like |
| 705 | | |
| 706 | | <code> |
| 707 | | <?php echo $yourvariable ?> |
| 708 | | </code> |
| 709 | | |
| 710 | | and that will output the value directly in the theme template file. |
| 711 | | |
| 712 | | === Use FormUI to Create an Options Page === |
| 713 | | |
| 714 | | Adding an options control to your plugin is also very easy, and most users will be more comfortable with setting the options via the admin panel than editing plugin code directly. Thankfully Habari provides a mechanism called FormUI tha |