Jump to content

ryan

Administrators
  • Posts

    16,715
  • Joined

  • Last visited

  • Days Won

    1,517

Everything posted by ryan

  1. I think what Diogo is saying is that with a URL segment you can take a different path depending on what the URL segment is. For instance: if($input->urlSegment1 == 'photos') { // output photo gallery } else if($input->urlSegment1 == 'rates') { // output rates table } else if($input->urlSegment1) { // unknown URL segment, send a 404 throw new Wire404Exception(); } else { // output default } So you don't need to have a separate page for the segments you are looking for like 'photos' and 'rates' and any others. This can be a worthwhile technique in some instances and it sounds like yours would be one of them.
  2. Just wanted to follow-up to say that there isn't anything built-in that can tell you what the most visited pages are. You could certainly add a hit counter field to a page and increment it, and save on every page view, but I think that would be kind of inefficient. It would also prevent you from using any cache features if you are having to save a page on every view. I think the best bet is to do what these guys suggested, or subscribe to a hit counter service that bundles this info into an RSS feed or JS widget.
  3. Regexp is definitely the easiest way to go here. You could do it with just string functions, but it would be a pain for sure. As for the block syntax, I would suggest that simpler is better. People will use them if they don't have to remember too much, so something like {tag} or even {{tag}} is I think easier to remember than {% tag %}. I'm not sure that I understand -- do you want to hook into a textformatter's format() function, or do you want the textformatter to hook into something else?
  4. Actually it needs to be whatever you've named your comments field, whether 'comments', 'comment' or feedback', etc.
  5. Good points on using the ID. Might require some core changes, which the workaround wouldn't. For the most part, I like the core to be geared at the common needs of all modules, rather than honed in on one. So I think a workaround isn't necessarily a bad thing. But the core does get more invovled in the needs of file-based modules than it does with any other kinds of modules, so there's some grey area here.
  6. No need to use a role for that. I would just use a page reference to relate them, or you could even do it by page name. You'd perform the check in your template code, but you could get exactly what you want that way.
  7. You could certainly take it a level deeper and then just display the links to it if they had access. On the deeper levels, you'd either want to limit view access to the 'investor' role (from the template access settings). Or if the template is being used for public stuff too, then perform the check in your template code like in the examples above. If you are performing your own check, you may want to redirect them to the login page when they don't have access, or say something like "Become an investor to get access", or just: throw Wire404Exception();
  8. This is a beautiful theme. Great update and nice to see it again. Only issue I'm running into is that if there are more than 4 top nav items, the 5th wraps to a second line where it gets cut off. Not sure if the issue is with the original Futura or the update. But it's a fairly minor thing as I think most probably don't have as many admin menu items as I do.
  9. $numApproved = 0; $numPending = 0; $numSpam = 0; foreach($page->comments as $comment) { if($comment->isApproved()) $numApproved++; else if($comment->status == Comment::statusPending) $numPending++; else if($comment->status == Comment::statusSpam) $numSpam++; } echo "<p>$numApproved approved comments.</p>"; echo "<p>$numPending comments awaiting moderation.</p>"; echo "<p>$numSpam spam comments.</p>";
  10. Any class method preceded with 3 underscores is hookable (assuming it extends a PW class like Wire or WireData). So just make your method name ___myFunction() rather than myFunction(). Use just myFunction() (no underscores) when you call it. I don't understand the question? Not easily done since PW include()'s templates rather than eval()'s them. Meaning, PW can't modify the template before executing it. The way it could be done is by using compiled templates where a compiler converts tags in a template file to PHP code and then saves it as a compiled template. PW then includes the compiled template rather than the original. It's something we'll probably eventually support, but it's a little complex. The other option is hooking into Page::render and replacing tags from there. But that's not ideal because you don't really know where those tags came from at that point. They could have come from user input (like a comment). So you lack the ability to filter at this stage. It's a PW class that I made 2 years ago, before PW was even released, and I haven't looked at it since then. I just took a look at it now, and it's not in a state where I think it would be helpful or functional. I'd made it as a proof of concept to revisit when the time came to support EE style loops and open/close tags with embeded markup. But that's all it does... it's not an actual tag engine. It's just notes to myself on how a markup embeeded tag might work. I'll still send it to you if you want it, but realize that: 1) it is not a functional module, and 2) It's been awhile, it's a mess, and inexplicable at the moment.
  11. Thanks Pete! I'll take you up on that because it sounds like you are the only one here that's setup MediaWiki before, so I think it makes the most sense for you to at least get the installation started. That's assuming you have time and are comfortable with doing it? I know you'd originally expressed some reservations about MediaWiki, so if you find something you think might suit us better then that's great too. I'll create an account, subdomain and DB. Let me know what else I can get setup here.
  12. The field only accepts digits, so something like a decimal point gets stripped. However, I think this can be solved by me just adding a float check in it's sanitizeValue() function, so I will add this.
  13. Very nice! I think that really showed it well. A very well put together presentation there too. I don't yet have a clear sense of how something like this might be implemented. I'm not sure this is something that can be implemented purely as a module, because the core assumes that files on a page are owned by the page. For instance, when you delete a page, it deletes all the files on the page. When you remove an image from a page, it deletes the image file when you save. But it goes beyond that (primarily in the core PagefilesManager, Pagefiles, Pageimages, Pagefile, and Pageimage classes). So the considerations would stretch pretty far beyond just the module. The only way I can think of to bypass that is to actually maintain a blank placeholder image file as the actual reference. The placeholder filename would be in some format where it could be identified as a reference, perhaps something like: page[id]-[fieldname]-[filename].jpg. Using that method, the core could continue to do what it does. When it deletes the image, it deletes the reference file rather than the original image. But when outputFormatting is on, the module would know to convert the images in that specific format to the one that is referenced. Still a bit complicated, but just thinking out loud how something like this might be accomplished, and this might be a way.
  14. You may also want to look at using multi-language fields, or multi-language alternate fields for this (if you aren't already): http://processwire.com/api/multi-language-support/multi-language-fields/ As for detecting a language from a URL, a GET var is a fine way to go. Though note that you'll want to keep your templates cache settings off, since GET vars aren't cachable. Other options include a URL segment (if turned on in your template) or a subdomain. A URL segment might look like this (for english): /boats/barca37016/en if($input->urlSegment1) { $language = $languages->get($sanitizer->pageName($input->urlSegment1)); if($language) $user->language = $language; } A subdomain might look like this (for english): en.yachbrokers.com $name = strstr($config->httpHost, '.', true); // requires PHP 5.3 $language = $languages->get($sanitizer->pageName($name)); if($language) $user->language = $language;
  15. It depends on the scope of the content. But it sounds to me like Option 2 is your best bet. This is the route I usually take. If it's content that you can include all on your portfolio-entry pages, then I would do that... no need to split it on multiple public vs. investor pages unless it's a whole lot of stuff, or it makes more sense with the site structure. Your portfolio-entry template will contain the fields of content that are public as well as investor-specific. But you will only display the investor-specific content if the user has the 'investor' role. Your template code might look like this: echo "<h1>{$page->title}</h1>"; echo $page->body; if($user->hasRole('investor')) { echo "<h2>Investor Data</h2>"; echo $page->investor_data; } That's basically repeating what you already included in your code, so I think you already arrived at a good solution.
  16. MySQL's fulltext indexes don't index commas. As you saw, commas and quotes will get trimmed from the front and back of the string. The sanitizer leaves single quote characters by themselves just in case they are an apostrophe. The sanitizer is fast but not smart here, which is why you saw it leave [what it thinks] is an apostrophe at the beginning of a couple of your tests. A comma in the middle of the string is fine. It'll be ignored by the fulltext index, but could still be used for an exact match '=' operation. I'm not certain why it's removing the comma from your guns n roses string, but looks like a bug to me. Apparently it doesn't like the combination of apostrophe and comma, because the string works fine as soon as I remove the "n'" part of it. I will use that to test and debug -- thanks.
  17. ryan

    Multisite

    Which direction you go largely depends on whether you want the sites to use independent databases or share the same one (perhaps for communicating to one another). If you want them to be technically separate, independently running sites on the same account, then use the built-in multi-site functionality that Diogo mentioned. Here are the docs for that: http://processwire.com/api/modules/multi-site-support/ If you want them to share data, then use Apeisa's great multisite module:
  18. It looks to me like TextboxList's schema is compatible with the Text/Textarea fieldtypes, so the getCompatibleFieldtypes() function in it could be updated to contain this: public function ___getCompatibleFieldtypes(Field $field) { $fieldtypes = new Fieldtypes(); foreach($this->fuel('fieldtypes') as $fieldtype) { if($fieldtype instanceof FieldtypeText) $fieldtypes->add($fieldtype); } return $fieldtypes; } I can help you get started with this if you'd like. But need more detail.
  19. I'm not sure about Chrome in that case, but in jQuery, most manipulations are done in $(document).ready(), which executes once the DOM is ready. The way you describe it, it sounds like maybe Chrome's inspector is giving you a picture of the structure before the javascript executed? I think that the best way is with a separate JS file. Inputfield modules will automatically load a CSS or JS file with has the same name as the module in the same dir. The same goes for any module that extends ModuleJS. However, there isn't much to it, and it would be easy to duplicate anywhere else. This is how it does it: public function init() { $class = $this->className(); if(is_file($this->config->paths->$class . "$class.css")) { $this->config->styles->add($this->config->urls->$class . "$class.css"); } if(is_file($this->config->paths->$class . "$class.js")) { $this->config->scripts->add($this->config->urls->$class . "$class.js"); } } Then your js file should look like this: jQuery(document).ready(function() { // your JS code });
  20. These two fieldtypes don't have any function outside of the PW PageEdit Process, so aren't really applicable in the API for the most part. Let me know if I've misunderstood your question? If you are building a form elsewhere, it's more likely that you would want to use the InputfieldFieldset: $form = wire('modules')->get('InputfieldForm'); $form->attr('method', 'post'); $form->attr('action', './'); $fieldset = wire('modules')->get('InputfieldFieldset'); $fieldset->label = 'This is a fieldset'; $fieldset->description = 'Some optional extra copy if you want it.'; $field = wire('modules')->get('InputfieldText'); $field->attr('name', 'title'); $field->label = 'Title'; $field->description = 'Extra description'; $fieldset->add($field); $form->add($fieldset); echo $form->render();
  21. Inputfields are just the input widget (no schema here), whereas Fieldtypes are the data format and storage (schema). For the most part, the schema of fieldtypes does not change from when it was created. The only exception is multi-language fieldtypes, which add new columns when a new language is added. For stuff that is more likely to change (like individual field settings) PW JSON encodes them in the 'fields' table. But this should only be used for things that don't need to be normalized or searchable. I think that the best starting point for a Fieldtype/Inputfield is the MapMarker fieldtype, which I made specifically for this purpose (as a well commented demonstration). I'm also here to assist in any way I can and guide you through it as you go. Admittedly, I'm not yet sure how I'd approach a fieldtype that does what you are wanting it to do, so not yet in a good spot to identify the next step on that. But I think part of that is that I can't yet see how it would work to the user. A good place to start might be to mock it up. That would mean to show how it would look or work on the front end. These kind of mock-ups help the direction become more apparent.
  22. Welcome to the forums Buothz! Good question. Here's how you could do it: $language = $languages->get("spanish"); $field = $fields->get('bandiera'); $label = $field->get("label$language"); echo "$label: $page->bandiera"; If you want a specific other language replace the first line above with this: $language = $languages->get('italia'); . Edit: Code fixed first example and changed to make more sense. (Soma)
  23. Looking good Slkwrm! You may want to instead hook into ProcessPageEdit::buildForm. That function returns an InputfieldWrapper that you can add new fields to. Here's how your hook function might do it: $f = wire('modules')->get('InputfieldSubmit'); $f->attr('name', 'submit_something'); $f->attr('value', 'hello'); $form = $event->return; $form->add($f); I'm not positive this will do exactly what you want, but it's a good place to start. I think that the problem may be here: $page = $this->modules->get("{$this->input->get->name}"); A module is not a $page (and it's one of the few things that isn't). There isn't such thing as a module having siblings because modules are not in any hierarchy. Though I suppose that you could sort the modules by name and figure out which is next by doing a foreach(), but you'd want to be careful here as you don't want to instantiate all the modules at once. I think it may be less hassle not to bother with the modules here. But if you still want to do it, let me know and I can suggest a good way. I don't understand the question. Can you provide additional context? I think we're all just using jQuery?
  24. If I'm understanding the need correctly, it's not that hard to do with Google Maps v3 API. Here's a few examples that uses the MapMarker fieldtype: http://www.di.net/almanac/firms/ http://www.di.net/almanac/buildings/tallest-buildings/ http://www.di.net/almanac/buildings/art-museums/ These use the stock Map Marker fieldtype, so that each item (firm, building, art museum, etc.) has a Map Marker fieldtype. Then the index page with the big map cycles through all the children and adds the coordinates for each: $js = "<script type='text/javascript'>RCDMap.init('map', 0, 0);"; foreach($page->children as $item) { $js .= "\nRCDMap.addMarker('{$item->title}', '{$item->url}', '{$item->map->lat}', {$item->map->lng});"; } $js .= "</script>"; echo $js; The above uses my RCDMap class. Feel free to grab it if you find it helpful. You'll want to view the source on any of those URLs above to see how it works. http://www.di.net/almanac/site/templates/scripts/RCDMap.js Note that you'll also need jQuery and Google Maps in your <head>: <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js" type="text/javascript"></script> <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
  25. Looking good Adam! I replied in Diogo's thread something that may be more applicable here: That link mentions referencing other pages with a tag. So one way to make tags extendable is by tying them to a page and rendering the output of the page. I think there are cool possibilities there, but don't think it's enough... If we're going to have an extendable tags system, it probably needs to be a module that other modules can add hook functions to, and they become tags. It would utilize the existing hook system. That way another module could add a {subpages} tag by doing something like this: public function init() { $tagscript = wire('modules')->get('Tagscript'); $tagscript->addHook('tag_subpages', $this, 'subpages'); } public function subpages($event) { $page = $event->arguments[0]; $children = $page->children(); $out = "<ul class='subpages'>"; foreach($children as $child) $out .= "<li><a href='{$child->url}'>{$child->title}</a></li>"; $out .= "</ul>"; $event->return = $out; } As for format of tags, I think it may make sense to use the existing selector format already used elsewhere in PW. There is already a built-in parser for it, it would be consistent, and it could pass the params in the selector directly to the tag event in the $event->data array. So an example of a tag would be this: {subpages: limit=10, include=all} ...and the tag_subpages function would retrieve them like this: $limit = 0; if(isset($event->data['limit'])) $limit = (int) $event->data['limit']; Further along, we'd also want to be able to do this for markup independence: {subpages: limit=10, include=all} <li><a href='{url}'>{title}</a></li> {/subpages} I have a parser that does that that I was working on awhile ago. Might be time to resurface it.
×
×
  • Create New...