<NME> _macro.twig
<BEF> {##
 # Output a username and link to their profile given an ID.
 #}
{% macro userlink(user_id) %}
    {% spaceless %}
        {% set user = getuser(user_id) %}
        {% if user is not empty %}
            <a href="{{ path('useredit', {'id': user.id}) }}">{{- user.displayname -}}</a>
        {% else %}
            {{ __('panel.latest-activity.unknown') }}
        {% endif %}
    {% endspaceless %}
{% endmacro %}

{##
 # Contentlink by id.
 #}
{% macro contentlink_by_id(contenttype, title, content_id) %}
    {% spaceless %}
        <a href="{{ path('editcontent', { 'contenttypeslug': contenttype.slug, 'id': content_id }) }}">
            {{- title|striptags[:70]|default("<em>(" ~ __('general.phrase.no-title') ~ ")</em>")|raw -}}
        </a>
    {% endspaceless %}
{% endmacro %}

{##
 # Contentlink.
 #}
{% macro contentlink(contenttype, content) %}
    {% import _self as crosslinks %}
    {% set title = content.getTitle() %}
    {{ crosslinks.contentlink_by_id(contenttype, title, content.id) }}
{% endmacro %}

{##
 # Outputs tag attributes.
 #}
{% macro attr(attributes) %}
    {% spaceless %}
        {% for attrname, value in attributes %}
            {% if attrname == 'value' %}
                value="{{ value }}"
            {% elseif value is not empty %}
                {% if attrname in ['required', 'disabled', 'selected', 'autofocus', 'multiple', 'readonly'] %}
                    {{ attrname }}="{{ attrname }}"
                {% elseif attrname == 'name_id' %}
                    name="{{ value }}" id="{{ value }}"
                {% elseif attrname == 'class' %}
                    class="{{ value|trim }}"
                {% elseif attrname == 'style' %}
                    style="{{ value|trim }}"
                {% elseif attrname == 'checked' %}
                    {% if value != false %}checked="checked"{% endif %}
                {% elseif attrname == '_bind' %}
                    data-bind="{{ {bind: value[0]}|merge(value[1]|default({}))|json_encode }}"
                {% else %}
                    {{ attrname|replace({'_': '-'}) }}="{{ value }}"
                {% endif %}
            {% endif %}
        {% endfor %}
    {% endspaceless %}
{% endmacro %}

{##
 # Actionform.
 #}
{% macro actionform(content, action, icon, text, confirmation_text) %}
    {% if action == 'held' %}
        {% set action = 'depublish' %}
    {% endif %}
    <a href="#" data-listing-cmd="record:{{ action }}"><i class="fa {{ icon }}"></i> {{ __(text) }}</a>
{% endmacro %}

{##
 # Typepopover.
 #}
{% macro typepopover(types) %}
    {% set types = types|default(config.get('general/accept_file_types')) %}
    {% set text = __("field.general.allowed-filetypes") ~ "<code>" ~ types|join("</code>, <code>") ~ "</code>." %}
    <span class="label label-default info-pop" data-title="" data-placement="left"  data-html="true" data-content="{{ text }}">
        <i class="fa fa-info-circle"></i>
        {{ __('general.phrase.types') }}
    </span>
{% endmacro %}

{##
 # Renders a datetime/date input component
 #
 # Required options:
 #    id:                 id of that group
 # Optional options:
 #    disabled  [false]:  disabled input
 #    required  [false]:  make input required
 #    class     []:       class added to date/time input
 #    errortext []:       error text
 #    options   []:       options passed to datepicker
 #
 # @param array opt Options defining the component
 #}
{% macro input_datetime(opt) %}
    {% from _self import attr %}

    {% set class = opt.class|default('')|replace({'form-control': ''}) ~ ' form-control' %}

    {% set attributes = {
        data: {
            id:          opt.id,
            name:        opt.name|default(opt.id),
            value:       opt.value,
            type:        'hidden',
            class:       'datetime',
            data_notice: opt.notice|default('')
        },

        date: {
            type:                'text',
            disabled:            opt.disabled|default(false),
            required:            opt.required|default(false),
            class:               (class ~ ' datepicker')|trim,
            data_errortext:      opt.errortext|default(''),
            data_field_options:  opt.options|default(false) ? opt.options|json_encode : ''
        },

        time: {
            type:      'text',
            disabled:  opt.disabled|default(false),
            required:  opt.required|default(false),
            class:     (class ~ ' timepicker')|trim,
            title:     __('general.phrase.time-format-24-12'),
            style:     'margin-right: 6px;'
        }
    } %}

    <div class="datetime-container">
        <div>
            <div class="input-group">
                <span class="input-group-btn">
                    <button type="button" class="btn btn-tertiary">
                        <i class="fa fa-calendar"></i>
                    </button>
                </span>
                <input{{ attr(attributes.date) }}>
            </div>
        </div>

        {% if opt.has_time is not defined or opt.has_time != false %}
            <div>
                <input{{ attr(attributes.time) }}>
            </div>
        {% endif %}

        <div>
            <input{{ attr(attributes.data) }}>
            <button type="button" class="btn btn-default btn-xs">
                <i class="fa fa-close"></i>
            </button>
        </div>
    </div>
{% endmacro %}

{##
 # Renders a upload button combo [Upload] [Select from Server] [Select from Stack]
 #
 # @param string type Either 'image' or 'other,document'
 # @param string attr_upload Attributes for the file upload button
 # @param string uploadpath Relative upload path
 # @param bool   multi If true allows uploading multiple files
 #}
{% macro upload_buttons(type, attr_upload, uploadpath, canUpload, multi) %}
    {% from _self import attr %}

    <div class="button-wrap fileselectbuttongroup">

        {# Button: Upload #}
        {% if canUpload %}
            <span class="btn btn-tertiary btn-sm fileinput-button">
                <i class="fa fa-upload"></i>
                <span>{{ (type == 'image') ? __('general.phrase.upload-image') : __('general.phrase.upload-file') }}</span>
                <input{{ attr(attr_upload) }}>
            </span>
        {% else %}
            <button type="button" class="btn btn-sm" disabled="disabled">
                {{ __('general.phrase.upload-not-allowed') }}
                {# creating a dummy stub, instead of the uploader. Needed (currently) to attach events to #}
                {% set attr_upload = attr_upload|merge({'type' : 'hidden'}) %}
                <input{{ attr(attr_upload) }}>
            </button>
        {% endif %}

        {# Button: Select from Server #}
        {% set attr = {
            'class': 'btn btn-tertiary btn-sm',
            'data-bolt-widget': {
                buicBrowser: {
                    url: path('asyncbrowse', {'namespace': 'files', 'path': uploadpath}),
                    multiselect: multi
                },
            },
            'type': 'button',
        } %}
        <button{{ hattr(attr) }}><i class="fa fa-download"></i> {{ __('field.general.select-from-server') }}</button>


        {# Button: Select from Stack #}
        {% if not config.get('general/backend/stack/disable', false) %}
        	{% set stack = stack(type) %}

		{% if stack %}

            <div class="btn-group">
    {% set items = stackitems(7, (type == 'image') ?  'image' : 'other,document') %}
    {% set href = paths.async ~ 'browse/files' ~ (uploadpath ? '/' ~ uploadpath : '' ) ~ '?key=' ~ key %}

    <button class="btn btn-secondary fileinput-button">
        <i class="fa fa-upload"></i>
        <span>{{ (type == 'image') ? __('Upload image') : __('Upload file') }}</span>
        <input{{ attr(attr_upload) }}>
    </button>

    <button class="btn btn-tertiary" data-target="#selectModal-{{ key }}" href="{{ href }}" data-toggle="modal">
        <i class="fa fa-download"></i>
        {{ __('field.general.select-from-server') }}
    </button>

    {% if items %}
        <div class="btn-group">
            <button class="btn btn-tertiary dropdown-toggle" data-toggle="dropdown">

<MSG> Add some comments
<DFF> @@ -211,17 +211,20 @@
     {% set items = stackitems(7, (type == 'image') ?  'image' : 'other,document') %}
     {% set href = paths.async ~ 'browse/files' ~ (uploadpath ? '/' ~ uploadpath : '' ) ~ '?key=' ~ key %}
 
+    {# Button: Upload #}
     <button class="btn btn-secondary fileinput-button">
         <i class="fa fa-upload"></i>
         <span>{{ (type == 'image') ? __('Upload image') : __('Upload file') }}</span>
         <input{{ attr(attr_upload) }}>
     </button>
 
+    {# Button: Select from Server #}
     <button class="btn btn-tertiary" data-target="#selectModal-{{ key }}" href="{{ href }}" data-toggle="modal">
         <i class="fa fa-download"></i>
         {{ __('field.general.select-from-server') }}
     </button>
 
+    {# Button: Select from Stack #}
     {% if items %}
         <div class="btn-group">
             <button class="btn btn-tertiary dropdown-toggle" data-toggle="dropdown">

{'commit': 'diff --git a/app/view/twig/_macro/_macro.twig b/app/view/twig/_macro/_macro.twig\nindex 646121dd6..8e8aee43c 100644\n--- a/app/view/twig/_macro/_macro.twig\n+++ b/app/view/twig/_macro/_macro.twig\n@@ -211,17 +211,20 @@\n     {% set items = stackitems(7, (type == \'image\') ?  \'image\' : \'other,document\') %}\n     {% set href = paths.async ~ \'browse/files\' ~ (uploadpath ? \'/\' ~ uploadpath : \'\' ) ~ \'?key=\' ~ key %}\n \n+    {# Button: Upload #}\n     <button class="btn btn-secondary fileinput-button">\n         <i class="fa fa-upload"></i>\n         <span>{{ (type == \'image\') ? __(\'Upload image\') : __(\'Upload file\') }}</span>\n         <input{{ attr(attr_upload) }}>\n     </button>\n \n+    {# Button: Select from Server #}\n     <button class="btn btn-tertiary" data-target="#selectModal-{{ key }}" href="{{ href }}" data-toggle="modal">\n         <i class="fa fa-download"></i>\n         {{ __(\'field.general.select-from-server\') }}\n     </button>\n \n+    {# Button: Select from Stack #}\n     {% if items %}\n         <div class="btn-group">\n             <button class="btn btn-tertiary dropdown-toggle" data-toggle="dropdown">\n', 'commit_subject': 'Add some comments', 'repo_name': 'bolt/bolt', 'committer': {'name': 'Woodstock', 'email': 'b257af45fbc9f52d0e728490f2c2da9e4f66647e@gmx.net', 'time_sec': '1417866862', 'tz_offset': '60', 'date': {'seconds': '1417866862'}}, 'commit_tree': '5bbbb9da322b586577f071807874029996cd12fb', 'commit_message': 'Add some comments', 'language_name': 'JavaScript', 'license': 'mit', 'hunks': '@@ -211,17 +211,20 @@\n     {% set items = stackitems(7, (type == \'image\') ?  \'image\' : \'other,document\') %}\n     {% set href = paths.async ~ \'browse/files\' ~ (uploadpath ? \'/\' ~ uploadpath : \'\' ) ~ \'?key=\' ~ key %}\n \n+    {# Button: Upload #}\n     <button class="btn btn-secondary fileinput-button">\n         <i class="fa fa-upload"></i>\n         <span>{{ (type == \'image\') ? __(\'Upload image\') : __(\'Upload file\') }}</span>\n         <input{{ attr(attr_upload) }}>\n     </button>\n \n+    {# Button: Select from Server #}\n     <button class="btn btn-tertiary" data-target="#selectModal-{{ key }}" href="{{ href }}" data-toggle="modal">\n         <i class="fa fa-download"></i>\n         {{ __(\'field.general.select-from-server\') }}\n     </button>\n \n+    {# Button: Select from Stack #}\n     {% if items %}\n         <div class="btn-group">\n             <button class="btn btn-tertiary dropdown-toggle" data-toggle="dropdown">\n', 'addition_count': 3, 'deletion_count': 0, 'src_file': 'a/app/view/twig/_macro/_macro.twig', 'tgt_file': 'b/app/view/twig/_macro/_macro.twig', 'file_extension': '.twig', 'before_file': '{##\n # Output a username and link to their profile given an ID.\n #}\n{% macro userlink(user_id) %}\n    {% spaceless %}\n        {% set user = getuser(user_id) %}\n        {% if user is not empty %}\n            <a href="{{ path(\'useredit\', {\'id\': user.id}) }}">{{- user.displayname -}}</a>\n        {% else %}\n            {{ __(\'panel.latest-activity.unknown\') }}\n        {% endif %}\n    {% endspaceless %}\n{% endmacro %}\n\n{##\n # Contentlink by id.\n #}\n{% macro contentlink_by_id(contenttype, title, content_id) %}\n    {% spaceless %}\n        <a href="{{ path(\'editcontent\', { \'contenttypeslug\': contenttype.slug, \'id\': content_id }) }}">\n            {{- title|striptags[:70]|default("<em>(" ~ __(\'general.phrase.no-title\') ~ ")</em>")|raw -}}\n        </a>\n    {% endspaceless %}\n{% endmacro %}\n\n{##\n # Contentlink.\n #}\n{% macro contentlink(contenttype, content) %}\n    {% import _self as crosslinks %}\n    {% set title = content.getTitle() %}\n    {{ crosslinks.contentlink_by_id(contenttype, title, content.id) }}\n{% endmacro %}\n\n{##\n # Outputs tag attributes.\n #}\n{% macro attr(attributes) %}\n    {% spaceless %}\n        {% for attrname, value in attributes %}\n            {% if attrname == \'value\' %}\n                value="{{ value }}"\n            {% elseif value is not empty %}\n                {% if attrname in [\'required\', \'disabled\', \'selected\', \'autofocus\', \'multiple\', \'readonly\'] %}\n                    {{ attrname }}="{{ attrname }}"\n                {% elseif attrname == \'name_id\' %}\n                    name="{{ value }}" id="{{ value }}"\n                {% elseif attrname == \'class\' %}\n                    class="{{ value|trim }}"\n                {% elseif attrname == \'style\' %}\n                    style="{{ value|trim }}"\n                {% elseif attrname == \'checked\' %}\n                    {% if value != false %}checked="checked"{% endif %}\n                {% elseif attrname == \'_bind\' %}\n                    data-bind="{{ {bind: value[0]}|merge(value[1]|default({}))|json_encode }}"\n                {% else %}\n                    {{ attrname|replace({\'_\': \'-\'}) }}="{{ value }}"\n                {% endif %}\n            {% endif %}\n        {% endfor %}\n    {% endspaceless %}\n{% endmacro %}\n\n{##\n # Actionform.\n #}\n{% macro actionform(content, action, icon, text, confirmation_text) %}\n    {% if action == \'held\' %}\n        {% set action = \'depublish\' %}\n    {% endif %}\n    <a href="#" data-listing-cmd="record:{{ action }}"><i class="fa {{ icon }}"></i> {{ __(text) }}</a>\n{% endmacro %}\n\n{##\n # Typepopover.\n #}\n{% macro typepopover(types) %}\n    {% set types = types|default(config.get(\'general/accept_file_types\')) %}\n    {% set text = __("field.general.allowed-filetypes") ~ "<code>" ~ types|join("</code>, <code>") ~ "</code>." %}\n    <span class="label label-default info-pop" data-title="" data-placement="left"  data-html="true" data-content="{{ text }}">\n        <i class="fa fa-info-circle"></i>\n        {{ __(\'general.phrase.types\') }}\n    </span>\n{% endmacro %}\n\n{##\n # Renders a datetime/date input component\n #\n # Required options:\n #    id:                 id of that group\n # Optional options:\n #    disabled  [false]:  disabled input\n #    required  [false]:  make input required\n #    class     []:       class added to date/time input\n #    errortext []:       error text\n #    options   []:       options passed to datepicker\n #\n # @param array opt Options defining the component\n #}\n{% macro input_datetime(opt) %}\n    {% from _self import attr %}\n\n    {% set class = opt.class|default(\'\')|replace({\'form-control\': \'\'}) ~ \' form-control\' %}\n\n    {% set attributes = {\n        data: {\n            id:          opt.id,\n            name:        opt.name|default(opt.id),\n            value:       opt.value,\n            type:        \'hidden\',\n            class:       \'datetime\',\n            data_notice: opt.notice|default(\'\')\n        },\n\n        date: {\n            type:                \'text\',\n            disabled:            opt.disabled|default(false),\n            required:            opt.required|default(false),\n            class:               (class ~ \' datepicker\')|trim,\n            data_errortext:      opt.errortext|default(\'\'),\n            data_field_options:  opt.options|default(false) ? opt.options|json_encode : \'\'\n        },\n\n        time: {\n            type:      \'text\',\n            disabled:  opt.disabled|default(false),\n            required:  opt.required|default(false),\n            class:     (class ~ \' timepicker\')|trim,\n            title:     __(\'general.phrase.time-format-24-12\'),\n            style:     \'margin-right: 6px;\'\n        }\n    } %}\n\n    <div class="datetime-container">\n        <div>\n            <div class="input-group">\n                <span class="input-group-btn">\n                    <button type="button" class="btn btn-tertiary">\n                        <i class="fa fa-calendar"></i>\n                    </button>\n                </span>\n                <input{{ attr(attributes.date) }}>\n            </div>\n        </div>\n\n        {% if opt.has_time is not defined or opt.has_time != false %}\n            <div>\n                <input{{ attr(attributes.time) }}>\n            </div>\n        {% endif %}\n\n        <div>\n            <input{{ attr(attributes.data) }}>\n            <button type="button" class="btn btn-default btn-xs">\n                <i class="fa fa-close"></i>\n            </button>\n        </div>\n    </div>\n{% endmacro %}\n\n{##\n # Renders a upload button combo [Upload] [Select from Server] [Select from Stack]\n #\n # @param string type Either \'image\' or \'other,document\'\n # @param string attr_upload Attributes for the file upload button\n # @param string uploadpath Relative upload path\n # @param bool   multi If true allows uploading multiple files\n #}\n{% macro upload_buttons(type, attr_upload, uploadpath, canUpload, multi) %}\n    {% from _self import attr %}\n\n    <div class="button-wrap fileselectbuttongroup">\n\n        {# Button: Upload #}\n        {% if canUpload %}\n            <span class="btn btn-tertiary btn-sm fileinput-button">\n                <i class="fa fa-upload"></i>\n                <span>{{ (type == \'image\') ? __(\'general.phrase.upload-image\') : __(\'general.phrase.upload-file\') }}</span>\n                <input{{ attr(attr_upload) }}>\n            </span>\n        {% else %}\n            <button type="button" class="btn btn-sm" disabled="disabled">\n                {{ __(\'general.phrase.upload-not-allowed\') }}\n                {# creating a dummy stub, instead of the uploader. Needed (currently) to attach events to #}\n                {% set attr_upload = attr_upload|merge({\'type\' : \'hidden\'}) %}\n                <input{{ attr(attr_upload) }}>\n            </button>\n        {% endif %}\n\n        {# Button: Select from Server #}\n        {% set attr = {\n            \'class\': \'btn btn-tertiary btn-sm\',\n            \'data-bolt-widget\': {\n                buicBrowser: {\n                    url: path(\'asyncbrowse\', {\'namespace\': \'files\', \'path\': uploadpath}),\n                    multiselect: multi\n                },\n            },\n            \'type\': \'button\',\n        } %}\n        <button{{ hattr(attr) }}><i class="fa fa-download"></i> {{ __(\'field.general.select-from-server\') }}</button>\n\n\n        {# Button: Select from Stack #}\n        {% if not config.get(\'general/backend/stack/disable\', false) %}\n        \t{% set stack = stack(type) %}\n\n\t\t{% if stack %}\n\n            <div class="btn-group">\n    {% set items = stackitems(7, (type == \'image\') ?  \'image\' : \'other,document\') %}\n    {% set href = paths.async ~ \'browse/files\' ~ (uploadpath ? \'/\' ~ uploadpath : \'\' ) ~ \'?key=\' ~ key %}\n\n    <button class="btn btn-secondary fileinput-button">\n        <i class="fa fa-upload"></i>\n        <span>{{ (type == \'image\') ? __(\'Upload image\') : __(\'Upload file\') }}</span>\n        <input{{ attr(attr_upload) }}>\n    </button>\n\n    <button class="btn btn-tertiary" data-target="#selectModal-{{ key }}" href="{{ href }}" data-toggle="modal">\n        <i class="fa fa-download"></i>\n        {{ __(\'field.general.select-from-server\') }}\n    </button>\n\n    {% if items %}\n        <div class="btn-group">\n            <button class="btn btn-tertiary dropdown-toggle" data-toggle="dropdown">\n', 'message': 'Add some comments', 'author_name': 'Woodstock', 'lang': 'twig'}