| 1634 | | |
| 1635 | | ########################################################################### |
| 1636 | | |
| 1637 | | =head2 App:Listing |
| 1638 | | |
| 1639 | | This application tag is used in MT application templates to produce |
| 1640 | | a table listing. It expects an C<object_loop> variable to be available, |
| 1641 | | or you can use the C<loop> attribute to have it use a different source. |
| 1642 | | |
| 1643 | | It will output it's contents once for each row of the input array. It |
| 1644 | | produces markup that is compatible with the MT application templates |
| 1645 | | and CSS structure, so it is not meant for general blog publishing use. |
| 1646 | | |
| 1647 | | The C<return_args> variable is recognized and will populate a hidden |
| 1648 | | field in the produced C<form> tag if available. |
| 1649 | | |
| 1650 | | The C<blog_id> variable is recognized and will populate a hidden |
| 1651 | | field in the produced C<form> tag if available. |
| 1652 | | |
| 1653 | | The C<screen_class> variable is recognized and will force the |
| 1654 | | C<hide_pager> attribute to 1 if it is set to 'search-replace'. |
| 1655 | | |
| 1656 | | The C<magic_token> variable is recognized and will populate a hidden |
| 1657 | | field in the produced C<form> tag if available (or will retrieve |
| 1658 | | a token from the current application if unset). |
| 1659 | | |
| 1660 | | The C<view_expanded> variable is recognized and will affect the |
| 1661 | | class name applied to the table. If assigned, the table tag will |
| 1662 | | receive a 'expanded' class; otherwise, it is given a 'compact' |
| 1663 | | class. |
| 1664 | | |
| 1665 | | The C<listing_header> variable is recognized and will be output |
| 1666 | | in a C<div> tag (classed with 'listing-header') that appears |
| 1667 | | at the top of the listing. This is only output when 'actions' |
| 1668 | | are shown (see 'show_actions' attribute). |
| 1669 | | |
| 1670 | | The structure of the output from a typical use like this: |
| 1671 | | |
| 1672 | | <MTApp:Listing type="entry"> |
| 1673 | | (contents of one row for table) |
| 1674 | | </MTApp:Listing> |
| 1675 | | |
| 1676 | | produces something like this: |
| 1677 | | |
| 1678 | | <div id="entry-listing" class="listing"> |
| 1679 | | <div class="listing-header"> |
| 1680 | | </div> |
| 1681 | | <form id="entry-listing-form" class="listing-form" |
| 1682 | | action="..../mt.cgi" method="post" |
| 1683 | | onsubmit="return this['__mode'] ? true : false"> |
| 1684 | | <input type="hidden" name="__mode" value="" /> |
| 1685 | | <input type="hidden" name="_type" value="entry" /> |
| 1686 | | <input type="hidden" name="action_name" value="" /> |
| 1687 | | <input type="hidden" name="itemset_action_input" value="" /> |
| 1688 | | <input type="hidden" name="return_args" value="..." /> |
| 1689 | | <input type="hidden" name="blog_id" value="1" /> |
| 1690 | | <input type="hidden" name="magic_token" value="abcd" /> |
| 1691 | | <$MTApp:ActionBar bar_position="top" |
| 1692 | | form_id="entry-listing-form"$> |
| 1693 | | <table id="entry-listing-table" |
| 1694 | | class="entry-listing-table compact" cellspacing="0"> |
| 1695 | | |
| 1696 | | (contents of tag are placed here) |
| 1697 | | |
| 1698 | | </table> |
| 1699 | | <$MTApp:ActionBar bar_position="bottom" |
| 1700 | | form_id="entry-listing-form"$> |
| 1701 | | </form> |
| 1702 | | </div> |
| 1703 | | |
| 1704 | | B<Attributes:> |
| 1705 | | |
| 1706 | | =over 4 |
| 1707 | | |
| 1708 | | =item * type (optional) |
| 1709 | | |
| 1710 | | The C<MT::Object> object type the listing is processing. If unset, |
| 1711 | | will use the contents of the C<object_type> variable. |
| 1712 | | |
| 1713 | | =item * loop (optional) |
| 1714 | | |
| 1715 | | The source of data to process. This is an array of hashes, similar |
| 1716 | | to the kind used with the L<Loop> tag. If unset, the C<object_loop> |
| 1717 | | variable is used instead. |
| 1718 | | |
| 1719 | | =item * empty_message (optional) |
| 1720 | | |
| 1721 | | Used when there are no rows to output for the listing. If not set, |
| 1722 | | it will process any 'else' block that is available instead, or, failing |
| 1723 | | that, will output an L<App:StatusMsg> tag saying that no data could be |
| 1724 | | found. |
| 1725 | | |
| 1726 | | =item * id (optional) |
| 1727 | | |
| 1728 | | Used to construct the DOM id for the listing. The outer C<div> tag |
| 1729 | | will use this value. If unset, it will be assigned C<type-listing> (where |
| 1730 | | 'type' is the object type determined for the listing; see 'type' |
| 1731 | | attribute). |
| 1732 | | |
| 1733 | | =item * listing_class (optional) |
| 1734 | | |
| 1735 | | Provides a custom class name that can be applied to the main |
| 1736 | | C<div> tag produced (this is in addition to the 'listing' class |
| 1737 | | that is always applied). |
| 1738 | | |
| 1739 | | =item * action (optional; default 'script_url' variable) |
| 1740 | | |
| 1741 | | Supplies the 'action' attribute of the C<form> tag produced. |
| 1742 | | |
| 1743 | | =item * hide_pager (optional; default '0') |
| 1744 | | |
| 1745 | | Controls whether the pagination controls are shown or not. |
| 1746 | | If unspecified, pagination is shown. |
| 1747 | | |
| 1748 | | =item * show_actions (optional; default '1') |
| 1749 | | |
| 1750 | | Controls whether the actions associated with the object type |
| 1751 | | processed are shown or not. If unspecified, actions are shown. |
| 1752 | | |
| 1753 | | =back |
| 1754 | | |
| 1755 | | =for tags application |
| 1756 | | |
| 1757 | | =cut |
| 1758 | | |
| 1759 | | sub _hdlr_app_listing { |
| 1760 | | my ($ctx, $args, $cond) = @_; |
| 1761 | | |
| 1762 | | my $type = $args->{type} || $ctx->var('object_type'); |
| 1763 | | my $class = MT->model($type) if $type; |
| 1764 | | my $loop = $args->{loop} || 'object_loop'; |
| 1765 | | my $loop_obj = $ctx->var($loop); |
| 1766 | | |
| 1767 | | unless ((ref($loop_obj) eq 'ARRAY') && (@$loop_obj)) { |
| 1768 | | my @else = @{ $ctx->stash('tokens_else') || [] }; |
| 1769 | | return &_hdlr_pass_tokens_else if @else; |
| 1770 | | my $msg = $args->{empty_message} || MT->translate("No [_1] could be found.", $class ? lowercase($class->class_label_plural) : ($type ? $type : MT->translate("records"))); |
| 1771 | | return $ctx->build(qq{<mtapp:statusmsg |
| 1772 | | id="zero-state" |
| 1773 | | class="info zero-state"> |
| 1774 | | $msg |
| 1775 | | </mtapp:statusmsg>}); |
| 1776 | | } |
| 1777 | | |
| 1778 | | my $id = $args->{id} || ($type ? $type . '-listing' : 'listing'); |
| 1779 | | my $listing_class = $args->{listing_class} || ""; |
| 1780 | | my $hide_pager = $args->{hide_pager} || 0; |
| 1781 | | $hide_pager = 1 if ($ctx->var('screen_class') || '') eq 'search-replace'; |
| 1782 | | my $show_actions = exists $args->{show_actions} ? $args->{show_actions} : 1; |
| 1783 | | my $return_args = $ctx->var('return_args') || ''; |
| 1784 | | $return_args = encode_html( $return_args ); |
| 1785 | | $return_args = qq{\n <input type="hidden" name="return_args" value="$return_args" />} if $return_args; |
| 1786 | | my $blog_id = $ctx->var('blog_id') || ''; |
| 1787 | | $blog_id = qq{\n <input type="hidden" name="blog_id" value="$blog_id" />} if $blog_id; |
| 1788 | | my $token = $ctx->var('magic_token') || MT->app->current_magic; |
| 1789 | | my $action = $args->{action} || '<mt:var name="script_url">'; |
| 1790 | | |
| 1791 | | my $actions_top = ""; |
| 1792 | | my $actions_bottom = ""; |
| 1793 | | my $form_id = "$id-form"; |
| 1794 | | if ($show_actions) { |
| 1795 | | $actions_top = qq{<\$MTApp:ActionBar bar_position="top" hide_pager="$hide_pager" form_id="$form_id"\$>}; |
| 1796 | | $actions_bottom = qq{<\$MTApp:ActionBar bar_position="bottom" hide_pager="$hide_pager" form_id="$form_id"\$>}; |
| 1797 | | } else { |
| 1798 | | $listing_class .= " hide_actions"; |
| 1799 | | } |
| 1800 | | |
| 1801 | | my $insides; |
| 1802 | | { |
| 1803 | | local $args->{name} = $loop; |
| 1804 | | defined($insides = _hdlr_loop($ctx, $args, $cond)) |
| 1805 | | or return; |
| 1806 | | } |
| 1807 | | my $listing_header = $ctx->var('listing_header') || ''; |
| 1808 | | my $view = $ctx->var('view_expanded') ? ' expanded' : ' compact'; |
| 1809 | | |
| 1810 | | my $table = <<TABLE; |
| 1811 | | <table id="$id-table" class="$id-table$view" cellspacing="0"> |
| 1812 | | $insides |
| 1813 | | </table> |
| 1814 | | TABLE |
| 1815 | | |
| 1816 | | if ($show_actions) { |
| 1817 | | local $ctx->{__stash}{vars}{__contents__} = $table; |
| 1818 | | return $ctx->build(<<EOT); |
| 1819 | | <div id="$id" class="listing $listing_class"> |
| 1820 | | <div class="listing-header"> |
| 1821 | | $listing_header |
| 1822 | | </div> |
| 1823 | | <form id="$form_id" class="listing-form" |
| 1824 | | action="$action" method="post" |
| 1825 | | onsubmit="return this['__mode'] ? true : false"> |
| 1826 | | <input type="hidden" name="__mode" value="" /> |
| 1827 | | <input type="hidden" name="_type" value="$type" /> |
| 1828 | | <input type="hidden" name="action_name" value="" /> |
| 1829 | | <input type="hidden" name="itemset_action_input" value="" /> |
| 1830 | | $return_args |
| 1831 | | $blog_id |
| 1832 | | <input type="hidden" name="magic_token" value="$token" /> |
| 1833 | | $actions_top |
| 1834 | | <mt:var name="__contents__"> |
| 1835 | | $actions_bottom |
| 1836 | | </form> |
| 1837 | | </div> |
| 1838 | | EOT |
| 1839 | | } |
| 1840 | | else { |
| 1841 | | return <<EOT; |
| 1842 | | <div id="$id" class="listing $listing_class"> |
| 1843 | | $table |
| 1844 | | </div> |
| 1845 | | EOT |
| 1846 | | } |
| 1847 | | } |
| 1848 | | |
| 1849 | | ########################################################################### |
| 1850 | | |
| 1851 | | =head2 App:Link |
| 1852 | | |
| 1853 | | Produces a application link to the current script with the mode and |
| 1854 | | attributes specified. |
| 1855 | | |
| 1856 | | B<Attributes:> |
| 1857 | | |
| 1858 | | =over 4 |
| 1859 | | |
| 1860 | | =item * mode |
| 1861 | | |
| 1862 | | Maps to a '__mode' argument. |
| 1863 | | |
| 1864 | | =item * type |
| 1865 | | |
| 1866 | | Maps to a '_type' argument. |
| 1867 | | |
| 1868 | | =back |
| 1869 | | |
| 1870 | | B<Example:> |
| 1871 | | |
| 1872 | | <$MTApp:Link mode="foo" type="entry" bar="1"$> |
| 1873 | | |
| 1874 | | produces: |
| 1875 | | |
| 1876 | | /cgi-bin/mt/mt.cgi?__mode=foo&_type=entry&bar=1 |
| 1877 | | |
| 1878 | | This tag produces unescaped '&' characters. If you use this tag |
| 1879 | | in an HTML tag attribute, be sure to add a C<escape="html"> attribute |
| 1880 | | which will encode these to HTML entities. |
| 1881 | | |
| 1882 | | =for tags application |
| 1883 | | |
| 1884 | | =cut |
| 1885 | | |
| 1886 | | sub _hdlr_app_link { |
| 1887 | | my ($ctx, $args, $cond) = @_; |
| 1888 | | my $app = MT->instance; |
| 1889 | | |
| 1890 | | my %args = %$args; |
| 1891 | | |
| 1892 | | # eliminate special '@' argument (and anything other refs that may exist) |
| 1893 | | ref($args{$_}) && delete $args{$_} for keys %args; |
| 1894 | | |
| 1895 | | # strip off any arguments that are actually global filters |
| 1896 | | my $filters = MT->registry('tags', 'modifier'); |
| 1897 | | exists($filters->{$_}) && delete $args{$_} for keys %args; |
| 1898 | | |
| 1899 | | # remap 'type' attribute since we always express this as |
| 1900 | | # a '_type' query parameter. |
| 1901 | | my $mode = delete $args{mode} or return $ctx->error("mode attribute is required"); |
| 1902 | | $args{_type} = delete $args{type} if exists $args{type}; |
| 1903 | | if (exists $args{blog_id} && !($args{blog_id})) { |
| 1904 | | delete $args{blog_id}; |
| 1905 | | } else { |
| 1906 | | if (my $blog_id = $ctx->var('blog_id')) { |
| 1907 | | $args{blog_id} = $blog_id; |
| 1908 | | } |
| 1909 | | } |
| 1910 | | return $app->uri(mode => $mode, args => \%args); |
| 1911 | | } |
| 1912 | | |
| 1913 | | ########################################################################### |
| 1914 | | |
| 1915 | | =head2 App:ActionBar |
| 1916 | | |
| 1917 | | Produces markup for application templates for the strip of actions |
| 1918 | | for a application listing or edit screen. |
| 1919 | | |
| 1920 | | B<Attributes:> |
| 1921 | | |
| 1922 | | =over 4 |
| 1923 | | |
| 1924 | | =item * bar_position (optional; default "top") |
| 1925 | | |
| 1926 | | Assigns a CSS class name indicating whether the control is above or |
| 1927 | | below the listing or edit form it is associated with. |
| 1928 | | |
| 1929 | | =item * hide_pager |
| 1930 | | |
| 1931 | | Assign either 1 or 0 to control whether the pagination controls are |
| 1932 | | displayed or not. |
| 1933 | | |
| 1934 | | =item * form_id |
| 1935 | | |
| 1936 | | Associates the pagition controls and item action widget with the |
| 1937 | | given form element. |
| 1938 | | |
| 1939 | | =back |
| 1940 | | |
| 1941 | | =for tags application |
| 1942 | | |
| 1943 | | =cut |
| 1944 | | |
| 1945 | | sub _hdlr_app_action_bar { |
| 1946 | | my ($ctx, $args, $cond) = @_; |
| 1947 | | my $pos = $args->{bar_position} || 'top'; |
| 1948 | | my $form_id = $args->{form_id} ? qq{ form_id="$args->{form_id}"} : ""; |
| 1949 | | my $pager = $args->{hide_pager} ? '' |
| 1950 | | : qq{\n <mt:include name="include/pagination.tmpl" bar_position="$pos">}; |
| 1951 | | my $buttons = $ctx->var('action_buttons') || ''; |
| 1952 | | return $ctx->build(<<EOT); |
| 1953 | | <div id="actions-bar-$pos" class="actions-bar actions-bar-$pos"> |
| 1954 | | <div class="actions-bar-inner pkg">$pager |
| 1955 | | <span class="button-actions actions">$buttons</span> |
| 1956 | | <span class="plugin-actions actions"> |
| 1957 | | <mt:include name="include/itemset_action_widget.tmpl"$form_id> |
| 1958 | | </span> |
| 1959 | | </div> |
| 1960 | | </div> |
| 1961 | | EOT |
| 1962 | | } |
| 1963 | | |
| 1964 | | ########################################################################### |
| 1965 | | |
| 1966 | | =head2 App:Widget |
| 1967 | | |
| 1968 | | An application template tag that produces HTML for displaying a MT CMS |
| 1969 | | dashboard widget. Custom widget templates should utilize this tag to wrap |
| 1970 | | their widget content. |
| 1971 | | |
| 1972 | | B<Attributes:> |
| 1973 | | |
| 1974 | | =over 4 |
| 1975 | | |
| 1976 | | =item * id (optional) |
| 1977 | | |
| 1978 | | If specified, will be used as the 'id' attribute for the outermost C<div> |
| 1979 | | tag for the widget. If unspecified, will use the 'widget_id' template |
| 1980 | | variable instead. |
| 1981 | | |
| 1982 | | =item * label (required) |
| 1983 | | |
| 1984 | | The label to display above the widget. |
| 1985 | | |
| 1986 | | =item * label_link (optional) |
| 1987 | | |
| 1988 | | If specified, this link will wrap the label for the widget. |
| 1989 | | |
| 1990 | | =item * label_onclick |
| 1991 | | |
| 1992 | | If specified, this JavaScript code will be assigned to the 'onclick' |
| 1993 | | attribute of a link tag wrapping the widget label. |
| 1994 | | |
| 1995 | | =item * class (optional) |
| 1996 | | |
| 1997 | | If unspecified, will use the id of the widget. This class is included in the |
| 1998 | | 'class' attribute of the outermost C<div> tag for the widget. |
| 1999 | | |
| 2000 | | =item * header_action |
| 2001 | | |
| 2002 | | =item * can_close (optional; default "0") |
| 2003 | | |
| 2004 | | Identifies whether widget may be closed or not. |
| 2005 | | |
| 2006 | | =item * tabbed (optional; default "0") |
| 2007 | | |
| 2008 | | If specified, the widget will be assigned an attribute that gives it |
| 2009 | | a tabbed interface. |
| 2010 | | |
| 2011 | | =back |
| 2012 | | |
| 2013 | | B<Example:> |
| 2014 | | |
| 2015 | | <mtapp:Widget class="widget my-widget" |
| 2016 | | label="<__trans phrase="All About Me">" can_close="1"> |
| 2017 | | (contents of widget go here) |
| 2018 | | </mtapp:Widget> |
| 2019 | | |
| 2020 | | =for tags application |
| 2021 | | |
| 2022 | | =cut |
| 2023 | | |
| 2024 | | sub _hdlr_app_widget { |
| 2025 | | my ($ctx, $args, $cond) = @_; |
| 2026 | | my $hosted_widget = $ctx->var('widget_id') ? 1 : 0; |
| 2027 | | my $id = $args->{id} || $ctx->var('widget_id') || ''; |
| 2028 | | my $label = $args->{label}; |
| 2029 | | my $class = $args->{class} || $id; |
| 2030 | | my $label_link = $args->{label_link} || ""; |
| 2031 | | my $label_onclick = $args->{label_onclick} || ""; |
| 2032 | | my $header_action = $args->{header_action} || ""; |
| 2033 | | my $closable = $args->{can_close} ? 1 : 0; |
| 2034 | | if ($closable) { |
| 2035 | | $header_action = qq{<a title="<__trans phrase="Remove this widget">" onclick="javascript:removeWidget('$id'); return false;" href="javascript:void(0);" class="widget-close-link"><span>close</span></a>}; |
| 2036 | | } |
| 2037 | | my $widget_header = ""; |
| 2038 | | if ($label_link && $label_onclick) { |
| 2039 | | $widget_header = "\n<h3 class=\"widget-label\"><a href=\"$label_link\" onclick=\"$label_onclick\"><span>$label</span></a></h3>"; |
| 2040 | | } elsif ($label_link) { |
| 2041 | | $widget_header = "\n<h3 class=\"widget-label\"><a href=\"$label_link\"><span>$label</span></a></h3>"; |
| 2042 | | } else { |
| 2043 | | $widget_header = "\n<h3 class=\"widget-label\"><span>$label</span></h3>"; |
| 2044 | | } |
| 2045 | | my $token = $ctx->var('magic_token') || ''; |
| 2046 | | my $scope = $ctx->var('widget_scope') || 'system'; |
| 2047 | | my $singular = $ctx->var('widget_singular') || ''; |
| 2048 | | # Make certain widget_id is set |
| 2049 | | my $vars = $ctx->{__stash}{vars}; |
| 2050 | | local $vars->{widget_id} = $id; |
| 2051 | | local $vars->{widget_header} = ''; |
| 2052 | | local $vars->{widget_footer} = ''; |
| 2053 | | my $app = MT->instance; |
| 2054 | | my $blog = $app->can('blog') ? $app->blog : $ctx->stash('blog'); |
| 2055 | | my $blog_field = $blog ? qq{<input type="hidden" name="blog_id" value="} . $blog->id . q{" />} : ""; |
| 2056 | | local $vars->{blog_id} = $blog->id if $blog; |
| 2057 | | my $insides = $ctx->slurp($args, $cond); |
| 2058 | | my $widget_footer = ($ctx->var('widget_footer') || ''); |
| 2059 | | my $var_header = ($ctx->var('widget_header') || ''); |
| 2060 | | if ($var_header =~ m/<h3[ >]/i) { |
| 2061 | | $widget_header = $var_header; |
| 2062 | | } else { |
| 2063 | | $widget_header .= $var_header; |
| 2064 | | } |
| 2065 | | my $corners = $args->{corners} ? '<div class="corners"><b></b><u></u><s></s><i></i></div>' : ""; |
| 2066 | | my $tabbed = $args->{tabbed} ? ' mt:delegate="tab-container"' : ""; |
| 2067 | | my $header_class = $tabbed ? 'widget-header-tabs' : ''; |
| 2068 | | my $return_args = $app->make_return_args; |
| 2069 | | $return_args = encode_html( $return_args ); |
| 2070 | | my $cgi = $app->uri; |
| 2071 | | if ($hosted_widget && (!$insides !~ m/<form\s/i)) { |
| 2072 | | $insides = <<"EOT"; |
| 2073 | | <form id="$id-form" method="post" action="$cgi" onsubmit="updateWidget('$id'); return false"> |
| 2074 | | <input type="hidden" name="__mode" value="update_widget_prefs" /> |
| 2075 | | <input type="hidden" name="widget_id" value="$id" /> |
| 2076 | | $blog_field |
| 2077 | | <input type="hidden" name="widget_action" value="save" /> |
| 2078 | | <input type="hidden" name="widget_scope" value="$scope" /> |
| 2079 | | <input type="hidden" name="widget_singular" value="$singular" /> |
| 2080 | | <input type="hidden" name="magic_token" value="$token" /> |
| 2081 | | <input type="hidden" name="return_args" value="$return_args" /> |
| 2082 | | $insides |
| 2083 | | </form> |
| 2084 | | EOT |
| 2085 | | } |
| 2086 | | return <<"EOT"; |
| 2087 | | <div id="$id" class="widget pkg $class"$tabbed> |
| 2088 | | <div class="widget-inner inner"> |
| 2089 | | <div class="widget-header $header_class"> |
| 2090 | | <div class="widget-header-inner pkg"> |
| 2091 | | $header_action |
| 2092 | | $widget_header |
| 2093 | | </div> |
| 2094 | | </div> |
| 2095 | | <div class="widget-content"> |
| 2096 | | <div class="widget-content-inner"> |
| 2097 | | $insides |
| 2098 | | </div> |
| 2099 | | </div> |
| 2100 | | <div class="widget-footer">$widget_footer</div>$corners |
| 2101 | | </div> |
| 2102 | | </div> |
| 2103 | | EOT |
| 2104 | | } |
| 2105 | | |
| 2106 | | ########################################################################### |
| 2107 | | |
| 2108 | | =head2 App:StatusMsg |
| 2109 | | |
| 2110 | | An application template tag that outputs a MT status message. |
| 2111 | | |
| 2112 | | B<Attributes:> |
| 2113 | | |
| 2114 | | =over 4 |
| 2115 | | |
| 2116 | | =item * id (optional) |
| 2117 | | |
| 2118 | | =item * class (optional; default "info") |
| 2119 | | |
| 2120 | | =item * rebuild (optional) |
| 2121 | | |
| 2122 | | Accepted values: "all", "index". |
| 2123 | | |
| 2124 | | =item * can_close (optional; default "1") |
| 2125 | | |
| 2126 | | =back |
| 2127 | | |
| 2128 | | =for tags application |
| 2129 | | |
| 2130 | | =cut |
| 2131 | | |
| 2132 | | sub _hdlr_app_statusmsg { |
| 2133 | | my ($ctx, $args, $cond) = @_; |
| 2134 | | my $id = $args->{id}; |
| 2135 | | my $class = $args->{class} || 'info'; |
| 2136 | | my $msg = $ctx->slurp; |
| 2137 | | my $rebuild = $args->{rebuild} || ''; |
| 2138 | | my $blog_id = $ctx->var('blog_id'); |
| 2139 | | my $blog = $ctx->stash('blog'); |
| 2140 | | if (!$blog && $blog_id) { |
| 2141 | | $blog = MT->model('blog')->load($blog_id); |
| 2142 | | } |
| 2143 | | $rebuild = '' if $blog && $blog->custom_dynamic_templates eq 'all'; |
| 2144 | | $rebuild = qq{<__trans phrase="[_1]Publish[_2] your site to see these changes take effect." params="<a href="javascript:void(0);" class="rebuild-link" onclick="doRebuild('$blog_id');">%%</a>">} if $rebuild eq 'all'; |
| 2145 | | $rebuild = qq{<__trans phrase="[_1]Publish[_2] your site to see these changes take effect." params="<a href="javascript:void(0);" class="rebuild-link" onclick="doRebuild('$blog_id', 'prompt=index');">%%</a>">} if $rebuild eq 'index'; |
| 2146 | | my $close = ''; |
| 2147 | | if ($id && ($args->{can_close} || (!exists $args->{can_close}))) { |
| 2148 | | $close = qq{<a href="javascript:void(0)" onclick="javascript:hide('$id');return false;" class="close-me"><span>close</span></a>}; |
| 2149 | | } |
| 2150 | | $id = defined $id ? qq{ id="$id"} : ""; |
| 2151 | | $class = defined $class ? qq{msg msg-$class} : "msg"; |
| 2152 | | return <<"EOT"; |
| 2153 | | <div$id class="$class">$close$msg $rebuild</div> |
| 2154 | | EOT |
| 2155 | | } |
| 2156 | | |
| 2157 | | ########################################################################### |
| 2158 | | |
| 2159 | | =head2 App:ListFilters |
| 2160 | | |
| 2161 | | An application template tag used to produce an unordered list of quickfilters |
| 2162 | | for a given listing screen. The filters are drawn from a C<list_filters> |
| 2163 | | template variable which is an array of hashes. |
| 2164 | | |
| 2165 | | B<Example:> |
| 2166 | | |
| 2167 | | <$mtapp:ListFilters$> |
| 2168 | | |
| 2169 | | =cut |
| 2170 | | |
| 2171 | | sub _hdlr_app_list_filters { |
| 2172 | | my ($ctx, $args, $cond) = @_; |
| 2173 | | my $app = MT->app; |
| 2174 | | my $filters = $ctx->var("list_filters"); |
| 2175 | | return '' if (ref($filters) ne 'ARRAY') || (! @$filters ); |
| 2176 | | my $mode = $app->mode; |
| 2177 | | my $type = $app->param('_type'); |
| 2178 | | my $type_param = ""; |
| 2179 | | $type_param = "&_type=" . encode_url($type) if defined $type; |
| 2180 | | return $ctx->build(<<EOT, $cond); |
| 2181 | | <mt:loop name="list_filters"> |
| 2182 | | <mt:if name="__first__"> |
| 2183 | | <ul> |
| 2184 | | </mt:if> |
| 2185 | | <mt:if name="key" eq="\$filter_key"><li class="current-filter"><strong><mt:else><li></mt:if><a href="<mt:var name="script_url">?__mode=$mode$type_param<mt:if name="blog_id">&blog_id=<mt:var name="blog_id"></mt:if>&filter_key=<mt:var name="key" escape="url">"><mt:var name="label"></a><mt:if name="key" eq="\$filter_key"></strong></mt:if></li> |
| 2186 | | <mt:if name="__last__"> |
| 2187 | | </ul> |
| 2188 | | </mt:if> |
| 2189 | | </mt:loop> |
| 2190 | | EOT |
| 2191 | | } |
| 2192 | | |
| 2193 | | ########################################################################### |
| 2194 | | |
| 2195 | | =head2 App:PageActions |
| 2196 | | |
| 2197 | | An application template tag used to produce an unordered list of actions |
| 2198 | | for a given listing screen. The actions are drawn from a C<page_actions> |
| 2199 | | template variable which is an array of hashes. |
| 2200 | | |
| 2201 | | B<Example:> |
| 2202 | | |
| 2203 | | <$mtapp:PageActions$> |
| 2204 | | |
| 2205 | | =for tags application |
| 2206 | | |
| 2207 | | =cut |
| 2208 | | |
| 2209 | | sub _hdlr_app_page_actions { |
| 2210 | | my ($ctx, $args, $cond) = @_; |
| 2211 | | my $app = MT->instance; |
| 2212 | | my $from = $args->{from} || $app->mode; |
| 2213 | | my $loop = $ctx->var('page_actions'); |
| 2214 | | return '' if (ref($loop) ne 'ARRAY') || (! @$loop); |
| 2215 | | my $mt = '&magic_token=' . $app->current_magic; |
| 2216 | | return $ctx->build(<<EOT, $cond); |
| 2217 | | <mtapp:widget |
| 2218 | | id="page_actions" |
| 2219 | | label="<__trans phrase="Actions">"> |
| 2220 | | <ul> |
| 2221 | | <mt:loop name="page_actions"> |
| 2222 | | <mt:if name="page"> |
| 2223 | | <li class="icon-left icon<mt:unless name="core">-plugin</mt:unless>-action"><a href="<mt:var name="page" escape="html"><mt:if name="page_has_params">&</mt:if>from=$from<mt:if name="id">&id=<mt:var name="id"></mt:if><mt:if name="blog_id">&blog_id=<mt:var name="blog_id"></mt:if>$mt&return_args=<mt:var name="return_args" escape="url">"<mt:if name="continue_prompt"> onclick="return confirm('<mt:var name="continue_prompt" escape="js">');"</mt:if>><mt:var name="label"></a></li> |
| 2224 | | <mt:else><mt:if name="link"> |
| 2225 | | <li class="icon-left icon<mt:unless name="core">-plugin</mt:unless>-action"><a href="<mt:var name="link" escape="html">&from=$from<mt:if name="id">&id=<mt:var name="id"></mt:if><mt:if name="blog_id">&blog_id=<mt:var name="blog_id"></mt:if>$mt&return_args=<mt:var name="return_args" escape="url">"<mt:if name="continue_prompt"> onclick="return confirm('<mt:var name="continue_prompt" escape="js">');"</mt:if>><mt:var name="label"></a></li> |
| 2226 | | </mt:if><mt:if name="dialog"> |
| 2227 | | <li class="icon-left icon<mt:unless name="core">-plugin</mt:unless>-action"><a href="javascript:void(0)" onclick="<mt:if name="continue_prompt">if(!confirm('<mt:var name="continue_prompt" escape="js">'))return false;</mt:if>return openDialog(false, '<mt:var name="dialog">', '<mt:if name="dialog_args"><mt:var name="dialog_args" escape="url">&</mt:if>from=$from<mt:if name="id">&id=<mt:var name="id"></mt:if><mt:if name="blog_id">&blog_id=<mt:var name="blog_id"></mt:if>$mt&return_args=<mt:var name="return_args" escape="url">')"><mt:var name="label"></a></li> |
| 2228 | | </mt:if></mt:if> |
| 2229 | | </mt:loop> |
| 2230 | | </ul> |
| 2231 | | </mtapp:widget> |
| 2232 | | EOT |
| 2233 | | } |
| 2234 | | |
| 2235 | | ########################################################################### |
| 2236 | | |
| 2237 | | =head2 App:Form |
| 2238 | | |
| 2239 | | Used for application templates that need to express a standard MT |
| 2240 | | application form. This produces certain hidden fields that are typically |
| 2241 | | required by MT application forms. |
| 2242 | | |
| 2243 | | B<Attributes:> |
| 2244 | | |
| 2245 | | =over 4 |
| 2246 | | |
| 2247 | | =item * action (optional) |
| 2248 | | |
| 2249 | | Identifies the URL to submit the form to. If not given, will use |
| 2250 | | the current application URI. |
| 2251 | | |
| 2252 | | =item * method (optional; default "POST") |
| 2253 | | |
| 2254 | | Supplies the C<form> method. "GET" or "POST" are the typical values |
| 2255 | | for this, but will accept any HTTP-compatible method (ie: "PUT", "DELETE"). |
| 2256 | | |
| 2257 | | =item * object_id (optional) |
| 2258 | | |
| 2259 | | Populates a hidden 'id' field in the form. If not given, will also use any |
| 2260 | | 'id' template variable defined. |
| 2261 | | |
| 2262 | | =item * blog_id (optional) |
| 2263 | | |
| 2264 | | Populates a hidden 'blog_id' field in the form. If not given, will also use |
| 2265 | | any 'blog_id' template variable defined. |
| 2266 | | |
| 2267 | | =item * object_type (optional) |
| 2268 | | |
| 2269 | | Populates a hidden '_type' field in the form. If not given, will also use |
| 2270 | | any 'type' template variable defined. |
| 2271 | | |
| 2272 | | =item * id (optional) |
| 2273 | | |
| 2274 | | Used to form the 'id' element of the HTML C<form> tag. If not specified, |
| 2275 | | the C<form> tag 'id' element will be assigned TYPE-form, where TYPE is the |
| 2276 | | determined object_type. |
| 2277 | | |
| 2278 | | =item * name (optional) |
| 2279 | | |
| 2280 | | Supplies the C<form> name attribute. If unspecified, will use the C<id> |
| 2281 | | attribute, if available. |
| 2282 | | |
| 2283 | | =item * enctype (optional) |
| 2284 | | |
| 2285 | | If assigned, sets an 'enctype' attribute on the C<form> tag using the value |
| 2286 | | supplied. This is typically used to create a form that is capable of |
| 2287 | | uploading files. |
| 2288 | | |
| 2289 | | =back |
| 2290 | | |
| 2291 | | B<Example:> |
| 2292 | | |
| 2293 | | <mtapp:Form id="update" mode="update_blog_name"> |
| 2294 | | Blog Name: <input type="text" name="blog_name" /> |
| 2295 | | <input type="submit" /> |
| 2296 | | </mtapp:Form> |
| 2297 | | |
| 2298 | | Producing: |
| 2299 | | |
| 2300 | | <form id="update" name="update" action="/cgi-bin/mt.cgi" method="POST"> |
| 2301 | | <input type="hidden" name="__mode" value="update_blog_name" /> |
| 2302 | | Blog Name: <input type="text" name="blog_name" /> |
| 2303 | | <input type="submit" /> |
| 2304 | | </form> |
| 2305 | | |
| 2306 | | =for tags application |
| 2307 | | |
| 2308 | | =cut |
| 2309 | | |
| 2310 | | sub _hdlr_app_form { |
| 2311 | | my ($ctx, $args, $cond) = @_; |
| 2312 | | my $app = MT->instance; |
| 2313 | | my $action = $args->{action} || $app->uri; |
| 2314 | | my $method = $args->{method} || 'POST'; |
| 2315 | | my @fields; |
| 2316 | | my $token = $ctx->var('magic_token'); |
| 2317 | | my $return = $ctx->var('return_args'); |
| 2318 | | my $id = $args->{object_id} || $ctx->var('id'); |
| 2319 | | my $blog_id = $args->{blog_id} || $ctx->var('blog_id'); |
| 2320 | | my $type = $args->{object_type} || $ctx->var('type'); |
| 2321 | | my $form_id = $args->{id} || $type . '-form'; |
| 2322 | | my $form_name = $args->{name} || $args->{id}; |
| 2323 | | my $enctype = $args->{enctype} ? " enctype=\"" . $args->{enctype} . "\"" : ""; |
| 2324 | | my $mode = $args->{mode}; |
| 2325 | | push @fields, qq{<input type="hidden" name="__mode" value="$mode" />} |
| 2326 | | if defined $mode; |
| 2327 | | push @fields, qq{<input type="hidden" name="_type" value="$type" />} |
| 2328 | | if defined $type; |
| 2329 | | push @fields, qq{<input type="hidden" name="id" value="$id" />} |
| 2330 | | if defined $id; |
| 2331 | | push @fields, qq{<input type="hidden" name="blog_id" value="$blog_id" />} |
| 2332 | | if defined $blog_id; |
| 2333 | | push @fields, qq{<input type="hidden" name="magic_token" value="$token" />} |
| 2334 | | if defined $token; |
| 2335 | | $return = encode_html($return) if $return; |
| 2336 | | push @fields, qq{<input type="hidden" name="return_args" value="$return" />} |
| 2337 | | if defined $return; |
| 2338 | | my $fields = ''; |
| 2339 | | $fields = join("\n", @fields) if @fields; |
| 2340 | | my $insides = $ctx->slurp($args, $cond); |
| 2341 | | return <<"EOT"; |
| 2342 | | <form id="$form_id" name="$form_name" action="$action" method="$method"$enctype> |
| 2343 | | $fields |
| 2344 | | $insides |
| 2345 | | </form> |
| 2346 | | EOT |
| 2347 | | } |
| 2348 | | |
| 2349 | | ########################################################################### |
| 2350 | | |
| 2351 | | =head2 App:SettingGroup |
| 2352 | | |
| 2353 | | An application template tag used to wrap a number of L<App:Setting> tags. |
| 2354 | | |
| 2355 | | B<Attributes:> |
| 2356 | | |
| 2357 | | =over 4 |
| 2358 | | |
| 2359 | | =item * id (required) |
| 2360 | | |
| 2361 | | A unique identifier for this group of settings. |
| 2362 | | |
| 2363 | | =item * class (optional) |
| 2364 | | |
| 2365 | | If specified, applies this CSS class to the C<fieldset> tag produced. |
| 2366 | | |
| 2367 | | =item * shown (optional; default "1") |
| 2368 | | |
| 2369 | | Controls whether the C<fieldset> is initially shown or not. If hidden, |
| 2370 | | a CSS "hidden" class is applied to the C<fieldset> tag. |
| 2371 | | |
| 2372 | | =back |
| 2373 | | |
| 2374 | | B<Example:> |
| 2375 | | |
| 2376 | | <MTApp:SettingGroup id="foo"> |
| 2377 | | <MTApp:Setting ...> |
| 2378 | | <MTApp:Setting ...> |
| 2379 | | <MTApp:Setting ...> |
| 2380 | | </MTApp:SettingGroup> |
| 2381 | | |
| 2382 | | =for tags application |
| 2383 | | |
| 2384 | | =cut |
| 2385 | | |
| 2386 | | sub _hdlr_app_setting_group { |
| 2387 | | my ($ctx, $args, $cond) = @_; |
| 2388 | | my $id = $args->{id}; |
| 2389 | | return $ctx->error("'id' attribute missing") unless $id; |
| 2390 | | |
| 2391 | | my $class = $args->{class} || ""; |
| 2392 | | my $shown = exists $args->{shown} ? ($args->{shown} ? 1 : 0) : 1; |
| 2393 | | $class .= ($class ne '' ? " " : "") . "hidden" unless $shown; |
| 2394 | | $class = qq{ class="$class"} if $class ne ''; |
| 2395 | | |
| 2396 | | my $insides = $ctx->slurp($args, $cond); |
| 2397 | | return <<"EOT"; |
| 2398 | | <fieldset id="$id"$class> |
| 2399 | | $insides |
| 2400 | | </fieldset> |
| 2401 | | EOT |
| 2402 | | } |
| 2403 | | |
| 2404 | | ########################################################################### |
| 2405 | | |
| 2406 | | =head2 App:Setting |
| 2407 | | |
| 2408 | | An application template tag used to display an application form field. |
| 2409 | | |
| 2410 | | B<Attributes:> |
| 2411 | | |
| 2412 | | =over 4 |
| 2413 | | |
| 2414 | | =item * id (required) |
| 2415 | | |
| 2416 | | Each application setting tag requires a unique 'id' attribute. This id |
| 2417 | | should not be re-used within the template. |
| 2418 | | |
| 2419 | | =item * required (optional; default "0") |
| 2420 | | |
| 2421 | | Controls whether the field is displayed with visual cues that the |
| 2422 | | field is a required field or not. |
| 2423 | | |
| 2424 | | =item * label |
| 2425 | | |
| 2426 | | Supplies the label phrase for the setting. |
| 2427 | | |
| 2428 | | =item * show_label (optional; default "1") |
| 2429 | | |
| 2430 | | Controls whether the label portion of the setting is shown or not. |
| 2431 | | |
| 2432 | | =item * shown (optional; default "1") |
| 2433 | | |
| 2434 | | Controls whether the setting is visible or not. If specified, adds |
| 2435 | | a "hidden" class to the outermost C<div> tag produced for the |
| 2436 | | setting. |
| 2437 | | |
| 2438 | | =item * label_class (optional) |
| 2439 | | |
| 2440 | | Allows an additional CSS class to be applied to the label of the |
| 2441 | | setting. |
| 2442 | | |
| 2443 | | =item * content_class (optional) |
| 2444 | | |
| 2445 | | Allows an addtional CSS class to be applied to the contents of the |
| 2446 | | setting. |
| 2447 | | |
| 2448 | | =item * hint (optional) |
| 2449 | | |
| 2450 | | Supplies a "hint" phrase that provides inline instruction to the user. |
| 2451 | | By default, this hint is hidden, unless the 'show_hint' attribute |
| 2452 | | forces it to display. |
| 2453 | | |
| 2454 | | =item * show_hint (optional; default "0") |
| 2455 | | |
| 2456 | | Controls whether the inline help 'hint' label is shown or not. |
| 2457 | | |
| 2458 | | =item * warning |
| 2459 | | |
| 2460 | | Supplies a warning message to the user regarding the use of this setting. |
| 2461 | | |
| 2462 | | =item * show_warning |
| 2463 | | |
| 2464 | | Controls whether the warning message is shown or not. |
| 2465 | | |
| 2466 | | =item * help_page |
| 2467 | | |
| 2468 | | Identifies a specific page of the MT help documentation for this setting. |
| 2469 | | |
| 2470 | | =item * help_section |
| 2471 | | |
| 2472 | | Identifies a section name of the MT help documentation for this setting. |
| 2473 | | |
| 2474 | | =back |
| 2475 | | |
| 2476 | | B<Example:> |
| 2477 | | |
| 2478 | | <mtapp:Setting |
| 2479 | | id="name" |
| 2480 | | required="1" |
| 2481 | | label="Username" |
| 2482 | | hint="The username used to login"> |
| 2483 | | <input type="text" name="name" id="name" value="<$mt:Var name="name" escape="html"$>" /> |
| 2484 | | </mtapp:setting> |
| 2485 | | |
| 2486 | | The basic structural output of a setting tag looks like this: |
| 2487 | | |
| 2488 | | <div id="ID-field" class="field pkg"> |
| 2489 | | <div class="field-inner"> |
| 2490 | | <div class="field-header"> |
| 2491 | | <label id="ID-label" for="ID">LABEL</label> |
| 2492 | | </div> |
| 2493 | | <div class="field-content"> |
| 2494 | | (content of App:Setting tag) |
| 2495 | | </div> |
| 2496 | | </div> |
| 2497 | | </div> |
| 2498 | | |
| 2499 | | =for tags application |
| 2500 | | |
| 2501 | | =cut |
| 2502 | | |
| 2503 | | sub _hdlr_app_setting { |
| 2504 | | my ($ctx, $args, $cond) = @_; |
| 2505 | | my $id = $args->{id}; |
| 2506 | | return $ctx->error("'id' attribute missing") unless $id; |
| 2507 | | |
| 2508 | | my $label = $args->{label}; |
| 2509 | | my $show_label = exists $args->{show_label} ? $args->{show_label} : 1; |
| 2510 | | my $shown = exists $args->{shown} ? ($args->{shown} ? 1 : 0) : 1; |
| 2511 | | my $label_class = $args->{label_class} || ""; |
| 2512 | | my $content_class = $args->{content_class} || ""; |
| 2513 | | my $hint = $args->{hint} || ""; |
| 2514 | | my $show_hint = $args->{show_hint} || 0; |
| 2515 | | my $warning = $args->{warning} || ""; |
| 2516 | | my $show_warning = $args->{show_warning} || 0; |
| 2517 | | my $indent = $args->{indent}; |
| 2518 | | my $help; |
| 2519 | | # Formatting for help link, placed at the end of the hint. |
| 2520 | | if ($help = $args->{help_page} || "") { |
| 2521 | | my $section = $args->{help_section} || ''; |
| 2522 | | $section = qq{, '$section'} if $section; |
| 2523 | | $help = qq{ <a href="javascript:void(0)" onclick="return openManual('$help'$section)" class="help-link">?</a><br />}; |
| 2524 | | } |
| 2525 | | my $label_help = ""; |
| 2526 | | if ($label && $show_label) { |
| 2527 | | # do nothing; |
| 2528 | | } else { |
| 2529 | | $label = ''; # zero it out, because the user turned it off |
| 2530 | | } |
| 2531 | | if ($hint && $show_hint) { |
| 2532 | | $hint = "\n<div class=\"hint\">$hint$help</div>"; |
| 2533 | | } else { |
| 2534 | | $hint = ''; # hiding hint because it is either empty or should not be shown |
| 2535 | | } |
| 2536 | | if ($warning && $show_warning) { |
| 2537 | | $warning = qq{\n<p><img src="<mt:var name="static_uri">images/status_icons/warning.gif" alt="<__trans phrase="Warning">" width="9" height="9" /> |
| 2538 | | <span class="alert-warning-inline">$warning</span></p>\n}; |
| 2539 | | } else { |
| 2540 | | $warning = ''; # hiding hint because it is either empty or should not be shown |
| 2541 | | } |
| 2542 | | unless ($label_class) { |
| 2543 | | $label_class = 'field-left-label'; |
| 2544 | | } else { |
| 2545 | | $label_class = 'field-' . $label_class; |
| 2546 | | } |
| 2547 | | my $indent_css = ""; |
| 2548 | | if ($indent) { |
| 2549 | | $indent_css = " style=\"padding-left: ".$indent."px;\"" |
| 2550 | | } |
| 2551 | | # 'Required' indicator plus CSS class |
| 2552 | | my $req = $args->{required} ? " *" : ""; |
| 2553 | | my $req_class = $args->{required} ? " required" : ""; |
| 2554 | | |
| 2555 | | my $insides = $ctx->slurp($args, $cond); |
| 2556 | | $insides =~ s/^\s*(<textarea)\b/<div class="textarea-wrapper">$1/g; |
| 2557 | | $insides =~ s/(<\/textarea>)\s*$/$1<\/div>/g; |
| 2558 | | |
| 2559 | | my $class = $args->{class} || ""; |
| 2560 | | $class = ($class eq '') ? 'hidden' : $class . ' hidden' unless $shown; |
| 2561 | | |
| 2562 | | return $ctx->build(<<"EOT"); |
| 2563 | | <div id="$id-field" class="field$req_class $label_class pkg $class"$indent_css> |
| 2564 | | <div class="field-inner"> |
| 2565 | | <div class="field-header"> |
| 2566 | | <label id="$id-label" for="$id">$label$req</label> |
| 2567 | | </div> |
| 2568 | | <div class="field-content $content_class"> |
| 2569 | | $insides$hint$warning |
| 2570 | | </div> |
| 2571 | | </div> |
| 2572 | | </div> |
| 2573 | | EOT |
| 2574 | | } |