Leaderboard
Popular Content
Showing content with the highest reputation on 07/11/2013 in all areas
-
Just finished another one: http://www.hirschenhotels.com Their styleguide is a bit weird for a "romantic" hotel. Futura as font and these green/red colors are not ideas of mine ;-) On the PW side pretty regular stuff, mostly core functions.8 points
-
ProcessWire Site Profile Using Zurb Foundation 4 This is a drop-in replacement for the default ProcessWire site profile. See the live demo at: http://processwire.com/foundation/ It is mobile-first and fully responsive, capturing all the benefits of Zurb Foundation 4. Ready to be expanded upon with built-in support for deeper levels of navigation nesting in the sidebar. Pagination ready with Foundation-specific pagination output, when/if you want it. Improved search engine, relative to the basic profile. Library of Foundation-specific markup generation functions included, primary for generation of navigation (in _nav.php). Uses ProcessWire 2.3+ prepend/append template file settings making it easy to work with. It is largely stock Foundation 4 in terms of look and feel, with a few tweaks. To Install Download this profile from GitHub or mods.pw/4u. Start with a copy of ProcessWire 2.3 or newer, and its default site profile. If starting with an uninstalled copy of ProcessWire Replace the /site-default/templates/ directory with the templates directory from this profile. Replace the /site-default/config.php file with the config.php file from this profile. Run the ProcessWire installer. If starting with an already-installed copy of ProcessWire Replace the /site/templates/ directory with the templates directory from this profile. Add the following two lines to your /site/config.php file: $config->prependTemplateFile = '_init.php'; $config->appendTemplateFile = '_main.php'; Desktop Screenshot Mobile Screenshot3 points
-
/site/config.php $config->dbHost = 'localhost'; changes.to $config->dbHost = '127.0.0.1'; o lo contrario ?3 points
-
Hi kyle, The below code should do it (not tested, just wrote it in the browser) Markup: $html = "<h3>Condimentum Purus</h3><p>Cras Sollicitudin Vulputate Nullam</p>"; $markup = $modules->get("InputfieldMarkup"); $markup->set("label", "Label for this"); $markup->set("value", $html); Default selected: $needed = "ProcessWire"; $array = array( array( "cms" => "Joomla", "value" => "If you don't mind code" ), array( "cms" => "modx", "value" => "Good for trouble shooters." ), array( "cms" => "ProcessWire", "value" => "Great, we selected this." ), ); $select = $modules->get('InputfieldSelect'); foreach($array as $option){ $attr = $needed == $option['cms'] ? array('selected' => 'selected') : null; $select->addOption($option['cms'], $option['value'], $attr); }3 points
-
ModulesManager doesn't have tabs. Well I guess you already know you use getModuleConfigInputfields(array $data){ ... } to add configuration inputfields (not fields!) And you need to add the ConfigurableModule to the implements list (implements Module, ConfigurableModule). Now you can create a new InputfieldWrapper and add Inputfields to it. static public function getModuleConfigInputfields(array $data) { // if you have a static $defaults array for defaults you can merge them with saved ones in $data $data = array_merge(self::$defaults, $data); $fields = new InputfieldWrapper(); ... return $fields; } From there it's pretty easy. You can use all inputfield modules for inputs. It's much like creating a front-end form using API. Know my famous thread? Those inputfields are not bound to the fieldtype, like when used in the admin on pages. So the InputfieldSelect is a simple select module you can fill in options as you like. They're also used in FormBuilder. Ryan has even adapted some a little to support pure interactive inputs better. When used on a page (fields) they're actually a mix of the fieldtype and the inputfield and they depend on each other. Fieldtypes are more used to sanitize and save to db, wakup or sleep values etc, while inputfields kinda serve as an plain interface seen by the user, thus having a render() method. Some special Inputfields are more bound to functionality of other modules like "process" modules, but only remember InputfieldPageListSelect. From there it's just generaly PW API coding. So this would look like this to add a multiple ASM select static public function getModuleConfigInputfields(array $data) { $data = array_merge(self::$defaults, $data); $fieldwrapper = new InputfieldWrapper(); $modules = wire("modules"); $field = $modules->get('InputfieldAsmSelect'); $field->attr('name', 'mymodules'); $field->attr('value', $data['mymodules']); $field->label = 'Select modules.'; foreach($modules as $m) { // loop all installed modules if(strpos("$m->name","Process") === 0) $field->addOption("$m", "$m->className"); } $fieldwrapper->append($field); return $fieldwrapper; }2 points
-
You have a couple of options here. First would be to make it a "global" field, which should make it appear on the first screen when adding a page. But not all fields support that, like files, images and repeaters for instance. The other option would be to copy /wire/modules/Process/ProcessPageAdd/ into /site/modules/Process/ProcessPageAddCustom/ and rename the file name/class name consistent with the directory name (ProcessPageAddCustom). Modify the module to do exactly what you want. In the admin, edit the page Admin > Pages > Add Page. Change the "process" field to be your custom version. Anything is possible, but this might be too abstract/vague of a request to provide a tangible answer. But it does potentially sound like you want a hook, or a custom Fieldtype or Inputfield to perform some automated actions.2 points
-
Thanks so much Ryan, I'm just getting started with PW and am totally new here. Being a Wordpress developer for at least 5 years, now I realize that I've been stucked too long in its fixed structure. PW opens my eyes and gives me more innovation. This new site profile is awesome and totally convince me to stay with PW. Again, thanks so much Ryan. You're a super man.2 points
-
Since you guys asked for it, I'll take a stab at a case study on the development process. Most of the development was done in about a week and a half. I started with the basic profile, but it ended up being something somewhat similar to the Blog profile in terms of how it's structured. Below I'll cover some details on the biggest parts of the project, which included data conversion, the template structure, the front-end development and anything else I can think of. Data Conversion from WordPress to ProcessWire One of the larger parts of the project was converting all of the data over from WordPress to ProcessWire. I wrote a conversion script so that we could re-import as many times as needed since new stories get added to cmscritic.com almost daily. In order to get the data out of WordPress, I queried the WordPress database directly (my local copy of it anyway) to extract what we needed from the tables wp_posts for the blog posts and pages, and then wp_terms, wp_term_relationships, and wp_term_taxonomy for the topics and tags. WordPress stores its TinyMCE text in a state that is something in between text and HTML, with the most obvious thing being that there are no <p> tags present in the wp_posts database. Rather than trying to figure out the full methodology behind that, I just included WP's wp-formatting.php file and ran the wpautop() function on the body text before inserting into ProcessWire. I know a lot of people have bad things to say about WordPress's architecture, but I must admit that the fact that I can just include a single file from WordPress's core without worrying about any other dependencies was a nice situation, at least in this case. In order to keep track of the WordPress pages imported into ProcessWire through repeat imports, I kept a "wpid" field in ProcessWire. That just held the WordPress post ID from the wp_posts table. That way, when importing, I could very easily tell if we needed to create a new page or modify an existing one. Another factor that had to be considered during import was that the site used a lot of "Hana code", which looked like [hana-code-insert name="something" /]. I solved this by making our own version of the Hanna code module, which was posted earlier this week. Here's an abbreviated look at how to import posts from WordPress to ProcessWire: $wpdb = new PDO("mysql:dbname=wp_cmscritic;host=localhost", "root", "root", array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8'")); $posts = wire('pages')->get('/posts/'); $sql = " SELECT * FROM wp_posts WHERE post_type='post' AND post_status='publish' ORDER BY post_date "; $query = $wpdb->prepare($sql); $query->execute(); while($row = $query->fetch(PDO::FETCH_ASSOC)) { $post = $posts->child("wpid=$row[ID]"); // do we already have this post? if(!$post->id) { // create a new post $post = new Page(); $post->template = 'post'; $post->parent = $posts; echo "Creating new post...\n"; } $post->of(false); $post->name = wire('sanitizer')->pageName($row['post_name']); $post->title = $row['post_title']; $post->date = $row['post_date']; $post->summary = $row['post_excerpt']; $post->wpid = $row['ID']; // assign the bodycopy after adding <p> tags // the wpautop() function is from WordPress /wp-includes/wp-formatting.php $post->body = wpautop($row['post_content']); $post->save(); echo "Saved post: $post->path\n"; } What I've left out here is the importing of images, topics, tags, and setting the correct authors for each post. If anyone is interested, I'll be happy to go more in depth on that, but didn't want to overwhelm this message with code. Template File Structure This site makes use of the $config->prependTemplateFile to automatically include the file _init.php before rendering a template file, and $config->appendTemplateFile to automatically include the file _main.php after. So the /site/config.php has this: $config->prependTemplateFile = '_init.php'; $config->appendTemplateFile = '_main.php'; You may recognize this as being the same setup from the Skyscrapers profile. The _init.php includes files containing functions we want to be available to all of our templates, and set default values for the regions we populate: /site/templates/_init.php /** * Include function and hook definition files * */ require_once("./includes/render.php"); require_once("./includes/hooks.php"); /** * Initialize variables populated by templates that get output in _main.php * */ $browserTitle = $page->get('browser_title|title'); $body = "<h1>" . $page->get('headline|title') . "</h1>" . $page->body; $side = ''; $renderMain = true; // whether to include the _main.php file The includes/render.php file that is included above includes several functions for generating markup of navigation and post summaries, or any other shared markup generation functions. Examples are renderPost(), renderNav(), renderTags(). This is similar to the blog.inc file from the Blog profile except that I'm letting these functions generate and return their own markup rather than splitting them into separate view files. I personally find this easier to maintain even if it's not as MVC. The includes/hooks.php sets up any hooks I want to be present for all of my templates. I could have also done this with an autoload module, but found this to just be a little simpler since my hooks were only needed on the front-end. The main hook of interest is one that makes all posts look like they live off the root "/" level rather than "/posts/" (where they actually live). This was in order to keep consistency with the URLs as they were in WordPress, so that the new site would have all the same URL as the old site, without the need for 301 redirects. /site/templates/includes/hooks.php /** * This hook modifies the default behavior of the Page::path function (and thereby Page::url) * * The primary purpose is to redefine blog posts to be accessed at a URL off the root level * rather than under /posts/ (where they actually live). * */ wire()->addHookBefore('Page::path', function($event) { $page = $event->object; if($page->template == 'post') { // ensure that pages with template 'post' live off the root rather than '/posts/' $event->replace = true; $event->return = "/$page->name/"; } }); Our /site/templates/_main.php contains the entire markup for the overall template used site wide, from <html> to </html>. It outputs those variables we defined in _init.php in the right places. For example, $body gets output in the <div id='bodycopy'>, $side gets output in the right <aside>, and $browserTitle gets output in the <title> tag. /site/templates/_main.php <?php if($renderMain): ?> <html> <head> <title><?=$browserTitle?></title> </head> <body> <div id='masthead'> // ... </div> <div id='content'> <div id='bodycopy'><?=$body?></div> <aside id='sidebar'><?=$side?></aside> </div> <footer> // ... </footer> </body> </html> <?php endif; ?> We use the rest of the site's template files to simply populate those $body, $side and $browserTitle variables with the contents of the page. As an example, this is an abbreviated version of the /site/templates/post.php template: /site/templates/post.php // functions from /site/templates/includes/render.php $meta = renderMeta($page); $tags = renderTags($page); $authorBox = renderAuthor($page->createdUser); $comments = renderComments($page); $body = " <article class='post post-full'> <header> <h1>$page->title</h1> $meta </header> $page->body $tags $authorBox $comments </article> "; if(count($page->related)) { $side = "<h4>Related Stories</h4>" . renderNav($page->related); } What might also be of interest is the homepage template, as it handles the other part of routing of post URLs since they are living off the root rather than in /posts/. That means the homepage is what is triggering the render of each post: /site/templates/home.php if(strlen($input->urlSegment2)) { // we only accept 1 URL segment here, so 404 if there are any more throw new Wire404Exception(); } else if(strlen($input->urlSegment1)) { // render the blog post named in urlSegment1 $name = $sanitizer->pageName($input->urlSegment1); $post = $pages->get("/posts/")->child("name=$name"); if($post->id) echo $post->render(); else throw new Wire404Exception(); // tell _main.php not to include itself after this $renderMain = false; } else { // regular homepage output $limit = 7; // number of posts to render per page $posts = $pages->find("parent=/posts/, limit=$limit, sort=-date"); $body = renderPosts($posts); } The rest of the site's template files were handled in the same way. Though most were a little simpler than this. Several were simply blank, since the default values populated in _init.php were all that some needed. Front-end development using Foundation 4 The front-end was developed with the Foundation 4 CSS framework. I started with the Foundation blog template and then tweaked the markup and css till I had something that I thought was workable. Then Mike and I sent the _main.php template file back and forth a few times, tweaking and changing it further. There was no formal design process here. It was kind of a photoshop tennis (but in markup and CSS) where we collaborated on it equally, but all under Mike's direction. After a day or two of collaboration, I think we both felt like we had something that was very good for the reader, even if it didn't originate from a design in Photoshop or some other tool like that. I think it helps a lot that Foundation provides a great starting point and lends itself well to fine tuning it the way you want it. I also felt that the mobile-first methodology worked particularly well here. Comments System using Disqus We converted the comments system over to Disqus while the site was still running WordPress. This was done for a few reasons: Disqus comments provide one of the best experiences for the user, in my opinion. They also are platform agnostic, in that we could convert the whole site from WP to PW and not have to change a thing about the comments… no data conversion or importing necessary. Lastly, ProcessWire's built-in comments system is not quite as powerful as WordPress's yet, so I wanted cmscritic.com to get an upgrade in that area rather than anything else, and Disqus is definitely an upgrade from WP's comments. In order to ensure that Disqus could recognize the relations of comment threads to posts, we again made use of that $page->wpid variable that keeps the original WordPress ID, and also relates to the ID used by the Disqus comments. This is only for posts that originated in WordPress, as new posts use a ProcessWire-specific ID.1 point
-
I used to be a long time user of Google Reader. Then sometime last year, I simply stopped using it. I stopped visiting the sites I relied on for so long for web dev and design news, tips/tricks, inspiration, etc. Now that Reader is dead, I decided to get back into RSS, so I downloaded/installed Tiny Tiny RSS. My question for you friends: what web design/development related blogs/feeds to you recommend? Of course I have some of the most popular ones: Noupe, CSS Tricks, Smashing Magazine. What else do you recommend? [Friend recommended Feedly, which I am really liking at the moment ]1 point
-
Hi guys. I just happened to need a method of allowing image uploads and what do you know? There's a whole thread dedicated to it. Matthew, nice work. Thank you. I have only 2 things to add: 1. The code as is makes the assumption that each user will only ever upload one image or that there are no people with the same name. Since the title is derived from the contactname an error is thrown if a second upload is made with the same name. I added: $n = 0; $np->title = $sanitizer->text($input->post->contactname) . "-" . (++$n); It ensures each upload will get a unique ID. 2. I noticed the images uploaded to the .temp directory don't get deleted. With extensive use this will lead to lots of wasted server space as the .temp folder gets more and more bloated with duplicate images. Is there a way to solve this? You made my job very easy anyway thanks again.1 point
-
Ok I'll do that but I have to wipe some stuff out of it and write a bit more comments to be helpfull for newbies1 point
-
Possibly just a slip, but.. you didn't mention A List Apart there? Other than that, http://www.zeldman.com/, http://davidwalsh.name and http://addyosmani.com/blog/ are quite entertaining... oh, and http://blog.ponyfoo.com/ of course! Too much good stuff to keep track of nowadays but that's what Twitter is for.1 point
-
Let that sink in. Ryan, I can't absorb the knowledge you share fast enough — thank you!1 point
-
Short excerpt from search.php of Foundation site profile: // if the above doesn't find anything (perhaps due to MySQL minimum word // length or stopwords), switch to non-indexed phrase match if(!count($matches)) $matches = $pages->find("title|body%=$q, limit=$limit"); This is actually pretty nice idea -- use faster method first and only if it seems to fail switch to slower one. Don't know how much difference that really makes, but still. Also: there's a pager now, which is pretty obvious improvement already1 point
-
Ah, now I see. No, no ajax-voodoo here ;-) Thx for pointing me to pjax, I used history.js for that purpose once.1 point
-
pjax is ajax + pushstate, a nice way to use regular ajax but having urls changing accordingly to the page you are looking at. ( more here ) Since left sidebar always remains at the same place (and didn't noticed any flashes when i change pages) I thought you were using that method to manage transitions ( it's a good thing IMHO ).1 point
-
This is amazing flexibility! @Vineet, I must admit I like the questions you ask; in most cases they lead to profound revelations/responses such as the one Ryan has just given..1 point
-
The more simpler and direct way for a custom select would be: $sel = $modules->get("InputfieldSelect"); $sel->attr("name", "cms"); $sel->addOptions(array( 'pw' => 'ProcessWire', 'joomla' => 'Joomla!', 'wp' => 'Wordpress' )); // setting the value will select the option, here with coming either from post or the default $sel->attr("value", $input->post->cms ? $input->post->cms : 'pw'); echo $sel->render();1 point
-
Most likely repeaters aren't what you want. You can create any structure with pages so that opens up your options, even if it makes input less convenient. But for specific needs like this, you can us the API to automate any input challenges. You could also make a spreadsheet that contains your data and use the ImportPagesCSV module to import them (or your own import script). Another option is to create your own SeatingChart Fieldtype an Inputfield. Fieldtypes are designed to represent potentially very complex data, and are the most efficient way to create a reusable complex data type. But creating a Fieldtype does require getting into database schema and more PHP than usual site development.1 point
-
I created an empty language pack. Go to: Admin > Setup > Languages Create a new language Drag & Drop the attached zip-file in the Language Translation Files Field. Start to edit the files. empty-lang_pack_pw_3.0.41.zip EDIT: Obsolete in latest PW Versions. Create a language pack by your own. Go to: Admin > Setup > Languages > Add New Save Press button: 'Find Files to Translate' Select all files in the box 'Translatable files in /wire/' Select files in the box 'Translatable files in /site/' which you want to add to your custom language pack Press 'Submit' Start translating Download zip or csv file by pressing the related button at the bottom of the page where translatable files are listed. Done1 point
-
I think this should do what you are looking for: $pages->find('created_users_id=n'); where n equals the id of the user you are looking for. If you are searching for the currently logged in user, you could replace this with $user->id PS, Welcome to PW!1 point
-
I would try to work as much with what PW gives you and adapt the CSS, I think there's even an responsive theme in Formbuilder... but could be wrong. If you really need to adapt the HTML markup and CSS classes used by the InputfieldWrapper you can. As in this thread already mentioned: from the InputfieldWrapper.php core class /** * Markup used during the render() method - customize with InputfieldWrapper::setMarkup($array) * */ static protected $defaultMarkup = array( 'list' => "\n<ul {attrs}>\n{out}\n</ul>\n", 'item' => "\n\t<li {attrs}>\n{out}\n\t</li>", 'item_label' => "\n\t\t<label class='ui-widget-header' for='{for}'>{out}</label>", 'item_content' => "\n\t\t<div class='ui-widget-content'>\n{out}\n\t\t</div>", 'item_error' => "\n<p><span class='ui-state-error'>{out}</span></p>", 'item_description' => "\n<p class='description'>{out}</p>", 'item_head' => "\n<h2>{out}</h2>", 'item_notes' => "\n<p class='notes'>{out}</p>", ); Using the form inputfield object you could simply $form->setMarkup(array('list' => "<div {attrs}>{out}</div>")); The same exists for the classes used. But at the end I don't know if messing with it helps. Rendering form fields: As I said earlier, it's always possible to render a certain field explicit. echo $form->get("name")->render(); You could even use the form building method in this thread starting post and render fields where you like. There'll be still markup being outputed depending on the inputfieldtype, but maybe allows for more flexibility. $showform = true; $form = $modules->get("InputfieldForm"); $field = $modules->get("InputfieldEmail"); $field->attr("name", "email"); $field->label = "Email"; $form->append($field); if($input->post->submit) $form->processInput($input->post); if($form->getErrors()) { $showform = true; } else { $showform = false; // form valid, do something } if($showform) { echo "<form action='#' method='post'>"; echo "<div class='row'>" . $form->get('email')->render() . "<div>"; ... } Anything is possible, just use what you need. Think it's almost same as you would work with fields or pages.1 point
-
1 point
-
After spending a fair amount of time comparing ExpressionEngine with ProcessWire, I have decided that I want to use ProcessWire for my future projects. The enthusiasm for the product among the members of this forum was one of the factors I considered in making the decision. So, I thank you all for taking the time to express your opinions and for making comparisons between the products. Informed opinions are incredibly valuable to those who want to avoid starting down the wrong path. I successfully installed and started using ProcessWire on my site within a couple of hours which is further evidence of its ease of use. Since most of my experience has been with building sites using Dreamweaver, I think the fastest way for me to be productive will be to build my templates in Dreamweaver using my prior work and then upload them to ProcessWire on my target site. I have already been successful with that approach. The question I have for this group is whether there is a step by step guide to installing ProcessWire on your local machine, including installing and setting up MySQL. I think that I need to do this so that I can test my templates locally before uploading to ProcessWire on my site. Since I have only worked with static web pages in the past, please let me know if any of you have used a different or better approach in leveraging your Dreamweaver knowledge. I am eager to learn as much as I can as quickly as I can, and I don't want to waste any of your valuable time because you are just good people who like to help others. Therefore, please steer me to any existing documentation, tutorials or online information that I will happily study. Thank you. Bill1 point
-
Hello wjkaluza, welcome to the forum! Glad you decided to go with PW Creating a hosting environment on your computer is very easy because there are programs that have all that you need bundled (Apache, PHP, MySQL): For MAC: http://www.mamp.info/ For windows (there are many, here are three examples): http://www.apachefriends.org/ http://www.wampserver.com/ http://www.uniformserver.com/ <- I like this one For Linux: Depends of the Distro, but if you are using Dreamweaver I can imagine you don't need this.1 point
-
Try clearing the sessions and caches in assets folder. If theres no sessions folder, create one. Enable debug mode in config.php. Create new password like martijn explains.1 point
-
Type in your home template or else. $u = $users->get('admin'); $u->of(false); $u->pass = 'superSecretPassword'; $u->save(); Then go to a page with that template. Then go to /processwire/ & login. --- I almost forgot: Welcome Bosse1981 !1 point
-
I'm not sure about repeaters API to create a new fields and repeater. repeaterFields doesn't seem really the way to add fields. This is only used on the field config UI to add and remove fields. So it exists but it's processed through a POST. Repeaters use a template/fieldgroup where the fields are added. So a way to add fields I found by trying is after saving the repeater you get the template used by this repeater with the prefix "repeater" and the fieldname $t = $fieldgroups->get("repeater_quotes"); $t->add("title"); $t->save();1 point
-
1 point
-
1 point
-
Hello Ovi Thanks for the info. I could connect and checked it out. I haven't done anything and it works. I only clicked "Check for new modules" once. The hook is getting executed and the output is shown in the review box after I submit the comment. Not sure what's about it, maybe you didn't look close enough but it's working as it should. I tested on this product /adaptasun-sea-and-tropics-spf-30/. Now I first looked also at what modules are installed, and the only strange thing is that you have 2 FieldtypeComments module, the one in core and one by Apeisa in site/modules ... ? Can they coexist like this? Well if it works, but I'm not sure if it would cause troubles or isn't needed. At least the core one can be deinstalled? Well so far, happy hacking.1 point
-
Thanks Diogo! You are right it has some concepts that a newbie like me will be lost trying to grasp the meaning/dependencies of all the files on the blog profile, I will start by carefully reading the mentioned tutorials and finish my current project in Modx, then I will try pWire on my next project. I look forward to start using pWire. Mais uma vez, muito obrigado Diogo. Thanks Ryan I'll have look into it too.1 point
-
Hi there! If you are only testing and you don't need to build a blog right now, I would advise to stay away from the blog profile for now, as it has some rather advanced concepts. Start by reading the docs and playing around with the default install. You can also follow the existing tutorials http://wiki.processwire.com/index.php/Small_Project_Walkthrough and http://wiki.processwire.com/index.php/Basic_Website_Tutorial. You will be comfortable with PW in no time, and then you will be able to fully understand the blog profile.1 point
-
Dear Ryan and Soma, Thank you both for your help. Soma, I *thought* I had looked at your "derefAsPage" suggestion, but I must have done it wrong, because now it works, with both single and multiple and empty values. if( $field->derefAsPage == 0) { # is array $field_value = ''; $total_pages = count( $page->$field_name ); $count = 0; foreach( $page->$field_name as $field_value_element ) { $count++; if ( $count < $total_pages ) { $field_value .= $field_value_element->select_value . '<br>'; } else { $field_value .= $field_value_element->select_value; } } } else { $field_value = $page->$field_name->select_value; } I must have missed something, but now it all seems good. Thank you both!!! Peter1 point
-
Just a quick note to those trying unsuccessfully to login via Twitter the past few weeks - this is finally fixed now and you can carry on as usual.1 point
-
You can construct a TemplateFile object without a filename, but there will be a problem with the render method if you haven't set a filename: public function ___render() { if(!$this->filename || !is_file($this->filename)) return ''; You could hook after TemplateFile::render() and check for the return value. If it's empty, return your $page->body content.1 point
-
There have been several commits to the dev branch the last couple of days to fix issues with pagination and language support. Upgrade to see if this helps, or if you've already done so maybe your problems come from the last commits. https://github.com/ryancramerdesign/ProcessWire/commits/dev1 point
-
Speaking of inline mode, I also prefer to use it in the admin, but you can't use custom styles with it For instance, I want all the images inside the editor to have a max-width of 200px so they work as thumbnails. With regular mode i would define a css file from the field settings, but, as I told, this is not possible in inline mode. So, how to overcome this limitation? In the admin theme .InputfieldCKEditorInline img{ max-width:200px; } Not the perfect solution, but it works.1 point
-
Check settings for the field "genres": in the details what's the options selected for "Dereference in API as"? To support multiple selections this should be "Multiple pages" but it sounds like you've got either of those "Single page" options selected at the moment. This is how it should *not* look like: (Edit: added "*not*" above the screen shot )1 point
-
You misunderstood what I meant with max width. I meant the width of the larger viewport side. So maybe what you have in mind already. It was just a little confusion what the desired result is with all those screenhots . I'm just curious what you plan to do if ratio/orientation changes or if images have extreme ratios? Meaning to calculate the space of the area and resize the images according to that may result in having a image larger than viewport... Well I once I had such a calculation (can't remember exactly) It should be pretty easy to get a max width or height depending on orientation ratio. $vw = 600; $vh = 600; $spacing = 50; $images = array( array(3000,1800), array(2300,2300), array(1500,2000) ); $ratio = $vw/$vh; if($ratio < 1) { // portrait $max = $vw - $spacing; } elseif($ratio > 1){ // landscape $max = $vh - $spacing; } else { // square $max = $vh - $spacing; } foreach($images as $im) { if($im[0] > $im[1]) { // landscape image echo "w: ". $max . " h: " . round($max/$im[0] * $im[1]) . "<br/>"; } elseif($im[0] < $im[1]) {// portrait echo "w: ". round($max/$im[1] * $im[0]) . " h: " . $max . "<br/>"; } else { // square echo "w: ". $max . " h: " . $max . "<br/>"; } } And this would be a area square calculation and you'll quickly see what I mean. $vw = 800; $vh = 600; $images = array( array(3000,1500), array(2300,2300), array(1500,2000) ); $area = $vw*$vh; echo "area: " . $area . "<br/>"; foreach($images as $im) { $r = sqrt($area/($im[0] * $im[1])); $w = floor($im[0] * $r); $h = floor($im[1] * $r); echo "w: ". $w . " h: " . $h . " (area = " . ($w * $h) . ")<br/>"; }1 point
-
A truly epic write up Ryan. I'm sure all those who visit this forum will benefit from your knowledge. Thanks for sharing it.1 point
-
Ok since you hook Page::viewable every page in PW will be somehow affected, even admin pages as they are also just pages. So the message with $event->object->name is the admin pages rendered in the admin template. I'd guess it's the navigation. But since the ProcessPageList module is ajax driven you won't see any messages from there. $event->arguments is nothing there I think, as the important with these page access hooks is the $event->return value. So you would do set it to false or true $event->return = false; // page won't be viewable All the viewable hook does is define if a page is viewable or throw an 404. In case of the admin page tree the page will still be visible and only have no -view- action button. That's all. If you really want to hide pages in the admin I'm with Ryan, but see that there's cases where it would be nice to hide pages from users and keep a branch hidden from them. I already stumbled and tried very hard 1-2 years ago, but realized it's not easy as there's no obvious hooks available where needed and it's done with ajax and there's some things to consider, didn't really bother. Now after thinking for some time and try error I found an easy way to just remove pages from the page list tree. The trick is to modify the JSON output that goes with the ajax response, convert it to an array and Long story short here's an example module for those interested. I used a pagelist_hidden page field added to the user template to define pages that are hidden for a user. Of course there could be endless configuration possibilities, with roles and what not, but don't want to go any further and maybe someone else finds this useful or as a start for a new module. If Ryan reads this and is still with me. Would you consider adding some hooks to ProcessPageList.module? Or do you think the JSON manipulation is a good way? Most likely there would have to be some additional take care to make those pages also not editable. Those page will still be accessible manually through admin url. Such a module shouldn't be used to hide pages for access restriction, and it's only and best suited for hiding "private" branches in the admin, or functional pages that can't be in the /Admin/ branch for some reasons.1 point
-
1 point
-
Greetings mindplay.uk, Now I see what you mean. I was imagining different uses. What you're talking about reminds me of the hardwired features in CMSs like Joomla, where there is a "blog" view and "list" view for articles (pages). After years of using Joomla, I was happy NOT to have that system any longer. In ProcessWire, I simply create a second template whose function is to pull the necessary fields from the page(s) I need for my "list" view. Yes, it's a second template, but it's completely flexible how I compose that "list" view. By contrast, the Joomla system essentially forces the "list" view to be composed of certain "fields" and pre-determined layouts. In ProcessWire, we define where someone enters the "list" and "full" views, so it makes sense to me that we would use a separate template for that. Thinking this through, if there were essentially two separate views for each template, I suppose we could have a way to define which one is rendered from which entry point. But then there's the issue of how many possible alternate views might exist. I'm working on a site now where -- in addition to the "list" and "full" views -- I also have views for "featured" pages. I can imagine even more variations. Always interesting... Thanks, Matthew1 point
-
Almonk, Here's one way you could do it (below), using ProcessWire's WireUpload class: <?php $page->setOutputFormatting(false); // instantiate the class and give it the name of the HTML field $u = new WireUpload('userfile'); // tell it to only accept 1 file $u->setMaxFiles(1); // tell it to rename rather than overwrite existing files $u->setOverwrite(false); // have it put the files in their final destination. this should be okay since // the WireUpload class will only create PW compatible filenames $u->setDestinationPath($page->files->path); // tell it what extensions to expect $u->setValidExtensions('jpg', 'jpeg', 'gif', 'png'); // execute() returns an array, so we'll foreach() it even though only 1 file foreach($u->execute() as $filename) $page->files->add($filename); // save the page $page->save(); Another way to do it would be a more traditional PHP way: <?php $page->setOutputFormatting(false); // we run the $name through $sanitizer to make it PW compatible... // ...this prevents the possibility of it getting renamed on the add() call below $name = strtolower($sanitizer->name($_FILES['userfile']['name'])); // prepend underscores to filename until it's unique... // ...this is just one possible way to handle duplicate filenames while(is_file($page->files->path . $name)) $name = "_" . $name; // validate the file extension $pos = strrpos($name, "."); if(!$pos) throw new WireException("File is missing extension"); $ext = substr($name, $pos+1); if(!in_array($ext, array('jpg', 'jpeg', 'gif', 'png'))) throw new WireException("Invalid extension"); // determine the final destination and store it in $file $file = $page->files->path . $name; // move the file to it's destination using PHP's function if(move_uploaded_file($_FILES['userfile']['tmp_name'], $file)) { // add it to the page $page->files->add($file); /// save the page $page->save(); } Btw, no need to turn outputFormatting back on unless you are rendering parts of that page in the same request. Neither of these examples perform much error checking, which you may want to add. Though the WireUpload class will populate PW's "$notices" API var with any errors: <?php foreach($notices as $notice) { if($notice instanceof NoticeError) { echo "<p>Error: {$notice->text}</p>"; } } If you are using the PW's admin templates, then it already does something like the above snippet.1 point