You are not logged in.
Glad you fixed the problems!
Using the mysqli interface is preferred since the old mysql has been deprecated as of PHP 5.5.0 (http://www.php.net/manual/en/intro.mysql.php). If you are running an older version and only have access to the old mysql interface, you can update your config.php file from:
$bigtree["config"]["sql_interface"] = "mysqli";
to:
$bigtree["config"]["sql_interface"] = "mysql";
What context are you using the field type (page, module, callout, setting)? It's working on my end, but maybe I;m missing something.
Here's a link to the Many to Array field. Install it by uploading the package through the developer section. The field type will require you to set a source table when building your forms. It will then store an array of the select item's IDs, so set the corresponding database column to 'text,' or at the very least 'varchar'. Let me know if you have any questions.
No problem! I'm guessing you found AutoModules's clearCache() function:
Fetching module data using the base class functions, like get() or getApproved(), will use the internal function replaceInternalPageLinks() to make sure these variables are replaced with the actual URL set in the config.php file. If you're writing a new function in a custom module, it's best to run each item through the module's get() function:
public function getTeamMembers() {
$team = array();
$q = sqlquery("SELECT ...");
while ($f = sqlfetch($q)) {
$team[] = $this->get($f);
}
return $team;
}
You are correct in assuming the built in user system is for the BigTree admins. Implementing your own front-end user system is ideal because it keeps users of your site separate from the admins. We've done this a few ways in the past, usually tailored to fit the exact needs of the project.
Internally we use simple form management module. We are currently in the process of documenting the source and deciding how it will be released though our up-coming extension library.
However this doesn't mean forms have to be a pain. Normally I will set up a routed template where the default.php file draws the form, process.php processes the submitted data, and thanks.php displays a submission confirmation message to the user.
default.php
This shouldn't be a problem, we've implemented custom editors in the past using plugins like Code Mirror.
When custom field types are made through the admin, a few files are created:
custom/admin/form-field-types/draw/your-field-id.php
custom/admin/form-field-types/draw/your-field-id.php
custom/admin/ajax/developer/field-options/your-field-id.php
The first and second files are where the heavy lifting happens, the last is in case you need to set custom options for the field (this file is loaded into the field options modal when editing a form in the developer area). If you take a look at the file for the built-in WYSIWYG (core/admin/form-field-types/draw/html.php) you'll notice that all it does is add the field's id to an array of WYSIWYG instances, then include the standard textarea field. The array is then used to initialize all instances based on their id. This is essentially what you'll be doing in each instance of the field:
That's actually the older example site, the newer version (available with the latest beta) follows the standard page-tree based site structure more closely. We feel the current incarnation is better example of the different design patterns possible with BigTree, everything from the standard hierarchical pages to dynamic module-driven content to reusable callouts.
However, to answer your question the videos are being pulled into the site by the YouTube API module. It's using the title of the current "Wonder" - the main content of the older example site - to search the vast YouTube landscape for related videos. One of the goals of that example site was to show how simple content curation, not just creation, is in BigTree.
Sorry, there aren't any videos at this time - but we are always open to community contributions!
Pages are rendered by BigTree using an "inside-out" flow:
1. Template
The template file is executed first, this is either 'Basic' (a single .php file) or 'Routed' (a group of files that work together) depending on the template the current page is set to use. Templates should contain any page-specific pieces. This content will be inserted into the layout in the next step. You can switch layouts by setting the variable $bigtree["layout"] to the name of the desired file, excluding the '.php' extension.
2. Layout
The content rendered by the page template is then inserted into the layout. Layouts should include any supporting or reused elements, like a global header, navigation and footer. These can be drawn directly in the layout file or included from separate .php files. The content rendered by the template in the first step is inserted by echoing the variable $bigtree["content"].
3. Render
Once the template has rendered content and that content has been inserted into the layout BigTree will send the page off to the user's browser.
*Note: This "inside-out" method of page rendering is made possible by a technique known as output buffering. Read more about how output buffering works.
The Analytics class requires either 'fopen' or 'cURL' to properly fetch data from Google. To find out if either is available, check phpinfo() and look for one of the following lines:
allow_url_fopen = On
//OR
cURL support – enabled
You can enable fopen by adding a line to your php.ini file (as long as your host allows it):
allow_url_fopen = oncURL is more difficult - if you're on a shared host and both are unavailable, you probably won't be able to take advantage of BigTree's GA integration.
Remember that the $config variable has be deprecated. Please use $bigtree["config"] instead.
Remember that the $config variable has be deprecated. Please use $bigtree["config"] instead.
Remember that the $config variable has be deprecated. Please use $bigtree["config"] instead.
You are correct, BigTree doesn't use 'themes' - just raw assets and templates. But it doesn't mean you can't have multiple 'mini-sites,' all with their own unique designs.
If you take a look at the example site's 'home' layout you'll see it includes a header, then echos the content (defined in the page's template), then includes the footer:
To switch the site's appearance simply create a new layout, let's say "mini-site.php":
Now any page set to use the 'mini-site' layout will be rendered using the mini-site's header and footer. You can set the layout for the current page in the selected template:
$bigtree["layout"] = "mini-site";
Sorting is always done by id DESC, so of 5 items, the 'top' item is position 4. Adding pagination to sortable views could be as simple as passing the current page, along with the current sub-set's order, and calculating the new offset order. So page 2 of 3, displaying 20 items each, would contain items ordered 39-19. We would then only update the effected rows. The only down side to having paginated sortable views would be that you will loose the ability to move an item from a deeper page to the top. If your project doesn't require sorting, feel free to remove it completely. Also, remember to make any modifications to core files by duplicating the file's directory location inside the custom folder. Core files will be overwritten if a mirror is found in the custom folder, allowing you to maintain the core code base while still customizing to no end.
The local_drawPageTree function is called lower in the view-tree.php file. It is a localized display function that is passed arrays generated by the admin functions getNaturalNavigationByParent, GetHiddenNavigationByParent and getPendingNavigationByParent.
One issue you may run into when trying to impliment pagination on the default sortable tree view is the actual re-ordering of the pages. We have squashed that bug limiting the size of the ajax call, but the process still requires the set's order to be passed in full. One fix could be to re-write the query to reorder the objects within the bounds of the current sub-set. let us know if you come up with something, we'll also take a closer look into tackling this issue.
If you ever need to keep prying eyes from your BigTree site during development, but don't want to mess with directory access, use this simple snippet:
if (!$_SESSION["bigtree"]["id"]) {
die("ACCESS DENIED: Please log in to view this page.");
}
This will keep users who are not logged into BigTree from viewing your site. Simply create a file named check-login.php containing those three lines in your custom/inc/required/ directory. You can also lock down individual pages or sections by adding those lines to the top of your template. You may want to switch out the die() statement for a hard redirect if blocking access to a section of a live site.
When a URL is requested BigTree tries to find a matching page and render it's content. If the URL string is an exact match for a page with a basic template assigned, that template will be rendered. If an exact match can not be found, BigTree will start chopping off segments until it does find a match. If it finds a matching page that is assigned a routed template, the left over URL segments are stored in the $commands array and made available in the rendered template. Read more about how BigTree routes pages. If BigTree can't find a basic or routed page that matches, it will render the "_404.php" file from the basic templates folder.
Routed modules are a bit different. Let's say you have a routed template, containing a "default.php" and "details.php" file, assigned to the page "http://www.example.com/products/". The URL "products/" will render the "default.php" file, while "products/details/" will render the "details.php" file. A request like "products/category-name/" could be used to query for, and display products from, a specific category. If the category doesn't actually exist, you may want to display a 404 page for your users:
$productsMod = new SiteProducts;
$categoriesMod = new SiteCategories;
if (isset($commands[0])) {
// $commands[0] = the route of the category
$activeCategory = $categoriesMod->getByRoute($commands[0]);
if (!$activeCategory) {
// Display a 404 since the category doesn't exits
include "../templates/basic[url]/_404.ph[/url]p";
} else {
// Get everything from the specific category
$products = $productsMod->getMatching(array("category"), array($activeCategory["id"]));
}
} else {
// Get everything when no category is defined
$products = $productsMod->getAll();
}
Feel free to style this page any way you want, use a custom layout, go crazy!
Once thing to keep in mind when developing in BigTree is that the page is always executed through the main "index.php" file in the "site" folder (this helps us with the fancy URL rewriting, along with the .htaccess file). This means when including files from different directories, relative file references should be based on the location of the "index.php" file. In the example above, we're including a file from the "basic" template folder in a file from the "routed" template folder, meaning we have to reference the included file with the relative path "../templates/basic/_404.php" (because "templates" is one directory back from "site"). If you are including a file from the same directory, simply reference the file name:
include "_product_search_form.php";
A simple comment system can be achieved by setting up a "comments" module. Build out a form to take the user input, as well as a process file that sanitizes the user input and makes use of the module's add() method. Something like:
$commentsMod = new SiteComments;
$keys = array(
"name",
"email",
"comment"
);
$vals = array(
$name,
$email,
$comment
);
if ($commentsMod->add($keys, $vals)) {
echo 'Yay!';
} else {
echo 'Boo!';
}
This process could also be run from an ajax call to avoid a new page load, sort of an auto-updating comment system.
If you're using something like MAMP to develop locally, one way to keep databases in sync is to use daily SQL backups. Apps like Sequel Pro make the import/export process really simple. Internally, we use a dedicated development server, so we all work from one file system.
Upgrading BigTree should be as simple as replacing the core folder. Our goal is to keep backwards compatibility between minor versions; Major version upgrades may require some development time. Any big changes that do require development time will be outlined in that version's release notes. We're currently releasing new beta versions about once a week - when a new version is released, simply upload the new core folder and refresh your admin. If you're using GIT, simply pull the latest from the "Development" branch.
This can be achieved one of two ways. Both will require a single relation table with a column for the category as well as one for each type of content. Set up each module to use the same relation table for it's many-to-many. Now we can get into the nitty gritty.
The first way to get the desired result is to query the relation table for all rows containing the category. Then loop through each relation row querying for the correct post:
function getMedia($category) {
$cat_rels = array();
$cat_q = $this->sqlquery("SELECT * FROM `media_categories_rel` WHERE category = " . $category . " ORDER BY id DESC");
while ($f = sqlfetch($cat_rels)) {
$cat_rels[] = $f;
}
$return_media = array();
foreach ($cat_rels as $rel) {
if (is_int($rel["video"])) {
$return_media[] = $this->get(sqlfetch(sqlquery("SELECT * FROM `media_videos` WHERE id = " . $rel["video"] . " LIMIT 1")));
} else if (is_int($rel["post"])) {
$return_media[] = $this->get(sqlfetch(sqlquery("SELECT * FROM `media_posts` WHERE id = " . $rel["post"] . " LIMIT 1")));
} else if (is_int($rel["gallery"])) {
$return_media[] = $this->get(sqlfetch(sqlquery("SELECT * FROM `media_galleries` WHERE id = " . $rel["gallery"] . " LIMIT 1")));
}
}
return $return_media;
}
This method might require a different sorting method depending on how the data is input.
The second and more efficient way is to write a nice big query to fetch everything at once:
function getMedia($category) {
$query = sqlquery("SELECT posts.* FROM (
(SELECT v.* FROM `media_videos` AS v, `media_categories_rel` AS rel WHERE v.id = rel.video AND rel.category = '" . $category . "' ORDER BY v.date DESC)
UNION ALL
(SELECT p.* FROM `media_posts` AS p, `media_categories_rel` AS rel WHERE p.id = rel.post AND rel.category = '" . $category . "' ORDER BY p.date DESC)
UNION ALL
(SELECT g.* FROM `media_galleries` AS g, `media_categories_rel` AS rel WHERE g.id = rel.gallery AND rel.category = '" . $category . "' ORDER BY g.date DESC)
) AS posts
ORDER BY posts.date DESC LIMIT 10");
$return_media = array();
while ($fetch = sqlfetch($query)) {
$return_media[] = $this->get($fetch);
}
return $return_media;
}
Both methods should be functions of a custom module class so they can make use of the function [url=http://www.bigtreecms.org/docs/code/core/BigTreeModule/#get]get(), ensuring all internal page links and json-encoded resources are properly translated. They are both also heavily reliant on direct SQL queries, so remember to clean any inputs.
Any fields that are not used in the current view or form will be listed here. Clicking the "X" to remove a field from a view or form and move it into this list. To add the field back, simply select the name of the field and click "Add".
Say you only want the "Title" column visible in the view, you would remove all others by clicking the "X". If later on you find you need to show a "Date" column for each item, start by editing the module's view. Select the name of your date field and click "Add." It will insert a new sortable row into the resource table where you can edit the field's details.
Nice find! This is a bug that has been successfully squashed in the beta 2 release.
If you're feeling adventurous you can fix it your self. Open up core/inc/bigtree/admin.php in your favorite text editor and look for the createTag() function. The issue is that the object $cms is out of scope and needs to be globalized:
// Change:
function createTag($tag) {
$tag = strtolower(html_entity_decode($tag));
// To:
function createTag($tag) {
global $cms;
$tag = strtolower(html_entity_decode($tag));
The array $commands is used a lot, it's where any pieces of a URL that aren't used to find the current file in a routed template are stored. In the 'News' example above there are two files in the 'news' routed template folder:
default.php
details.php
If you were to request the URL 'http://www.example.com/news/' BigTree will render the file default.php. Requesting 'http://www.example.com/news/details/' will render details.php, with an empty $commands array. Adding your newly generated route to the URL, like 'http://www.example.com/news/details/breaking-news/', will still render details.php but the $commands array will now contain 'breaking-news' as the first item.
This covers the most standard usage, but you can also use $commands to define actions within a routed template.