module CamaleonCms::ShortCodeHelper # Internal method def shortcodes_init @_shortcodes = [] @_shortcodes_template = {} @_shortcodes_descr = {} shortcode_add("widget", nil, "Renderize the widget content in this place. Don't forget to create and copy the shortcode of your widgets in appearance -> widgets Sample: [widget widget_key]") shortcode_add("load_libraries", lambda{|attrs, args| cama_load_libraries(*attrs["data"].to_s.split(",")); return ""; }, "Permit to load libraries on demand, sample: [load_libraries data='datepicker,tinymce']") shortcode_add("asset", lambda{|attrs, args| url = attrs["as_path"].present? ? ActionController::Base.helpers.asset_url(attrs["file"]) : ActionController::Base.helpers.asset_url(attrs["file"]) if attrs["image"].present? ActionController::Base.helpers.image_tag(attrs["file"], class: attrs["class"], style: attrs["style"]) else url end }, "Permit to generate an asset url ( add file='' asset file path, add as_path='true' to generate only the path and not the full url, add class='my_class' to setup image class, add style='height: 100px; width: 200px;...' to setup image style, add image='true' to generate the image tag with this url), sample: or [asset image='true' file='themes/my_theme/assets/img/signature.png' style='height: 50px;']") shortcode_add("data", lambda{|attrs, args| cama_shortcode_data(attrs, args) rescue "" }, "Permit to generate specific data of a post. Attributes: object: (String, defaut post) Model name: post | posttype | category | posttag | site | user |theme | navmenu id: (Integer) Post id key: (String) Post slug field: (String) Custom field key, you can add render_field='true' to render field as html element, also you can add index=2 to indicate the value in position 2 for multitple values attrs: (String) attribute name post: title | created_at | excerpt | url | link | thumb | updated_at | author_name | author_url posttype: title | created_at | excerpt | url | link | thumb | updated_at category: title | created_at | excerpt | url | link | thumb | updated_at posttag: title | created_at | excerpt | url | link | thumb | updated_at site: title | created_at | excerpt | url | link | thumb | updated_at user: title | created_at | excerpt | url | link | thumb | updated_at theme: title | created_at | excerpt | url | link | thumb | updated_at navmenu: title | created_at | excerpt | url | link | thumb | updated_at Note: If id and key is not present, then will be rendered for current model Sample: [data id='122' attr='title'] ==> return the title of post with id = 122 [data key='contact' attr='url'] ==> return the url of post with slug = contact [data key='contact' attr='link'] ==> return the link with title as text of the link of post with slug = contact [data object='site' attr='url'] ==> return the url of currrent site [data key='page' object='posttype' attr='url'] ==> return the url of post_type with slug = page [data field=icon index=2] ==> return the second value (multiple values) for this custom field with key=icon of current object [data key='contact' field='sub_title'] ==> return the value of the custom_field with key=sub_title registered for post.slug = contact [data object='site' field='sub_title'] ==> return the value of the custom_field with key=sub_title registered for current_site") end # add shortcode # key: shortcode key # template: template to render, if nil will render "shortcode_templates/" # Also can be a function to execute that instead a render, sample: lambda{|attrs, args| return "my custom content"; } # descr: description for shortcode def shortcode_add(key, template = nil, descr = '') @_shortcodes << key @_shortcodes_template = @_shortcodes_template.merge({"#{key}"=> template}) if template.present? @_shortcodes_descr[key] = descr if descr.present? end # add or update shortcode template # key: chortcode key to add or update # template: template to render, if nil will render "shortcode_templates/" def shortcode_change_template(key, template = nil) @_shortcodes_template[key] = template end # delete shortcode # key: chortcode key to delete def shortcode_delete(key) @_shortcodes.delete(key) end # run all shortcodes in the content # content: (string) text to find a short codes # args: custom arguments to pass for short codes render, sample: {owner: my_model, a: true} # if args != Hash, this will re send as args = {owner: args} # args should be include the owner model who is doing the action to optimize DB queries # sample: do_shortcode("hello [greeting 'world']!", @my_post) ==> "hello world!" # sample: do_shortcode("hello [greeting 'world']", {attr1: 'asd', owner: @my_post}) # return rendered string def do_shortcode(content, args = {}) args = {owner: args} unless args.is_a?(Hash) content.scan(/#{cama_reg_shortcode}/) do |item| shortcode, code, space, attrs = item content = content.sub(shortcode, _eval_shortcode(code, attrs, args)) end content end # remove all shortcodes from text # Arguments # text: String that contains shortcodes # return String def cama_strip_shortcodes(text) text.gsub(/#{cama_reg_shortcode}/, "") end # render direct a shortcode # text: text that contain the shortcode # key: shortcode key # template: template to render, if nil this will render default render file # Also can be a function to execute that instead a render, sample: lambda{|attrs, args| return "my custom content"; } # render_shortcode("asda dasdasdas[owen a='1'] [bbb] sdasdas dasd as das[owen a=213]", "owen", lambda{|attrs, args| puts attrs; return "my test"; }) def render_shortcode(text, key, template = nil) text.scan(/#{cama_reg_shortcode(key)}/).each do |item| shortcode, code, space, attrs = item text = text.sub(shortcode, _eval_shortcode(code, attrs, {}, template)) end text end private # create the regexpression for shortcodes # codes: (String) shortcode keys separated by | # sample: load_libraries|asset # if empty, codes will be replaced with all registered shortcodes # Return: (String) reg expression string def cama_reg_shortcode(codes = nil) "(\\[(#{codes || (@_shortcodes || []).join("|")})(\s|\\]){0}(.*?)\\])" end # determine the content to replace instead the shortcode # return string def _eval_shortcode(code, attrs, args={}, template = nil) template ||= (@_shortcodes_template[code].present? ? @_shortcodes_template[code] : "camaleon_cms/shortcode_templates/#{code}") if @_shortcodes_template[code].class.name == "Proc" res = @_shortcodes_template[code].call(_shortcode_parse_attr(attrs), args) else res = render :file => template, :locals => {attributes: _shortcode_parse_attr(attrs), args: args}, formats: [:html] end res end # parse the attributes of a shortcode def _shortcode_parse_attr(text) res = {} return res unless text.present? text.scan(/(\w+)\s*=\s*"([^"]*)"(?:\s|$)|(\w+)\s*=\s*\'([^\']*)\'(?:\s|$)|(\w+)\s*=\s*([^\s\'"]+)(?:\s|$)|"([^"]*)"(?:\s|$)|(\S+)(?:\s|$)/).each do |item| item.each_with_index do |c, index| if c.present? res[c] = item[index+1] break end end end res end # execute shortcode data def cama_shortcode_data(attrs, args) res = "" object = attrs["object"].downcase || "post" attr = attrs["attr"] || "title" if (args[:owner].present? && object == args[:owner].class.name.parseCamaClass.downcase) || !attrs["object"].present? model = args[:owner] else model = cama_shortcode_model_parser(object, attrs) || args[:owner] end return res unless model.present? if attrs["field"].present? # model custom fields field = model.get_field_object(attrs["field"]) if attrs["render_field"].present? return render :file => "custom_fields/#{field.options["field_key"]}", :locals => {object: model, field: field, field_key: attrs["field"], attibutes: attrs} else if attrs["index"] res = model.the_fields(attrs["field"])[attrs["index"].to_i-1] rescue "" else res = model.the_field(attrs["field"]) end return res end else # model attributes case attr when "title" res = model.the_title when "created_at" res = model.the_created_at when "updated_at" res = model.the_updated_at when "excerpt" res = model.the_excerpt rescue "" when "url" res = model.the_url rescue "" when "link" res = model.the_link rescue "" when "thumb" case object when "site" res = model.the_logo when "user" res = model.the_avatar else res = model.the_thumb_url end else case object when 'site' case attr when "title" when "title" end when 'post' case attr when "author_name" res = model.the_author.the_name rescue '' when "author_url" res = model.the_author.the_name rescue '' end end end end res end # return the model object according to the type def cama_shortcode_model_parser(object, attrs) model = nil case object.downcase when "post" model = current_site.the_post(attrs["id"].to_i) if attrs["id"].present? model = current_site.the_post(attrs["key"].to_s) if attrs["key"].present? when "posttype" model = current_site.the_post_type(attrs["id"].to_i) if attrs["id"].present? model = current_site.the_post_type(attrs["key"].to_s) if attrs["key"].present? when "category" model = current_site.the_category(attrs["id"].to_i) if attrs["id"].present? model = current_site.the_category(attrs["key"].to_s) if attrs["key"].present? when "posttag" model = current_site.the_tag(attrs["id"].to_i) if attrs["id"].present? model = current_site.the_tag(attrs["key"].to_s) if attrs["key"].present? when "site" model = current_site when "theme" model = current_theme when "navmenu" model = current_site.nav_menu_items.find(attrs["id"]) if attrs["id"].present? model = current_site.nav_menu_items.find_by_slug(attrs["key"]) if attrs["key"].present? when "user" model = current_site.the_user(attrs["id"].to_i) if attrs["id"].present? model = current_site.the_user(attrs["key"].to_s) if attrs["key"].present? end model end end