Jump to content

ryan

Administrators
  • Posts

    17,239
  • Joined

  • Days Won

    1,701

Everything posted by ryan

  1. Sorry I forgot to put that in the example, I've updated the example to include it.
  2. This is the correct behavior. Not ideal I know, but that's also why it's best to use this particular feature carefully. The issue here is that TinyMCE saves a bunch of HTML markup, and that markup can feasibly have anything in it (images and links on site or off site). ProcessWire doesn't know anything about the markup that TinyMCE is saving. When you add an image in there, you are essentially adding an <img> tag like in any other HTML document, and the same rules apply. If you pull images from other pages (for TinyMCE), it's best to setup a shared 'gallery' page (or pages) designated for the purpose and you generally assume that all those images are in use until proven otherwise. Even better is to upload images on the page where you are using them (assuming the same image doesn't need to be populated on several pages). Down the road, I do think we'll be able to solve this by making a module that scans textarea fields for recognized paths (when you save a page) and keeps a list of them in a DB table. When you try to delete something, it'll abort if it finds a link to that asset on another page. While I don't like to have PW getting involved in trying to hunt down and manage links in HTML documents, it's probably worth the compromise. On the other hand, pulling images or files from other pages via the API is a safe bet. If an image gets deleted, it no longer shows up in the API call. So it's quite common to pull the first image on a page for showing a thumbnail with a listing (for example) or pull an image randomly from a page that has several. It's only when dealing with TinyMCE that you may not always want to exercise the power that it gives you in pulling images/files from anywhere (unless you've already made a plan for it).
  3. I think that your simplexml_load_file() is attempting to load from your file system, not from http. So if you wanted to load it that way, you'd probably need to put in an http address, like this: <?php $data = file_get_contents("http://domain.com/sitecontent/"); $xmldata = simplexml_load_string($data); But that's kind of a lot of overhead, to have one http request launching another on the same server. Granted, it happens all the time, but ideally you'd get some caching going here so that you don't have to do an http request and simplexml on every page load. If you can include PW's API, then I think it'd be preferable to avoid the extra http request, like this: <?php include('./sitecontent/index.php'); $home = wire('pages')->get('/'); $home->setOutputFormatting(true); $data = $home->render(); $xmldata = simplexml_load_string($data); Then again, if you can load PW's API, you probably don't need to be dealing with SimpleXML at all. But if you just need to get something going quickly, either of these code examples above should work.
  4. Just posted full documentation on multi-language fields, language-alternate fields, and how to use them. Also includes examples of how to use language fields to create full multi-language websites. Examples include using subdomains, URL post-segments, URL pre-segments, and sessions. I'm interested in your feedback. http://processwire.com/api/multi-language-support/multi-language-fields/'>http://processwire.com/api/multi-language-support/multi-language-fields/ I'm also working on more additions to the new multi language support section of the documentation (http://processwire.com/api/multi-language-support/). Thanks, Ryan
  5. That's not a problem, you can just tell jQuery to only target <a> links that have an href pointing to your site's files. Something like this should work, though could be taken further too. $(document).ready(function() { $("#bodycopy a[href*=site/assets/]:has(img)").fancybox(); });
  6. You are missing out on some good stuff if you haven't used these before. First off, textile and markdown are considered lightweight markup languages. This is the kind of stuff that you want clients to use in places where they might otherwise have to use HTML tags: About LMLs: http://en.wikipedia.org/wiki/Lightweight_markup_language More on Markdown: http://en.wikipedia.org/wiki/Markdown More on Textile: http://en.wikipedia.org/wiki/Textile_%28markup_language%29
  7. I was just about to reply to this and you beat me to it. But I'll continue my original reply anyway– I was going to say that the 'description' field that goes with each image is really intended to be for the 'alt' tag of the image (though not limited to it). But as a result, it's not something that is meant to have markup in it by default. However, if you want to have markup in it there are many ways to go. The way I would probably do it is to use markdown or textile codes in the description, and then run it through that textformatter at output time so that it converts to HTML: <?php $markdown = $modules->get('TextformatterMarkdownExtra'); $description = $page->image->description; $markdown->format($description); echo $description; // outputs HTML
  8. The "link to larger version" is actually intended to be without implementation so that you can implement it with a lightbox of your choice. Rarely in my sites do I actually leave it as literally linking to the larger version. Instead, I'll usually put in some javascript like this: $(document).ready(function() { $("#bodycopy a:has(img)").fancybox(); }); Or if you want to add some attributes and do it that way: $(document).ready(function() { $("#bodycopy a:has(img)").addClass('lightbox').attr('rel', 'gallery'); $("a.lightbox").fancybox(); }); Now if you want to be able to support more then one way of linking to a large image (i.e. have one link to the larger version and another opening in a lightbox) then you'd probably need to take another approach (or maybe make a module). Let me know if that is your need.
  9. I've posted full documentation for how to use ProcessWire's translation features in your own code: http://processwire.com/api/multi-language-support/code-i18n/
  10. Anything is possible, but not sure I totally understand. What would the additional checkbox be for? What does the cssextras plugin do that you are wanting to duplicate?
  11. Steve, glad that worked for you. Regarding housecleaning, ProcessWire is still doing it. When you exit() the objects still have their destructors called and ProcessWire's shutdown function is still executed. It should be just fine to use exit() in this case.
  12. ryan

    IE7 Support?

    One thing about IE6/IE7 stats is that as part of those aren't actually IE6/IE7. There are lots of forced IE6/IE7 useragents out there because many sites require it (though hopefully not so much anymore). It used to be I couldn't use my bank's website (among others) unless I disguised Firefox as IE7 (in the useragent). This is due to crappy web developers out there that [used to] develop IE-only sites. Most crawlers and bots use one of the IE useragents when they are trying to disguise themselves as well. Though you'd see those more in the server access lots and less so in the Google Analytics type logs. Basically I think we are going to continue seeing some IE6 and IE7 useragents long after anyone is actually using them. Good idea about Modernizr. I haven't tried it but have been meaning to. Chrome Frame also seems like a great thing.
  13. ryan

    IE7 Support?

    I honestly don't know if it works with IE7 or not. It's certainly possible that it does. Support for old versions of IE is just a matter of limited resources to support a browser that none of my clients use. However, if a big project came along and the client said they had to use IE7, then I would add IE7 support if the resources were there in the budget to do it. The same goes for anyone else's projects. I'll be happy to add IE7 support if some individual or client wants to sponsor the time to do it, or someone else may want to take upon the task (and we can merge in official support). But my experience with older versions of IE has been that anytime I change or add anything at all, it's got to be tested (and often adjusted) to work in old versions of IE… it's a bit of a ball and chain.
  14. We're duplicating GetText functionality here, not just a string translator. Everything about it is geared towards making it super-simple to use, and able to scale to any size. I actually think we have a solution that is significantly less complex than GetText, while duplicating its functionality. For example, take a look in the WordPress i18n documentation and read the sections for: POT files, PO files, MO files, "Choosing and loading textdomains", and "Generating POT files". Note that you don't have to deal with any of that in ProcessWire, nor do you have to install GNU Internationalization utilities, nor do you have to install and use POEdit. Yet you get all the same capability and power–ProcessWire's Language Support does it all for you. If you want to compare ProcessWire's implementation, compare it to another of the same capabilities like in WordPress or Drupal (both of which use GetText). I think you'll find ProcessWire's implementation is far simpler and just as powerful from every standpoint. The example you posted doesn't involve a parser. By that, I mean a parser like GetText that sifts through PHP files and locates the translatable phrases on it's own, outside of program execution. Without a parser, you have to predefine everything on your own in a separate PHP file (or some other file), like in your example. This is okay for small things, but we need something more powerful and scalable than that. While there's a lot of power under the hood, I think our basic translation API is about as simple as it gets: <?php echo __("text"); // outside of a class echo $this->_("text"); // inside of a class With regard to number of translation function calls on a line, there's no problem with placing multiple __() function calls on the same line from a PHP perspective–all those functions will still get called at runtime. It all has to do with the external parser (like GetText, or in our case PW's LanguageParser.php). We need to have a way to let the parser identify the translatable phrases outside of PHP while also optionally communicating additional meta data about the translation. This part happens at translation time, not at runtime, so that everything is cached and ready to go with no parsing at runtime. The 1-translation per-line requirement is to ensure that optional meta data about the translation can be communicated to the parser (and people doing translations), and that meta data is communicated via comments placed at the end of the line. Since this meta is optional, it's feasible we could just ignore it when there are multiple translations on a line (and perhaps will add that), but for now I'm trying to keep it simple with clear guidelines and best practices. It goes beyond technicalities or rules too. Keeping translations on one line helps to keep things more readable and clear (for me at least, having now made dozens of files translatable). Language designed for translation is different from regular language in that it requires more careful consideration. I've had to rethink my use of English in many cases. Due to the differences in languages, translatable phrases are by nature independent pieces of information that must always be static and carefully considered, especially when it comes to how it flows with other dynamic text. Note that GetText (WordPress/Drupal) has the same requirement when it comes to providing meta data to a translation function call. However, they also don't prevent you from putting several calls on one line (with no meta data) so we may update to do the same if there is enough demand for it. But I'd still encourage people to follow these rules even if we just make them optional guidelines.
  15. Nice branch Almonk. I agree it does fee like a Futura Lite or "Futura Minima". I think this might be the first admin theme "family". Both look great.
  16. Good find Oliver! I hadn't realized that, but you are right, it's using a different Page Title depending on what URL you access it from. I've just pushed an update that ensures that page title is consistent so that it doesn't have to translate it twice. It should now always be 'Pages'. Thanks for finding this. <title><?php echo __($page->get("title|name")); ?> • ProcessWire</title> … <h1 id='title'><?php echo __($this->fuel->processHeadline ? $this->fuel->processHeadline : $page->get("title|name")); ?></h1> I'm actually pulling a bit of a trick there to enable dynamic page titles like 'Pages' and 'Setup' to be part of static language packs. The above __() function calls won't register with the parser because they have no static text defined in them. However, I know that there are certain words like 'Pages' and 'Setup' that are part of almost every PW installation, and I want them translated when they happen to show up. The comment near the top of the file helps to explain it: /* * Dynamic phrases that we want to be automatically translated * * These are in a comment so that they register with the parser, * in place of the dynamic __() function calls with page titles. * * __("Pages"); * __("Setup"); * __("Modules"); * __("Access"); * __("Admin"); * */ Those function calls in the comment above are seen by the parser but not by PHP. So the end result is that if they appear by themselves in the <title> or <h1> tags above, they will get translated automatically. This method isn't strictly necessary, as we could have done it with multilanguage page title fields. But since translations in multilanguage fields aren't part of language packs, this was a way of ensuring they could be part of language packs. Thanks for the update Jasper! Here is a list of all the current translatable files. I will plan to add an official and always up-to-date list to our language translation documentation (currently in production). This list will continue to grow over the coming weeks. Inputfield Modules /wire/modules/Inputfield/InputfieldEmail.module /wire/modules/Inputfield/InputfieldFile/InputfieldFile.module /wire/modules/Inputfield/InputfieldImage/InputfieldImage.module /wire/modules/Inputfield/InputfieldPageListSelect/InputfieldPageListSelect.module /wire/modules/Inputfield/InputfieldPageName/InputfieldPageName.module /wire/modules/Inputfield/InputfieldPassword.module /wire/modules/Inputfield/InputfieldSubmit/InputfieldSubmit.module /wire/modules/Inputfield/InputfieldTinyMCE/InputfieldTinyMCE.module /wire/modules/Inputfield/InputfieldURL.module Language Support Modules /wire/modules/LanguageSupport/LanguageSupport.module /wire/modules/LanguageSupport/ProcessLanguageTranslator.module Process Modules /wire/modules/Process/ProcessForgotPassword.module /wire/modules/Process/ProcessLogin/ProcessLogin.module /wire/modules/Process/ProcessPageAdd/ProcessPageAdd.module /wire/modules/Process/ProcessPageClone.module /wire/modules/Process/ProcessPageEdit/ProcessPageEdit.module /wire/modules/Process/ProcessPageEditImageSelect/ProcessPageEditImageSelect.module /wire/modules/Process/ProcessPageEditLink/ProcessPageEditLink.module /wire/modules/Process/ProcessPageList/ProcessPageList.module /wire/modules/Process/ProcessPageSearch/ProcessPageSearch.module /wire/modules/Process/ProcessPageSort.module /wire/modules/Process/ProcessPageType/ProcessPageType.module /wire/modules/Process/ProcessProfile/ProcessProfile.module Admin Theme /wire/templates-admin/default.php
  17. This one should already be fixed (just tested to confirm). Thanks for the translation! It just depends how you code the site. You'd have to set their language, like this: $user->language = $languages->get('dutch'); So you might do that if you'd set a value to $session->language, or if $input->urlSegment1 == 'nl' or something like that. Lots of possibilities.
  18. Nice job Pete. It's easier to follow on GitHub just because we can pull in updates automatically without downloading, unzipping, etc. So many great new modules lately. I need to make a lot of additions to the modules directory.
  19. Great update, thanks Pete! What do you think about putting this on GitHub? (whether now or in the future)? For the cache time, you could always make it configurable with the module if you wanted to. Let me know if I can assist. I also like your alternative for time based caching, though I'm guessing time based caching is adequate for most. But if you want to pursue that alternative, you'd use the CacheFile class directly and have a Pages::save hook clear the cache file (or maybe just Pages::added and Pages::deleted hooks). I wasn't aware of the <sitemapindex>, this sounds like a good idea for the large sites. But also sounds like a much more complex module.
  20. Now I understand what you mean. I've just updated the source so that now it uses the field labels rather than the names. That way it'll pull in the field label in the language that it's in. So for the examples you posted, you'd want to edit the language and language_files fields in Setup > Fields > Filters > Show Built in Fields. I've also made ProcessPageType translatable so that everything else in that file can be in future language packs (including the 'Name' field, in the column headers). That's a good observation. There are a couple rules set by the parser that vary from regular gettext. One is that there can only be one translation per line. Another is that a translation block cannot contain split strings, and thus cannot span more than one line (though you can put literal "\n" returns in it if you want). So to achieve the example you posted, you'd need to do this: <?php $this->method(array( $this->_('Text1'), $this->_('Text2') )); or this: <?php $field->value = "<span>".$this->_('partoftext')."</span> ". $this->_('another part of the text'); or this: <?php $a = $this->_('part of text'); $b = $this->_('another part of the text'); $field->value = "<span>$a</span> $b"; The reason for this is that the parser considers comments on the same line as the translation to be notes for the translator: <?php $this->method(array( $this->_('Text1'), // This will show up as an optional label for the translation field $this->_('Text2') // Some label // a second comment on the line adds an extra 'notes' field visible to translators ));
  21. Pete's right that there probably are a lot of considerations here. You don't really want to add the watermark to the original because then it's going to be in other sizes (thumbnails, etc.) and you may not want that. You don't want to use a filename based on the original because then someone can pry and find your non-watermarked version. But then if you create a different filename, it's no longer tied to the original and will stick around if the original ever gets deleted–we might need to add a new hook to Pageimage::getVariations in order to solve that one. Actually I think all the issues are solvable, but just a little more work than it sounds like at first. One approach is to put the watermark capability in it's own module: <?php $w = $modules->get("WatermarkImage"); $w->setWatermark("mark.png"); $image = $w->watermark($page->image, "new-file.png"); // or just $w->watermark($page->image); I'm guessing something like this would return the URL to the new file, or a new Pageimage object. Another approach would be to make an autoload module that adds a new watermark() function to the Pageimage class and works the same way as the size(), width() or height() functions, returning a new Pageimage: <?php $image = $page->image->watermark("mark.png"); Still another option would be to just create a new Image fieldtype that automatically adds a watermark (configured in the field settings) to every image uploaded to it. Or, every image with the checkbox, like you mentioned. Antti's CropImage fieldtype is probably a great example to look at for how to implement a module like that. If you decide to build a new module, just let me know anything I can do to help.
  22. Pete, nice job with this module, it looks very well put together and provides a helpful function. I like the simplicity of it being a module and how easy that makes installation. But there are a couple potential issues with this approach I wanted to mention. First is that it's taking the place of the 404 page and a 404 header is getting sent before the sitemap.xml output is displayed. This will probably be an issue for any search engines that hit it. You can avoid this by moving everything from your generateSitemap() function into your init() function. You don't need to use any hooks. Of course, you won't have a $page to check at the init() stage, but I don't think you need it–just get rid of the $page->template != 'admin' check... your strpos() below it is likely just as fast. Next concern is scalability. Generating this sitemap could be a slow thing on a large site. Anything that's slow to generate can be a DDOS hole. Because it's in a module, you can't as easily cache the output with a template setting. However, you could use the MarkupCache module to perform your own caching, and that's something I'd probably recommend here. Last thing is that I'd suggest renaming the module since it falls in the Markup group of modules. Perhaps the name MarkupSitemapXML? Other than that, I think it looks great.
  23. Sorry, I forgot about this earlier. Here's how to add such a configuration option. First off, tell ProcessWire that your module will be configurable by adding 'implements ConfigurableModule', like this: class SchedulePages extends WireData implements Module, ConfigurableModule { Next, determine the name of the variable you will use to hold the template IDs: I'll use $scheduleTemplateIDs. Set that in your __construct() to initialize it as a known variable in your module: <?php public function __construct() { $this->set('scheduleTemplateIDs', array()); } Now you need to implement the ConfigurableModule interface by adding a static function called getModuleConfigInputfields. It is static so that ProcessWire's Modules section can call upon it without actually initializing the module. Or to put it another way, it ensures that if you have CSS or JS files being loaded in your __construct() or init() then they won't be altering the display of the module configuration screen. This function is given an array of the current configuration data saved with your module. If it's the first time your module is configured, it will very likely be empty. <?php static public function getModuleConfigInputfields(array $data) { // create a wrapper to hold our field(s) $form = new InputfieldWrapper(); // set our default if this config var isn't already present if(!isset($data['scheduleTemplateIDs'])) $data['scheduleTemplateIDs'] = array(); // create a field to select templates $f = wire('modules')->get('InputfieldCheckboxes'); $f->label = 'Select the templates you want'; $f->description = 'Additional description if you want it'; $f->notes = 'Some optional extra notes at the bottom'; $f->attr('name', 'scheduleTemplateIDs'); // add the checkbox options foreach(wire('templates') as $template) { $f->addOption($template->id, $template->name); } // set the current value $f->attr('value', $data['scheduleTemplateIDs']); // add it to the form $form->add($f); return $form; } Now when the user clicks on your module in Admin > Modules, they will see checkboxes they can use. After they save, PW will now know to automatically send a $scheduleTemplateIDs var to your module every time it's loaded. That variable will be set before your module's init() is called. So you could do something like this in your init() or anywhere in your module: <?php $page = wire('page'); if(in_array($page->template->id, $this->scheduleTemplateIDs)) { // do something }
  24. The item description field is actually configurable in the module settings. In the admin, go to Modules > Markup > RSS. Click on it to configure the various settings it can use. This sets the defaults for all instances of MarkupRSS. If you prefer, you can also change the settings at runtime for any individual instance like this: <?php $rss = $modules->get('MarkupRSS'); $rss->itemDescriptionField = 'body'; echo $rss->render($yourPages); Also, thanks for the great example stillmovingdesign!
  25. Sorry about that, had an extraneous debug message in the dev branch. I just committed an update that should remove it.
×
×
  • Create New...